2014-02-05 103 views
9

的F#教程包括下面的代碼片段:匿名的記錄類型內識別聯合

/// A record for a person's first and last name 
type Person = {  
    First : string 
    Last : string 
} 

/// define a discriminated union of 3 different kinds of employees 
type Employee = 
    | Engineer of Person 
    | Manager of Person * list<Employee>   // manager has list of reports 
    | Executive of Person * list<Employee> * Employee // executive also has an assistant 

是經理和執行被描述爲元組冒犯了我的感情(我很容易生氣)的事實。它讓我覺得不是非常有表現力。我試圖對其進行修改如下:

/// define a discriminated union of 3 different kinds of employees 
type Employee = 
    | Engineer of Person 
    | Manager of { Name: Person; Reports: Employee list }   // manager has list of reports 
    | Executive of { Name: Person; Reports: Employee list; Assistant: Employee} // executive also has an assistant 

可悲的是,經理和執行的定義現在給出一個錯誤:「該構建過時;考慮使用一個單獨的記錄類型,而不是」。好吧,看起來很公平,我們稱之爲ManagerType。但是請等待... ManagerType引用Employee(對於Reports部分),Employee引用ManagerType(對於Manager選項)。

這裏有解決方案嗎?兩個數據結構是不可能相互定義的?

回答

10

您可以定義相互依賴的類型使用and

type Employee = 
    | Engineer of Person 
    | Manager of Manager   // manager has list of reports 
    | Executive of Executive 
    and Manager = { Name: Person; Reports: Employee list } 
    and Executive = { Name: Person; Reports: Employee list; Assistant: Employee } 
+0

有趣。我們也可以使用繼承嗎? Executive可以從經理處獲得嗎?或者這隻適用於記錄? –

10

如果您使用F#3.1版,您可以使用named union fields [MSDN](和保護你嬌嫩的感情):

type Employee = 
    | Engineer of Person 
    | Manager of Name: Person * Reports: Employee list 
    | Executive of Name: Person * Reports: Employee list * Assistant: Employee 
+1

此解決方案我不好(它確實避免了我的弱體質),但是如果我只想從經理中提取報告,比如模式匹配表達式,看起來會是什麼樣子?使用其他解決方案將是:'|經理({Reports = rep}) - >無論是什麼。 – CSJ

+2

我沒有安裝v3.1,但根據我的答案中鏈接的MSDN頁面,它將是'|經理(報告= rep) - > ...'。 – Daniel

6

相互遞歸類型的聲明與type ... = ... and ... = ...

type Employee = 
    | Engineer of Person 
    | Manager of Manager 
    | Executive of Executive 
and Manager = { Name: Person; Reports: Employee list } 
and Executive = { Name: Person; Reports: Employee list; Assistant: Employee} 
+0

對不起,李偷偷溜了一下:) – CSJ