Haskell中的异常如何工作?

Dan*_*ner 86 haskell exception

在GHCi中:

Prelude> error (error "")
*** Exception: 
Prelude> (error . error) ""
*** Exception: *** Exception: 
Run Code Online (Sandbox Code Playgroud)

为什么第一个不是嵌套异常?

Don*_*art 101

答案是,这是不精确异常的(有些令人惊讶的)语义

当纯代码可以显示为评估一异常值(即erroror 的值 undefined,并且显然不是IO中生成的异常类型)时,语言允许返回该组的任何值.Haskell中的异常值更像NaN是浮点代码,而不是命令式语言中基于控制流的异常.

即使是高级Haskellers的偶然问题也是如下情况:

 case x of
   1 -> error "One"
   _ -> error "Not one"
Run Code Online (Sandbox Code Playgroud)

由于代码评估为一组异常,GHC可以自由选择一个.通过优化,您可能会发现它总是评估为"不是一个".

我们为什么要做这个?因为否则我们会过度约束语言的评估顺序,例如我们必须修复确定性结果:

 f (error "a") (error "b")
Run Code Online (Sandbox Code Playgroud)

例如,如果存在错误值,则要求从左到右进行评估.非哈斯克利!

由于我们不希望削弱可以对我们的代码进行的优化只是为了支持error,因此解决方案是指定结果是来自异常值集的非确定性选择:不精确的异常!在某种程度上,返回所有异常,并选择一个异常.

通常,您不关心 - 异常是异常 - 除非您关心异常中的字符串,在这种情况下使用error调试非常容易混淆.


参考文献:不精确异常的语义,Simon Peyton Jones,Alastair Reid,Tony Hoare,Simon Marlow,Fergus Henderson.Proc编程语言设计与实现(PLDI'99),亚特兰大.(PDF)

  • @Peaker死代码elim - 优化器不需要查看x来查看错误是结果,所有分支都产生"相同"值,因此它可以完全忽略输入值.在不精确的例外情况下,这不是一个错误! (8认同)
  • @Peaker我认为你是对的.如果他们想要按照不精确的例外文件中规定的规则进行游戏,我认为ghc不应该优化这个表达式. (3认同)
  • 那些不精确的例外文件**似乎在说*如果*case scrutinee*是一个错误值,那么可以返回分支的错误值.所以(x:xs)的`case error"banana" - >错误"bonobo"`可以给你`*异常:bonobo`. (3认同)
  • 我理解 GHC 选择了可能遇到的任何异常之一。但是在您的“案例”示例中,输入为 1 时不会遇到“不是一个”异常,因此我仍将其归类为错误。 (2认同)