捕获除了AsyncException之外的所有异常



我需要执行许多计算,这些计算可能会以多种难以想象的方式失败,但这些失败可以忽略(通知用户)。但是,我不想像UserInterrupt那样忽略AsyncException,所以用户可以使用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

这是语言的黑暗角落。实际上,AsyncException在转换为SomeException时被包装成SomeAsyncException。使用asyncExceptionFromException代替cast(或强制转换为SomeAsyncException)

最新更新