I'm trying to understand the motivation behind the MonadPlus
. Why is it necessary if there are already the typeclasses Monad
and Monoid
?
Granted, instances of Monoid
are concrete types, whereas instances of Monad
require a single type parameter. (See Monoid vs MonadPlus for a helpful explanation.) But couldn't you rewrite any type constraint of
(MonadPlus m) => ...
as a combination of Monad
and Monoid
?
(Monad m, Monoid (m a)) => ...
Take the guard
function from Control.Monad
, for example. Its implementation is:
guard :: (MonadPlus m) => Bool -> m ()
guard True = return ()
guard False = mzero
I was able to implement it using only Monad
and Monoid
:
guard' :: (Monad m, Monoid (m ())) => Bool -> m ()
guard' True = return ()
guard' False = mempty
Could someone please clarify the real difference between MonadPlus
and Monad
+ Monoid
?
But couldn't you rewrite any type constraint of
(MonadPlus m) => ...
as a combination of Monad and Monoid?
No. In the top answer to the question you link, there is already a good explanation about the laws of MonadPlus vs. Monoid. But there are differences even if we ignore the typeclass laws.
Monoid (m a) => ...
means that m a
has to be a monoid for one particular a
chosen by the caller, but MonadPlus m
means that m a
has to be a monoid for all a
. So MonadPlus a
is more flexible, and this flexibility is helpful in four situations:
If we don't want to tell the caller what a
we intend to use.
MonadPlus m => ...
instead of Monoid (m SecretType) => ...
If we want to use multiple different a
.
MonadPlus m => ...
instead of (Monoid (m Type1), Monoid (m Type2), ...) => ...
If we want to use infinitely many different a
.
MonadPlus m => ...
instead of not possible.
If we don't know what a
we need.
MonadPlus m => ...
instead of not possible.