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
的值;但是你实际上说的是有两个新的值级构造函数命名为Int
和Bool
,每个都不包含类型为A
的信息。同样,您认为data AB=A|B
表示您可以是类型A
或类型B
,但实际上您说您可以具有值 A
或值 B
。
要记住的关键是有两个名称空间,类型级和术语级,它们是不同的。
这里有一个简单的例子来说明如何正确使用:
data A=A
data B=B
data AB=L A|R B
最后一行声明了两个新的术语级构造函数L
和R
。L
构造函数携带一个类型 A
的值,而R
构造函数携带一个类型 B
的值。
您可能还喜欢Either
类型,定义如下:
data Either a b = Left a | Right b
你可以用它来实现你的AB
,如果你想:
type AB = Either A B
同样,您可以使用Either Int Bool
作为Int
和Bool
的标记联合。
当您说data AB = A | B
时,您不是指类型 A
和B
,而是定义数据构造器 A
和B
。这些函数与前几行定义的构造函数冲突。
如果你想创建一个类型AB
,它是A
和B
的和,你必须提供包含A
和B
类型的数据构造函数,例如:
data AB = ABA A | ABB B
因为使用数据构造函数A
或B
创建的值的类型将是不明确的。例如,当我有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
,以及数据构造函数A
和B
。B
构造函数接受/保存一个c类型的实参。
Haskell的主要规范和类型是Either
:
data Either a b = Left a | Right b