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
ます。
最終的には、「モノイドが要件ではないのはなぜですか?」という質問に対する答えです。「それはより実用的であり、最終的には必要ないからです」というのは非常に退屈です。
詳細については、すべての始まりとなった論文Applicative Programming with Effectsを参照してください。