捕获除AsyncException之外的每个Exception

时间:2016-06-25 19:13:31

标签: haskell exception-handling

我需要执行许多可能以多种难以想象的方式失败的计算,但可以忽略失败(通知用户)。但是,我不想忽略像AsyncException这样的UserInterrupt,因此用户可以使用 Control - C 停止程序。

如果我尝试中止下面的程序,它只会输出# failed: user interrupt - 好像无法将异常强制转换为AsyncException。从正在打印的user interrupt开始,我们知道例外UserInterrupt可以投放(cast UserInterrupt :: Maybe AsyncException)。

为什么UserInterrupt例外已识别且重新抛出

import Control.Exception
import Control.Monad
import Data.Typeable

main = forM_ [1..500000] processNumber

processNumber n =
    handle h (simulateComputation n)
  where
    h (SomeException e) =
        case (cast e :: Maybe AsyncException) of
            Just ae ->
                throw ae
            Nothing ->
                putStrLn $ show n ++ " failed: " ++ show e

simulateComputation n = do
    putStrLn "...Obtaining data and computing..."
    --when (n `mod` 1000 == 0) $
    --    throw (ErrorCall "ComputationFailed")
    --when (n `mod` 1111 == 0) $
    --    throw DivideByZero

1 个答案:

答案 0 :(得分:2)

这是该语言的一个黑暗角落。实际上AsyncExceptionconverted to SomeException时会被SomeAsyncException包裹。使用asyncExceptionFromException代替cast(或投放到SomeAsyncException)。