6

我已经开始了这个新问题,因为它是我之前问题的后续问题。

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

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

4 回答 4

13

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

如果你能做到这一点,应该X是 -或的类型?最明显的答案是,但是您将无法在需要 a或 a的上下文中使用它(请注意,Haskell 没有子类型),因此这会破坏整个构造的目的。CABCAB

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

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

AC然后你可以用或构造函数包装一个 CBC来分别创建一个A或类型的值B

于 2012-09-09T21:44:52.050 回答
4

你不能这样做的原因

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

如下。假设您稍后编写一些代码:

foo n = (n,X)

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

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

sinceX是 type 的构造函数A,但同样有效的是

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

因为X是类型的构造函数B。如果您有两个同名的构造函数,则无法为使用它们的函数推断出唯一类型。所以你不能给同一个模块中的两个构造函数同名。

于 2012-09-10T07:56:52.233 回答
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"

如果这有意义...

于 2012-09-10T11:38:24.610 回答
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
于 2012-09-10T20:16:59.290 回答