Skip to content

Instantly share code, notes, and snippets.

@robinp
Created January 31, 2013 13:49
Show Gist options
  • Save robinp/4682995 to your computer and use it in GitHub Desktop.
Save robinp/4682995 to your computer and use it in GitHub Desktop.
Constructing lens manually
{-# LANGUAGE ExistentialQuantification, Rank2Types #-}
import Control.Monad.Identity
import qualified Control.Monad.State as S
-- with guidance from http://hackage.haskell.org/package/lens "Minimizing dependencies"
type Lens c d a b = forall f . (Functor f) => (a -> f b) -> c -> f d
get :: c -> Lens c d a () -> a
get c l = fst $ l (flip (,) ()) c
put :: c -> Lens c d a b -> b -> d
put c l b = runIdentity $ l (const $ Identity b) c
modify :: c -> Lens c d a b -> (a -> b) -> d
modify c l f = runIdentity $ l (Identity . f) c
modifyS :: (S.MonadState c m) => Lens c c a b -> (a -> b) -> m ()
modifyS l f = S.modify (\x -> modify x l f)
-- actual lens
data Foo a = Foo Int Int a
deriving Show
fooLastL :: Functor f => (a -> f b) -> Foo a -> f (Foo b)
fooLastL f (Foo x y a) = (Foo x y) `fmap` (f a)
main = do
print $ (Foo 1 2 3) `get` fooLastL
print $ put (Foo 1 2 3) fooLastL "apple"
print $ modify (Foo 1 2 3) fooLastL (*10)
print $ S.execState (modifyS fooLastL (*5)) (Foo 1 2 3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment