我是Haskell的新手,可能这里缺少一些基本知识,但是我无法在不同数据类型之间重用同一值构造函数。
data Colour = Red | Pink | Orange | Yellow
data Fruit = Apple | Orange | Banana
这会产生错误提示
Multiple declarations of ‘Orange’
不确定为什么不允许这样做,我在学习Haskell之前一直使用OCaml并能够定义这样的类型
答案 0 :(得分:6)
作为快速练习,请尝试仅定义一种数据类型,然后打开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。在此已经定义了类似的其他问题,但我将列举几个
参考资料以供进一步阅读。
答案 1 :(得分:0)
没有特别的原因,那就是语言的设计方式。我认为这个想法是要确保编译器可以推断出尽可能多的表达式的类型。请注意,如果语言允许重用构造函数,则必须为show Orange
表达式指定类型-编译器无法再推断出它。尽管现在很多人没有认真考虑这个原因,并且许多现代语言扩展确实破坏了编译器为许多表达式推断类型的能力。所以我想几年后您会发现您的示例已经起作用了:)