'Anonymous type variables are not permitted in this declaration' 在 F# 中将参数添加到已区分的联合案例时出错

'Anonymous type variables are not permitted in this declaration' error when adding parameters to discriminated union cases in F#

所以我有一些(我假设相当不寻常)用于构建函数树的代码。这是现在:

type FunctionTree<'Function> =
    | BranchNode of seq<FunctionTree<'Function>>
    | Leaf of (a:'Function -> unit) with
        member __.Execute() = do a

表达式 a:'Function -> unit 让编译器出错,给我错误 'Anonymous type variables are not permitted in this declaration' 我不知道为什么。我试过向 BranchNode 添加一个变量,在表达式周围添加(令人讨厌的)双括号,但似乎没有任何效果。

编译器错误问题的答案

这不编译...

Leaf of (a:'Function -> unit)

...因为区分的字段名称可以添加到 DU 案例的 types,而不是 function types[=56= 的类型] 在 DU 案例中。相比之下,这编译...

Leaf of a: ('Function -> unit)

...因为字段名称 a 被用于命名类型 (Function -> unit).

关于代码的补充讨论

但是,还有一个问题。正如您的代码所暗示的那样,您要添加的成员 Execute 并未添加到叶节点。它被添加到整个功能树中。因此,您将无法访问 Execute 实现中的标签 a。可以这样想...

type FunctionTree<'Function> =
    | BranchNode of seq<FunctionTree<'Function>>
    | Leaf of a: ('Function -> unit)
    with member __.Execute() = do a

... 成员向左移动以阐明它适用于整个联合,而不仅仅是叶案例。这就解释了为什么上面的代码现在有一个不同的编译器错误...a is not defined。字段名称 a 用于阐明 Leaf case 的实例化。字段名称 a 在其他地方不可用。

let leaf = Leaf(a: myFunc)

因此,您的 Execute 成员无法使用标签 a。你需要做这样的事情......

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