In his answer to the question “Distinction between typeclasses MonadPlus, Alternative, and Monoid?”, Edward Kmett says that
Moreover, even if
Applicativewas a superclass ofMonad, you’d wind up needing theMonadPlusclass anyways, because obeyingempty <*> m = emptyisn’t strictly enough to prove that
empty >>= f = emptySo claiming that something is a
MonadPlusis stronger than claiming it isAlternative.
It’s clear that any applicative functor which is not a monad is automatically an example of an Alternative which is not a MonadPlus, but Edward Kmett’s answer implies that there exists a monad which is an Alternative but not a MonadPlus: its empty and <|> would satisfy the Alternative laws,1 but not the MonadPlus laws.2 I can’t come up with an example of this by myself; does anybody know of one?
1 I wasn’t able to find a canonical reference for a set of Alternative laws, but I lay out what I believe them to be roughly halfway through my answer to the question “Confused by the meaning of the Alternative type class and its relationship to other type classes” (search for the phrase “right distributivity”). The four laws I believe ought to hold are:
- Right distributivity (of
<*>):(f <|> g) <*> a = (f <*> a) <|> (g <*> a) - Right absorption (for
<*>):empty <*> a = empty - Left distributivity (of
fmap):f <$> (a <|> b) = (f <$> a) <|> (f <$> b) - Left absorption (for
fmap):f <$> empty = empty
I’d also happily accept being given a more useful set of Alternative laws.
2 I know that there’s some ambiguity about what the MonadPlus laws are; I’m happy with an answer that uses left distribution or left catch, although I would weakly prefer the former.
The clue to your answer is in the HaskellWiki about MonadPlus you linked to:
So according to your favoured choice,
Maybeisn't a MonadPlus (although there's an instance, it doesn't satisfy left distribution). Let's prove it satisfies Alternative.Maybeis an Alternative<*>):(f <|> g) <*> a = (f <*> a) <|> (g <*> a)Case 1:
f=Nothing:Case 2:
a=Nothing:Case 3:
f=Just h, a = Just x<*>):empty <*> a = emptyThat's easy, because
fmap):f <$> (a <|> b) = (f <$> a) <|> (f <$> b)Case 1:
a = NothingCase 2:
a = Just xfmap):f <$> empty = emptyAnother easy one:
Maybeisn't a MonadPlusLet's prove the assertion that
Maybeisn't a MonadPlus: We need to show thatmplus a b >>= k = mplus (a >>= k) (b >>= k)doesn't always hold. The trick is, as ever, to use some binding to sneak very different values out:Now
here I've used bind
(>>=)to snatch failure (Nothing) from the jaws of victory becauseJust Falselooked like success.Here the failure (
k False) was calculated early, so got ignored and we"Made it!".So,
mplus a b >>= k = Nothingbutmplus (a >>= k) (b >>= k) = Just "Made it!".You can look at this as me using
>>=to break the left-bias ofmplusforMaybe.Validity of my proofs:
Just in case you felt I hadn't done enough tedious deriving, I'll prove the identities I used:
Firstly
which come from the instance declaration
Secondly
which just come from
(<$>) = fmapandThirdly, the other three take a bit more work:
Which comes from the definitions
so
so if
mformxare Nothing, the result is alsoNothing, whereas ifmf = Just fandmx = Just x, the result isJust (f x)