
On Friday 07 May 2010 7:54:21 pm Limestraƫl wrote:
Personally I think fail is a terrible wart, and should be shunned.
So do I. I can't understand its purpose since monads which can fail can be implemented through MonadPlus.
Understanding why fail exists requires going back to before Haskell 98. Back then, there was a MonadZero, and when you did pattern matching in do syntax, a MonadZero constraint would be generated in most cases, like: do Just x <- m ... *But*, there were cases where MonadZero wasn't required. This happened when you did a match like: do (x, y) <- m ... In this case, there's no need to fail 'in the monad', because either the value in question *is* of the form (x, y), or it is bottom, in which case the whole expression should be bottom anyhow (because we're not supposed to be able to detect bottoms like that). Patterns like the above had a special distinction, called "unfailable". This is not the same as irrefutable, although the latter would be a special case of the former; unfailable patterns are those that can at most be refuted by a partially defined value, rather than refuted by a sum. So, for reasons that I don't recall off the top of my head (perhaps pedagogy), it was decided that Haskell 98 should no longer have this additional notion of unfailable pattern. However, when you get rid of them, there's a fair amount of valid code with a context of Monad m that now needs MonadZero (or, Plus, since Zero is gone), and that's rather inconvenient. So, fail was introduced into Monad so that pattern matching can be desugared in any Monad, and you're once again allowed to write: foo :: Monad m => m (a,b) -> ... foo m = do (x, y) <- m ... Which is always okay, even though other matches/etc. you can do with fail really isn't. Personally, I don't really understand why unfailable patterns were canned (they don't seem that complicated to me), so I'd vote to bring them back, and get rid of fail. But hind sight is 20/20, I suppose (or perhaps there exist cogent arguments that I haven't heard). -- Dan