Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell中不同数据类型的字段标签之间的名称冲突_Haskell_Syntax - Fatal编程技术网

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

从各种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

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类型名称符合条件,但它仍将显示不符合条件的超链接。)