Functional programming 获取ast的子树

Functional programming 获取ast的子树,functional-programming,ocaml,abstract-syntax-tree,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

我有一个布尔抽象语法树

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 []
我得到一个错误:

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

还尝试了以下方法:

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 []

编译很好,但从不终止

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


这是因为在前两种情况下返回类型为
list
的值,在后三种情况下返回类型为atom的值。此外,(编译器还没有提到它,但很快就会提到)
构造函数不接受
bast
,但您试图用
bast列表创建它,首先,它不应该编译,因为
bast
应该是小写的


这是因为在前两种情况下返回类型为
list
的值,在后三种情况下返回类型为atom的值。此外,(编译器还没有提到它,但很快就会提到)
不是
构造函数接受
bast
,但您正在尝试使用
bast列表创建它

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
    编写
    exp=true
    (在您的例子中是
    f tree
    ),因为这意味着
    exp
    属于
    布尔类型,并且结果值将完全相同(请编写真值表以验证这一点)
  • 我将
    mylist@[tree]
    替换为
    tree::mylist
    ,后者速度更快,但生成的列表顺序相反。如果您关心该顺序,并且希望在列表末尾有最新的测试树,只需对结果应用
    list.rev
    (您当然可以将其包含在
    findtrees
    的主体中)
  • 因为您的树表示布尔表达式,所以可能有更好的方法来处理您试图解决的问题
      作为第一次工作尝试,我可能会写以下内容:

      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
        编写
        exp=true
        (在您的例子中是
        f tree
        ),因为这意味着
        exp
        属于
        布尔类型,并且结果值将完全相同(请编写真值表以验证这一点)
      • 我将
        mylist@[tree]
        替换为
        tree::mylist
        ,后者速度更快,但生成的列表顺序相反。如果您关心该顺序,并且希望在列表末尾有最新的测试树,只需对结果应用
        list.rev
        (您当然可以将其包含在
        findtrees
        的主体中)
      • 因为您的树表示布尔表达式,所以可能有更好的方法来处理您试图解决的问题

      尝试使用
      | Not(e)->Not(findtree e子树)
      同样的错误,@chrisstewart如果您不关心结果顺序,您可能希望返回
      mylist@[Not(findtree e子树)]
      或更简单的
      (Not(findtree e子树))::mylist
      。在接下来的匹配中,
      以及
      也是如此。两者都不起作用,@didiercLet澄清了你函数的目标:你想遍历给定树的每一个子树(包括子树的子树),并返回给定函数所接受的所有子树
      f
      ,对吗?尝试使用
      | Not(e)->Not(findtree e子树)
      相同错误,@chrisstewart您可能希望返回
      mylist@[Not(findtree e子树)]
      或更简单的
      (Not(findtree e子树))::mylist
      如果你不关心结果的顺序。在接下来的匹配中,
      也是如此。两者都不起作用,@didiercLet澄清了你函数的目标:你想遍历给定树的每一个子树(包括子树的子树)然后返回给定函数
      f
      ,对吗?感谢您的帮助,@ivg!对此有什么建议吗?您需要确保函数的所有分支上的返回类型都相同。在Ocaml中,不能像在d中一样在同一个函数中返回
      list
      bast
      类型的内容动态类型语言,如python。您希望函数返回
      bast
      还是
      list
      ?我希望返回f参数返回true的所有子树的列表。我认为,您混淆了自己并试图做错误的事情。首先,如果您的函数
      f
      已经接受
      bast
      ,则恩,它应该递归到树中。这意味着,你确实有两个嵌套循环。而且,任务在我看来是错误的。我认为,你正在尝试做类似的事情。但我可能错了。我建议你,从一个例子开始,说明你的函数应该如何工作。就像给定这个输入,我期望这个输出。问题是,当我在叶子上返回一个bast类型(如果是f tree,那么是tree)没有其他条件,因为我的ast不支持空值。因此我返回列表。感谢您的帮助,@ivg!对此有什么建议吗?您需要确保返回类型在函数的所有分支上都是相同的。您不能在Ocaml中与c相同的函数中返回
      list
      bast
      类型的内容动态类型语言(如python)中的。是否希望函数返回
      bast
      list
      ?我希望返回f参数返回true的所有子树的列表。我认为,您混淆了自己并试图做错误的事情。首先,如果您的函数
      f
      已经接受
      bast然后它应该递归到树中。这意味着,您确实有两个嵌套循环。而且,任务在我看来是错误的。我认为,您正在尝试做类似的事情。但我可能是