module Data.Generics.Internal.Lens where
import Control.Applicative (Const(..))
import Data.Functor.Identity (Identity(..))
import Data.Profunctor (Choice(right'), Profunctor(dimap))
import GHC.Generics ((:*:)(..), (:+:)(..), Generic(..), K1(..), M1(..), Rep)
type Lens' s a
= forall f. Functor f => (a -> f a) -> s -> f s
type Prism' s a
= forall p f. (Choice p, Applicative f) => p a (f a) -> p s (f s)
type Iso' s a
= forall p f. (Profunctor p, Functor f) => p a (f a) -> p s (f s)
(^.) :: s -> ((a -> Const a a) -> s -> Const a s) -> a
s ^. l = getConst (l Const s)
infixl 8 ^.
set :: ((a -> Identity b) -> s -> Identity t) -> b -> s -> t
set l b
= runIdentity . l (\_ -> Identity b)
first :: Lens' ((a :*: b) x) (a x)
first f (a :*: b)
= fmap (:*: b) (f a)
second :: Lens' ((a :*: b) x) (b x)
second f (a :*: b)
= fmap (a :*:) (f b)
left :: Prism' ((a :+: b) x) (a x)
left = prism L1 $ \x -> case x of
L1 a -> Right a
R1 _ -> Left x
right :: Prism' ((a :+: b) x) (b x)
right = prism R1 $ \x -> case x of
L1 _ -> Left x
R1 a -> Right a
combine :: Lens' (s x) a -> Lens' (t x) a -> Lens' ((s :+: t) x) a
combine sa _ f (L1 s) = fmap (\a -> L1 (set sa a s)) (f (s ^. sa))
combine _ ta f (R1 t) = fmap (\a -> R1 (set ta a t)) (f (t ^. ta))
prism :: (a -> s) -> (s -> Either s a) -> Prism' s a
prism bt seta = dimap seta (either pure (fmap bt)) . right'
repIso :: Generic a => Iso' a (Rep a x)
repIso = dimap from (fmap to)
mIso :: Iso' (M1 i c f p) (f p)
mIso = dimap unM1 (fmap M1)
kIso :: Iso' (K1 t a x) a
kIso = dimap unK1 (fmap K1)
sumIso :: Iso' ((a :+: b) x) (Either (a x) (b x))
sumIso = dimap f (fmap t)
where f (L1 x) = Left x
f (R1 x) = Right x
t (Left x) = L1 x
t (Right x) = R1 x
_Left :: Prism' (Either a c) a
_Left = prism Left $ either Right (Left . Right)
_Right :: Prism' (Either c a) a
_Right = prism Right $ either (Left . Left) Right