
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? Most examples I can think for exception unwinding code would prefer the original exception be propagated -- for example, HDBC has a function which rolls back a DB transaction on exception; it implements it like so:
withTransaction conn func = do r <- onException (func conn) doRollback commit conn return r where doRollback = -- Discard any exception from (rollback conn) so original -- exception can be re-raised Control.Exception.catch (rollback conn) doRollbackHandler doRollbackHandler :: SomeException -> IO () doRollbackHandler _ = return () IMHO, it'd be easier to just write: withTransaction conn func = do r <- onException (func conn) (rollback conn) commit conn return r
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.
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? Thanks, -Brian _________________________________________________________________ Microsoft brings you a new way to search the web. Try Bing™ now http://www.bing.com?form=MFEHPG&publ=WLHMTAG&crea=TEXT_MFEHPG_Core_tagline_try bing_1x1