在Haskell中使用数据类型

时间:2012-09-09 21:38:06

标签: haskell typing subtyping

我已经开始这是一个新问题,因为它成为我上一个问题的后续内容。

如果我有两个由类似构造函数组成的数据类型:

data A = X | Y | Z
data B = X | Y

我无法以某种方式将其表示为:

data A = C | Z
data B = C

data C = X | Y

如果你能看到我在做什么 - 我正在尝试将X |分组Y为一种数据类型,然后可由多种其他数据类型使用。我似乎无法让编译器允许这个,或者如果它,我不能模式匹配X或Y,只有C ??

我收到多次声明C的错误消息。

我认为我可以使用类型,但它们不允许多种类型。

修改

即使我声明了很长的路(如下所示),它仍然无法编译,并说X和Y有多个声明:

data A = X | Y | Z
data B = X | Y

4 个答案:

答案 0 :(得分:13)

你不仅不能这样做,你也不能做你的第一个选择 - 即你不能在同一模块中有两种类型,它们都有名为XY的构造函数

如果您可以这样做,X的类型应该是什么?CAB?最明显的答案是C,但是您无法在需要AB的上下文中使用它(请注意,Haskell没有子类型) ,这将破坏整个结构的目的。

您可以做的最好的事情是将C包装在A和B的构造函数中,即:

data A = AC C | Z
data B = BC C
data C = X | Y

然后,您可以使用ACBC构造函数包装C,以分别创建类型AB的值。

答案 1 :(得分:4)

你不能这样做的原因

data A = X | Y | Z
data B = X | Y

如下。假设你稍后写了一些代码:

foo n = (n,X)

构建一对由第一个插槽中的n和第二个插槽中的X组成的对。编译器应该推断出什么类型?有效的类型是

foo :: a -> A -> (a,A)

因为XA类型的构造函数,但同样有效的是

foo :: a -> B -> (a,B)

因为XB类型的构造函数。如果有两个具有相同名称的构造函数,则无法推断使用它们的函数的唯一类型。因此,您不允许在同一模块中为两个构造函数提供相同的名称。

答案 2 :(得分:1)

你不能这样做:

data A = C | Z
data B = C

data C = X | Y

(顺便说一句,如果B 相同C,那么为什么要B?)

但你可以做的事情是这样的:

data A = A_Other C | Z
data B = B_Other C

data C = X | Y

然后你可以像这样模式匹配:

foo :: A -> String
foo (A_Other X) = "X"
foo (A_Other Y) = "Y"
foo (        Z) = "Z"

bar :: B -> String
bar (B_Other X) = "X"
bar (B_Other Y) = "Y"

foobar :: C -> String
foobar X = "X"
foobar Y = "Y"

如果这是有道理的......

答案 3 :(得分:0)

由于您要声明多个数据构造函数,因此无法执行您想要的操作。在

data A = X | Y | Z

您实际上是在引入类型A,其中包含3个构造函数(值)XYZ。这就是为什么你的第一段代码不能编译,它会看到同样的名称被列为两种不同类型的构造函数!如果你能做到这一点,你必须问自己是

X :: A

X :: B

在非面向对象的环境中是可怕的!因此,您需要提供不同的构造函数名称来共享基础数据C

如果您想要考虑这一点,您可以这样做,因为其他帖子在每个数据类型的唯一构造函数中都有建议和分解数据

data A = CForA C | Z
data B = CForB C

data C = X | Y