【问题标题】:multiple declaration errors of algebraic data type代数数据类型的多个声明错误
【发布时间】:2015-09-13 16:15:55
【问题描述】:

一些代数数据类型..

data Cell0=Cell0 {c0str::Text,c0uid::Uid}
           deriving (Data,Typeable,Show)
data Cell1=Cell1 {c1start::Uid,c1end::Uid,c1str::Text,c1uid::Int}
           deriving (Data,Typeable,Show)
data Cell2=Cell2 {c2start::Uid,c2end::Uid,c2str::Text,c2uid::Int}
           deriving (Data,Typeable,Show)
data Acell=Cell0|Cell1

但最后一行导致编译错误“Cell0 的多个声明”

我也试过这样的:

data A=Aasdfdsf {sdf::Text}
      deriving (Data,Typeable,Show)
data B=Bsdfsd
data AB=A|B

它编译!好奇怪。。

【问题讨论】:

  • data Cell0 = Cell0 ... 定义了一个 Cell0 构造函数,然后 data Acell = Cell0 | Cell1 再次这样做。也许将其更改为data Acell = ACell0 Cell0 | ACell1 Cell1
  • 可行但太多余了..
  • 一种选择是使用Either
  • 您确定需要单独的Cell0Cell1Cell2 类型吗?也许您应该只使用一个带有三个构造函数的 Cell 类型。

标签: haskell types algebraic-data-types


【解决方案1】:
data Acell=Cell0|Cell1

这不是 ADT 的工作方式。

当您编写似乎是“Acell 是 Cell0 或 Cell1”时,您在想什么。但是 Haskell 规范说这实际上意味着“引入一个新类型 Acell,并引入一个不带参数的新构造函数 Cell0,并引入一个不带参数的新构造函数 Cell1”。

因此,您的类型定义根本不包含对类型 Cell0 的引用,但它引入了一个新的构造函数 Cell0,它与名为 Cell0 的现有构造函数发生冲突。因此出现错误。

您使用data AB=A|B 的第二个示例 工作。它可以编译,但如果您尝试过,您会发现不能将A 类型的元素放入AB 类型中。 AB 要么是构造函数 A(不包含其他数据),要么是构造函数 B(不包含其他数据);与A型和B型完全无关。

问题在于 ADT 有 标记 联合;在data 声明(由| 分隔)的每个分支中,必须有一个新的构造函数,并且然后 将存储在构造函数中的类型。因此,例如,您可以说:

data Acell = Acell0 Cell0 | Acell1 Cell1

构造函数起到“标签”的作用,允许您在不查看内部数据的情况下判断正在使用哪个“分支”,即使这些分支实际上存储了相同的数据(例如data Foo = L Integer | R Integer)。没有办法拥有未标记的联合并省略构造函数。

【讨论】:

    【解决方案2】:

    在第一个示例中,您实际上是在声明构造函数Cell0 两次;一次在第一种类型,一次在最后一种。你也对Cell1 做同样的事情,但是编译器还没有到那里产生错误。构造函数的类型不同并不重要。所有构造函数都必须具有唯一的名称(记录字段也是如此;不幸的是 Haskell 的一部分)。

    在您的第二个示例中,您从不尝试重新声明构造函数,因此它可以编译。

    【讨论】:

    • 那么如何以最小的方式修改代码以使其工作?最直接的方法可能是:data Cell0=Cell0c {c0str::Text,c0uid::Uid} deriving (Data,Typeable,Show)
    • 如果你这样做,data Acell = Cell0 | Cell1 仍然不起作用,因为Cell0 不会引用类型,它将被解释为构造函数。如果您不希望这样,请将Cell0 声明移动到Acell 定义中,即data Acell = Cell0 {c0str...} | Cell1 {c1start...}
    • @doofin 我会给每种类型一个更具描述性的名称来描述其用途。例如,Cell01 变体有什么区别?
    • @doofin 另请注意,如果您在最后一种类型中的意图是引用先前的构造函数,其中ACell 可以是Cell0Cell1 类型,则它不起作用像这样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 2015-12-09
    相关资源
    最近更新 更多