在Java中,null
是每种类型,但有一点例外。在Haskell中是否有类似的对象?
答案 0 :(得分:11)
简短答案:是
如同任何明智的图灵完备语言一样,无限循环可以指定为任何类型:
loop :: a
loop = loop
这个(好吧,this,或者也许是this)有时可用作暂时性的占位符,用于尚未实现的功能,或者作为信号通知读者我们由于某种原因而处于死枝太繁琐而无法向编译器解释。但通常根本不像Java代码中通常使用null
的方式那样使用它。
通常,当这是一件明智的事情时,它就表示缺少值,而是使用
Nothing :: Maybe a
虽然根本不能是任何类型,但可能根本没有任何类型。
答案 1 :(得分:8)
从技术上讲是肯定的,正如丹尼尔·瓦格纳(Daniel Wagner)的回答所述。
但是,我认为“可以用于每种类型的值”和“像Java的null
之类的值”实际上是非常不同的要求。 Haskell没有后者。我认为这是一件好事(托尼·霍尔(Tony Hoare)也是这样,他曾著名地将他的null引用的发明称为billion-dollar mistake)。
类似Java的null
没有属性除了,您可以检查给定引用是否等于它。您要求的其他任何内容都将在运行时爆炸。
Haskell undefined
(或error "my bad"
或let x = x in x
或fromJust Nothing
,或任何无限的获取方式)根本没有属性。您要求的所有内容都会在运行时爆炸,包括包括的任何给定值是否等于它。
这是一个至关重要的区别,因为它使它作为“缺失”值几乎毫无用处。在Haskell中,无法使用if (thing == null) { do_stuff_without_thing(); } else { do_stuff_with(thing); }
来代替undefined
来进行null
的等效操作。唯一可以安全处理可能未定义的值的代码是根本不会检查该值的代码,因此,当您只能安全地 pass undefined
传递给其他代码知道它将不会以任何方式使用 1 。
由于我们无法执行“空指针检查”,因此在Haskell代码中,我们几乎总是使用T
类型(用于参数,变量和返回类型)来表示将会 >是类型T
的值,当我们表示可能存在或可能不存在类型Maybe T
的值时,我们使用T
2 。>
因此Haskellers在Java程序员使用Nothing
的地方大致使用null
,但是实际上,Nothing
与Haskell的每种类型的值都有很大的不同。 Nothing
不能用于每种类型,只能用于“ Maybe
种类型”-但是每种类型都有一个“ Maybe
版本”。 T
和Maybe T
之间的类型区别意味着从类型上可以清楚地知道是否可以省略值,何时需要处理可能缺少值的 3 等。在Java中,您依靠正确的(正确的)文档来获取这些知识。
1 懒惰确实意味着“根本不会受到检查”的情况比像Java这样的严格语言中出现的情况要多得多,因此可能不是底值的子表达式并不少见。但是,即使它们的使用也与Java的习惯用法(可能是null
的用法)完全不同。
2 Maybe
是定义为data Maybe a = Nothing | Just a
的数据类型,无论Nothing
构造函数是否不包含其他信息以及Just
构造函数仅存储类型为a
的单个值。因此,对于给定类型T
,Maybe T
添加了附加的“可能不存在”功能,而对基本类型T
则没有其他作用。
3 并且处理可能的缺失的Haskell版本通常使用诸如maybe
或fromMaybe
之类的组合器或模式匹配,所有这些组合器都比{{1 }},编译器知道代码的哪一部分正在处理缺失值,哪一部分正在处理该值。
答案 2 :(得分:2)
简短答案:否
拥有它并不是非常安全的类型。也许您可以为问题提供更多信息,以了解您要完成的任务。
编辑:Daniel Wagner是正确的。无限循环可以是每种类型。
答案 3 :(得分:2)
简短答案:是。但也没有。
虽然确实存在无限循环,也就是undefined
(在denotational semantics中是相同的)存在于每种类型中,但通常就足以对程序进行推理,就好像这些值不存在一样,如流行论文Fast and Loose Reasoning is Morally Correct所示。
答案 4 :(得分:0)
Bottom居住在Haskell中的每种类型。可以在GHC中将其明确表示为undefined
。
答案 5 :(得分:0)
我几乎不同意这个问题的其他答案。
loop :: a
loop = loop
不定义任何类型的值。它甚至没有定义值。
loop :: a
是 promise ,它返回类型为a
的值。
loop = loop
是一个无休止的循环,所以承诺破灭了。由于loop
根本不会返回,因此也就不会返回类型a
的值。因此,即使在技术上也没有,Haskell中没有null
值。
最接近null
的地方是使用Maybe
。使用Maybe
,您拥有Nothing
,这在许多情况下都可以使用。它也更加明确。
类似的参数可以用于undefined
。在非严格设置中使用undefined
时,您只会遇到一个thunk,该thunk将在评估后立即抛出错误。但这绝对不会给您所承诺类型的价值。
Haskell具有底部类型,因为它是不可避免的。由于停顿问题,您永远无法证明一个函数实际上将完全返回,因此始终有可能违反承诺。仅仅因为有人答应给您100美元,并不意味着您实际上会得到它。他总是可以说“我没有指定何时您会得到这笔钱”,或者只是拒绝遵守诺言。诺言甚至不能证明他有钱,或者在被问到钱时就能够提供。
一个来自苹果世界的例子。
目标C的值为null
,它被称为nil
。较新的Swift语言已切换为Optional
类型,其中Optional<a>
可以缩写为a?
。它的行为与Haskells Maybe
monad完全一样。他们为什么这么做?可能是因为Tony Hoare's apology。也许是因为Haskell是Swifts的榜样之一。