Подмножество членов Союза как "параметр" в сопоставлении с образцом

Давайте определим тип для дерева с несколькими типами бинарных узлов среди других типов узлов, т.е.

type Tree =
| BinaryNodeA of Tree * Tree
| BinaryNodeB of Tree * Tree
| [Other stuff...]

Я хочу манипулировать этим деревом, используя рекурсивную функцию, которая может, например, менять подузлы любого типа двоичного узла (путем создания нового узла). Проблема, которая сводит меня с ума: как сопоставить все BinaryNodes, чтобы аромат узла стал "параметром", чтобы иметь общий обмен, который можно применить к любому вкусу BinaryNode для возврата замененного узла этого вкуса?

Я знаю, как сопоставить все деревья, которые являются BinaryNodes, используя активный шаблон:

let (|BinaryNode|_|) (tree : Tree) =
    match tree with
    | BinaryNodeA _ | BinaryNodeB _ -> Some(tree)
    | _ -> None

Но этого недостаточно, потому что следующее не представляется достижимым:

match tree with
| [cases related to unary nodes..]
| BinaryNode a b -> BinaryNode b a

Другими словами, я не нашел способа использовать аромат BinaryNode, как если бы это был параметр, подобный a и b. Вместо этого кажется, что я должен сопоставить каждый вариант BinaryNode отдельно. Это могло бы иметь практическое значение, если бы существовало большое количество разновидностей бинарных узлов. Дерево типов - это AST для синтаксического анализатора / лексера, сгенерированного Fsyacc/Fslex, что ограничивает возможности его реструктуризации. Есть идеи?

1 ответ

Решение

Вам просто нужно изменить определение вашего активного шаблона:

type Flavor = A | B

let (|BinaryNode|_|) (tree : Tree) =
    match tree with
    | BinaryNodeA(x,y) -> Some(A,x,y) 
    | BinaryNodeB(x,y) -> Some(B,x,y)
    | _ -> None

let mkBinaryNode f t1 t2 =
    match f with
    | A -> BinaryNodeA(t1,t2)
    | B -> BinaryNodeB(t1,t2)

Тогда вы можете достичь того, что вы хотите, как это:

match tree with
| [cases related to unary nodes..]
| BinaryNode(f,t1,t2) -> mkBinaryNode f t2 t1

Но если это общая потребность, то, возможно, имеет смысл изменить определение Tree включать аромат вместо того, чтобы иметь дело с этим, используя активные образцы.

Другие вопросы по тегам