{-# LANGUAGE RankNTypes #-} module Graphics.Rasterific.MiniLens ( -- * Types Lens , Lens' , Traversal , Traversal' , lens -- * Getter , (.^) , view , use -- * Setter , (.~) , (.=) , (%=) , (+=) , set -- * Helper , (&) ) where import Control.Monad.Identity import Control.Applicative import Control.Monad.State as State import Data.Function( (&) ) infixl 8 .^ infixr 4 .~ infix 4 .=,%=,+= -- | Does it look familiar? yes it's the official -- Lens type. type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t -- | Try to match the Lens' type alias. type Lens' s a = Lens s s a a -- | Traversal type, matched to the one of the lens -- package. type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t type Traversal' s a = Traversal s s a a -- | Create a full lens out of setter and getter lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b {-# INLINE lens #-} lens accessor setter = \f src -> fmap (setter src) $ f (accessor src) view :: s -> Lens s t a b -> a {-# INLINE view #-} view v l = getConst (l Const v) (.^) :: s -> Lens s t a b -> a {-# INLINE (.^) #-} (.^) = view set :: Lens' s a -> a -> s -> s {-# INLINE set #-} set l new v = runIdentity $ l (\_ -> Identity new) v (.~) :: Lens' s a -> a -> s -> s {-# INLINE (.~) #-} (.~) = set (.=) :: MonadState s m => Lens' s a -> a -> m () {-# INLINE (.=) #-} (.=) l v = State.modify (l .~ v) (%=) :: MonadState s m => Lens' s a -> (a -> a) -> m () {-# INLINE (%=) #-} (%=) l f = State.modify $ \s -> s & l .~ f (s .^ l) (+=) :: (Num a, MonadState s m) => Lens' s a -> a -> m () {-# INLINE (+=) #-} (+=) l n = l %= (+ n) use :: MonadState s m => Lens s t a b -> m a {-# INLINE use #-} use l = State.gets (.^ l)