因此,我有一些(我认为很不寻常)用于构建功能树的代码。现在是这里:
type FunctionTree<'Function> =
| BranchNode of seq<FunctionTree<'Function>>
| Leaf of (a:'Function -> unit) with
member __.Execute() = do a
表达式a:'Function -> unit
是使编译器适合的原因,给我错误消息“此声明中不允许使用匿名类型变量”,我也不知道为什么。我尝试将变量添加到BranchNode,在表达式周围添加(讨厌的)双括号,但似乎没有任何效果。
答案 0 :(得分:6)
回答编译器错误问题
这无法编译...
Leaf of (a:'Function -> unit)
...因为在DU案例中,可以将已区分的字段名称添加到DU案例的类型中,而不是添加到功能类型的类型中。相反,它会编译...
Leaf of a: ('Function -> unit)
...因为使用字段名a
来命名类型(Function -> unit)
。
有关代码的其他讨论
但是,还有另一个问题。正如您的代码所暗示的那样,您要添加的成员Execute
不会被添加到Leaf节点。它被添加到整个功能树中。因此,您将无法在实现a
内访问标签Execute
。这样想吧...
type FunctionTree<'Function> =
| BranchNode of seq<FunctionTree<'Function>>
| Leaf of a: ('Function -> unit)
with member __.Execute() = do a
...,该成员向左移动以说明其适用于整个联合,而不仅适用于叶子情况。这就解释了为什么上面的代码现在有不同的编译器错误... a is not defined
。字段名称a
用于阐明Leaf实例的实例化。字段名称a
在其他位置不可用。
let leaf = Leaf(a: myFunc)
因此,a
成员无法使用标签Execute
。您将需要执行以下操作……
with member x.Execute(input) =
match x with
| BranchNode(b) -> b |> Seq.iter(fun n -> n.Execute(input))
| Leaf(f) -> f(input) |> ignore
在上面的代码中,请注意x
的值是FunctionTree
。
替代实施
我们可以继续前进。但是,我认为以下可能会实现您的目标:
type FunctionTree<'T> =
| BranchNode of seq<FunctionTree<'T>>
| LeafNode of ('T -> unit)
let rec evaluate input tree =
match tree with
| LeafNode(leaf) -> leaf(input)
| BranchNode(branch) -> branch |> Seq.iter (evaluate input)
BranchNode([
LeafNode(printfn "%d")
LeafNode(printfn "%A")
])
|> evaluate 42