替换歧视联盟中的元素

时间:2016-01-17 17:29:51

标签: f#

是否可以进行搜索并替换'在一个有区别的联盟上,例如用Foo替换Bar,例如。

type Expression
| Foo of Expression list
| Bar of Expression list

高度嵌套的表达式定义可以有任何深度。

1 个答案:

答案 0 :(得分:5)

语言中没有内置功能可以让您自动执行此操作。基本方法是编写递归函数 - 如果要为Foo切换Bar,这很容易:

let rec switch = function
  | Foo es -> Bar(List.map switch es)
  | Bar es -> Foo(List.map switch es)

您可以尝试从指定应该如何转换的位开始抽象遍历树的部分。这并不能解决这个简单的问题,但它对于更复杂的转换非常有用。

例如,以下函数在所有节点上调用它。如果函数返回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)

现在,您可以轻松地将Bar []替换为Foo []并保持所有其他表达不变:

Foo [ Bar []; Bar[] ] |> transform (fun e ->
  match e with
  | Bar [] -> Some(Foo [])
  | _ -> None)