Haskell 哈斯克尔:有没有像Java中的'null'这样的各种类型的对象?

Haskell 哈斯克尔:有没有像Java中的'null'这样的各种类型的对象?,haskell,Haskell,在Java中,除了一点例外,null是所有类型的。Haskell中有类似的对象吗?简短回答:没有 有了它就不太安全了。也许你可以为你的问题提供更多的信息,以了解你想要实现的目标 编辑:丹尼尔·瓦格纳是对的。无限循环可以是任何类型。简短回答:否 有了它就不太安全了。也许你可以为你的问题提供更多的信息,以了解你想要实现的目标 编辑:丹尼尔·瓦格纳是对的。无限循环可以是任何类型。简短回答:是 与任何合理的图灵完备语言一样,无限循环可以被赋予任何类型: loop :: a loop = loop 这很

在Java中,除了一点例外,null是所有类型的。Haskell中有类似的对象吗?

简短回答:没有

有了它就不太安全了。也许你可以为你的问题提供更多的信息,以了解你想要实现的目标

编辑:丹尼尔·瓦格纳是对的。无限循环可以是任何类型。

简短回答:否

有了它就不太安全了。也许你可以为你的问题提供更多的信息,以了解你想要实现的目标

编辑:丹尼尔·瓦格纳是对的。无限循环可以是任何类型。

简短回答:是

与任何合理的图灵完备语言一样,无限循环可以被赋予任何类型:

loop :: a
loop = loop
这很好,或者可能偶尔有用,作为尚未实现的功能的临时占位符,或者作为向读者发出的信号,我们处于一个死分支中,原因过于繁琐,无法向编译器解释。但它的使用方式与Java代码中通常使用null的方式完全不同

通常情况下,当这是一件明智的事情时,人们会使用

Nothing :: Maybe a
虽然它不可能是任何类型,但也可能是缺少任何类型。

简短回答:是的

与任何合理的图灵完备语言一样,无限循环可以被赋予任何类型:

loop :: a
loop = loop
这很好,或者可能偶尔有用,作为尚未实现的功能的临时占位符,或者作为向读者发出的信号,我们处于一个死分支中,原因过于繁琐,无法向编译器解释。但它的使用方式与Java代码中通常使用null的方式完全不同

通常情况下,当这是一件明智的事情时,人们会使用

Nothing :: Maybe a

虽然它不可能是任何类型,但也可能是缺少任何类型。

存在于Haskell的每种类型中。它可以在GHC中显式地写为未定义。

存在于Haskell中的每种类型中。它可以在GHC中明确地写为未定义。

技术上是的,正如Daniel Wagner的回答所述

然而,我认为可以用于每种类型的值和像Java的null这样的值实际上是非常不同的需求。哈斯克尔没有后者。我认为这是一件好事,正如托尼·霍尔(Tony Hoare)所做的那样,他曾著名地称自己发明了空引用

类似Java的null没有属性,只是可以检查给定引用是否等于它。您对它提出的任何其他要求都会在运行时爆炸

Haskell undefined或error my bad,或让x=x in x,或fromJust Nothing,或任何获取它的无限方式都没有任何属性。您对它的任何请求都将在运行时爆炸,包括是否有任何给定值等于它

这是一个关键的区别,因为它使它几乎没有用处,因为它缺少一个值。如果thing==null{do_stuff_withthing;}或者{do_stuff_withthing;}在Haskell中使用undefined代替null,那么就不可能实现与if thing==null{do_stuff_withthing;}等价的操作。唯一可以安全地处理可能未定义值的代码是根本不检查该值的代码,因此只有在知道未定义值不会以任何方式使用时,才能安全地将其传递给其他代码1

由于我们不能进行空指针检查,在Haskell代码中,当我们表示存在类型t的值时,我们几乎总是使用一些类型t作为参数、变量和返回类型,当我们表示可能存在或不存在类型t的值时,我们可能使用T2

因此Haskeller在Java程序员使用null时没有使用任何东西,但是在实践中没有任何东西与Haskell版本的每种类型的值有很大的不同。没有什么不能用在每种类型上,只有Maybe类型-但是每种类型都有Maybe版本。T和Maybe T之间的类型区别意味着,当您需要处理可能缺少值3等情况时,从类型中可以清楚地看出您是否可以省略值。在Java中,您依赖正确的文档来获得这些知识

1懒惰确实意味着在任何情况下都不会被检查,这比在像Java这样的严格语言中要多得多,因此可能是或可能不是底部值的子表达式并不少见。但即使是它们的使用也与Java关于可能为null的值的习惯用法大不相同

2 Maybe是一种数据类型,定义为data Maybe a=Nothing | Just a,无论Nothing构造函数是否不包含其他信息,Just构造函数是否只存储类型a的单个值。因此,对于给定的类型T,可能T向基类型T添加了一个额外的可能不存在的特性,而没有其他特性

3和Haskell版本的处理可能缺失通常使用组合符,如maybe或fromMaybe,或模式匹配,所有这些都比if thing==null有优势,因为compi
ler知道代码的哪个部分正在处理丢失的值,哪个部分正在处理该值。

技术上是的,正如Daniel Wagner的回答所述

然而,我认为可以用于每种类型的值和像Java的null这样的值实际上是非常不同的需求。哈斯克尔没有后者。我认为这是一件好事,正如托尼·霍尔(Tony Hoare)所做的那样,他曾著名地称自己发明了空引用

类似Java的null没有属性,只是可以检查给定引用是否等于它。您对它提出的任何其他要求都会在运行时爆炸

Haskell undefined或error my bad,或让x=x in x,或fromJust Nothing,或任何获取它的无限方式都没有任何属性。您对它的任何请求都将在运行时爆炸,包括是否有任何给定值等于它

这是一个关键的区别,因为它使它几乎没有用处,因为它缺少一个值。如果thing==null{do_stuff_withthing;}或者{do_stuff_withthing;}在Haskell中使用undefined代替null,那么就不可能实现与if thing==null{do_stuff_withthing;}等价的操作。唯一可以安全地处理可能未定义值的代码是根本不检查该值的代码,因此只有在知道未定义值不会以任何方式使用时,才能安全地将其传递给其他代码1

由于我们不能进行空指针检查,在Haskell代码中,当我们表示存在类型t的值时,我们几乎总是使用一些类型t作为参数、变量和返回类型,当我们表示可能存在或不存在类型t的值时,我们可能使用T2

因此Haskeller在Java程序员使用null时没有使用任何东西,但是在实践中没有任何东西与Haskell版本的每种类型的值有很大的不同。没有什么不能用在每种类型上,只有Maybe类型-但是每种类型都有Maybe版本。T和Maybe T之间的类型区别意味着,当您需要处理可能缺少值3等情况时,从类型中可以清楚地看出您是否可以省略值。在Java中,您依赖正确的文档来获得这些知识

1懒惰确实意味着在任何情况下都不会被检查,这比在像Java这样的严格语言中要多得多,因此可能是或可能不是底部值的子表达式并不少见。但即使是它们的使用也与Java关于可能为null的值的习惯用法大不相同

2 Maybe是一种数据类型,定义为data Maybe a=Nothing | Just a,无论Nothing构造函数是否不包含其他信息,Just构造函数是否只存储类型a的单个值。因此,对于给定的类型T,可能T向基类型T添加了一个额外的可能不存在的特性,而没有其他特性

3和Haskell版本的处理可能缺失通常使用组合符,如maybe或fromMaybe,或模式匹配,所有这些都比if thing==null有优势,编译器知道代码的哪个部分在处理缺失值,哪个部分在处理值。

简短回答:是的。但也不是

诚然,一个无限循环(又称未定义循环)存在于每种类型中,在中是相同的,这是事实,但正如流行的论文中所展示的那样,对程序进行推理,就好像这些值不存在一样,通常就足够了。

简短回答:是的。但也不是


虽然每个类型中都有一个相同的无限循环(又称未定义循环)是真的,但正如流行的论文所展示的那样,对程序进行推理,就好像这些值不存在一样,这通常就足够了。

我不同意这个问题的几乎所有其他答案

loop :: a
loop = loop
不定义任何类型的值。它甚至没有定义一个值

loop :: a
是返回类型为a的值的承诺

是一个无止境的循环,所以诺言被打破了。因为循环根本不会返回,所以它不会返回类型为a的值。因此,即使从技术上讲,Haskell中也没有空值

最接近null的是使用Maybe。也许你什么都没有,这在很多情况下都会用到。它也更加明确

类似的参数可用于未定义的。当您在非严格设置中使用undefined时,您只有一个thunk,它将在评估后立即抛出错误。但它永远不会给你承诺类型的价值

Haskell有一个底部类型,因为它是不可避免的。由于停止问题,您永远无法证明函数将实际返回,因此总是有可能违背承诺。仅仅因为有人答应给你100美元,并不意味着你会得到它。他总是说我没有具体说明你什么时候能拿到钱,或者只是拒绝遵守诺言。这个承诺甚至不能证明他有这笔钱,或者当被问及此事时,他能够提供这笔钱

苹果世界的一个例子

目标C有一个空值,它被称为nil。新的
r Swift语言切换为可选类型,其中可选。也许是因为哈斯克尔是雨燕队的榜样之一

我不同意这个问题的几乎所有其他答案

loop :: a
loop = loop
不定义任何类型的值。它甚至没有定义一个值

loop :: a
是返回类型为a的值的承诺

是一个无止境的循环,所以诺言被打破了。因为循环根本不会返回,所以它不会返回类型为a的值。因此,即使从技术上讲,Haskell中也没有空值

最接近null的是使用Maybe。也许你什么都没有,这在很多情况下都会用到。它也更加明确

类似的参数可用于未定义的。当您在非严格设置中使用undefined时,您只有一个thunk,它将在评估后立即抛出错误。但它永远不会给你承诺类型的价值

Haskell有一个底部类型,因为它是不可避免的。由于停止问题,您永远无法证明函数将实际返回,因此总是有可能违背承诺。仅仅因为有人答应给你100美元,并不意味着你会得到它。他总是说我没有具体说明你什么时候能拿到钱,或者只是拒绝遵守诺言。这个承诺甚至不能证明他有这笔钱,或者当被问及此事时,他能够提供这笔钱

苹果世界的一个例子


目标C有一个空值,它被称为nil。较新的Swift语言切换为可选类型,其中可选。也许是因为哈斯克尔是雨燕队的榜样之一

谢谢,我想这基本上回答了我的问题——除了理解哈斯克尔,我并不是真的想完成任何事情。我遇到了这些函数的非类型化类型声明,比如myFunc::a->a。在不知道a是什么的情况下,似乎没有多少函数可以使用这种类型声明。对于myFunc::a->b的类型声明,似乎没有任何对象可以具有这种类型,除非存在每种类型的对象。类型A->b的函数不能在haskell中完成。除非它真的发生了。Unsafeceorce正好有这个类型,但我们并没有真正使用它,正如您可以证明不应该有类型a->b的函数一样,您也可以证明应该只有一个类型a->a的函数作为标识函数。有关此的更多信息,这个属性允许我们证明类型a->a的唯一功能是类型的标识和许多其他有用的东西!被称为,这给了你所谓的。这些定理也来自范畴论。这里有很深的东西@补充汉克斯,我想这基本上回答了我的问题——除了理解哈斯克尔,我并不是真的想完成任何事情。我遇到了这些函数的非类型化类型声明,比如myFunc::a->a。在不知道a是什么的情况下,似乎没有多少函数可以使用这种类型声明。对于myFunc::a->b的类型声明,似乎没有任何对象可以具有这种类型,除非存在每种类型的对象。类型A->b的函数不能在haskell中完成。除非它真的发生了。Unsafeceorce正好有这个类型,但我们并没有真正使用它,正如您可以证明不应该有类型a->b的函数一样,您也可以证明应该只有一个类型a->a的函数作为标识函数。有关此的更多信息,这个属性允许我们证明类型a->a的唯一功能是类型的标识和许多其他有用的东西!被称为,这给了你所谓的。这些定理也来自范畴论。这里有很深的东西@Addem@user2864740你能详细说明一下吗?你是赞成还是反对?如果你反对,你特别反对什么?我认为用户2864740只是对你的答案中使用“任何”一词而不是“每个”一词有点小题大做。“吹毛求疵的语义学,”嗯,也许是吧。不过,我相信我是相当小心的。尽管无限循环可以被赋予一个对应于Haskell中每种类型的类型,但并非所有合理的图灵完备语言都具有这样做所必需的多态性。但即使在没有a语言类型的语言中。a、 你通常可以构造任何具体类型的无限循环。该死的图灵完全语言。你在那里抓住我了。已经有一段时间没有加入Haskell了,现在我想起了我讨厌它的地方:实际上,更深入一点:我们可以从一个空中构造任何类型。无限循环只是其中的一个例子。函数rubic::Void->a显示了这有多荒谬。@user2864740您能详细说明一下吗?你是赞成还是反对?如果你反对,你特别反对什么?我认为用户2864740只是对你的答案中使用“任何”一词而不是“每个”一词有点小题大做。“吹毛求疵的语义学,”嗯,也许是吧。然而,我相信我是相当

仔细的尽管无限循环可以被赋予一个对应于Haskell中每种类型的类型,但并非所有合理的图灵完备语言都具有这样做所必需的多态性。但即使在没有a语言类型的语言中。a、 你通常可以构造任何具体类型的无限循环。该死的图灵完全语言。你在那里抓住我了。已经有一段时间没有加入Haskell了,现在我想起了我讨厌它的地方:实际上,更深入一点:我们可以从一个空中构造任何类型。无限循环只是其中的一个例子。函数荒谬::Void->a显示了这是多么荒谬。我认为真正的错误是缺少对副产品的直接支持;包含其组成部分之一的复合类型。结构、类等为产品类型提供了直接的支持,即复合类型包含其所有组成部分,但不包含其自然对偶。没有副产品,如果没有null之类的东西,就很难过日子,除非你积累了足够多的其他特性,最终可以模拟副产品;你确实需要这样的选择。当你有了副产品,你就可以做一些事情,比如在库代码中。@WillNess当然是这样。它也不像Java做的那样干净,至少上次我用它时没有这么干净。@DanielWagner感谢您的确认。实际上,我在考虑C/C++及其结构、类、联合和yes空指针。的确,标记的并集不是C语言中的一个语言构造,但它非常接近它…@Willence绝对标记的并集是副产品。我可以讨论C风格的联合是否算作对副产品的直接支持,因为您必须手动管理标记。在处理缺失值方面,它们实际上并不比空指针更有吸引力。但是,C语言也不是一种真正有意义的语言,在这种语言中,谈论一个假设的版本,它有corproducts而不是nulls;在这个层次上,你无法摆脱无效指针的概念。我认为真正的错误是缺乏对副产品的直接支持;包含其组成部分之一的复合类型。结构、类等为产品类型提供了直接的支持,即复合类型包含其所有组成部分,但不包含其自然对偶。没有副产品,如果没有null之类的东西,就很难过日子,除非你积累了足够多的其他特性,最终可以模拟副产品;你确实需要这样的选择。当你有了副产品,你就可以做一些事情,比如在库代码中。@WillNess当然是这样。它也不像Java做的那样干净,至少上次我用它时没有这么干净。@DanielWagner感谢您的确认。实际上,我在考虑C/C++及其结构、类、联合和yes空指针。的确,标记的并集不是C语言中的一个语言构造,但它非常接近它…@Willence绝对标记的并集是副产品。我可以讨论C风格的联合是否算作对副产品的直接支持,因为您必须手动管理标记。在处理缺失值方面,它们实际上并不比空指针更有吸引力。但是,C语言也不是一种真正有意义的语言,在这种语言中,谈论一个假设的版本,它有corproducts而不是nulls;在那个级别,你无法摆脱无效指针的概念。Bottom不是一个类型。Void是Bottom。@uwap ugh。context.Bottom不是类型。Void是Bottom。@uwap ugh。背景。我觉得自己像个小丑,喜欢看着世界燃烧,因为我的小问题让每个人都陷入了一场圣战我觉得自己像个小丑,喜欢看着世界燃烧,因为我的小问题让每个人都陷入了一场圣战