2011-07-18 48 views
2

我經常需要聲明包含地圖或列表,例如一個類型:哪種風格更適合在Ocaml中聲明類型?

type my_type_1 = my_type_0 IntMap.t 
type my_type_2 = my_type_0 List 

而且我看到聲明的另一種風格,它封裝映射或列表中的記錄,例如:

type my_type_1 = 
    | Bot_1 
    | Nb_1 of my_type_0 IntMap.t 
type my_type_2 = 
    | Bot_2 
    | Nb_2 of my_type_0 List 

我的問題是,是否有一些情況下,第二種風格是必要的,比第一種風格更好?

非常感謝!

回答

2

由於在第二種情況下添加了Bot構造函數,因此您給出的兩種類型不相同。這意味着兩個my_type_1不具有相同的語義。順便提及,構造已經由標準型'a option提供,構造SomeNone,所以你的第二樣品的my_type_1類型是等同於第一個的my_type_1 option

是否使用option類型或您自己的構造函數名稱取決於您。一般來說,如果您的類型的語義與option失敗,缺席或未定義的想法一致,我會向您建議一個選項類型。考慮到你的名字Bot,我認爲這可能是你在做什麼,但是定義你自己的構造函數名也可以,在某些情況下可以更清楚。這個問題已在this blog post from ezyang中深入討論過。

現在,假設你的兩種類型定義當量(即,在不存在Bot)的構造函數,什麼是添加一個代數數據類型層,一個新的構造,而不是使用一個簡單的類型別名的目的是什麼?那麼它的作用就是使你的類型與表示類型不同。例如,如果您定義了type 'a stack = Stack of 'a list,則'a stack'a list不能相互混淆,如果您這樣做,編譯器會引發錯誤。因此,可以用來強制執行(輕)型分離,用構造作爲類型註釋:

let empty = Stack [] 
let length (Stack li) = List.length li 

我會說這是主要的品味的問題,但我會建議使用代數數據類型,而不是如果您想確保原始類型不會出現任何錯誤,請使用別名。缺點是你必須包裝原始數據類型的操作,就像我在上面的函數length中那樣。

0

第二個不是「記錄」(這是不同的事情)。它創建一個代數數據類型。我不確定如何解釋它,但如果你使用Haskell或Standard ML,你會知道。它基本上是一個標記的聯盟。 A my_type_1或者 a Bot_1(其不攜帶數據)或Nb_1(攜帶my_type_0 IntMap.t作爲數據)。

第一個只是一個類型的同義詞(就像C中的typedef)。

+0

感謝您的意見 – SoftTimur

1

那些不是不同樣式,但不同類型的:所述第一類型聲明是一個專門的實例的縮寫(mytype_0)多態性List,或IntMap的。

第二組定義呈現「構造」類型,其Bot_1(和Bot_2)提供值。例如,可以使用這些「替代方案」來創建類型爲T -> my_type_1的函數,在計算不允許返回列表的特殊情況下返回Bot_1,類似於option type允許的方式。第一組定義(誰必須始終提供所需的列表有效載荷)是不可能的。

+0

感謝您的評論 – SoftTimur