[Haskell] Better Exception Handling
Ben Rudiak-Gould
Benjamin.Rudiak-Gould at cl.cam.ac.uk
Tue Nov 23 12:20:19 EST 2004
John Goerzen wrote:
>myfunc :: String -> Int
>
>This does some sort of string parsing and returns an Int. Or it may
>raise an exception if it couldn't parse the string. But it would do
>that every time.
>
>Now, let's say we have a non-IO catchJust. Of course, if we never need
>the value, we never run the function -- or catchJust. If we do need the
>value, we run the function in the context of catchJust. If it raises
>our exception, catchJust handles it and returns some default. If it
>raises no exception, it's the same as having no handler at all. And if
>it raises some other exception, it's also the same as having no handler
>at all.
>
>So what am I missing here?
myfunc might raise more than one exception. For example,
myfunc = error "x" + error "y"
Haskell doesn't specify which exception will actually be thrown, and
this indeterminism is modeled by putting exception-catching functions in
the IO monad. There's a paper explaining it [1].
I'm not convinced this is the best solution. I can't think of a
situation in which there's a piece of code that throws different
exceptions depending on evaluation order, /and/ I care which one of
those I catch. If each particular implementation were just consistent
about which exception it reports in these situations, I think the
exception-catching functions would be pure. In any case, mapException is
pure, and it's good enough for most of the cases where one might want to
catch exceptions outside the IO monad.
The second problem with exceptions in Haskell, which I think is rather
more serious, is that they can hide inside of data structures. This
means that you can't, for example, wrap an exception handler around
(readConfigFile :: FilePath -> IO [ConfigOption]) and be sure that you
will catch any exceptions that are thrown during the parsing of the
configuration file. Depending on how readConfigFile is written, those
exceptions may be hiding inside the returned list, where they won't be
noticed until some other part of the program inspects that part of the
list, at which point your exception handler is no longer in scope. The
only remedy is to use deepSeq (which really ought to be derivable).
A question I don't know the answer to is whether (catchJust :: a ->
Maybe a), which lumps all exceptions into a Nothing return, is pure. It
seems like it would be; if so, why don't we have it? Or do we?
-- Ben
[1] http://research.microsoft.com/~simonpj/Papers/imprecise-exn.htm
More information about the Haskell
mailing list