获得ast的子树

时间:2014-10-27 11:35:25

标签: functional-programming ocaml abstract-syntax-tree

我有一个布尔抽象语法树

type bast =
    True
  | False
  | Not of bast 
  | Or of bast * bast 
  | And of bast * bast 

我希望在它上面应用一个函数并获取所有为此函数返回true的子树。

我的尝试:

let findtrees f (ast: bast ) =
    let rec findtree (tree: bast ) (mylist: bast list) = match tree with
        | True ->
            if (f tree)=true then mylist@[tree] else []
        | False ->
            if (f tree)=true then mylist@[tree] else []
        | Not e     ->  Not (findtree e subtrees)
        | And (e1,e2) ->  And (findtree e1 mylist, findtree e2 mylist)
        | Or  (e1,e2) ->  Or  (findtree e1 mylist, findtree e2 mylist)
    in findtree ast []

我收到错误:

  

错误:变体类型列表没有构造函数Not

也试着用这个:

let findtrees f (ast: bast) =
    let rec findtree (tree: bast) (mylist: bast list) = match tree with
          (True|False) -> mylist
        | subtree ->
            if (f subtree)=true then
                mylist@[subtree]
            else
                select_tree subtree mylist
    in findtree ast []

编译好但永远不会终止!

2 个答案:

答案 0 :(得分:5)

首先,它不应该编译,因为Bast应该是小写的。

这是因为你在前两种情况下返回类型list的值,在后三种情况下返回一个原子。此外,(编译器尚未提及它,但很快就会提到)Not构造函数接受bast,但您尝试使用bast list

答案 1 :(得分:1)

这是我可能会写的第一次尝试:

let findtrees f (ast: bast ) =
  let rec findtree tree mylist = 
    let mylist = if f tree then tree::mylist else mylist in
    match tree with
      | True| False -> mylist
      | Not e -> findtree e mylist
      | Or (e1,e2)
      | And (e1,e2) ->  findtree e2 @@ findtree e1 mylist
  in findtree ast []

一些评论:

  • 您不需要为任何表达式exp = true(在您的情况下为exp)写f tree,因为它意味着exp的类型为boolean {1}}和结果值完全相同(请写下真值表来验证)
  • 我将mylist@[tree]替换为tree::mylist更快,但会以相反的顺序生成列表。如果您关心该订单,并希望在列表末尾添加最新的测试树,只需将List.rev应用于结果(当然,您可以在findtrees的正文中包含该树) / LI>
  • 因为您的树代表布尔表达式,所以可能有更好的方法来处理您尝试解决的问题。