我想在深入研究複雜示例之前弄清楚F#的基本知識。我正在學習的材料引入了歧視聯盟和記錄類型。我已經審查了兩者的材料,但我仍然不清楚爲什麼我們會使用這兩種材料。何時使用歧視聯盟與F#中的記錄類型
我創造的大多數玩具例子似乎都可以在兩者中實現。記錄似乎是非常接近我所認爲的在C#中的對象,但我想避免依賴映射到C#的方式來了解F#
所以......
是有明確的理由使用一個在另一個?
是否存在某些適用的規範情況?
是否有某些功能可用於其中一個,但不是 其他?
我想在深入研究複雜示例之前弄清楚F#的基本知識。我正在學習的材料引入了歧視聯盟和記錄類型。我已經審查了兩者的材料,但我仍然不清楚爲什麼我們會使用這兩種材料。何時使用歧視聯盟與F#中的記錄類型
我創造的大多數玩具例子似乎都可以在兩者中實現。記錄似乎是非常接近我所認爲的在C#中的對象,但我想避免依賴映射到C#的方式來了解F#
所以......
是有明確的理由使用一個在另一個?
是否存在某些適用的規範情況?
是否有某些功能可用於其中一個,但不是 其他?
認爲它是一個記錄是'和',而歧視的工會是'或'。 這是一個字符串和一個int:
type MyRecord = { myString: string
myInt: int }
,而這是一個字符串或一個整數,但不能同時一個值:
type MyUnion = | Int of int
| Str of string
這個虛構的遊戲可以在標題畫面,在遊戲中,或顯示最終得分,但只有其中一個選項。
type Game =
| Title
| Ingame of Player * Score * Turn
| Endgame of Score
那麼,在DU中是否有任何方法來創建一個擴展Game的組合類型?例如| InGameTitle的Title * Ingame。即一個包含Title * Player * Score *的元組* Turn –
@Chris:這隻會引出一個問題:你爲什麼想要? – ildjarn
@ildjarn你是對的。當我第一次寫評論時,我並沒有完全理解DU的目的。 MisterMetaphor先生的回答幫助我理解了爲什麼你會像Robert那樣使用它,但不是如我所述。 –
如果你來自C#,你可以瞭解記錄爲密封類與附加價值:
歧視聯盟編碼替代例如
type Expr =
| Num of int
| Var of int
| Add of Expr * Expr
| Sub of Expr * Expr
的DU上述被讀出如下:表達式是要麼的整數,或一個變量,或加成兩個表達式或兩個表達式之間減法。這些情況不能同時發生。
您需要所有字段才能構建記錄。您也可以在記錄中使用DU,反之亦然
type Name =
{ FirstName : string;
MiddleName : string option;
LastName : string }
上面的示例顯示中間名是可選的。
在F#中,您經常使用元組或記錄開始建模數據。當需要高級功能時,您可以將它們移動到類上。
另一方面,歧視聯盟用於替代模型和互斥案件之間的關係。
謝謝。這個答案和另一個都指出了DU是一種OR關係的事實。但據瞭解,單個DU可以保存多個值。即「類型名稱」可以具有「FirstName,MiddleName和LastName」的值。這仍然讓我有點不確定,一個具有所有字段值的記錄與一個具有所有字段值的DU之間的區別是什麼。難道DU可以做某種形式的推理或記錄不能做的操作嗎?或者這裏的不變屬性是不同的? –
使用記錄複雜的數據(在函數式編程理論所謂的產品類型),這是由幾個屬性描述,如數據庫記錄或一些模型實體:爲
type User = { Username : string; IsActive : bool }
type Body = {
Position : Vector2<double<m>>
Mass : double<kg>
Velocity : Vector2<double<m/s>>
}
使用識別聯合(稱爲總和類型)數據的可能值可以列舉。例如:
type NatNumber =
| One
| Two
| Three
...
type UserStatus =
| Inactive
| Active
| Disabled
type OperationResult<'T> =
| Success of 'T
| Failure of string
注意,對於一個識別聯合值可能值也相互排斥 - 用於操作的結果可以是在同一時間Success
或Failure
,但不能同時使用。
你可以使用一個記錄類型的結果編碼的操作,像這樣:
type OperationResult<'T> = {
HasSucceeded : bool
ResultValue : 'T
ErrorMessage : string
}
但在操作失敗的情況下,這是ResultValue
沒有意義。因此,圖案這種類型的區分聯合版本匹配應該是這樣的:
match result with
| Success resultValue -> ...
| Failure errorMessage -> ...
如果您模式符合我們的操作類型的記錄類型版本,它將使意義不大:
match result with
| { HasSucceeded = true; ResultValue = resultValue; ErrorMessage = _ } -> ...
| { HasSucceeded = false; ErrorMessage = errorMessage; ResultValue = _ } -> ...
它看起來冗長而笨拙,可能效率也不高。我認爲當你有這樣的感覺時,這可能暗示你正在使用錯誤的工具來完成任務。
感謝您的回覆。我現在看到DU在哪裏特別有意義。 –
理解一個DU的方法之一就是將它看作一個奇特的C#「union」,而記錄更像是一個普通的對象(具有多個獨立的字段)。
查看DU的另一種方法是將DU視爲一個兩層的類層次結構,其中最上面的DU類型是抽象基類,DU的例子是子類。這個視圖實際上接近實際的.NET實現,儘管編譯器隱藏了這個細節。
OO繼承層次結構的一個重要區別是,DU的不同情況僅僅是標記,而不是不同(子)類型。有時候會讓新人感到困惑。 – Frank
本頁面末尾有一個簡短的段落http://msdn.microsoft.com/en-us/library/dd233205.aspx。 –