Proposal: Extensible exceptions
Isaac Dupree
isaacdupree at charter.net
Sat Jul 5 20:15:46 EDT 2008
Ian Lynagh wrote:
>> In fact, this applies to catchAny too. It should come with a strong
>> warning, and a suggestion that any unrecognised exceptions should be
>> re-thrown. Most uses of catchAny are to implement an on-error action
>> anyway, I think this ought to be provided as a combinator. We have
>> bracketOnError, but perhaps we should also have
>>
>> onException :: IO a -> IO b -> IO a
>
> Sounds good to me.
similar to `finally` but only for when there are exceptions.
finally :: IO a -> IO b -> IO a
bracket is to bracketOnError as finally is to... onException? perhaps we
can call it finallyOnError so we can understand the parallelism more
naturally? :-) (and why is there no "bracket_OnError" :-)
But I'd think that sometimes we want to have the exception (e.g. to
print it) even if we're `onException`, so we get a slightly more similar
signature to catchAny, but safer because it rethrows the exception after
the second clause completes:
onAny :: IO a -> (forall e . Exception e => e -> IO b) -> IO a
Then we encourage this as another alternative to catchAny depending on
user's needs. What should we call it -- onAny is bad? Really,
`finally` corresponds to `bracket_` -- I'm not too happy with the
Control.Exception naming situation right now, maybe I'll try to rethink
all the names at once and post a proposal (even if we decide we don't
want the API breakage, it'll be useful to make sure we're not leaving
out anything else important).
By the way, what happens if a `finally` or `onException` clause throws
an exception? That exception replaces the the one that we were planning
on rethrowing? Does this already induce a risk of accidentally deleting
Timeout exceptions (e.g. we replace it with a DiskFull exception
accidentally produced by logging a message, that some higher level code
catches and then proceeds as normal)? Or do we ignore exceptions in
those blocks? (Similar to how exceptions in C++ destructors are just a
Bad Idea.) But that risks ignoring a HeapOverflow or asynchronous
exception (killThread, timeout...)? no it doesn't, those are just
blocked from arriving until the end of the handling-block, and it's just
the *synchronous* exceptions that are swallowed? But if the handler
does some blocking I/O and thus (unblock), does that mean we risk losing
those exceptions again? This confuses me a lot. Are we any better off
than imperative languages, e.g. because most of our code isn't in I/O
and so it uses proper data structures (Maybe, Either, etc.), rather than
exceptions, for legitimate computational possibilities?
-Isaac
More information about the Libraries
mailing list