F#error FS0695,此递归绑定使用递归形式的无效混合

时间:2014-06-17 12:45:00

标签: f# immutability

以下代码导致编译器错误," FS0695:此递归绑定使用无效的递归形式混合。"

type Parent =
    { ParentName : string
      Children : Child list }

and Child = 
    { ChildName : string 
      Parent : Parent }

let createChild parent childName =
    { ChildName = childName
      Parent = parent }

let createParent parentName childNames =
    let rec children = childNames |> List.map (fun childName -> createChild parent childName)
    and parent = {
        ParentName = parentName
        Children = children
    }
    parent

错误消息是什么意思?我该如何更正此代码?

该代码旨在使用循环引用初始化F#不可变记录。我尝试应用解决方案herehere,但没有成功。

2 个答案:

答案 0 :(得分:4)

我不熟悉这个错误,似乎没有记录在任何地方,但这是我可以推测一下它之后可以推测的。

问题似乎在于parent如何被lambda表达式关闭,而lambda表达式本身就在children的定义中。这显然抛弃了类型检查器(tc.fs) - 我的猜测是因为children绑定本身的右侧包含一个表达式(lambda表达式),它本身包含一个递归引用,但真正的原因可能比这更微妙。请注意,如果您反转这样的声明:

let createParent parentName childNames =
    let rec parent = {
        ParentName = parentName
        Children = children }
    and children = childNames |> List.map (fun childName -> createChild parent childName)
    parent

您还会在绑定children的行上看到此警告:

  

警告:通过使用延迟引用,将在运行时检查对定义的对象的此递归引用和其他递归引用的初始化 - 健全性。这是因为您定义了一个或多个递归对象,而不是递归函数。

要解决这个问题,似乎你可以把关闭拉出一个级别:

let createParent parentName childNames =
    let rec makeChild n = createChild parent n 
    and parent = {
        ParentName = parentName
        Children = children }
    and children = childNames |> List.map makeChild
    parent

或者将parent参数加入到createChild方法的值中(注意makeChild之后必须声明parent):

let createParent parentName childNames =
    let rec parent = {
        ParentName = parentName
        Children = children }
    and makeChild = createChild parent
    and children = childNames |> List.map makeChild
    parent

或更简单地这样:

let createParent parentName childNames =
    let rec parent = {
        ParentName = parentName
        Children = children }
    and children = childNames |> List.map (createChild parent)
    parent

答案 1 :(得分:0)

因为双方都需要是功能而不是属性

请改为尝试:

let createParent parentName childNames =
    let rec children names =
        names |> List.map (fun childName -> createChild (parent ()) childName)
    and parent () = {
        ParentName = parentName
        Children = children childNames
    }
    parent ()