标准makeLenses
实现为记录的所有字段生成镜头,以下划线开头。出于多种原因,我非常不喜欢将这种尴尬的命名约定引入我的记录。我想要做的只是为记录的所有字段生成镜头,并通过在字段名称后附加后缀“L”来命名它们。
使用 fc-labels 库,我必须做的就是
mkLabelsWith (++ "L") [''MyRecord]
但是镜头库有一个更加复杂的配置rulesets和东西,这并不容易理解。所以我要求一个特定的配方来实现同样的目标。
答案 0 :(得分:18)
shachaf的回答并不适用于更换模板与haskell相关API的镜头4.4+。
以下是适用于这些版本的实现:
import Language.Haskell.TH
myMakeLenses :: Name -> DecsQ
myMakeLenses = makeLensesWith $ lensRules
& lensField .~ \_ _ name -> [TopName (mkName $ nameBase name ++ "L")]
(这是4.5+,在4.4中,lambda只需要\_ name
作为参数)
答案 1 :(得分:15)
查看代码,看起来非常简单。 LensRules
有一个函数lensField :: String -> Maybe String
(要么为镜头命名,要么失败)。所以你可以做一个像
myMakeLenses = makeLensesWith $ lensRules
& lensField .~ (\name -> Just (name ++ "L"))
并使用它代替makeLenses
。当然,您可以在(++ "L")
上对您的函数进行参数化。
如果您愿意,也可以内联编写,例如
makeLensesWith ?? ''Foo $ lensRules
& lensField .~ (\name -> Just (name ++ "L"))
(注意(??)
只是中缀flip
,用于以正确的顺序传递参数。在这种情况下,您可以将其视为第二个参数填充的“漏洞”。 (&)
刚刚翻转($)
。)