Haskell中的undefined和Java中的null有什么区别?

两者都是术语,其类型是所有类型的交集(无人居住)。 两者都可以在代码中传递,而不会失败,直到尝试评估它们为止。 我可以看到的唯一区别是,在Java中,有一个漏洞允许null对一个操作进行评估,这是一个引用相等比较( == ) - 而在Haskell中, undefined根本不能被评估而不会抛出一个例外。 这是唯一的区别吗?

编辑

我真正想要解决这个问题的是,为什么在Java中包含null这样一个显然很差的决定,以及Haskell如何逃避它? 在我看来,真正的问题是你可以用null做一些有用的事情,即你可以检查它是否为空。 因为您可以这样做,所以在代码中传递空值并使它们指示“无结果”而不是“此程序中存在逻辑错误”已成为标准约定。 而在Haskell中,没有办法检查一个术语是否评估到底,而没有对它进行评估和程序爆炸,所以它永远不能用于表示“无结果”。 相反,我们不得不使用像Maybe这样的东西。

很抱歉,如果看起来我在“评估”这个术语中玩得很快并且松动......我试图在这里作一个比喻,并且无法准确地说出它的措词。 我想这是一个类比不精确的迹象。


Haskell中的undefined和Java中的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如此有趣和富有表现力的一部分。 Haskell对懒惰的结果是特别关注bottom价值。

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

  • 将引用与null进行比较(尽管注意,不是null本身,这是明确定义的);
  • 被零除;
  • 越界例外;
  • 无限循环等
  • 你只是没有能力很容易地将一个底部替换成另一个底部,而Java编译器对底部值的推理并没有太多的理由。 但是,这样的价值在那里。

    综上所述,

  • 在Java中取消引用null值是一个在Java中产生最低值的特定表达式;
  • Haskell中undefined值是一个通用的底部收益表达式,可以在Haskell需要的最低值处使用。
  • 这就是他们的相似之处。

    后记

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

  • 首先,Java的null基本上等同于在Haskell中为每个类型a添加隐式Maybe a
  • 解引用null相当于仅用于Just案例的模式匹配: f (Just a) = ... a ...
  • 所以当传入的值为Nothing (在Haskell中)或null (在Java中)时,程序会达到未定义的状态。 这很糟糕:你的程序崩溃了。

    所以,通过为每种类型添加null ,您可以轻松创建bottom值 - 这些类型不再对您有所帮助。 你的语言不再帮助你防止那种特殊的错误,那很糟糕。

    当然,其他底部值仍然存在:异常( undefined )或无限循环。 为每个函数添加一个新的可能的失败模式 - 解引用null - 只是使编写崩溃的程序变得更容易。


    您的描述不完全正确。 你说null不能被评估。 然而,由于Java是一种热切的语言,这将意味着, f(null)将抛出一个NPE不管定义什么f是(因为该方法之前运行方法参数始终评估)。

    你可以在haskell中传递undefined的唯一原因是haskell是懒惰的,除非需要,否则不计算参数。

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

    在Java中, null是一个关键字。 如果没有null关键字,你将无法定义它(做相当于haskell定义,即Object myNull = throw(new Exception())不起作用,因为表达式将在那里被评估) 。

    链接地址: http://www.djcxy.com/p/7499.html

    上一篇: What's the difference between undefined in Haskell and null in Java?

    下一篇: In Haskell, why non