在Haskell中实现可折叠

时间:2015-03-27 08:00:20

标签: haskell tree-traversal

例如,我有一些数据类型。让它成为二叉树:

data Tree a = Leaf a | Branch (Tree a) (Tree a)

例如,我实现了树的遍历:

treeFoldt :: Tree t -> [t]
treeFoldt = foldt1 (:) []

效果很好。但我想实现Foldable接口。

我想,我应该这样写:

instance Foldable Tree where
  foldr = treeFoldt

但它不起作用。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:12)

我可以尝试告诉您代码的问题在哪里,但遗憾的是您没有给出foldt1的定义

但是这应该有用(如果你的treeFoldt的实现没问题 - 请记住:[]Foldable的实例):

instance Foldable Tree where
  foldr f s = Data.Foldable.foldr f s . treeFoldt

使用Monoid

的基本定义

无论如何,我认为在这种情况下最简单的方法是只实现foldMap部分:

import Data.Foldable
import Data.Monoid

data Tree a = Leaf a | Branch (Tree a) (Tree a)

instance Foldable Tree where
 foldMap f (Leaf a)     = f a
 foldMap f (Branch l r) = foldMap f l `mappend` foldMap f r 

这肯定有效。

示例/用法

λ> let t = Branch (Branch (Leaf $ Sum 2) (Leaf $ Sum 4)) (Leaf $ Sum 6)
λ> fold t
Sum {getSum = 12}

λ> let t = Branch (Branch (Leaf 2) (Leaf 4)) (Leaf 6)
λ> foldMap Sum t
Sum {getSum = 12}

当然,您根本不需要Monoid部分 - 默认实施工作正常:

λ> Data.Foldable.foldr1 (+) t
12
顺便说一下

foldr1 (+)只能用foldMap来表达Foldable,这很可能并不明显(高级)运动试图自己做:D


外部资源

我认为Foldable and Traversable by A. ArnoldTraversable(和{{1}})上的博客文章相当不错 - 也许您觉得它也很有用