我正在尝试定义和创建一个树结构,其中父级了解子级,反之亦然。
我创建了以下 F# 代码,它不显示任何警告(在 fsx 中),并且似乎编译得很好。
type Parent = {
Name : string
Age : int
Children : Child list }
and Child = {
Name : string
Parent : Parent }
let createParent name children =
{ Name = name
Age = 42
Children = children }
let createChild name parent =
{ Name = name
Parent = parent }
let create name kids =
let rec makeChild name = createChild name parent
and makeParent name = createParent name children
and parent = name |> makeParent
and children = kids |> List.map makeChild
parent
create "Peter" [ "Sarah"; "Max" ]
|> printfn "%A"
但是当我运行这个脚本时,我可以看到“Children”为空。
我是否遗漏了什么,或者这样的数据结构根本无法在 F# 中构建?
我绝不是这个主题的专家,但我认为这是因为 F# 开箱即用的不变性以及您在 Parent 和 Child 之间引入的循环依赖关系。
有一次我正在开发一个项目,该项目在域模型和数据模型之间具有这种循环依赖关系。
每次添加新实体时,我都会从域模型开始,但无法完成它,因为它依赖于数据模型。因此,我不得不放弃领域模型,转向数据模型来实现它。但我再次无法完成数据模型的实现,因为它依赖于域模型。因此,我必须返回到域模型来完成该操作,然后再次返回到数据模型以执行相同的操作。
当我编写该代码时,我可以保留一些未完成的部分,即类的实现,但在初始化 F# 记录时不能这样做。
我认为最好的解决方案是设计出循环依赖。
如果这是不可能的,您可以考虑使一个引用可变,例如:
type Parent =
{ Name: string
Age: int
mutable Children: Child list option }
and Child =
{ Name: string
Parent: Parent }
然后做这样的事情:
let create name kids =
let parent = createParent name None
let children = kids |> List.map (fun k -> createChild k parent)
parent.Children <- Some children
parent