标准makeLenses
实现为以下划线开头的记录的所有字段生成镜头。由于许多原因,我非常不喜欢在我的记录中引入如此尴尬的命名约定的想法。我想要做的只是为记录的所有字段生成镜头,并通过在字段名称后附加一个后缀“L”来命名它们。
有了一个fc-labels库,我所要做的就是
mkLabelsWith (++ "L") [''MyRecord]
但是镜头库的规则集和东西的配置要复杂得多,这并不容易引起人们的注意。所以我要求一个特定的配方来达到同样的效果。
标准makeLenses
实现为以下划线开头的记录的所有字段生成镜头。由于许多原因,我非常不喜欢在我的记录中引入如此尴尬的命名约定的想法。我想要做的只是为记录的所有字段生成镜头,并通过在字段名称后附加一个后缀“L”来命名它们。
有了一个fc-labels库,我所要做的就是
mkLabelsWith (++ "L") [''MyRecord]
但是镜头库的规则集和东西的配置要复杂得多,这并不容易引起人们的注意。所以我要求一个特定的配方来达到同样的效果。
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
作为参数)
查看代码,它似乎非常简单。LensRules
有一个功能lensField :: String -> Maybe String
(要么给出镜头的名称,要么失败)。所以你可以做一个像
myMakeLenses = makeLensesWith $ lensRules
& lensField .~ (\name -> Just (name ++ "L"))
并使用它代替makeLenses
. 当然你可以参数化你的函数在(++ "L")
.
或者,如果您愿意,也可以内联编写它,例如
makeLensesWith ?? ''Foo $ lensRules
& lensField .~ (\name -> Just (name ++ "L"))
(请注意,这(??)
只是flip
按正确顺序传递参数的中缀。在这种情况下,您可以将其视为第二个参数被填充的“洞”。并且(&)
只是翻转($)
。)