
Oh, I'm sorry! On a closer reading of your message, you're asking not only asking why 'fail' was added to Monad, but why unfailable patterns were removed. Well, from the message linked: In Haskell 1.4 g would not be in MonadZero because (a,b) is unfailable (it can't fail to match). But the Haskell 1.4 story is unattractive becuase a) we have to introduce the (new) concept of unfailable b) if you add an extra constructor to a single-constructor type then pattern matches on the original constructor suddenly become failable (b) is a real killer: suppose that you want to add a new constructor and fix all of the places where you assumed there was only one constructor. The compiler needs to emit warnings in this case, and not silently transform these into failable patterns handled by MonadZero... Edward Excerpts from Gregory Crosswhite's message of Thu Jan 19 21:47:42 -0500 2012:
Today I learned (tldr; TIL) that the "fail" in the Monad class was added as a hack to deal with the consequences of the decision to remove "unfailable" patterns from the language. I will attempt to describe the story as I have picked it up from reading around, but please feel free to correct me on the details. :-)
An "unfailable" pattern (which is a generalization of an "irrefutable" pattern) is a pattern which can never fail (excluding the possibility of _|_), such as
let (x,y) = pair
Before "fail" was a method of the Monad class, using refutable patterns in a monad required the type to be an instance of MonadZero (that is, MonadPlus without the plus), so that for example
do Just x <- m
required that the monad be an instance of MonadZero. If you avoided such patterns, your Monad did not have to have this instance, so that for example
do (x,y) <- pair
would not require MonadZero because the pattern is unfailable.
To me this seems like a lovely way of handling the whole matter, and much improved over the incredibly ugly wart of having a "fail" method in the Monad class. In fact, I think I remember people on this list and in other forums occasionally bringing something like this approach up as a way of getting rid of the "fail" wart.
So my question is, why did we go to all of the trouble to transition away from the MonadZero approach to the current system to begin with? What was so bad about "unfailable" patterns that it was decided to remove them and in doing so replace MonadZero with a mandatory "fail" method in Monad? I mean, this *is* Haskell, so my safest assumption is that smart people were involved in making this decision and therefore the reasons much have been really good (or at least, seemed good given the information at the time). :-)
Cheers, Greg