I can understand the reason for mappend and associativity requirement for it. But why do we need the identity element what is the pragmatic usefulness in it? Or maybe I've missed something important and without definition of it in instances the whole logic won't work. Thank you!
The mempty
certainly is needed for some applications. For instance, what should be the result of foldMap
ping over an empty list? There's no a
value you could feed the mapped function to obtain an m
. So, there needs to be a “default”. It's nice if this is an identity element of an associative operation – for example it allows arbitrary reordering/chunking the fold without changing the result. When folding over a tree, actually a lot of mempty
s may show up in the middle but you always know they will get “squeezed out” in the end result, so you don't depend on the exact tree layout for reproducable results.
That said, you're right with your concern: Semigroup
would quite often be sufficient, and it would probably be better if this class were used wherever mempty
isn't needed (since there are actually a few quite nifty types that are Semigroup
but not Monoid
). However, the early design of the standard library apparently did not consider this important enough to warrant the extra class, so lots of code came to rely on Monoid
without really needing a monoid.
So – much the same issue as we used to have with Monad
: lots of code really only needed Applicative
or even just Functor
, but for historical reasons was stuck with Monad
anyway until the AMP. Ultimately the problem is that Haskell class hierarchies can't really be refined after the fact, only extended downwards, not upwards.
These days base
features classes for both Semigroup
and Monoid
(and plans are afoot to make the latter imply the former), so you don't have to choose between the two abstractions - just use the weakest assumption suitable for your purpose.
That said, Monoid
does seem to be somewhat more useful in daily practice than Semigroup
. Why is this? I can think of a couple of lines of argument:
Monoid
naturally abstracts composable collections of things in a way that Semigroup
doesn't. (For example, []
, the free Monoid
, is a classic example of a collection.)Semigroup
s but not Monoid
s tend to lose precision when you start composing them. Given two non-empty lists xs
and ys
, we know that xs <> ys
has at least two elements. But its type only promises that it has at least one; useful information has been discarded.return
and categories-sans-id
, installing the semigroupoids
package requires a chunk of the "Kmett Platform".If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With