为什么我不能在不同的数据类型之间重用相同的值构造函数?

为什么我不能在不同的数据类型之间重用相同的值构造函数?

问题描述:

我是Haskell的新手,可能在这里错过了一些非常基本的东西,但是我无法在不同的数据类型之间重用相同的值构造函数.

i am new to Haskell and probably missing something really basic here, but i am not able to re-use same value constructor among different data types.

data Colour = Red | Pink | Orange | Yellow
data Fruit  = Apple | Orange | Banana

这会产生错误提示

Multiple declarations of ‘Orange’

不确定为什么不允许这样做,我在学习Haskell之前一直使用OCaml并能够定义这样的类型

Not sure why this isn't allowed, i have been using OCaml before learning Haskell and was able to define types like this

作为快速练习,请尝试仅定义一种数据类型,然后打开GHCi进行检查.

As a quick exercise try just defining one of your data types and then opening up GHCi to inspect it.

data Colour = Red | Pink | Orange | Yellow

如果您在GHCi中使用:t,它将告诉您任何内容的类型.

If you use :t in GHCi, it will tell you the type of anything.

> :t Red
Red :: Colour
> :t Orange 
Orange :: Colour 

因此,这告诉您数据构造函数Orange实际上只是一个不带任何参数并生成类型为Colour的值的函数.

So this tells you that your data constructor Orange is really just a function that takes no arguments and produces a value of type Colour.

那么,如果添加重复的声明会怎样?

So what happens if you add a duplicate declaration?

data Colour = Red | Pink | Orange | Yellow
data Fruit  = Apple | Orange | Banana

现在,您已经定义了一个函数Orange,该函数不带任何参数,并且产生类型为Colour的值或类型为Fruit的值.这根本行不通!就像定义您自己的自定义函数foo并为其赋予多个类型签名一样:

Now you have defined a function Orange that takes no arguments and produces a value of type Colour or a value of type Fruit. This won't work at all! It would be the same as defining your own custom function foo and giving it multiple type signatures:

foo :: Int 
foo :: String
foo = "6"

这显然也不起作用.

要解决此问题,您可以在自己的模块中定义每种数据类型,并使用合格的导入来正确定义它们的范围:

To get around this, you can define each data type in its own module, and use a qualified import to scope them correctly:

import qualified Colour as C -- Module Colour.hs 
import qualified Fruit as F -- Module Fruit.hs 

orange1 = C.Orange :: C.Colour 
orange2 = F.Orange :: F.Fruit

现在,您可能会想编译器很聪明,当我使用它时,它应该知道我在说什么Orange." 您会部分正确.正在努力将重载或重复记录字段引入Haskell.在此已经定义了类似的其他问题,但我将列举几个 参考资料以供进一步阅读.

Now, you might be thinking "The compiler is smart, it should know what Orange I'm talking about when I'm using it." and you'd be partially right. There is an ongoing effort to bring Overloaded or Duplicate record fields into Haskell. There are various other questions of that ilk already defined here, but I'll list a few references for further reading.

  • Why DuplicateRecordFields cannot have type inference?
  • https://github.com/adamgundry/ghc-proposals/blob/overloaded-record-fields/proposals/0000-overloaded-record-fields.rst
  • https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/DuplicateRecordFields