Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Monoid is not a requirement for foldr/foldl?

I am looking at the Foldable class in Haskell. Two of the methods fold, foldMap requires a Monoid instance. But foldr or foldl don't have any such constraint.

fold :: Monoid m => t m -> m
foldMap :: Monoid m => (a -> m) -> t a -> m
foldr :: (a -> b -> b) -> b -> t a -> b
foldl :: (b -> a -> b) -> b -> t a -> b

For the results of foldr/foldl to be equivalent, shouldn't it restrict the given folding function to be associative? Are there any examples where the results of foldr/foldl are different on the same list?

Shouldn't a Foldable instance wrap a Monoidal value? Or Foldable is more general?

like image 681
zeronone Avatar asked Jun 22 '16 16:06

zeronone


People also ask

What is the difference between Foldr and Foldl?

Difference Between foldl and foldr The difference is that foldl is tail-recursive, whereas foldr is not. With foldr and non-optimized patterns, proc is applied to the current value and the result of recursing on the rest of the list. That is, evaluation cannot complete until the entire list has been traversed.

Is Foldr or Foldl more efficient?

Haskell Wiki compares foldr , foldl and foldl' and recommends using either foldr or foldl' . foldl' is the more efficient way to arrive at that result because it doesn't build a huge thunk.

What is Foldable in haskell?

Haskell, in turn, has two fundamental functions representing reducing, or, as we call it, folding – foldl and foldr – that differ in the order of the folding. foldl reduces elements of a container from left to right (as reduce in other languages usually does), while foldr reduces from right to left.

Should I Choose foldl or foldr?

When you wonder whether to choose foldl or foldr you may remember, that both foldl and foldl' can be expressed as foldr . ( foldr may lean so far right it came back left again.) It holds (The converse is not true, since foldr may work on infinite lists, which foldl variants never can do.

Is it possible to use foldr with infinite lists?

It holds (The converse is not true, since foldr may work on infinite lists, which foldl variants never can do. However, for finite lists, foldr can also be written in terms of foldl (although losing laziness in the process), in a similar way like this:

Is there a way to write foldr in terms of foldl?

However, for finite lists, foldr can also be written in terms of foldl (although losing laziness in the process), in a similar way like this: How can someone find a convolved expression like this?


1 Answers

For the results of foldr/foldl to be equivalent, shouldn't it restrict the given folding function to be associative? Are there any examples where the results of foldr/foldl are different on the same list?

Yes. If you pass a non-associative function (like subtraction (-)) you will absolutely get different results. And as you rightly point out there is no Monoid instance that corresponds to something like (-).

But that is by design. There is no such restriction on Foldable instances that foldr and foldl must take associative functions. There are situations where you might want to fold with something like subtraction. An instance of Foldable f is more interested in constraining what the f can do. The laws in particular are:

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)

You can see in the sources that foldr by default does something clever with the newtype Endo a = Endo (a -> a) endomorphism monoid:

-- | 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

to build a monoidal fold out of possibly non-monoidal f and z.

So ultimately the answer to the question "Why is Monoid not a requirement?" is the very boring "because it is more practical and, in the end, not necessary."

For more information I refer you to the paper that started it all, Applicative Programming with Effects.

like image 134
hao Avatar answered Sep 20 '22 02:09

hao