[Haskell-cafe] New Hackage category: Error Handling

Alexander Dunlap alexander.dunlap at gmail.com
Mon Dec 7 01:40:46 EST 2009

On Sat, Dec 5, 2009 at 3:00 PM, Michael Snoyman <michael at snoyman.com> wrote:
> On Sun, Dec 6, 2009 at 12:55 AM, Henning Thielemann
> <lemming at henning-thielemann.de> wrote:
>> On Sun, 6 Dec 2009, Michael Snoyman wrote:
>>> I think there are plenty of examples like web servers. A text editor with
>>> plugins? I
>>> don't want to lose three hours worth of work just because some plugin
>>> wasn't written
>>> correctly. For many classes of programs, the distinction between error
>>> and exception is
>>> not only blurred, it's fully irrelevant. Harping on people every time
>>> they use error in
>>> the "wrong" sense seems unhelpful.
>>> Hope my commenting on this subject doesn't become my own form of
>>> *pedantry*.
>> In an earlier thread I have explained that one can consider a software
>> architecture as divided into levels. What is an error in one level (text
>> editor plugin, web server thread, operating system process) is an exception
>> in the next higher level (text editor, web server, shell respectively). This
>> doesn't reduce the importance to distinguish between errors and exceptions
>> within one level. All approaches so far that I have seen in Haskell just mix
>> exceptions and errors in an arbitrary way.
> I think we can all appreciate why it would be a bad thing is we treat
> exceptions as errors. For example, I don't want my program to crash on a
> file not found.
> On the other hand, what's so bad about treating errors as exceptions? If
> instead of the program crashing on an array-out-of-bound or pattern-match it
> throws an exception which can be caught, so what?
> Michael

I think the key is in the difference between the user/client and
programmer/developer. As Henning has been saying, these roles change
as you go through the different levels of the program, but I see the
difference between an error and an exception as this: when a problem
is relevant to the user/client, it's an exception; when it is
irrelevant to the user/client, it's an error. Suppose you were using
some sort of exception framework and you got an error from a piece of
library code (not the head function) saying that "head" had failed
somewhere. This is absolutely meaningless to a client. It just means
there's a problem in the library code; it doesn't mean anything is
amiss in the client's space. The client basically has to throw the
function out, whether by gracefully aborting the program, disabling
the plugin, etc. Contrast this with an exception, such as "index not
in map." This is entirely relevant to the client. All of the code
knows exactly what is going on; it's just that the index isn't in the
map. The client can recover from this by, say, substituting a default
value, adding the index to the map, etc. Now, suppose the client knew
a priori that the index was *supposed* to be in the map. Now this
becomes an *error* to the *client* of the client, since there is a bug
in the first client's code.

I guess my point is that if I have a function, say, sort :: Ord a =>
[a] -> [a], and sort calls head somewhere in it, there's no point
having "sort" throw an exception for "Prelude.head: []" since that
means nothing to the client. It would make more sense to have an
InternalError type that just says "OK, sorry client, I screwed up,
just clean things up as best you can". If really were something that
the client could have responded to, sort should have caught the head
error inside the function definition and rethrown a different
exception; say, SortEmptyListError if your sort function didn't work
on empty lists (contrived example, sorry).


More information about the Haskell-Cafe mailing list