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

Why can't i re-use same value constructor among different data types?

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

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

这会产生错误

Multiple declarations of ‘Orange’

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

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

data Colour = Red | Pink | Orange | Yellow

如果你在 GHCi 中使用 :t,它会告诉你任何东西的类型。

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

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

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

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

现在您已经定义了一个函数 Orange,它不接受任何参数并生成一个 Colour 类型的值或一个 Fruit 类型的值。这根本行不通!这与定义您自己的自定义函数 foo 并为其提供多个类型签名相同:

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

这显然也行不通。

为了解决这个问题,您可以在其自己的模块中定义每个数据类型,并使用限定导入来正确限定它们:

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

现在,您可能会想 "The compiler is smart, it should know what Orange I'm talking about when I'm using it." 并且您可能部分正确。正在努力将重载或重复的记录字段引入 Haskell。这里已经定义了类似的其他各种问题,但我会列出一些 进一步阅读的参考资料。

没有特别的原因,语言就是这样设计的。我认为这个想法是为了确保编译器可以为尽可能多的表达式推断类型。请注意,如果语言允许重用构造函数,那么您必须为 show Orange 表达式指定类型——编译器无法再推断它。尽管现在很多人并不认真对待这个原因,而且很多现代语言扩展确实破坏了编译器为许多表达式推断类型的能力。所以我想几年后你会发现你的例子已经有效了:)