2013-06-16 5 views
8

Die Standardimplementierung makeLenses erzeugt Linsen für alle Felder eines Datensatzes, die mit Unterstrich beginnen. Ich mag die Idee, aus vielen Gründen eine so unangenehme Benennungskonvention in meine Aufzeichnungen aufnehmen zu müssen, sehr. Ich möchte nur Linsen für alle Felder eines Datensatzes erzeugen und sie benennen, indem ich einfach ein Suffix "L" an die Feldnamen angehängt habe.Generieren von Linsen für eine "Linsen" -Bibliothek mit einem benutzerdefinierten Namensprozessor anstelle des standardmäßigen "Unterstrichs" -basierten

Mit einer fc-Etikett Bibliothek alles, was ich tun musste, um die

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

war zu erreichen, aber die Linse Bibliothek hat eine viel mehr beteiligt Konfiguration mit rulesets und Sachen, die nicht so ist leicht zu verstehen. Ich frage nach einem bestimmten Rezept, um dasselbe zu erreichen.

Antwort

15

Mit Blick auf den Code scheint es ziemlich einfach. LensRules haben eine Funktion lensField :: String -> Maybe String (die entweder den Namen für ein Objektiv gibt oder ausfällt). So können Sie eine Funktion wie

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

herzustellen und verwenden, dass anstelle von makeLenses. Natürlich können Sie Ihre Funktion auf (++ "L") parametrieren.

Oder Sie könnten es inline schreiben, wenn Sie bevorzugen, z.

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

(Beachten Sie, dass (??) nur flip ist infix die Argumente in der richtigen Reihenfolge für das Bestehen. Sie es als ein „Loch“ denken kann, in diesem Fall, dass das zweite Argument in gefüllt werden. Und (&) ist gerade umgedreht ($).)

+0

Great! Vielen Dank! –

+0

Beachten Sie, dass dies jetzt mit lens-4.4 gebrochen ist, das den Template-Haskell-Code geändert hat. –

18

Die Antwort von shachaf funktioniert nicht mit Objektiven 4.4+, die die Template-Haskell-APIs geändert haben.

ist die Implementierung, die mit diesen Versionen funktioniert:

import Language.Haskell.TH 

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

(dies ist 4.5+, die Lambda-nimmt in 4.4 nur \_ name als Parameter würde)

Verwandte Themen