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

use*_*472 3 haskell algebraic-data-types value-constructor user-defined-data-types

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

data Colour = Red | Pink | Orange | Yellow
data Fruit  = Apple | Orange | Banana
Run Code Online (Sandbox Code Playgroud)

这会产生错误

Multiple declarations of ‘Orange’

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

jke*_*len 7

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

data Colour = Red | Pink | Orange | Yellow
Run Code Online (Sandbox Code Playgroud)

如果您:t在GHCi中使用它,它会告诉您任何类型.

> :t Red
Red :: Colour
> :t Orange 
Orange :: Colour 
Run Code Online (Sandbox Code Playgroud)

所以这告诉你,你的数据构造函数Orange实际上只是一个不带参数并产生类型值的函数Colour.

那么如果添加重复声明会发生什么?

data Colour = Red | Pink | Orange | Yellow
data Fruit  = Apple | Orange | Banana
Run Code Online (Sandbox Code Playgroud)

现在,您已经定义了一个Orange不带参数的函数,并生成一个类型Colour的值或类型的值Fruit.这根本不起作用!它与定义您自己的自定义函数foo并为其提供多种类型签名相同:

foo :: Int 
foo :: String
foo = "6"
Run Code Online (Sandbox Code Playgroud)

这显然也无效.

要解决此问题,您可以在其自己的模块中定义每种数据类型,并使用限定导入来正确地对其进行范围调整:

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
Run Code Online (Sandbox Code Playgroud)

现在,您可能会想"编译器很聪明,它应该知道Orange我在使用它时所说的内容." 而且你会部分正确.目前正在努力将重载或重复记录字段引入Haskell.此处已经定义了其他各种问题,但我会列出一些参考资料以供进一步阅读.

  • 您可以使用`OrangeColour`和`OrangeFruit`作为构造函数(即使名称不同),也可以将定义移动到不同的模块.这两种解决方案都适合你! (2认同)