This is a question that has come up several times for me in the design code, especially libraries. There seems to be some interest in it so I thought it might make a good community wiki.
The fail method in Monad is considered by some to be a wart; a somewhat arbitrary addition to the class that does not come from the original category theory. But of course in the current state of things, many Monad types have logical and useful fail instances.
The MonadPlus class is a sub-class of Monad that provides an mzero method which logically encapsulates the idea of failure in a monad.
So a library designer who wants to write some monadic code that does some sort of failure handling can choose to make his code use the fail method in Monad or restrict his code to the MonadPlus class, just so that he can feel good about using mzero, even though he doesn't care about the monoidal combining mplus operation at all.
Some discussions on this subject are in this wiki page about proposals to reform the MonadPlus class.
So I guess I have one specific question:
What monad instances, if any, have a natural fail method, but cannot be instances of MonadPlus because they have no logical implementation for mplus?
But I'm mostly interested in a discussion about this subject. Thanks!
EDIT: One final thought occured to me. I recently learned (even though it's right there in the docs for fail) that monadic "do" notation is desugared in such a way that pattern match failures, as in (x:xs) <- return [] call the monad's fail.
It seems like the language designers must have been strongly influenced by the prospect of some automatic failure handling built in to haskell's syntax in their inclusion of fail in Monad.
Think of
Either. It's monadic instance looks like this:(We need FlexibleInstances in order to allow an instance like
Either String)So it's basically like
Maybewith an optional error message if something happens. You can't recreate this withmzero, as you can't add an error message to the failure. It's somewhat different fromfail.Each instance of
mplusshould satisfy these two laws:Simple, isn't it? But these laws make
mplusspecial. With them, it's possible to write a reasonableMonadPlusinstance for it:What is this? It represents a choice. If the first computation is successful, it will be returned. Else,
mplusreturns the second computation. Note how it differs from(>>), which doesn't satisfies the laws:(>>)will stop on the first computation, whilemplustries the second one instead.[]also behaves like this:This is just to discuss the aspects of
MonadPlusand specially the aspect ofmplusin contrast to(>>).