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.