我在评论中的狡辩无法忍受,我认为 sclv 回答了你问题的第一部分,但至于
如果所有 Haskell 类型都包含一个模式匹配的 Java-null-like 值而不是底部,那么会丢失哪些有用的属性?
换句话说:为什么不明智地通过提升所有类型的空值来使所有 Haskell 函数总计?
在这里,您似乎在区分非终止和异常。所以,虽然不可能(由于停止问题)在非终止时进行模式匹配,但为什么不能在异常时进行模式匹配呢?
我用我自己的一个问题来回答这个问题:那些从不抛出异常的函数呢?Haskell 毕竟具有全部功能。如果已知某些东西是非异常的,我不应该使用模式匹配来确保它是非异常的。Haskell 作为一种束缚和纪律语言,自然会想在类型上传达这种差异。也许通过写作
Integer
对于已知不是异常的整数类型和
?Integer
对于可能是异常的整数类型。答案是我们已经这样做了:Haskell 在前奏中有一个类型
data Maybe a = Just a | Nothing
可以理解为“要么有,a
要么什么都没有”。我们可以进行模式匹配,Maybe
所以这个提议不会给我们任何东西。(我们也有类型Either
更丰富的“可能出错的计算”以及花哨的 monad 语法/组合器,以使这些易于使用)。
那么,为什么会有例外呢?在 Haskell 中,除了 IO monad 之外,我们不能“捕获”异常。如果我们可以完美地模拟异常Maybe
,Either
为什么语言中有异常?
对此有几个答案,但核心是Haskell 异常是不精确的。可能会出现异常,因为您的程序内存不足,或者您正在执行的线程被另一个线程杀死,或者一大堆其他不可预测的原因。此外,通常对于异常,我们关心我们得到哪个异常。那么下面的表达式会导致什么结果呢?
(error "error 1") + (error "error 2") :: Integer
这个表达式显然应该导致异常,但是哪个异常呢? (+)
专门针对 Integer 的两个参数都很严格,所以这无济于事。我们可以决定它是第一个值,但一般来说我们会有
x + y =/= y + x
这将限制我们对等式推理的选择。Haskell 提供了一种行为不精确的异常概念,这很重要,因为语言的纯部分具有完全精确的行为,并且可能会受到限制。