haskellmonadsmonoidsmonadplus

Why MonadPlus and not Monad + Monoid?


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?


Solution

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

    1. If we don't want to tell the caller what a we intend to use.
      MonadPlus m => ... instead of Monoid (m SecretType) => ...

    2. If we want to use multiple different a.
      MonadPlus m => ... instead of (Monoid (m Type1), Monoid (m Type2), ...) => ...

    3. If we want to use infinitely many different a.
      MonadPlus m => ... instead of not possible.

    4. If we don't know what a we need. MonadPlus m => ... instead of not possible.