代码之家  ›  专栏  ›  技术社区  ›  Tom Crockett

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

  •  50
  • Tom Crockett  · 技术社区  · 14 年前

    null 只计算一个操作,即引用相等比较( == undefined 在不引发异常的情况下根本无法计算。这是唯一的区别吗?

    编辑

    我想问的是,为什么 在Java中,这显然是一个糟糕的决定,Haskell是如何逃脱的呢?在我看来,真正的问题是你能做点什么 有用的 具有 ,也就是说你可以检查它 . 因为允许这样做,所以在代码中传递空值并让它们指示“没有结果”而不是“程序中有逻辑错误”已成为标准约定。然而,在Haskell中,如果一个术语的计算结果是bottom而没有对它进行计算,程序就会爆炸,那么就无法用它来表示“没有结果”。相反,人们被迫使用 Maybe .

    抱歉,如果我好像在玩弄“评估”这个词。。。我试着在这里做个类比,却很难准确地表达出来。我想这说明这个类比是不精确的。

    2 回复  |  直到 13 年前
        1
  •  74
  •   Don Stewart    14 年前

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

    好吧,让我们退后一点。

    Haskell中的“undefined”是“bottom”值(表示)的一个例子。这样的值表示程序中任何未定义、卡住或部分状态。

    undefined :: a 是将程序置于未定义状态的值的规范示例。

    undefined 它本身并不是特别的——它没有连接进来——而且您可以实现Haskell的 未定义 使用任何底部屈服表达式。E、 g.这是 未定义 :

     > undefined = undefined
    

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

     > undefined | False = undefined
    

    你为什么想要这样的价值?好吧,在一种懒惰的语言中,你经常可以操作存储底层值的结构或函数,而程序本身并不是底层的。

    E、 无限循环的列表是非常复杂的:

     > 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.
    

    这种对无限事物的操控是哈斯克尔如此有趣和富有表现力的部分原因。懒惰的结果是哈斯克尔特别关注 bottom 价值观。

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

    • 将引用与null进行比较(尽管注意,不是 null 本身,定义明确);
    • 越界例外;
    • 无限循环等。

    您只是没有能力很容易地用一个底值替换另一个底值,而Java编译器也没有做很多关于底值的推理工作。然而,这样的价值观是存在的。

    总之,

    • 解引用 无效的 Java中的值是一个特定的表达式,它在Java中产生一个底值;
    • 未定义 Haskell中的value是一个通用的底部生成表达式,可以在Haskell中需要底部值的任何地方使用。

    这就是他们的相似之处。

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

    • 首先,Java的 无效的 本质上等同于 Maybe a 每种类型 a .
    • 解引用 无效的 仅对 Just f (Just a) = ... a ...

    所以当传入的值是 Nothing (在哈斯克尔),或 (在Java中),程序达到未定义状态。这很糟糕:你的程序崩溃了。

    所以,通过添加 无效的 每一个 输入,你只是让它更容易创建 底部 值是偶然的——类型不再帮助您。你的语言不再帮助你防止那种特殊的错误,那是很糟糕的。

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

        2
  •  7
  •   sepp2k    14 年前

    null 无法评估。然而,由于java是一种迫切需要的语言,这意味着 f(null) 不管什么定义 f 是(因为方法参数总是在方法运行之前求值)。

    你可以到处转悠的唯一原因 undefined 在haskell中,没有异常的是haskell很懒,除非需要,否则不会计算参数。

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

    在Java中 是一个关键字。如果没有 无效的 关键字,您将无法定义它(执行与haskell定义等效的操作,即。 Object myNull = throw(new Exception())