该文件说:
throwIO变量应优先使用throw引发IO monad中的异常,因为它可以保证相对于其他IO操作的排序,而throw则不能。
看完之后我还是很困惑。是否有示例显示throw会导致问题,而throwIO不会导致问题?
附加问题:
以下陈述正确吗?
throw用于在IO中引发异常,则不能保证异常的顺序。throw用于将异常抛出为非IO值,则可以保证异常的顺序。如果我需要在Monad Transformer中抛出一个异常,我必须使用它来throw代替throwIO,它是否可以保证异常的顺序?
我认为文档可以改进。您需要记住的问题throw等是throw返回一个在评估时“爆炸”(引发异常)的底部值;但是由于懒惰,很难控制是否以及何时进行评估。
例如:
Prelude Control.Exception> let f n = if odd n then throw Underflow else True
Prelude Control.Exception> snd (f 1, putStrLn "this is fine")
this is fine
Run Code Online (Sandbox Code Playgroud)
这可以说是你想要发生的事情,但通常不是。例如,不是上面的元组,您最终可能会得到一个大数据结构,其中包含一个爆炸元素,导致在您的 Web 服务器向用户返回 200 或其他内容后引发异常。
throwIO 允许您按顺序引发异常,就好像它是另一个 IO 操作一样,因此可以对其进行严格控制:
Prelude Control.Exception> throwIO Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
Run Code Online (Sandbox Code Playgroud)
...就像做print 1 >> print 2。
但请注意,你其实可以代替throwIO用throw,例如:
Prelude Control.Exception> throw Underflow >> putStrLn "this is fine"
*** Exception: arithmetic underflow
Run Code Online (Sandbox Code Playgroud)
从现在开始,爆炸值的类型为IO a。throwIO除了记录一个习语之外,我实际上不清楚为什么存在。也许其他人可以回答这个问题。
作为最后一个示例,这与我的第一个示例存在相同的问题:
Prelude Control.Exception> return (throw Underflow) >> putStrLn "this is fine"
this is fine
Run Code Online (Sandbox Code Playgroud)