Edward Z. Yang ezyang at MIT.EDU
Fri Jan 20 04:19:06 CET 2012

```Hello Gregory,

The original (1998!) conversation can be found here:

I think Simon Peyton-Jones' example really sums up the whole issue:

But [MonadZero] really sticks in my craw.  How can we explain this:

f :: Monad m => m (a,b) -> m a
f m1 = do { x <- m1; return (fst x) }

g :: MonadZero m => m (a,b) -> m a
g m1 = do { (a,b) <- m1; return a }

h :: Monad m => m (a,b) -> m a
h m1 = do { ~(a,b) <- m1; return a }

Why must g be in MonadZero?  Because the pattern (a,b) is refutable (by
bottom).

In my opinion, the /flexibility/ that was added by mfail was the real
mistake; we should have just had incomplete <- matches be handled the same
way ordinary incomplete pattern matches were accomodated, and figured out
how to nicely allow for multiple patterns in do-notation.  In other words,
MonadZero has no place in dealing with pattern match failure!

But this ship has long sailed.

Cheers,
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
>

```