是否有可能做一个"查找和替换"上可区分联合,例如更换Foo
与Bar
与如实例
type Expression
| Foo of Expression list
| Bar of Expression list
Run Code Online (Sandbox Code Playgroud)
?
高度嵌套的表达式定义可以是任何深度.
该语言中没有内置功能可以让您自动执行此操作.基本方法是写一个递归函数-如果你想切换Foo
的Bar
,这是很容易的:
let rec switch = function
| Foo es -> Bar(List.map switch es)
| Bar es -> Foo(List.map switch es)
Run Code Online (Sandbox Code Playgroud)
您可以尝试从指定应该如何转换的位来抽象遍历树的部分.这并不能解决这个简单的问题,但它对于更复杂的转换非常有用.
例如,以下函数在所有节点上调用它.如果函数返回Some
,则替换节点:
let rec transform f e =
match f e with
| Some n -> n
| None ->
match e with
| Foo es -> Foo(List.map (transform f) es)
| Bar es -> Bar(List.map (transform f) es)
Run Code Online (Sandbox Code Playgroud)
现在,你可以,例如,轻松地更换Bar []
具有Foo []
并保持所有其他表达式不变:
Foo [ Bar []; Bar[] ] |> transform (fun e ->
match e with
| Bar [] -> Some(Foo [])
| _ -> None)
Run Code Online (Sandbox Code Playgroud)