问题描述
Haskell 没有记录成员的点符号.对于每个记录成员,编译器都会创建一个同名的函数,类型为 RecType -> FieldType.这会导致名称冲突.有什么办法可以解决这个问题,即如何让多个记录具有相同的字段名称?
Haskell doesn't have dot notation for record members. For each record member a compiler creates a function with the same name with a type RecType -> FieldType. This leads to name conflicts. Are there any ways to work around this, i.e. how can I have several records with the same field names?
推荐答案
另一种避免这个问题的方法是使用 lens一> 包.它提供了一个 makeFields 模板 haskell 函数,你可以这样使用:
Another way to avoid this problem is to use the lens package. It provides a makeFields template haskell function, which you can use like this:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeSynonymInstances #-}
import Control.Lens
data A = A
{ _aText :: String
}
makeFields ''A -- Creates a lens x for each record accessor with the name _aX
data B = B
{ _bText :: Int
, _bValue :: Int
}
-- Creates a lens x for each record accessor with the name _bX
makeFields ''B
main = do
let a = A "hello"
let b = B 42 1
-- (^.) is a function of lens which accesses a field (text) of some value (a)
putStrLn $ "Text of a: " ++ a ^. text
putStrLn $ "Text of b: " ++ show (b ^. text)
如果您不想使用 TemplateHaskell 和 lens,您也可以手动执行lens 使用TemplateHaskell 自动执行的操作:
If you don't want to use TemplateHaskell and lens, you can also do manually what lens automates using TemplateHaskell:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeSynonymInstances #-}
data A = A
{ aText :: String
}
data B = B
{ bText :: Int
, bValue :: Int
}
-- A class for types a that have a "text" field of type t
class HasText a t | a -> t where
-- An accessor for the text value
text :: a -> t
-- Make our two types instances of those
instance HasText A String where text = aText
instance HasText B Int where text = bText
main = do
let a = A "hello"
let b = B 42 1
putStrLn $ "Text of a: " ++ text a
putStrLn $ "Text of b: " ++ show (text b)
但我真的可以推荐学习镜头,因为它还提供了许多其他实用程序,例如修改或设置字段.
But I can really recommend learning lens, as it also provides lots of other utilities, like modifying or setting a field.
这篇关于Haskell 记录中的名称冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!