Given the following data type definition:
data FormTree = Empty | Node FormTree FormTree deriving Show
I want to write a function which generates an infinite list containing all possible trees sorted after length e.g. the amount of nodes.
The following code almost does what I need but it only descends the tree on the right side by inserting additional nodes every time but I need it to alternate between both sides.
allPossibleTrees :: [FormTree]
allPossibleTrees = Empty : [Node x y | x <- recursive, y <- recursive]
where recursive = allPossibleTrees
Executing
take 5 allPossibleTrees
gives:
[Empty,Node Empty Empty,Node Empty (Node Empty Empty),Node Empty (Node Empty (Nodes Empty Empty)),Node Empty (Node Empty (Node Empty (Node Empty Empty)))]
but it should be something like:
[Empty,Node Empty Empty,Node (Node Empty Empty) Empty,Node Empty (Node Empty Empty),Node (Node Empty Empty) (Node Empty Empty)]
The list comprehension
starts by considering
x=1
and building all the pairs(1,y)
for all the possibley
s. Then follows withx=2
and all the(2,y)
pairs. and so on.However, there are infinitely many
(1,y)
pairs, sox=2
will only be considered after an infinite amount of time -- that is, not at all.Your code suffers from the same problem.
To see a possible solution, you can refer to this related question exploiting the Omega monad to achieve a fair scheduling among all the cases.
Here's a nice trick, reminiscent of the standard Fibonacci numbers trick. We'll build a lazy list; each member of the list will be a list of all trees with a given number of nodes. There's just one tree with no nodes,
Empty
, and that will serve as our base case. To build all the trees withn
nodes, we'll assume we already know how to build trees with0
,1
,2
, ...,n-1
nodes. Then we'll just non-deterministically choose a pairing of those that sums ton-1
and stuck aNode
on top.In code:
Then we can simply define
allPossibleTrees = concat sizes
if that's wanted. The first few entries:We can do a quick sanity check:
...which is indeed the first ten Catalan numbers, so we probably got it right!
One way is to keep track of the size of the tree (i.e. the number of
Node
constructors used.)Suppose you had a function like this which returned the trees using exactly n Node constructors:
Then
allTrees
could be defined as:The definition of
treesOfSize
can be recursively defined which I'll let you figure out:control-monad-omega
library seems to do the trick with your original code:First 10 trees look good to me: