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

Nik*_*kov 8 haskell template-haskell lenses haskell-lens

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

有了fc标签库,我必须做的就是实现这一目标

mkLabelsWith (++ "L") [''MyRecord]
Run Code Online (Sandbox Code Playgroud)

但是镜头库有一个更复杂的配置,包括规则集和内容,这并不容易让人大开眼界.所以我要求一个特定的配方来实现同样的目的.

Emm*_*ery 18

shachaf的答案不适用于镜头4.4+,它改变了模板与haskell相关的API.

以下是适用于这些版本的实现:

import Language.Haskell.TH

myMakeLenses :: Name -> DecsQ
myMakeLenses = makeLensesWith $ lensRules
    & lensField .~ \_ _ name -> [TopName (mkName $ nameBase name ++ "L")]
Run Code Online (Sandbox Code Playgroud)

(这是4.5+,在4.4中,lambda仅\_ name作为参数)


sha*_*haf 15

看一下代码,看起来非常简单.LensRules有一个功能lensField :: String -> Maybe String(要么给出镜头的名称或失败).所以你可以做一个像这样的功能

myMakeLenses = makeLensesWith $ lensRules
  & lensField .~ (\name -> Just (name ++ "L"))
Run Code Online (Sandbox Code Playgroud)

并使用它而不是makeLenses.当然你可以参数化你的功能(++ "L").

或者,如果您愿意,可以将其写入内联,例如

makeLensesWith ?? ''Foo $ lensRules
  & lensField .~ (\name -> Just (name ++ "L"))
Run Code Online (Sandbox Code Playgroud)

(注意,这(??)只是flip用于以正确的顺序传递参数的中缀.在这种情况下,您可以将其视为"漏洞",第二个参数将被填充.并且(&)只是翻转($).)