I wonder how to model relationships in functional programming.
Let's take employees, for example: Employees can have friendships with 0..n colleagues. Friendships are always mutual: if A is a friend of B then B is a friend of A.
How can I model this? I had 3 ideas (listed below). Each of them has downsides.
First try:
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.
*)
Second try:
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.
*)
Third try:
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.
*)
Can this be done better? Thank you.
Employeeobject would be good enough.Set<EmployeeId * EmployeeId>and make sure you always store the tuple in order to avoid duplicates/ambiguities. The downside you point out is inevitable in this case but not grave.