[Haskell-cafe] exceptions vs. Either

Marcin 'Qrczak' Kowalczyk qrczak at knm.org.pl
Tue Aug 3 09:06:51 EDT 2004


W liście z wto, 03-08-2004, godz. 13:05 +0200, Bjoern Knafla napisał:

> Herb Sutter gave these rules :
> 
> An error is any failure that prevents a function from succeeding. Three 
> main kind of errors:
[...]

These kinds don't explain much. They don't give a clue which errors
to report by exceptions and which by return values, because they don't
distinguish the reasons for which a (pre|post)condition can't be
fulfilled. And I see no point in distinguishing potential errors on
this axis.

I divide exceptional situations into 4 groups:

1. Expected error: The result can't be computed from this data; the
   caller was not supposed to check this beforehand because it would
   duplicate work of the function, or there would be a race condition,
   or the design is simpler that way.

2. Program error: The given function was not supposed to be invoked
   in this way by other parts of the program (with these arguments,
   or with this external state, in this order wrt. other functions
   etc.).

3. Out of resource: The function is sorry that it was not able to
   produce the result due to limited memory or arithmetic precision
   or similar resources. "Not yet supported" is also in this group.

4. Impossible error: The function thought this couldn't happen, it must
   have a bug. This is like 2 in that there is a bug somewhere, but like
   1 in that the calling code is probably fine.

I/O errors can be expected errors or out of resource conditions,
depending on whether they were caused by bad input or by external
failure.

Group 1 should be reported in Haskell by a distinguished result (Maybe,
Either, custom type) or by an exception passed in a suitable monad
(well, Maybe is a monad; this could be even the IO monad).

Other groups are handled in a similar way. In Haskell they can be
reported by a bottom, e.g. 'error' function. It makes sense to catch
them on a toplevel of the program or a large unit, and it's good that
GHC provides a way to catch them. There may be other actions possible
than just aborting the program: report the problem to the user, abort
just the given operation, but try to continue other work; save user data
before aborting; log the error or report it in an appropriate channel,
e.g. output a HTML page in case of a CGI program.

Sometimes the same function makes sense in two variants: one which
reports an expected error, and another which treats it as a program
error. Example: lookup in a dictionary.

Sometimes the qualification of an error changes while it is propagated.
I haven't thought about all cases, but for example program errors become
impossible errors if the caller thought that the arguments it passed
were good, and expected errors become program errors if the caller's
caller was not supposed to give arguments which cause such problems.

The most important distinction is between expected errors, whose way of
reporting should be visible in the interface and which should be checked
for in the calling code, and program errors, which should be
automatically propagated and reported near the toplevel.

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak at knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/



More information about the Haskell-Cafe mailing list