functional-programming - 函数式编程: How to model relationships?

标签 functional-programming f# modeling

我想知道如何在函数式编程中建模关系。

我们以员工为例: 员工可以与 0..n 个同事建立友谊。 友谊总是相互的:如果 A 是 B 的 friend ,那么 B 就是 A 的 friend 。

我该如何建模?我有 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}}

但是,编译器会给出以下警告:

This and other recursive references to the object(s) being defined will be checked for initialization-soundness at runtime through the use of a delayed reference. This is because you are defining one or more recursive objects, rather than recursive functions. This warning may be suppressed by using '#nowarn "40"' or '--nowarn:40'.

...这指出了一个可以说更好的解决方案:

type Employee =
    { 
        name : string
        friendships : unit -> Employee list
    }

let rec peter = {name="Peter"; friendships=fun () -> [paul; mary]}
and paul = {name="Paul"; friendships=fun () -> [peter; mary]}
and mary = {name="Mary"; friendships=fun () -> [peter; paul]}

关于functional-programming - 函数式编程: How to model relationships?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60232682/

相关文章:

functional-programming - F# 中是否有类似于 scalaz、cats 和 arrow (Kotlin) 的库?

haskell - 人们使用恒等函数做什么?

recursion - 实现最后一个非零而不延续

c# - 禁用搜索 GAC

performance - 一般如何优化 F# 程序

object - 作为对象的数字,或存储数字的属性

f# - Stackless trampoline Monad/计算表达式

lambda - F# 不带参数的 lambda 表达式

uml - 我们什么时候使用UML,什么时候不使用?

python - 随机森林 - 使空值在决策树中始终有自己的分支