在 GHCi 中:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
为什么第一个异常不是嵌套异常?
error
或undefined
的值,并且明确地不是在IO中生成的那种异常),则语言允许返回该集合中的任何一个值。在Haskell中,异常值更像是浮点代码中的NaN
,而不是命令式语言中基于控制流的异常。即使对于高级的Haskellers来说,偶尔也会遇到这样的情况。 case x of
1 -> error "One"
_ -> error "Not one"
由于代码的评估结果是一组异常,GHC可以随意选择其中一个。如果开启优化,你可能会发现它总是评估为“Not one”。
为什么要这样做呢?因为否则我们会过度限制语言的评估顺序,例如我们将不得不为以下内容固定确定性结果:
f (error "a") (error "b")
例如,可以要求按照从左到右的顺序计算,以防出现错误值。 这非常不像 Haskell!
由于我们不想削弱代码的优化以支持 error
,因此解决方案是指定结果是异常值集合中的一个非确定性选择:不精确的异常! 在某种程度上,所有异常都被返回,并且选择其中一个。
通常,您不关心 - 异常就是异常 - 除非您关心异常中的字符串,在这种情况下,使用 error
进行调试会非常令人困惑。
参考文献:A semantics for imprecise exceptions,Simon Peyton Jones,Alastair Reid,Tony Hoare,Simon Marlow,Fergus Henderson。 Proc Programming Languages Design and Implementation(PLDI'99),Atlanta。(PDF)
throw
抛出时),而您可以使用throwIO
确定性地抛出异常。 - FunctorSaladcase error "banana" of (x:xs) -> error "bonobo"
可以给你 * Exception: bonobo
。 - Ben Millwood
error
是一种特殊的错误机制,不是真正的异常机制。如果想要使用真正可以捕获的异常,请看Error
monad。 - Cat Plus Pluserror = error
,并据此编写程序。 - Gabriella Gonzalezundefined
的方式:http://hackage.haskell.org/packages/archive/gofer-prelude/2.30.3/doc/html/src/Prelude-Gofer.html#undefined - Don Stewart