使用自定义名称处理器为“镜头”库生成镜头,而不是默认的“下划线”库

时间:2013-06-16 10:49:03

标签: haskell template-haskell lenses lens

标准makeLenses实现为记录的所有字段生成镜头,以下划线开头。出于多种原因,我非常不喜欢将这种尴尬的命名约定引入我的记录。我想要做的只是为记录的所有字段生成镜头,并通过在字段名称后附加后缀“L”来命名它们。

使用 fc-labels 库,我必须做的就是

mkLabelsWith (++ "L") [''MyRecord]

但是镜头库有一个更加复杂的配置rulesets和东西,这并不容易理解。所以我要求一个特定的配方来实现同样的目标。

2 个答案:

答案 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,用于以正确的顺序传递参数。在这种情况下,您可以将其视为第二个参数填充的“漏洞”。 (&)刚刚翻转($)。)