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