我是Haskell的新手,可能在这里遗漏了一些非常基本的东西,但是我无法在不同的数据类型中重用相同的值构造函数。
data Colour = Red | Pink | Orange | Yellow
data Fruit = Apple | Orange | Banana
这会产生错误
Multiple declarations of ‘Orange’
不知道为什么不允许这样做,我在学习Haskell之前一直在使用OCaml,并且能够定义这样的类型
快速练习尝试定义一种数据类型,然后打开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
现在,您可能会想“编译器很聪明,它应该知道我在使用它时所说的Orange
。”而且你会部分正确。目前正在努力将重载或重复记录字段引入Haskell。此处已经定义了其他各种问题,但我会列出一些参考资料以供进一步阅读。
没有特别的原因,就是语言的设计方式。我认为这个想法是为了确保编译器可以为尽可能多的表达式推断类型。请注意,如果语言允许重用构造函数,那么您必须为show Orange
表达式指定类型 - 编译器不能再推断它。虽然现在很多人都没有认真对待这个原因,但是很多现代语言扩展确实打破了编译器推断许多表达式的类型的能力。所以我想在几年内你会发现你的例子已经有效:)