{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeOperators #-}
module Data.Generics.Internal.Profunctor.Prism where
import Data.Profunctor (Choice(..), Profunctor(..))
import Data.Tagged
import Data.Profunctor.Unsafe ((#.), (.#))
import GHC.Generics
import Data.Coerce
type APrism s t a b = Market a b a b -> Market a b s t
type Prism s t a b
= forall p . (Choice p) => p a b -> p s t
type Prism' s a = forall p . (Choice p) => p a a -> p s s
left :: Prism ((a :+: c) x) ((b :+: c) x) (a x) (b x)
left = prism L1 $ gsum Right (Left . R1)
right :: Prism ((a :+: b) x) ((a :+: c) x) (b x) (c x)
right = prism R1 $ gsum (Left . L1) Right
prism :: (b -> t) -> (s -> Either t a) -> Prism s t a b
prism bt seta eta = dimap seta (either id bt) (right' eta)
_Left :: Prism (Either a c) (Either b c) a b
_Left = prism Left $ either Right (Left . Right)
_Right :: Prism (Either c a) (Either c b) a b
_Right = prism Right $ either (Left . Left) Right
prismPRavel :: (Market a b a b -> Market a b s t) -> Prism s t a b
prismPRavel l pab = (prism2prismp $ l idPrism) pab
build :: (Tagged b b -> Tagged t t) -> b -> t
build p = unTagged #. p .# Tagged
match :: Prism s t a b -> s -> Either t a
match k = withPrism k $ \_ _match -> _match
without' :: Prism s t a b -> Prism s t c d -> Prism s t (Either a c) (Either b d)
without' k =
withPrism k $ \bt _ k' ->
withPrism k' $ \dt setc ->
prism (foldEither bt dt) $ \s -> fmap Right (setc s)
where foldEither _ g (Right r) = g r
foldEither f _ (Left l) = f l
{-# INLINE without' #-}
withPrism :: APrism s t a b -> ((b -> t) -> (s -> Either t a) -> r) -> r
withPrism k f = case k idPrism of
Market bt seta -> f bt seta
prism2prismp :: Market a b s t -> Prism s t a b
prism2prismp (Market bt seta) = prism bt seta
idPrism :: Market a b a b
idPrism = Market id Right
gsum :: (a x -> c) -> (b x -> c) -> ((a :+: b) x) -> c
gsum f _ (L1 x) = f x
gsum _ g (R1 y) = g y
plus :: (a -> b) -> (c -> d) -> Either a c -> Either b d
plus f _ (Left x) = Left (f x)
plus _ g (Right y) = Right (g y)
data Market a b s t = Market (b -> t) (s -> Either t a)
instance Functor (Market a b s) where
fmap f (Market bt seta) = Market (f . bt) (either (Left . f) Right . seta)
{-# INLINE fmap #-}
instance Profunctor (Market a b) where
dimap f g (Market bt seta) = Market (g . bt) (either (Left . g) Right . seta . f)
{-# INLINE dimap #-}
lmap f (Market bt seta) = Market bt (seta . f)
{-# INLINE lmap #-}
rmap f (Market bt seta) = Market (f . bt) (either (Left . f) Right . seta)
{-# INLINE rmap #-}
( #. ) _ = coerce
{-# INLINE ( #. ) #-}
( .# ) p _ = coerce p
{-# INLINE ( .# ) #-}
instance Choice (Market a b) where
left' (Market bt seta) = Market (Left . bt) $ \case
Left s -> case seta s of
Left t -> Left (Left t)
Right a -> Right a
Right c -> Left (Right c)
{-# INLINE left' #-}