haskell - throw 和 throwIO 有什么区别

标签 haskell exception

The documentation说:

The throwIO variant should be used in preference to throw to raise an exception within the IO monad because it guarantees ordering with respect to other IO operations, whereas throw does not.



读完之后我还是一头雾水。有没有一个例子表明 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
    

    这可以说是你想要发生的事情,但通常不是。例如而不是上面的元组,您最终可能会得到一个带有单个爆炸元素的大数据结构,这会导致在您的 Web 服务器向用户返回 200 或其他内容后引发异常。
    throwIO允许您按顺序引发异常,就像它是另一个 IO 操作一样,因此可以严格控制它:
    Prelude Control.Exception> throwIO Underflow >> putStrLn "this is fine"
    *** Exception: arithmetic underflow
    

    ...就像做 print 1 >> print 2 .

    但请注意,您实际上可以替换 throwIOthrow , 例如:
    Prelude Control.Exception> throw Underflow >> putStrLn "this is fine"
    *** Exception: arithmetic underflow
    

    从现在开始,爆炸值的类型为 IO a .我实际上并不清楚为什么 throwIO除了记录成语之外,还存在。也许其他人可以回答这个问题。

    作为最后一个示例,这与我的第一个示例具有相同的问题:
    Prelude Control.Exception> return (throw Underflow) >> putStrLn "this is fine"
    this is fine
    

    关于haskell - throw 和 throwIO 有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53999720/

    相关文章:

    haskell - Yesod 一个站点有多个持久后端

    Haskell-从根到叶的列表

    android - 使用 HttpResponse 时出现异常 response = client.execute(request);

    带有消息的 C++ 异常

    function - 是否可以使用通用函数在元组中获取元组的第二个元素?

    haskell - 如何在这里避免显式类型签名?

    haskell - 无意义编程时 readFile 和 IO monad 之间没有合作

    android - Fatal Exception : main java. lang.RuntimeException: Unable to start activity 很多bug

    c++ - 如果我在转换中丢失数据,我可以在 C++ 中引发异常吗?

    c# - 为什么没有在闭包中捕获异常?