给出以下数据类型定义:
data FormTree = Empty | Node FormTree FormTree deriving Show
我想编写一个函数,该函数生成一个包含所有可能在长度之后排序的树的无限列表,例如节点数量。
下面的代码几乎可以满足我的需求,但它只是通过每次插入额外的节点来降低右侧的树,但我需要它在两边之间交替。
allPossibleTrees :: [FormTree]
allPossibleTrees = Empty : [Node x y | x <- recursive, y <- recursive]
where recursive = allPossibleTrees
执行
take 5 allPossibleTrees
给出:
[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)))]
但它应该是这样的:
[Empty,Node Empty Empty,Node (Node Empty Empty) Empty,Node Empty (Node Empty Empty),Node (Node Empty Empty) (Node Empty Empty)]
答案 0 :(得分:7)
这是一个很好的技巧,让人联想到标准的斐波那契数字技巧。我们将建立一个懒惰的列表;列表的每个成员将是具有给定节点数的所有树的列表。只有一棵树没有节点,Empty
,这将作为我们的基本案例。要使用n
个节点构建所有树,我们假设我们已经知道如何使用0
,1
,2
,...,{{1节点。然后,我们将非确定性地选择那些总和为n-1
并将n-1
置于顶部的配对。
在代码中:
Node
然后我们可以简单地定义import Control.Monad
import Data.List
sizes :: [[FormTree]]
sizes = [Empty] : (map go . drop 1 . inits) sizes where
go smaller = do
(ls, rs) <- zip smaller (reverse smaller)
liftM2 Node ls rs
是否需要。前几个条目:
allPossibleTrees = concat sizes
我们可以快速进行健全检查:
*Main> mapM_ print (take 4 sizes)
[Empty]
[Node Empty Empty]
[Node Empty (Node Empty Empty),Node (Node Empty Empty) Empty]
[Node Empty (Node Empty (Node Empty Empty)),Node Empty (Node (Node Empty Empty) Empty),Node (Node Empty Empty) (Node Empty Empty),Node (Node Empty (Node Empty Empty)) Empty,Node (Node (Node Empty Empty) Empty) Empty]
......这确实是前十Catalan numbers,所以我们可能做对了!
答案 1 :(得分:4)
列表理解
[ (x,y) | x<-[1..] , y<-[1..] ]
首先考虑x=1
并为所有可能的(1,y)
构建所有对y
。然后是x=2
和所有(2,y)
对。等等。
但是,有(1,y)
对无限多,所以x=2
只会在无限长的时间后才会被考虑 - 也就是说,根本不会被考虑。
您的代码遇到同样的问题。
要查看可能的解决方案,您可以参考this related question利用Omega monad来实现所有案例中的公平调度。
答案 2 :(得分:1)
一种方法是跟踪树的大小(即使用的Node
构造函数的数量。)
假设您有一个这样的函数,它使用 n 节点构造函数返回树:
treesOfSize :: Int -> [FormTree]
然后allTrees
可以定义为:
allTrees = concatMap treesOfSize [0..]
treesOfSize
的定义可以递归定义,我会让你弄明白:
treesOfSize 0 = [Empty]
treesOfSize n = [ Node t1 t2 | ... ]
答案 3 :(得分:1)
control-monad-omega
库似乎可以使用您的原始代码执行操作:
{-# LANGUAGE MonadComprehensions #-}
import Control.Monad.Omega
data Empty = Empty | Node Empty Empty deriving Show
allPossibleTrees :: [Empty]
allPossibleTrees = Empty :
runOmega [Node x y | x <- each allPossibleTrees, y <- each allPossibleTrees]
前10棵树对我来说很好看:
*Main> mapM_ print $ take 10 allPossibleTrees
Empty
Node Empty Empty
Node Empty (Node Empty Empty)
Node (Node Empty Empty) Empty
Node Empty (Node Empty (Node Empty Empty))
Node (Node Empty Empty) (Node Empty Empty)
Node (Node Empty (Node Empty Empty)) Empty
Node Empty (Node (Node Empty Empty) Empty)
Node (Node Empty Empty) (Node Empty (Node Empty Empty))
Node (Node Empty (Node Empty Empty)) (Node Empty Empty)