函数forkFinally
要求您针对SomeException
编写处理程序。我需要的是一种重新抛出未处理异常的方法。这是一个示例代码,无法编译,因为在最后一行e
是不明确的:
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
当然首先想到的是简单地抛出someE
,即:
...
| otherwise -> cleanUp >> throwIO someE
确实会编译,但是当它们通过这个处理程序时,它会导致SomeException
中所有传入异常的包装。这不可能是正确的。如果我在堆栈中有多个这样的处理程序会怎么样 - 我会得到像SomeException $ SomeException $ RealException
这样的垃圾。
我错过了什么吗?处理这种情况的正确方法是什么?
答案 0 :(得分:2)
您是否看到了意外行为?如果你没有真正触发一些不可取的东西,那么我认为你无所畏惧。快速测试表明“正确的事情”已经完成。也就是说,如果你抓住然后抛出SomeException
,你仍然可以捕获原始异常。以下是使用ErrorCall
作为基础异常的示例:
> catch (catch (throw (SomeException (ErrorCall "hi")))
(\(e::SomeException) -> throw e))
(\(ErrorCall e) -> putStrLn e)
hi
这是因为throw
使用toException
和toException
的定义是SomeException
的身份:
instance Exception SomeException where
toException se = se
fromException = Just