Haskell Language Writing a lens without Template Haskell


To demystify Template Haskell, suppose you have

data Example a = Example { _foo :: Int, _bar :: a }


makeLenses 'Example

produces (more or less)

foo :: Lens' (Example a) Int
bar :: Lens (Example a) (Example b) a b

There's nothing particularly magical going on, though. You can write these yourself:

foo :: Lens' (Example a) Int
--  :: Functor f => (Int -> f Int) -> (Example a -> f (Example a))    ;; expand the alias
foo wrap (Example foo bar) = fmap (\newFoo -> Example newFoo bar) (wrap foo)

bar :: Lens (Example a) (Example b) a b
--  :: Functor f => (a -> f b) -> (Example a -> f (Example b))    ;; expand the alias
bar wrap (Example foo bar) = fmap (\newBar -> Example foo newBar) (wrap bar)

Essentially, you want to "visit" your lens' "focus" with the wrap function and then rebuild the "entire" type.