Ошибка «анонимные переменные типа не допускаются в этой декларации» при добавлении параметров в случаи различного объединения в F # - PullRequest
2 голосов
/ 23 мая 2019

Итак, у меня есть некоторый (я предполагаю, довольно необычный) код, который предназначен для построения деревьев функций.Вот это прямо сейчас:

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

Выражение a:'Function -> unit - это то, что заставляет компилятор подбрасывать, давая мне ошибку «Переменные анонимного типа не разрешены в этом объявлении», и я понятия не имею, почему,Я попытался добавить переменную в BranchNode, добавив (yucky) двойные скобки вокруг выражения, но, похоже, ничего не помогло.

1 Ответ

6 голосов
/ 23 мая 2019

Ответ на вопрос об ошибке компилятора

Это не компилируется ...

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 используется для пояснения случая создания листа. Имя поля 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  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...