替换歧视联盟中的元素

Dmi*_*ruk 1 f#

是否有可能做一个"查找和替换"上可区分联合,例如更换FooBar与如实例

type Expression
| Foo of Expression list
| Bar of Expression list
Run Code Online (Sandbox Code Playgroud)

高度嵌套的表达式定义可以是任何深度.

Tom*_*cek 5

该语言中没有内置功能可以让您自动执行此操作.基本方法是写一个递归函数-如果你想切换FooBar,这是很容易的:

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)