总和类型-为什么在Haskell中show(Int | Double)与`(show Int)|不同?(显示双)`


9

为什么这些不相等?

show $ if someCondition then someInt else some double

if someCondition then show someInt else show someDouble

我了解,如果您将if ... else第一个示例中的部分本身与一个表达式隔离开,那么您就无法用匿名和类型来表示其类型Int | Double,就像您可以在TypeScript中轻松进行的操作(提及TypeScript,因为它是我经常使用的语言,该语言支持Sum类型),因此必须诉诸使用Either数据,然后再基于调用show

我在这里给出的示例很简单,但对我来说,认为“好吧,我们将要显示某些东西,而某些东西取决于someCondition”,而不是“好吧,如果someCondition为true,则显示someInt,否则显示someDouble”,并且也允许减少代码重复(此处的显示重复了两次,但它也可能是一个长函数的应用程序,而不是if ... else可能要考虑的> 2个分支)

在我看来,对于编译器而言,检查构成求和类型的每种类型(在此处Int | Double)是否可以用作show函数的参数并确定类型是否正确应该很容易。更好的是,无论参数的类型如何,show函数总是会返回string,因此编译器不必随身携带所有可能的“分支”(因此所有可能的类型)。

是否选择不存在这样的功能?还是我认为实施起来更加困难?


2
一个if ... then ... else ...thenelse部分必须具有相同的类型。在某些编程语言中,您可以将其视为三元运算符。
Willem Van Onsem

1
我同意making all conversions explicit。在我的问题中,我不希望Haskell将a转换Int为a Double,反之亦然。我仅以这两种类型为例。你可以每天更换IntaDoubleb我的问题,其中两种类型的派生Show。我知道anonymous sum typesHaskell 中没有这种语言,但是我想知道为什么会这样,是什么使我们无法设计具有这种语言的语言。
Mehdi Saffar,

4
我认为这类类型称为联合类型。sum类型本质上是并集类型的带标记变体,其中每个值都必须带有超出内部类型值的left / right标记。我希望很难实现具有联合类型的类型推断以及Haskell的所有类型级别的功能。如果x :: Int | Bool并且我们必须进行编译show x,则没有简单的方法来知道show在基于类型擦除的RTS中使用哪个指针指向函数。我们可能需要在运行时保留一些类型级别的信息。

1
Haskell设计师的设计决定是不具有匿名和类型。我不太确定他们会带来什么样的好处,我确实知道他们会使事情复杂化。因此,我的猜测是它们不存在,因为成本/收益比不存在。但是要绝对确定,您需要询问原始语言的设计者和/或当前的维护者。我认为这不会成为一个很好的SO问题,因为在设计语言时会涉及很多个人见解和喜好。
n。代词

4
(String, Int)不是匿名的。它只是具有有趣语法的常规产品类型。(String | Int)将会有很大的不同。首先问自己是否(Int|Int)应该相同Int以及为什么相同。
n。代词

Answers:


8

表达式的所有部分都必须正确键入。的类型if someCondition then someInt else someDouble必须类似exists a. Show a => a,但是Haskell不支持这种存在性量化。

更新:正如chi在评论中指出的那样,如果Haskell支持联合/交叉类型(与求和/乘积类型不同),这也是可能的,但不幸的是,它不是。


您能否详细说明联合/交叉类型与总和/乘积类型之间的区别?我一直以为他们是一样的,除了匿名?
Mehdi Saffar,

1
@MehdiSaffar匿名(未标记),而不是未命名的构造函数。换句话说,如果您有一个Int ∪ Double,那么您将知道自己是两者中的一个,但无法进行模式匹配以查看哪个,因此您只能针对这两种可能性进行有效的处理。
约瑟夫·西布尔-恢复莫妮卡

2
为了清楚起见,TypeScript在运行时提供了类型信息,因此它具有一个typeof运算符,该运算符可以弥补标记的不足,并查看仍然使用哪种类型。Haskell已完全擦除了类型,因此,如果它支持此功能,那么将没有与之等效的功能。
约瑟夫·西布尔-恢复莫妮卡

7

(,)在Haskell中有使用轻量级语法编写的产品类型。一个带有轻量级语法的sum类型(例如(Int | String))将是一个好主意。现实更加复杂。让我们看看为什么(我对拥有一些自由Num,它们并不重要)。

if someCondition then 42 else "helloWorld"

如果这将返回类型为的值(Int | String),那么以下内容应返回什么?

if someCondition then 42 else 0

(Int | Int)显然,但是如果这与普通的有所不同,Int那么我们将陷入严重困境。因此(Int | Int)应该与普通相同Int

可以立即看到,这不仅是求和类型的轻量级语法,而且是一种全新的语言功能。如果愿意,可以使用另一种类型的类型系统。我们应该有一个吗?

让我们看一下这个函数。

mysteryType x a b = if x then a else b

现在有什么类型mysteryType?明显

mysteryType :: Bool -> a -> b -> (a|b)

对?现在,如果ab属于同一类型怎么办?

let x = mysteryType True 42 0

Int正如我们先前所同意的,这应该是简单的。现在mysteryType,根据您传递的参数,有时返回匿名和类型,有时则不返回。您如何模式匹配这样的表达式?你到底能做什么?除了琐碎的事情,例如“ show”(或其他类型类的任何方法,它将是其实例),不是很多。除非您将运行时类型信息添加到该语言中,否则它typeof是可用的,这会使Haskell成为一门完全不同的语言。

嗯是的。为什么Haskell没有TypeScript?因为我们不需要另一个TypeScript。如果需要TypeScript,则知道在哪里可以找到它。


1
@MichaWiedenmann坦白说,我不知道“相关”是否正确。我认为这在某种程度上是有帮助的。是的,我确实停了一会儿,想一想是否将其包括在内。但是我知道有时候是错的。
n。代词

没问题,您可以决定。
米查·维登曼

那你的代词是什么?
dfeuer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.