Reputation: 484
I have a boolean abstract syntax tree
type bast =
True
| False
| Not of bast
| Or of bast * bast
| And of bast * bast
and I want to apply on it a function and get all the subtrees that return true for this function.
My try:
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 []
I get an error:
Error: The variant type list has no constructor Not
Tried also with this:
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 []
Compiles fine but never terminates!
Upvotes: 1
Views: 357
Reputation: 14730
Here's what I would probably write as a first working attempt:
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 []
Some remarks:
exp = true
for any expression exp
(in your case it was f tree
), since it implies that that exp
is of type boolean
and the resulting value would be exactly the same (please write the truth table to verify that)mylist@[tree]
with tree::mylist
which is faster, but will produce a list in reverse order. If you care about that order, and wish to have the latest tested tree at the end of the list, simply apply List.rev
to the result (you may of course include that in the body of findtrees
)Upvotes: 1
Reputation: 35210
first of all, it shouldn't compile, since Bast
should be lowercased.
That is because you return a value of type list
on first two cases, and an atom on a latter three. Moreover, (compiler didn't mentioned it yet, but will soon) Not
constructor accepts a bast
, but you're trying to create it with a bast list
Upvotes: 5