为什么Haskell在部分函数中使用bottom而不是null?
我正在阅读有关Haskell指称语义(http://en.wikibooks.org/wiki/Haskell/Denotational_semantics),我不明白为什么在一个类型中,底部“值”被放置在与“正常”相比较的另一个层次上,值,例如为什么它不能被模式匹配。
我认为模式修补底部会导致麻烦,因为底部也表示非终止计算,但为什么非终止计算和错误应该被视为相同? (我假设调用不支持的参数的部分函数可以被视为一个错误)。
如果所有的Haskell类型都包含一个模式匹配的Java-null-like值而不是底部,那么会丢失哪些有用的属性?
换句话说:为什么通过提升所有类型的空值来完成所有Haskell函数并不明智?
(非终止计算完全需要特殊类型吗?)
如果不限制语言的图灵度完备性,并且停止问题,我们通常无法检测到非终结点并将其替换为一个值,您无法摆脱非终结点。
所以每一个完整的语言都有底线。
Haskell和Java之间的唯一区别是Java有底和空。 Haskell没有后者,这很方便,因为我们不必检查空值!
换一种说法,因为底部是不可避免的(在图灵完全的世界中),那么除了邀请错误之外,还有什么可以让所有东西都是空的?
另外请注意,尽管Prelude中的某些函数由于历史原因而是部分函数,但现代Haskell风格倾向于几乎在任何地方编写总体函数,并且在函数中使用明确的Maybe
返回类型,例如head
,否则将会是部分函数。
我在评论中不敢恭维,我想sclv回答你的问题的第一部分,但是
如果所有的Haskell类型都包含一个模式匹配的Java-null-like值而不是底部,那么会丢失哪些有用的属性?
换句话说:为什么通过提升所有类型的空值来完成所有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
这个表达式应该明显导致异常,但是哪个异常? (+)
专用于整数在两个参数中都是严格的,所以这不会有帮助。 我们可以决定这是第一个价值,但总体而言我们会有
x + y =/= y + x
这会限制我们选择等式推理。 Haskell以不精确的行为提供了异常的概念,这很重要,因为该语言的纯粹部分具有完全精确的行为,并且可能是有限的。
链接地址: http://www.djcxy.com/p/1151.html上一篇: Why Haskell uses bottom instead of null in partial functions?