【发布时间】:2013-05-26 08:11:50
【问题描述】:
我正在学习“Learn You a Haskell”,我正在学习 monoids 部分。在本节中,作者为一棵树定义 foldMap 方法如下:
instance F.Foldable Tree where
foldMap f Empty = mempty
foldMap f (Node x l r) = F.foldMap f l `mappend`
f x `mappend`
F.foldMap f r
效果很好,而且非常棒。然而,他接着说“现在我们的树类型有一个可折叠的实例,我们可以免费获得 foldr 和 foldl!”并显示以下代码:
testTree = Node 5
(Node 3
(Node 1 Empty Empty)
(Node 6 Empty Empty)
)
(Node 9
(Node 8 Empty Empty)
(Node 10 Empty Empty)
)
ghci> F.foldl (+) 0 testTree
42
ghci> F.foldl (*) 1 testTree
64800
现在我很困惑。没有任何地方是为 Trees 编写的 foldl 或 foldr 实现。这些函数似乎有点像 foldmap,但是将初始累加器作为树的头部,然后 foldMapping 在适当的幺半群上,但它实际上不能像这样工作,因为 foldl 和 foldr 比幺半群 '+' 和 '*' 作为参数。 foldl 和 foldr 实际在哪里实现,它们是如何工作的,为什么定义 foldMap 会导致它们存在?
【问题讨论】:
-
你看过 Data.Foldable 的源代码吗? Foldable 类中的定义应该足以回答您的问题。
-
Haskell 类型类可以有一些方法的默认实现。在这一点上,它们类似于 mixin 在其他语言中的工作方式。例如,在 Ruby 中,您只需定义 即可访问 Comparable 的其余方法。