What’s the difference between undefined in Haskell and null in Java?
好吧,让我们再来一点。
Haskell中的“undefined”是“bottom”值(表示为⊥)的示例。这样的值表示程序中的任何未定义,卡住或部分状态。
许多不同形式的底层存在:非终止循环,异常,模式匹配失败 – 基本上程序中的任何状态在某种意义上是未定义的。值undefined :: a是一个将程序置于未定义状态的值的规范示例。
undefined本身并不是特别的 – 它没有接线 – 你可以使用任何底部产生表达式实现Haskell的未定义。例如。这是一个有效的未定义实现:
> undefined = undefined
或立即退出(旧的Gofer编译器使用此定义):
> undefined | False = undefined
底部的主要属性是,如果表达式求值为bottom,则整个程序将求值为bottom:程序处于未定义状态。
你为什么要这样的价值?那么,在懒惰的语言中,你经常可以操纵存储底值的结构或函数,而不是程序本身。
例如。无限循环的列表是完全cromulent:
> let xs = [ let f = f in f
, let g n = g (n+1) in g 0
]
> :t xs
xs :: [t]
> length xs
2
我只是不能做很多与列表的元素:
> head xs
^CInterrupted.
这种对无限东西的操作是Haskell为什么如此有趣和富有表现力的一部分。懒惰的结果是Haskell特别密切关注底部值。
然而,很明显,bottom的概念同样适用于Java或任何(非总体)语言。在Java中,有许多表达式产生“底部”值:
>比较一个引用和null(虽然注意,不是null本身,这是明确定义的);
>除以零;
>超出范围的例外;
>无限循环等
你只是没有能力替换一个底部的另一个很容易,Java编译器不做很多理由底值。然而,这样的值存在。
综上所述,
>解除引用Java中的空值是一种在Java中产生底值的特定表达式;
> Haskell中的未定义值是一个通用的底部表达式,可以在Haskell中需要底值的任何位置使用。
这就是它们的类似。
后记
至于null本身的问题:为什么它被认为是坏的形式?
>首先,Java的null本质上等同于向Haskell中的每个类型添加一个隐式Maybe a。
>解除引用null相当于只有Just情况的模式匹配:f(Just a)= … a …
因此,当传入的值为Nothing(在Haskell中)或null(在Java中)时,您的程序将达到未定义的状态。这是坏的:你的程序崩溃。
所以,通过为每个类型添加null,你只是使它更容易创建底部值意外 – 类型不再帮助你。你的语言不再帮助你防止这种特定的错误,这是坏的。
当然,其他底值仍然存在:异常(如未定义)或无限循环。为每个函数添加一个新的可能失败模式 – 解除引用null – 只是使编写程序崩溃变得更容易。