两者都是其类型是所有类型(无人居住)的交点的术语。两者都可以通过代码传递而不会失败,直到一次尝试评估它们。我唯一可以看到的是,在Java中,有一个漏洞 null 要精确地评估一个操作,这是参考平等比较(==) - 而在哈斯克尔 undefined 根本无法在没有抛出例外的情况下进行评估。这是唯一的区别吗?

编辑

我真正想解决这个问题的是,为什么包括 null 在Java中,这是一个明显不当的决定,Haskell如何逃脱它?在我看来,真正的问题是你可以做某事 有用null, ,即您可以检查 无效. 。因为允许您执行此操作,所以它已成为标准惯例,可以通过代码中的空值传递,并指示它们“不结果”,而不是“此程序中存在逻辑错误”。尽管在Haskell中,没有办法检查一个术语是否在不进行评估的情况下对底部进行评估,并且程序爆炸了,因此永远无法以这种方式使用它来指示“无结果”。相反,人们被迫使用类似的东西 Maybe.

对不起,如果我看上去像“评估”一词一样快速而宽松……我正在尝试在这里进行类比,并且难以精确地措辞。我想这是一个类比不精确的迹象。

有帮助吗?

解决方案

Java中Haskell和Null中未定义有什么区别?

好的,让我们备份一点。

Haskell中的“未定义”是“底部”值(表示为⊥)的示例。这样的值代表程序中任何未定义,卡住或部分状态。

存在许多不同形式的底部:非终止循环,异常,模式匹配失败 - 基本上是程序中未定义的任何状态。价值 undefined :: a 是将程序处于未定义状态的价值的规范示例。

undefined 本身并不是特别特别的 - 它不连接 - 您可以实施Haskell的 undefined 使用任何底部收益表达。例如,这是一个有效的实现 undefined:

 > undefined = undefined

或立即退出(旧的Gofer编译器使用此定义):

 > undefined | False = undefined

底部的主要属性是,如果表达式评估为底部,则整个程序将评估为底部:该程序处于未定义状态。

您为什么要这样的价值?好吧,用一种懒惰的语言,您通常可以操纵存储底部值的结构或功能,而无需程序本身。

例如,无限循环列表非常奇特:

 > 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如此有趣和表现力的一部分。懒惰的结果是哈斯克尔特别关注 bottom 值。

但是,很明显,底部的概念同样适用于Java或任何(非全部)语言。在Java中,有许多表达式产生“底部”值:

  • 将参考与null进行比较(尽管注意到,不是 null 本身,定义明确);
  • 被零除;
  • 外部异常;
  • 无限循环,等等。

您只是没有能力很容易地将一个底部替换为另一个底部,而Java编译器对底部值没有太大的作用。但是,此类值在那里。

总之,

  • 提出a null Java中的值是一种在Java中产生底值的特定表达式。
  • undefined Haskell中的值是一种通用的底部收益表达式,可以在任何地方使用Haskell中需要底部值。

他们就是这样类似的。

后记

关于问题 null 本身:为什么它被认为是不良形式?

  • 首先,爪哇的 null 本质上等同于 添加隐式 Maybe a 到每种类型 a 在哈斯克尔.
  • 提出 null 仅与图案匹配仅 Just 案子: f (Just a) = ... a ...

因此,当价值通过时是 Nothing (在Haskell)或 null (在Java中),您的程序达到了一个未定义的状态。这是不好的:您的程序崩溃了。

因此,通过添加 null每一个 类型,您只是使创建变得更加容易 bottom 价值观 - 类型不再帮助您。您的语言不再帮助您防止这种特殊的错误,这很糟糕。

当然,其他底部值仍然存在:异常(例如 undefined),或无限循环。在每个功能中添加新的可能的故障模式 - 删除 null - 只是使编写崩溃的程序变得更容易。

其他提示

您的描述不太正确。你是说 null 无法评估。但是,由于Java是一种渴望的语言,这意味着 f(null) 无论是什么定义,都会抛出NPE f IS(因为方法参数在方法运行之前始终进行评估)。

您可以传递的唯一原因 undefined 在没有例外的Haskell中,Haskell是懒惰的,除非需要,否则不会评估参数。

未定义和零之间的另一个区别是 undefined 是标准库中定义的简单值。如果标准库中未定义它,则可以自己定义它(通过编写 myUndefined = error "My Undefined 例如)。

在Java null 是关键字。如果没有 null 关键字,您将无法定义它(执行相当于Haskell定义,即 Object myNull = throw(new Exception()), ,由于表达式将在那里进行评估,因此行不通。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top