我需要执行许多可能以多种难以想象的方式失败的计算,但可以忽略失败(通知用户)。但是,我不想忽略像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
答案 0 :(得分:2)
这是该语言的一个黑暗角落。实际上AsyncException
在converted to SomeException
时会被SomeAsyncException
包裹。使用asyncExceptionFromException
代替cast
(或投放到SomeAsyncException
)。