我的树看起来像这样,一棵树在每个节点都可以有或没有整数:
data Tree = Empty | Node (Maybe Integer) Tree Tree deriving Show
我想总结树中的所有值,不包括Nothing值,如果tree不为空但只有Nothing值,只返回Nothing,或者空树为0.这些情况我理解如何。
我想深入思考第一次遍历是最好的,或者只是一般的基本遍历,但是如何优雅地实现它。
treeValues :: Tree - >也许是整数
答案 0 :(得分:6)
您可以将您的树设为Foldable
个实例,并免费获得许多功能,包括sum
:
sum ::(可折叠t,Num a)=> t a - >来源
sum函数计算结构数的总和。
但您需要将Tree
设为参数类型:
data Tree a = Empty | Node (Maybe a) Tree Tree
此外,使用GHC 7.10,几乎所有Prelude函数都将使用Foldable
和Traversable
类型类而不是列表,然后您可以自由地为树使用它们,如果您实现这些类型类。
答案 1 :(得分:5)
您已经知道如何对列表求和,因此您可以先将树转换为列表:
> toList :: Tree -> [Integer]
> toList Empty = []
> toList (Node a l r) = maybeToList a ++ toList l ++ toList r
> where maybeToList (Just x) = [x]
> maybeToList Nothing = []
现在,您希望在空树(Empty
)和仅包含Nothing
的树之间有所不同。由于toList
过滤了所有Nothing
值,因此归结为
> sumTree :: Tree -> Maybe Integer
> sumTree Empty = Just 0
> sumTree tree = case toList tree of
> [] -> Nothing -- all values in the tree are Nothing
> xs -> Just $ sum xs -- some were Just x
sumTree
还不是很好。如果我们想要计算Tree
的乘积怎么办?嗯。好吧,我们可以拿一棵树,把它变成一个列表,并使用......折叠功能!
> type I = Integer -- otherwise the lines get ridiculously long
>
> foldrTree' :: (I -> I -> I) -> I -> Tree -> Maybe I
> foldrTree' _ init Empty = init
> foldrTree' f init tree = case toList tree of
> [] -> Nothing
> xs -> Just $ foldr f init xs
> -- ^^^^^
现在我们可以使用任何(Integer -> Integer -> Integer)
并生成单个值,只要我们的操作是关联的:
> productTree :: Tree -> Maybe Integer
> productTree = foldrTree' (*) 1
>
> sumTree' :: Tree -> Maybe Integer
> sumTree' = foldrTree' (+) 0
答案 2 :(得分:4)
这里有一个提示:
data Tree a = Empty | Node a (Tree a) (Tree a)
reduce :: (a -> r -> r -> r) -> r -> Tree a -> r
reduce f z = go
where
go Empty = z
go (Node x l r) = f x (go l) (go r)
答案 3 :(得分:1)
关于上述解决方案和评论以及lyah和Brent Yorgeys advice,我汇编了以下提案(在ghci
中尝试使用):
:set -XDeriveFoldable -XDeriveFunctor
:m + Data.Foldable Data.Monoid
data Tree a = Empty | Node (Maybe a) (Tree a) (Tree a) deriving (Show, Functor, Foldable)
let tree :: Tree Integer ; tree = Node Nothing (Node (Just 42) Empty Empty) (Node Nothing Empty Empty)
foldMap Sum tree
虽然在两种情况下只返回0
,但只给出了Nothing
个值,而树是Empty
但我希望它稍后会为像我这样的学习者提示。