Haskell:返回多路树的所有叶子?

时间:2014-09-21 04:25:08

标签: haskell tree traversal

返回二叉树的所有叶子很简单:

data BinTree a = Empty | Node (BinTree a) a (BinTree a) deriving (Eq, Show)

getLeaves :: BinTree a -> [a]
getLeaves Empty = []
getLeaves (Node left current right) = [current]++getLeaves left++getLeaves right

但是,树不是二进制树而是多路树(即树中的每个节点都可以有任意数量的子节点和叶子),那么呢?

data MWTree a = Empty | Node [MWTree a] deriving (Eq, Show)

我没有找人为我发布解决方案;我只是不确定一般的Haskell概念可能值得学习解决为这种类型的树编写getLeaves的问题。

2 个答案:

答案 0 :(得分:2)

您可能有兴趣看到两种情况下的getLeaves都可以FoldableTraversable的模式实施。 FoldabletoList :: Foldable f => f a -> [a],它编码了收集Foldable容器f中所有值的想法。 Traversable具有更强大的traverse :: (Applicative f, Traversable t) => (a -> t b) -> (f a -> t (f b)),它编码了对Traversable容器t进行某种遍历的想法。 Traversable隐含Foldable

newtype K b a = K { unK :: b } deriving Functor

instance Monoid b => Applicative (K b) where
  pure = K mempty
  K e <*> K f = K (e <> f)

foldMapDefault :: (Traversable t, Monoid m) => (a -> m) -> (t a -> m)
foldMapDefault f = unK . traverse (K . f)

答案 1 :(得分:2)

我认为您的代码中存在错误,您将树的所有节点添加到叶子列表中,这是错误的,您需要先检查某个节点是否为叶子,然后才能将其添加到叶子中清单。

data BinTree a = Empty | Node (BinTree a) a (BinTree a) deriving (Eq, Show)

getLeaves :: BinTree a -> [a]
getLeaves Empty = []
getLeaves (Node Empty current Empty) = [current] 
getLeaves (Node left current right) = getLeaves left++getLeaves right

非二叉树也是如此(我认为你的代码中也存在错误)

data MWTree a = Empty | Node a [MWTree a] deriving (Eq, Show)

getLeaves :: (Eq a) => MWTree a -> [a]
getLeaves Empty      = []
getLeaves (Node current []) = [current]
getLeaves (Node current children) = if all (==Empty) children 
                                then [current]
                                else (children >>= getLeaves) 
                              --else concat $ map getLeaves children (another way of writing the same thing)