代数数据类型的多重声明错误 [英] multiple declaration errors of algebraic data type

查看:155
本文介绍了代数数据类型的多重声明错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一些代数数据类型..
$ b $ pre $ code数据Cell0 = Cell0 {c0str :: Text,c0uid :: Uid}
derived(Data,Typeable,Show)
data Cell1 = Cell1 {c1start :: Uid,c1end :: Uid,c1str :: Text,c1uid :: Int}
派生(Data,Typeable,Show )
data Cell2 = Cell2 {c2start :: Uid,c2end :: Uid,c2str :: Text,c2uid :: Int}
派生(Data,Typeable,Show)
数据Acell = Cell0 | Cell1

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



我也试过这样的东西:

  data A = Aasdfdsf {sdf :: Text } 
导出(Data,Typeable,Show)
数据B = Bsdfsd
数据AB = A | B

它编译!所以weired ..

解决方案

  data Acell = Cell0 | Cell1 
code>

这不是ADT的工作方式。



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

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

第二个例子是 data AB = A | B 没有 工作。它会编译,但是如果你尝试了它,你会发现你不能在 AB A C $ C>。 AB是构造函数A(不包含其他数据)或构造函数B(不包含其他数据);与类型A和B完全无关。



问题是ADT有标记的工会;在 data 声明的每个分支中(由 | 分隔),必须有一个新的构造函数,然后 / em>将存储在构造函数中的类型。例如,您可以说:

  data Acell = Acell0 Cell0 | Acell1 Cell1 

构造函数作为标签使用,可以告诉您正在使用哪个分支而无需查看内部数据,即使分支实际存储相同的数据(例如 data Foo = L Integer | R Integer )。没有标记的联合体并且没有构造函数。


some algebraic data types..

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

but the last line induces a compile error "multiple declarations of Cell0"

I also tried sth like this:

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

It compiles! so weired..

解决方案

data Acell=Cell0|Cell1

That's not how ADTs work.

What you're thinking when you write that seems to be "an Acell is either a Cell0 or a Cell1". But the Haskell spec says that this actually means "introduce a new type Acell, and introduce a new constructor Cell0 that takes no arguments, and introduce a new constructor Cell1 that takes no arguments".

Thus your type definition contains no references at all to the type Cell0, but it introduces a new constructor Cell0 that clashes with the existing constructor named Cell0. Hence the error.

Your second example with data AB=A|B does not work. It compiles, but if you'd tried it you'd see that you cannot put an element of the type A in the type AB. An AB is either the constructor A (containing no other data), or the constructor B (containing no other data); totally unrelated to the types A and B.

The problem is that ADTs have tagged unions; in every branch of a data declaration (separated by |) there must be a new constructor and then the types that will be stored in the constructor. So, for example, you could say:

data Acell = Acell0 Cell0 | Acell1 Cell1

The constructors function as "tags" and allow you to tell which "branch" is being used without looking at the data inside, and even if the branches actually store the same data (e.g. data Foo = L Integer | R Integer). There's no way to have untagged unions and leave out the constructors.

这篇关于代数数据类型的多重声明错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆