我试图牢牢掌握异常,以便改进我的条件循环实现。为此,我进行了各种实验,扔东西,看看会被抓到什么。
这个让我惊喜不已:
% cat X.hs
module Main where
import Control.Exception
import Control.Applicative
main = do
throw (userError "I am an IO error.") <|> print "Odd error ignored."
% ghc X.hs && ./X
...
X: user error (I am an IO error.)
% cat Y.hs
module Main where
import Control.Exception
import Control.Applicative
main = do
throwIO (userError "I am an IO error.") <|> print "Odd error ignored."
% ghc Y.hs && ./Y
...
"Odd error ignored."
我认为替代方案应该完全忽略 IO 错误。(不知道我从哪里得到这个想法,但我当然不能提供一个在替代链中会被忽略的非 IO 异常。)所以我想我可以手工制作并提供一个 IO 错误。事实证明,它是否被忽略取决于包装和内容:如果我throw
是一个 IO 错误,它就不再是一个 IO 错误。
我完全迷路了。为什么它会这样工作?是有意的吗?这些定义深入到 GHC 内部模块;虽然我自己或多或少可以理解不同代码片段的含义,但我很难看到整个画面。
如果很难预测,甚至应该使用这个替代实例吗?如果它消除任何同步异常,而不仅仅是以特定方式定义并以特定方式抛出的一小部分异常,这不是更好吗?