Haskell中不同数据类型的字段标签之间的名称冲突
从各种OO语言的背景来看Haskell,有一点对我来说似乎有点缺点,那就是函数和字段名的作用域不限于它们关联的类型,因此如果不同的数据类型有同名的字段,很容易发生冲突 如果我有这三个模块:Haskell中不同数据类型的字段标签之间的名称冲突,haskell,syntax,Haskell,Syntax,从各种OO语言的背景来看Haskell,有一点对我来说似乎有点缺点,那就是函数和字段名的作用域不限于它们关联的类型,因此如果不同的数据类型有同名的字段,很容易发生冲突 如果我有这三个模块: module One where data Foo a = Foo { value :: a } ---- module Two where data Bar a = Bar { value :: a } ---- module Three where import One import Two
module One where
data Foo a = Foo { value :: a }
----
module Two where
data Bar a = Bar { value :: a }
----
module Three where
import One
import Two
foo = Foo { value = 42 } -- compile error here
n = value foo -- and here
模块三个中对值的非限定引用被认为是不明确的,即使在这种情况下,两个导入的名称中只有一个是有意义的。(在OO语言中,对foo.value
和bar.value
的引用是明确的。)
当然,我可以通过编写Foo{One.value=42}
来消除歧义,但这看起来很尴尬。我也可以对字段进行不同的命名,例如“fooValue”和“barValue”,但是Foo{fooValue=42}
中的冗余看起来也很尴尬
这实际上是不同模块中更一般的函数问题的特例,这些模块具有相同的名称,但在不同的、不相关的类型上运行。不过,我似乎更经常在字段名中遇到它。例如,我有几个数据类型,这些数据类型与类型类无关,但经常一起使用,它们包含颜色值,因此我希望每个数据类型都有一个名为“color”的字段
>经验丰富的Haskell开发人员如何命名事物,并将其组织成模块,以避免这种情况?< P>您可以考虑类型类,如果在所有这些类型上都有一个公共访问器函数。例如
class Fieldable a where
field :: a -> b
instance Fieldable (a,b) where
field = fst
等等
有经验的Haskell开发人员如何命名事物,并将它们组织到模块中,以避免这种情况
我只与少数有经验的Haskell开发人员合作过,他们做了一些糟糕的事情,比如
data Foo a = Foo { foo_value :: a }
data Bar a = Bar { bar_value :: a }
甚至
data Apocalypse a = A { ap_value :: a }
总的来说,我觉得很多老哈斯凯尔人不喜欢限定的名字,他们真的想假装世界上只有一个大的名字空间,直接走出黑暗时代。(曾经有一段时间,C编译器对字段名有相同的限制,这就是为什么struct stat
中的模式被称为st_模式
,而不仅仅是普通的模式
)
您可以用类型类重载名称,但我认识的有经验的开发人员不喜欢免费的类型类。我永远也搞不清楚他们什么时候认为类型类是免费的
我希望有一天Haskell的人会接受一个分层的名字空间,并开始使用限定的名字。如上帝所愿。GHC扩展将允许foo=foo{value=42}
(但不允许n=value-foo
)
关于Haskell当前记录系统的缺点和替代者,以及一些试图现在提供更好解决方案的图书馆,都有很多争议。是我个人唯一用过的
与此类似,其中的一些答案也可能对您有用
这真的是一个特殊的例子
中函数的更一般性问题
具有相同功能的不同模块
名称不同,但操作方式不同,
不相关的类型
别名通常足以解决这个问题。数据类型的字段名是否可以作为类实例的一部分?如果我在value::a->b
中创建一个类值为ab,那么要将我的两个类型与之关联,我必须执行类似实例值(fooa)a的操作,其中value=value
无效(值的两种含义冲突)。如果函数的名称事先已经定义好,我似乎无法将其定义为类实例的一部分。次要问题:您在定义Bar
@Travis Brown:Oops时缺少构造函数,这是一个输入错误。谢谢你指出这一点。当你实际上不需要多态记录选择器时,我觉得不必为了一些小的语法方便而强制使用它们是有意义的。即使您可以使用限定名称,但在我看来,为很少使用的字段(尤其是通常只能通过帮助函数访问的字段)声明一个通用名称是一种糟糕的形式。我已经尽可能多地使用限定名称。语言本身能很好地处理它;唯一的问题是Haddock对于限定名称的用处要小得多,因为它仍然采用一个大名称空间。(您可以使Haddock show类型名称符合条件,但它仍将显示不符合条件的超链接。)