Skip to content

Instantly share code, notes, and snippets.

@chrisdone
Last active February 13, 2017 22:17
$(lens 'foo) -- handy one-off lens maker for record fields
{-# LANGUAGE TemplateHaskell #-}
-- | For when you have a record that doesn't have lenses derived for
-- it and you need a lens, just use @$(lens 'thefield)@ and away you go.
module Control.Lens.FieldTH where
import Language.Haskell.TH
lens :: Name -> Q Exp
lens name = do
[|\f r ->
fmap
$(lamE
[varP (mkName "a")]
(recUpdE (varE (mkName "r")) [return (name, VarE (mkName "a"))]))
(f ($(varE name) r))|]
> data X = X { field1 :: Int} deriving Show
> import Control.Lens.Basic
> view $(lens 'field1) (X 123)
123
> over $(lens 'field1) (*2) (X 123)
X {field1 = 246}
> data Y a = Y { field2 :: a} deriving Show
> over $(lens 'field2) (*2) (Y 123)
Y {field2 = 246}
> over $(lens 'field2) show (Y 123)
Y {field2 = "123"}
@louispan
Copy link

This is awesome! Would you be able to make this available on hackage?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment