为了foldr
/的结果foldl
是等价的,它不应该限制给定的折叠函数是关联的吗?是否有任何示例在同一列表中foldr
/的结果不同?foldl
是的。如果您传递一个非关联函数(如减法(-)
),您绝对会得到不同的结果。正如您正确指出的那样,没有任何 Monoid
实例对应于(-)
.
但这是设计使然。对于并且必须采用关联函数的Foldable
实例没有这样的限制。在某些情况下,您可能想用减法之类的方法弃牌。的一个实例对限制可以做什么更感兴趣。具体法律如下:foldr
foldl
Foldable f
f
foldr f z t = appEndo (foldMap (Endo . f) t ) z
foldl f z t = appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z
fold = foldMap id
-- if f is a Functor
foldMap f = fold . fmap f
foldMap f . fmap g = foldMap (f . g)
你可以在源代码中看到默认情况下对内同态幺半群foldr
做了一些聪明的事情:newtype Endo a = Endo (a -> a)
-- | Right-associative fold of a structure.
--
-- @'foldr' f z = 'Prelude.foldr' f z . 'toList'@
foldr :: (a -> b -> b) -> b -> t a -> b
foldr f z t = appEndo (foldMap (Endo #. f) t) z
用可能的非单面f
和建立一个单面折叠z
。
所以最终回答了“为什么 Monoid 不是必需的?”这个问题。是非常无聊的“因为它更实用,最终没有必要”。
有关更多信息,请参阅开始这一切的论文,Applicative Programming with Effects。