Skip to content

Instantly share code, notes, and snippets.

@chrisdone
Last active February 13, 2017 22:17
Show Gist options
  • Save chrisdone/c50e2ffc9e71a38d4fed9813fa90bbf4 to your computer and use it in GitHub Desktop.
Save chrisdone/c50e2ffc9e71a38d4fed9813fa90bbf4 to your computer and use it in GitHub Desktop.
$(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