module Control.Lens.Projection
( Projection
, Projective(..)
, project
, by
, Project(..)
, projection
, stereo
, mirror
, SimpleProjection
) where
import Control.Applicative
import Control.Lens.Type
import Control.Lens.Getter
import Data.Functor.Identity
import Control.Lens.Iso
type Projection s t a b = forall k f. (Projective k s b, Applicative f) => k (a -> f b) (s -> f s)
class Projective k a d where
projective :: (d -> a) -> (x -> y) -> k x y
instance Projective (->) a d where
projective _ x = x
data Project s b x y = Project (b -> s) (x -> y)
stereo :: Projective k s a => Project t a y z -> Project s t x y -> k x z
stereo (Project g f) (Project i h) = projective (i.g) (f.h)
instance (s ~ s', b ~ b') => Projective (Project s b) s' b' where
projective = Project
project :: Projective k s b => Overloaded (Project s b) f s s a b -> Overloaded k f s s a b
project (Project f g) = projective f g
by :: Project s b (b -> Identity b) (s -> Identity s) -> Getter b s
by (Project g _) = to g
projection :: (b -> s) -> (s -> Maybe a) -> Projection s t a b
projection bs sma = projective bs (\afb a -> maybe (pure a) (fmap bs . afb) (sma a))
mirror :: Projective k s a => Simple Iso s a -> Simple Projection s a
mirror l = projection (^.from l) (\a -> Just (a^.l))
type SimpleProjection s a = Projection s s a a