Meta-point: backward compatibility

Dan Doel dan.doel at gmail.com
Wed Apr 23 18:05:29 EDT 2008


On Wednesday 23 April 2008, Chris Smith wrote:
> I don't think I agree that fail in the Monad typeclass is a good example
> here, or necessarily that there is a good example.
>
> We should remember that there is a cohesive community of Haskell
> programmers; not a bunch of unrelated individuals who never talk to each
> other.  It's entirely possible to spend some time recommending against
> using fail (as many people have been doing), and then eventually remove
> it.  It doesn't need to break very much.  This is working in our favor,
> so we may as well use it.  IMO, this argues strongly in favor of making
> any backward compatible changes incrementally, instead of adopting a
> "Python 3000" model of postponing them and then breaking everything at
> once.
>
> (This is ignoring technical issues in this particular example; like what
> happens when a pattern match fails if there is no fail in Monad.  It's
> entirely possible that discouraging use is the right answer in this case,
> and that removal need not happen.  That's beside the point.)

The thing is, fail isn't evil because it's intrinsically evil; it's evil 
because it's in the wrong place. Many monads don't have a proper notion of 
failure, so error just gets called, which is undesirable. (Even if they do 
have a proper notion of failure, it's also easy to forget to define fail 
appropriately, if you're defining your own monad.)

Discouraging people from ever using fail, or even monadic pattern matching is 
also undesirable, because there are plenty of places where it is appropriate. 
As an example, I saw a blog post that included code like so (I don't remember 
the exact code, but this is comparable):

    f c l = length [ () | (c':'h':_) <- tails l, c == c' ]

In the comments of that blog, someone had written that the code was evil, 
because it was an abuse of fail. But that isn't an abuse of fail (it doesn't 
even use fail at all, technically, since list comprehensions have their own 
desugaring in the report), it's appropriate use of fail. So clearly, people 
are already getting the wrong idea from the "don't use fail" push, and may be 
avoiding appropriate use of it, when it would make for clearer code.

So, if you ask me, the solution isn't "discourage all use of fail." There's 
nothing wrong with failing in an arbitrary monad-with-failure. And we already 
have a class for that, called MonadPlus (or MonadZero if you split them up as 
in 1.4). If you move fail there, then you can encourage use of fail when 
appropriate. Currently, it seems difficult to do that (witness the readM 
thread on the libraries list, where it was proposed that fail be used 
(because there are multiple ways to fail), but with type restricted to 
MonadPlus; most people still seemed to dislike that because 'fail is evil').

-- Dan


More information about the Haskell-prime mailing list