让我们有一个类型的定义,其中有几种类型的二进制节点,以及其他类型的节点,即。
type Tree =
| BinaryNodeA of Tree * Tree
| BinaryNodeB of Tree * Tree
| [Other stuff...]
我想使用一个递归函数来操纵这棵树,例如,任何类型的二进制节点的交换子节点(通过构造新节点)。使我发疯的问题:如何匹配所有二进制词,以使节点的味道变成"参数",以便具有可以应用于任何二进制节点味的通用交换来返回该风味的交换节点?
我知道如何使用主动模式匹配所有是二进制的树的树:
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
换句话说,我还没有找到使用二进制式风味的方法,就像是a和b一样的参数。取而代之的是,似乎我必须分别匹配每个二进制词的风味。如果有大量的二元节点口味,这可能具有实际意义。类型树是FSACC/FSLEX生成的解析器/Lexer的AST,它限制了重组它的选项。有什么想法吗?
您只需要更改活动模式的定义:
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
的定义以包括风味而不是使用主动模式来处理它可能是有意义的。