Haskell sum类型多重声明错误


data A=A
data B=B
data AB=A|B

使得a和b的和类型为AB

但是最后一行会导致编译错误"multiple declarations of B"

我也试过这样做:

data A=Int|Bool

它编译。但是为什么GHC不允许我为用户定义的类型制作sum类型?

你被骗了。当你写data A=Int|Bool的时候你认为你在说一个类型为A的值可以是一个类型为Int的值或者是一个类型为Bool的值;但是你实际上说的是有两个新的值级构造函数命名为IntBool,每个都不包含类型为A的信息。同样,您认为data AB=A|B表示您可以是类型A或类型B,但实际上您说您可以具有 A B

要记住的关键是有两个名称空间,类型级和术语级,它们是不同的。

这里有一个简单的例子来说明如何正确使用:

data A=A
data B=B
data AB=L A|R B

最后一行声明了两个新的术语级构造函数LRL构造函数携带一个类型 A的值,而R构造函数携带一个类型 B的值。

您可能还喜欢Either类型,定义如下:

data Either a b = Left a | Right b

你可以用它来实现你的AB,如果你想:

type AB = Either A B

同样,您可以使用Either Int Bool作为IntBool的标记联合。

当您说data AB = A | B时,您不是指类型 AB,而是定义数据构造器 AB。这些函数与前几行定义的构造函数冲突。

如果你想创建一个类型AB,它是AB的和,你必须提供包含AB类型的数据构造函数,例如:

data AB = ABA A | ABB B

因为使用数据构造函数AB创建的值的类型将是不明确的。例如,当我有a = B时,a是什么类型?是A还是AB ?

应该考虑使用不同的数据构造函数,如下所示:

data A = MkA
data B = MkB
data AB = A A | B B

Sum类型必须被标记。a+a必须从a进行两次注射

要理解代数数据类型是如何工作的,举一个简单的例子:
data X = A | B C

定义了一个新的类型构造函数X,以及数据构造函数ABB构造函数接受/保存一个c类型的实参。

Haskell的主要规范和类型是Either:

data Either a b = Left a | Right b

相关内容

最新更新