There are too many error handling conventions used in library
ajb at spamcop.net
ajb at spamcop.net
Sun Mar 11 08:02:44 EDT 2007
Quoting Donald Bruce Stewart <dons at cse.unsw.edu.au>:
> This article on the 8 different error handling strategies various common
> Haskell libs use:
> got me thinking:
> we need to standardise/recommend a small set of methods for library
> error handling.
For the record, here are the eight ways:
1. Call error
2. Return Maybe
3. Return Either
4. Return a generic Monad, a.k.a. NotJustMaybe.
5. Use MonadError and a custom error type.
7. ioError and catch
8. Monad transformers, implementing some combination of the above.
Note: NotJustMaybe is claimed to be a generalisation of 1-3; in fact
that's not quite true, since using this idiom to call Error does require
a wrapper call. Perhaps this wrapper should be given a shorter and
snappier name than runIdentity?
One other one has been left out, and that's continuation-based error
Some general comments:
1. I've never seen some of these (8 in particular) used in any general-
2. If it doesn't cross an API boundary, it's none of my business what
error handling scheme you use.
3. Prolog, sadly, encourages failure-driven loops. Java, even more sadly,
seems to encourage loops where normal termination is achieved by throwing
an exception. Haskell, by contrast, never encourages a compromise like
4. There are clearly different kinds of error/exception, and we shouldn't
expect one size to fit all.
As some examples:
- Failure to meet a precondition includes division by zero, head of
an empty list, array bounds checking etc. Anything which the
client could trivially ensure but hasn't must be due to a bug in
the client code. Calling "error" is appropriate.
- True absence of a return value, such as looking up a value in a
Data.Map which isn't there, calls for Maybe or generic Monad.
In the absence of a short-and-snappy version of runIdentity,
there is an argument for also providing an "error" version.
We need a good naming convention for this.
- Exceptions are _undesired_ conditions which would otherwise
break the logical flow of control. These come in two varieties:
Some you want the client to intercept and deal with (e.g. Parsec
parse errors) and some you want to leave it up to the client to
decide (e.g. most I/O exceptions).
> * what role does MonadError play here, as a generic error handler?
I think this is a perfect fit for any exception which the client MUST
deal with. It's the Haskell equivalent of Java's checked exceptions,
which are a right royal pain when they're mandatory, but occasionally a
godsend when they're not.
> * can we make precise recommendations about which error strategies to
No, but I think we can state some general principles.
More information about the Libraries