I'm not familiar with this error and it doesn't appear to be documented anywhere, but here's what I can surmise after playing around with it a bit.
The issue seems to be in how the parent
is closed over by the lambda expression, which itself is inside the definition of children
. This apparently throws off the type checker (tc.fs)—my guess is because the right side of the children
binding itself contains an expression (the lambda expression) that itself contains a recursive reference, but the true cause may be more subtle than this. Notice that if you reverse the declarations like this:
let createParent parentName childNames =
let rec parent = {
ParentName = parentName
Children = children }
and children = childNames |> List.map (fun childName -> createChild parent childName)
parent
You'll also see this warning on the line where children
is being bound:
Warning: 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.
To fix this, it seems you can pull the closure out one level:
let createParent parentName childNames =
let rec makeChild n = createChild parent n
and parent = {
ParentName = parentName
Children = children }
and children = childNames |> List.map makeChild
parent
Or curry the parent
parameter into the value into createChild
method like this (notice that makeChild
must be declared after parent
):
let createParent parentName childNames =
let rec parent = {
ParentName = parentName
Children = children }
and makeChild = createChild parent
and children = childNames |> List.map makeChild
parent
Or more simply like this:
let createParent parentName childNames =
let rec parent = {
ParentName = parentName
Children = children }
and children = childNames |> List.map (createChild parent)
parent