[Haskell-cafe] Why were unfailable patterns removed and "fail" added to Monad?
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:
http://www.mail-archive.com/haskell@haskell.org/msg03002.html
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
>
More information about the Haskell-Cafe
mailing list