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
可悲的是,Manager和Executive的定义现在给出了一个错误:“不推荐使用此结构;请考虑使用单独的记录类型。”好吧,看起来很公平,我们称之为ManagerType。但等等...... ManagerType指Employee(报表部分),Employee指ManagerType(表示Manager选项)。
这里有解决方案吗?两个数据结构是否不可能相互定义?
答案 0 :(得分:11)
您可以使用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 }
答案 1 :(得分:10)
如果你正在使用F#v3.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
答案 2 :(得分: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}
答案 3 :(得分:0)
从FSharp 4.6开始,您可以将Anonymous Records与联合使用。因此,可以用这种方式定义您的示例:
type Person = {
First : string
Last : string
}
type Employee =
| Engineer of Person
| Manager of {| Name: Person; Reports: Employee list |}
| Executive of {| Name: Person; Reports: Employee list; Assistant: Employee |}