Creating lenses for the “lens” library using a special name processor instead of the standard “underline” based on

The standard makeLenses implementation creates lenses for all recording fields that begin with underscores. I really dislike the idea of ​​introducing such an awkward naming convention into my notes for many reasons. I just want to create lenses for all fields of the record and call them simply adding the suffix "L" to the field names.

With the fc tag library that I had to do to achieve this was

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

but the lens library has a much more complex configuration with rule sets, etc., which is not so easy for the mind. Therefore, I ask for a specific recipe in order to achieve the same.

+8
haskell lenses template-haskell lens
source share
2 answers

Looking at the code, it looks pretty simple. LensRules have a function lensField :: String -> Maybe String (which either gives a name for the lens or does not work). So you can make a function like

 myMakeLenses = makeLensesWith $ lensRules & lensField .~ (\name -> Just (name ++ "L")) 

and use this instead of makeLenses . Of course, you can parameterize your function to (++ "L") .

Or you can write it in a string if you like, for example.

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

(Note that (??) is just an infix flip to pass arguments in the correct order. You can think of it as a “hole” in this case when the second argument is populated. And (&) just clicked ($) .)

+15
source share

Shachaf's answer does not work with 4.4+ lenses that have changed the API associated with the haskell pattern.

Here is an implementation that works with these versions:

 import Language.Haskell.TH myMakeLenses :: Name -> DecsQ myMakeLenses = makeLensesWith $ lensRules & lensField .~ \_ _ name -> [TopName (mkName $ nameBase name ++ "L")] 

(this is 4.5+, in 4.4 the lambda will only accept \_ name as parameters)

+18
source share

All Articles