
On Thu, 2009-10-01 at 03:29 +0000, Brian Bloniarz wrote:
I had a question about onException & friends: what's the rationale for having: (error "foo") `onException` (error "bar")
give bar and not foo?
I.e. why does an exception raised during exception handling get propagated past the exception that triggered the handler?
Because it's the obvious and sensible thing to do and it what every other mainstream language with exceptions does. The behaviour you want, to automatically discard any exceptions raised in the handler and to always re-raise the original exception can be implemented using the current semantics, but the reverse is not true.
Most examples I can think for exception unwinding code would prefer the original exception be propagated
Then do not rethrow a different exception.
This same argument applies to bracket, bracket_, bracketOnError & finally; even the common:
bracket openSomeHandle closeSomeHandle doAction If some error arises during doAction, there's a chance closeSomeHandle might fail (even a good chance, given that exception unwinding paths are usually poorly tested), and probably doAction has more accurate information about what went wrong than closeSomeHandle.
Then catch and ignore the exception from closeSomeHandle (though not all exceptions or you'd block ^C etc). That said, how will you know that closeSomeHandle ever works if you always ignore any exceptions it raises? For example in the case of your database transaction, having the transaction fail and roll back is something your application may be set up to handle. But transation failing during the rollback may be much more catastrophic and may want to be treated differently. If it fails in the rollback it might be leaking resources and at the very least you may want to log it differently from just a transaction that was successfully rolled back.
This is just a thought; I hadn't seen this discussed somewhere. I know for example that Java has the same approach as the current Control.Exception, so there must be good arguments for that too. One that I can think of: using onException to rethrow an exception as a different type, though that's what mapException is for, correct?
mapException is for the case of exceptions raised by pure code. As you say, being able to rethrow a different kind of exception, or simply handle the exception there and then are useful. I think using onException is the best one for your use case. If you really really want to ignore an exception raised by rollback then you have the tools available to do so. As I mentioned earlier do not just catch and discard all exceptions, see: http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception... Duncan