The function forkFinally requires you to write a handler against SomeException. What I need is a way to rethrow the unhandled exceptions. Here's a sample code, which fails to compile because on the last line the e is ambiguous:
finallyHandler :: Either SomeException () -> IO ()
finallyHandler z = case z of
Right () -> cleanUp
Left someE | Just ThreadKilled <- fromException someE -> cleanUp
| Just e <- fromException someE -> cleanUp >> throwIO e
Of course the first thing coming to mind is to simply throw the someE instead, i.e.:
...
| otherwise -> cleanUp >> throwIO someE
And indeed it will compile, but then it will result in wrapping of all of incoming exceptions in SomeException when they pass this handler. This just can't be right. And what if I have multiple such handlers down the stack - I'll get a trash like SomeException $ SomeException $ RealException.
Am I missing something? What's the proper way of handling this situation?
Are you seeing unexpected behavior? If you haven't actually triggered something undersirable then I think you are worrying over nothing. A quick test indicates that the "right thing" is already being done. That is, if you catch then throw a SomeException you can still catch the original exception. Here's an example using ErrorCall as the underlying exception:
> catch (catch (throw (SomeException (ErrorCall "hi")))
(\(e::SomeException) -> throw e))
(\(ErrorCall e) -> putStrLn e)
hi
This is because the definition of throw uses toException and toException is identity for SomeException:
instance Exception SomeException where
toException se = se
fromException = Just
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With