54 haskell types records namespaces
我在程序中使用了很多不同的记录,其中一些使用相同的字段名称,例如
data Customer = Customer { ..., foo :: Int, ... }
data Product = Product { ..., foo :: Int, ... }
Run Code Online (Sandbox Code Playgroud)
现在,由于访问器函数"foo"被定义了两次,我得到"多个声明"错误.避免这种情况的一种方法是使用完全限定导入的不同模块,或者只是重命名字段(我不想这样做).
在Haskell处理这个问题的官方建议方法是什么?
Ozg*_*gur 23
这是一个非常毛茸茸的问题.有几个修复记录系统的建议.在相关的说明中,请参阅TDNR和咖啡馆的相关讨论.
使用当前可用的语言功能,我认为最好的选择是在两个不同的模块中定义两种类型,并进行合格的导入.除此之外,如果需要,您可以实现一些类型类机器.
在Customer.hs中
module Customer where
data Customer = Customer { ..., foo :: Int, ... }
Run Code Online (Sandbox Code Playgroud)
在Product.hs中
module Product where
data Product = Product { ..., foo :: Int, ... }
Run Code Online (Sandbox Code Playgroud)
使用它们时,在Third.hs中
module Third where
import qualified Customer as C
import qualified Product as P
.. C.foo ..
.. P.foo ..
Run Code Online (Sandbox Code Playgroud)
然而,我想你在解决递归依赖模块的问题之前还为时不晚.
Tho*_*son 12
(仅供参考,这个问题几乎肯定是重复的)
解决方案:
1)使用指示类型的标记前缀字段(非常常见)
data Customer = Customer {..., cFoo :: Int, ...}
Run Code Online (Sandbox Code Playgroud)
2)使用类型类(不太常见,人们抱怨前缀像是cFoo
不方便但显然不是那么糟糕,他们会写一个类和实例或使用TH来做同样的事情).
class getFoo a where
foo :: a -> Int
instance getFoo Customer where
foo = cFoo
Run Code Online (Sandbox Code Playgroud)
3)使用更好的字段名称如果字段实际上不同(这并非总是如此,我的计算机的年龄与我的员工一样),那么这是最佳解决方案.
另见Has包:http://chrisdone.com/posts/duck-typing-in-haskell
如果您现在确实需要可扩展记录,则可以始终使用HList.但是在你对中等先进的Haskell非常熟悉和熟悉之前我不会推荐这个,即便如此,我还是会检查你是否需要它.
Haskelldb的版本稍微轻一些:http://hackage.haskell.org/packages/archive/haskelldb/2.1.0/doc/html/Database-HaskellDB-HDBRec.html
然后是葡萄柚frp库的另一个版本的可扩展记录:http://hackage.haskell.org/package/grapefruit-records
再次,为了您的目的,我会咬紧牙关,只是重命名字段.但是这些参考文献表明,当你真正需要可扩展记录的全部功能时,有很多方法可以做到,即使没有一个像设计良好的语言扩展那样令人愉快.
有一种语言扩展DuplicateRecordFields
,允许重复字段函数,并使其类型由类型注释推断.
这是一个小例子(haskell-stack脚本):
#!/usr/bin/env stack
-- stack runghc --resolver lts-8.20 --install-ghc
{-# LANGUAGE DuplicateRecordFields #-}
newtype Foo = Foo { baz :: String }
newtype Bar = Bar { baz :: String }
foo = Foo { baz = "foo text" }
bar = Bar { baz = "bar text" }
main = do
putStrLn $ "Foo: " ++ baz (foo :: Foo) -- Foo: foo text
putStrLn $ "Bar: " ++ baz (bar :: Bar) -- Bar: bar text
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6324 次 |
最近记录: |