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 > _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe