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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么我不能在不同的数据类型中重用相同的值构造函数?相关的知识,希望对你有一定的参考价值。

我是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表达式指定类型 - 编译器不能再推断它。虽然现在很多人都没有认真对待这个原因,但是很多现代语言扩展确实打破了编译器推断许多表达式的类型的能力。所以我想在几年内你会发现你的例子已经有效:)

以上是关于为什么我不能在不同的数据类型中重用相同的值构造函数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能将“UIView”类型的值转换为其他视图?

java技术第二次作业

如何存储多个数据类型的数组

Flutter:如何在构造函数中传递值,以便我可以重用我的小部件?

常量数据与只读字段

正确的做法?重用相同的故事板视图和视图控制器