我想知道如何在函数式编程中建立关系模型。
以雇员为例:员工可以与0..n同事建立友谊。友谊总是相互的:如果A是B的朋友,那么B是A的朋友。
如何建模?我有3个想法(在下面列出)。他们每个人都有缺点。
第一次尝试:
type Employee =
{ name : string
friendships : Employee list
}
// My list is mutable because I want to be able to update employees.
// I suppose the same problems would occur with e. g. Elmish.
let mutable employees : Employee list = [ (* ... *) ]
(* Downsides:
Friendships are copies. Changes to an employee would have to be propagated manually.
*)
第二次尝试:
type EmployeeId = int
type Employee =
{ id : EmployeeId
name : string
friendships : EmployeeId list
}
let mutable employees : Employee list = [ (* ... *) ]
(* Downsides:
Friendships are not modeled as mutual.
When the friendship of an employee changes,
the friend's friendships don't change accordingly.
*)
第三次尝试:
type EmployeeId = int
type Friendships = list<EmployeeId * EmployeeId>
type Employee =
{ id : EmployeeId
name : string
}
let mutable employees : Employee list = [ (* ... *) ]
(* Downsides:
After deleting an employee from the list,
employeeFriendships contain invalid "references"
to the deleted Employee.
*)
这可以做得更好吗?谢谢。
使用let rec
/ and
可能是最直接的方法。您需要通过将friendships
更改为IEnumerable
来引入懒惰。
type Employee =
{
name : string
friendships : seq<Employee>
}
let rec peter = {name="Peter"; friendships=seq {yield paul; yield mary}}
and paul = {name="Paul"; friendships=seq {yield peter; yield mary}}
and mary = {name="Mary"; friendships=seq {yield peter; yield paul}}
编译器警告:
对定义的对象的此和其他递归引用将通过运行时在运行时检查初始化是否健全使用延迟参考。这是因为您正在定义一个或更多的递归对象,而不是递归函数。这个警告可以通过使用'#nowarn“ 40”'或'--nowarn:40'来取消。