[prev in list] [next in list] [prev in thread] [next in thread] 

List:       haskell
Subject:    Re: Sets of IOErrors?
From:       Fergus Henderson <fjh () cs ! mu ! OZ ! AU>
Date:       1999-09-28 16:17:32
Message-ID: 19990929021225.A15980 () murlibobo ! cs ! mu ! OZ ! AU
[Download RAW message or body]

On 08-Sep-1999, Alastair Reid <reid@cs.utah.edu> wrote:
> 
> I recently had occasion to write this function:
> 
>   -- do a, if that fails do b, if that fails, raise b's exception
>   (?) :: IO a -> IO a -> IO a
>   a ? b = a `catch` \_ -> b 
> 
> Simple enough, but if b fails, I don't really want to raise b's
> exception, I want to raise both a's exception and b's exception.

Yes, that kind of thing is not that uncommon.

BTW, you didn't explain why you need to raise both exceptions.
The reason is to correctly handle the case where programs test the
type of the exception raised and attempt some corrective action
accordingly.  For example, a program which is attempting to access a
network might have a high-level exception handler that checks for
network I/O errors and tries to handle them by restarting the network
connection and then retrying.  If a network I/O error occurs, and then
a lower-level handler tries some alternative means of recovery, and
that alternative throws some other kind of exception, it's important
that the exception thrown to the higher-level handler still include the
information that a network I/O error occurred, so that the higher-level
handler will restart the network connection.

The C++ standardization committee considered the issue of multiple
exceptions, and basically decided that it was too difficult to deal
with.  If a C++ exception handler itself throws an exception, then the
default behaviour is to abort the program.  You can install a special
handler to deal with such situtations, but that special handler can't
throw an exception, so there's not much it can safely do other than to
abort.  In theory it's possible to program around that kind of thing in
C++, but in practice this is exceedingly difficult (for various
reasons, including problems related to memory management and the lack
of a clone() member in the std::exception class), and furthermore
requires agreement between the different parts of the program about how
sets of exceptions are represented, so in practice nobody does it, as
far as I am aware.

It would be nice if Haskell could handle that problem better than C++.
Automatic memory management and the ease of writing higher-order combinators
such as `?' above mean that it is already much easier in Haskell.
However, some kind of standard library support is also essential if
library packages written by different authors are to cooperate.
So I agree with the essence of Alistair Reid's suggestions.
However, I have some quibbles about the details.

> What
> I'd like (in some future version of Haskell) is an IOError constructor
> which lets me merge two IOErrors together and appropriate operations
> to test for it and, perhaps, take it apart:
> 
>   IO.multipleErrors   :: [IOError] -> IOError
>   IO.isMultipleErrors :: IOError -> Bool
>   IO.ioeGetErrors     :: IOError -> [IOError]
> 
> The intention is that an IOError is a non-empty list of atomic errors
> (ie any of the existing IOErrors).  Thus "multipleErrors" is
> essentially concat, ioeGetErrors is (essentially) the identity
> function (it returns a list of IOErrors which are guaranteed to be
> non-empty) and all existing functions for testing IOErrors are
> modified to be defined only over singleton lists.

What existing functions for testing IOErrors?
Apart from the Eq and Show classes, Haskell 98 doesn't define any, AFAIK.
If you're suggesting that Eq or Show be undefined for IOErrors that
represent sets of exceptions, then I would have to disagree...

Perhaps you meant the Hugs/ghc functions for testing Exceptions.
If so, the above suggestions should be revised to refer to Exceptions
rather than IOErrors.

The exception handling in Haskell 98 needs substantial work, IMHO.
IMHO Haskell 200X should pick up the Hugs/ghc extensions related to
exception handling, or something along those lines, in particular:
	(a) allow throwing exceptions from arbitrary code, not just from within
	    the IO monad
	(b) allow throwing and catching of dynamically typed values,
	    e.g. using an interface like the Hugs/ghc Dynamic library

Once you have (b), then supporting sets of exceptions is straight-forward.
However, to handle the multiple exceptions problem, support for sets of
exceptions still needs to be part of the standard library, to ensure that
applications and library packages cooperate in this respect.

-- 
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3        |     -- the last words of T. S. Garp.



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic