重新抛出一些异常

时间:2013-10-23 18:03:03

标签: exception haskell

函数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这样的垃圾。

我错过了什么吗?处理这种情况的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

您是否看到了意外行为?如果你没有真正触发一些不可取的东西,那么我认为你无所畏惧。快速测试表明“正确的事情”已经完成。也就是说,如果你抓住然后抛出SomeException,你仍然可以捕获原始异常。以下是使用ErrorCall作为基础异常的示例:

> catch (catch (throw (SomeException (ErrorCall "hi")))
               (\(e::SomeException) -> throw e)) 
        (\(ErrorCall e) -> putStrLn e)
hi

这是因为throw使用toExceptiontoException的定义是SomeException的身份:

instance Exception SomeException where
    toException se = se
    fromException = Just