我正在检查目前没有使用模板 - haskell /某些镜头的一些幻想来处理简单的情况:
data Person = Person {
name :: String,
...
}
data Company = Company {
name :: String,
...
}
目前我通过限定导入来避免污染全局命名空间,但它确实使记录访问变得笨拙。
import Person as P
isFred :: Person -> Bool
isFred p = (P.name p) == "Fred"
还有没有更好的方法来访问记录字段?
我接受了@Emmanuel Touzery的答案,因为有关同一理由的另一个问题的有用链接。另一个问题并没有显示在" haskell命名空间"上的搜索。其他答案没有错,但我只能接受其中一个。
那里提到的解决方案使用模板Haskell,镜头,类型等等基本上为每个字段创建一个类型类#34; HasName"使用单一功能" name"。然后,每个数据类型都是具有自己的实现的该类的实例。然后有一些魔法,我不完全理解允许涉及不同的类型。
对于任何想知道这是什么的Haskell新手来说,它是因为记录基本上是元组,其中字段选择器被实现为普通函数,选择(例如)该元组的第二个元素。如果你导出这些字段选择器函数,那么它们就会位于全局命名空间中,迟早(通常会更快)就会发生冲突。
所以 - 您要么对导入进行限定(如上面的示例所示),要么尝试提出不会发生冲突的名称(名称前缀并希望最好)。
截至2013年,镜头材料风靡一时,可以选择现场选择器/吸气器+定位器等。镜头的基本概念并不复杂,但实现方式正在我的脑海中。
对于记录(哈!)我认为另一篇文章中的解决方案可能就是我之后的问题,但它确实涉及大量的魔术(5个扩展仅用于假记录命名空间)。
答案 0 :(得分:7)
一般来说,只有两种方法,但遗憾的是社区中没有关于它们的理由:
将包含函数的记录放在单独的文件中,并使用完全别名限定,如下所示:
import qualified Data.Person as Person; import Data.Person (Person)
isFred :: Person -> Bool
isFred p = (Person.name p) == "Fred"
考虑这种方法与Java这样的语言相同,其中文件只包含一个类。
将您的记录放在同一个文件中,同时在字段名称前加上记录名称,例如:
data Person = Person {
personName :: String,
personAge :: Int,
...
}
镜片库都没有解决这个问题。
答案 1 :(得分:2)
已经提出了类似的问题,你可以在这里看到一个答案: https://stackoverflow.com/a/17488365/516188
目前镜头是Haskell社区的一个流行词,他们肯定有自己的用途,而且它们可能是这个命名空间问题解决方案的一部分,长期存在。但是目前只使用镜头来解决这个问题的人我认为是少数。正如Nikita Volkov所说,合格的进口和前缀将是目前的典型解决方案。
更新:发现有关this other option但尚未最终确定但似乎很骄傲。这里在this blog post结束时提到。
答案 2 :(得分:0)
这是我的方法。在实践中,我发现我不经常需要导出记录名称,因此命名空间污染只是模块本身的一个问题。所以我使用短前缀,通常是类型类的第一个字母,如下所示:
data Person = Person {
pName :: String,
...
}
data Company = Company {
cName :: String,
...
}
在我需要允许其他模块直接访问字段的情况下,通常只有一个或两个字段。而且我经常只想允许读访问。所以在这种情况下,我可能会有点创意,也许就是这样。
module Whatever
{
Person,
personName,
Company,
companyName,
...
}
data Person = Person {
pName :: String,
...
}
data Company = Company {
cName :: String,
...
}
personName :: Person -> String
personName = pName
companyName :: Company -> String
companyName = cName