#if __GLASGOW_HASKELL__ >= 702 && __GLASGOW_HASKELL__ <= 708
#endif
module Data.Profunctor.Composition
(
Procompose(..)
, procomposed
, idl
, idr
, assoc
, upstars, kleislis
, downstars, cokleislis
, Rift(..)
, decomposeRift
) where
import Control.Arrow
import Control.Category
import Control.Comonad
import Control.Monad (liftM)
import Data.Functor.Compose
import Data.Profunctor
import Data.Profunctor.Adjunction
import Data.Profunctor.Closed
import Data.Profunctor.Monad
import Data.Profunctor.Rep
import Data.Profunctor.Unsafe
import Prelude hiding ((.),id)
type Iso s t a b = forall p f. (Profunctor p, Functor f) => p a (f b) -> p s (f t)
data Procompose p q d c where
Procompose :: p x c -> q d x -> Procompose p q d c
instance ProfunctorFunctor (Procompose p) where
promap f (Procompose p q) = Procompose p (f q)
instance Category p => ProfunctorMonad (Procompose p) where
proreturn = Procompose id
projoin (Procompose p (Procompose q r)) = Procompose (p . q) r
procomposed :: Category p => Procompose p p a b -> p a b
procomposed (Procompose pxc pdx) = pxc . pdx
instance (Profunctor p, Profunctor q) => Profunctor (Procompose p q) where
dimap l r (Procompose f g) = Procompose (rmap r f) (lmap l g)
lmap k (Procompose f g) = Procompose f (lmap k g)
rmap k (Procompose f g) = Procompose (rmap k f) g
k #. Procompose f g = Procompose (k #. f) g
Procompose f g .# k = Procompose f (g .# k)
instance Profunctor p => Functor (Procompose p q a) where
fmap k (Procompose f g) = Procompose (rmap k f) g
instance (Representable p, Representable q) => Representable (Procompose p q) where
type Rep (Procompose p q) = Compose (Rep q) (Rep p)
tabulate f = Procompose (tabulate id) (tabulate (getCompose . f))
rep (Procompose g f) d = Compose $ rep g <$> rep f d
instance (Corepresentable p, Corepresentable q) => Corepresentable (Procompose p q) where
type Corep (Procompose p q) = Compose (Corep p) (Corep q)
cotabulate f = Procompose (cotabulate (f . Compose)) (cotabulate id)
corep (Procompose g f) (Compose d) = corep g $ corep f <$> d
instance (Strong p, Strong q) => Strong (Procompose p q) where
first' (Procompose x y) = Procompose (first' x) (first' y)
second' (Procompose x y) = Procompose (second' x) (second' y)
instance (Choice p, Choice q) => Choice (Procompose p q) where
left' (Procompose x y) = Procompose (left' x) (left' y)
right' (Procompose x y) = Procompose (right' x) (right' y)
instance (Closed p, Closed q) => Closed (Procompose p q) where
closed (Procompose x y) = Procompose (closed x) (closed y)
idl :: Profunctor q => Iso (Procompose (->) q d c) (Procompose (->) r d' c') (q d c) (r d' c')
idl = dimap (\(Procompose g f) -> rmap g f) (fmap (Procompose id))
idr :: Profunctor q => Iso (Procompose q (->) d c) (Procompose r (->) d' c') (q d c) (r d' c')
idr = dimap (\(Procompose g f) -> lmap f g) (fmap (`Procompose` id))
assoc :: Iso (Procompose p (Procompose q r) a b) (Procompose x (Procompose y z) a b)
(Procompose (Procompose p q) r a b) (Procompose (Procompose x y) z a b)
assoc = dimap (\(Procompose f (Procompose g h)) -> Procompose (Procompose f g) h)
(fmap (\(Procompose (Procompose f g) h) -> Procompose f (Procompose g h)))
upstars :: Functor g
=> Iso (Procompose (UpStar f ) (UpStar g ) d c )
(Procompose (UpStar f') (UpStar g') d' c')
(UpStar (Compose g f ) d c )
(UpStar (Compose g' f') d' c')
upstars = dimap hither (fmap yon) where
hither (Procompose (UpStar xgc) (UpStar dfx)) = UpStar (Compose . fmap xgc . dfx)
yon (UpStar dfgc) = Procompose (UpStar id) (UpStar (getCompose . dfgc))
downstars :: Functor f
=> Iso (Procompose (DownStar f ) (DownStar g ) d c )
(Procompose (DownStar f') (DownStar g') d' c')
(DownStar (Compose f g ) d c )
(DownStar (Compose f' g') d' c')
downstars = dimap hither (fmap yon) where
hither (Procompose (DownStar gxc) (DownStar fdx)) = DownStar (gxc . fmap fdx . getCompose)
yon (DownStar dgfc) = Procompose (DownStar (dgfc . Compose)) (DownStar id)
kleislis :: Monad g
=> Iso (Procompose (Kleisli f ) (Kleisli g ) d c )
(Procompose (Kleisli f') (Kleisli g') d' c')
(Kleisli (Compose g f ) d c )
(Kleisli (Compose g' f') d' c')
kleislis = dimap hither (fmap yon) where
hither (Procompose (Kleisli xgc) (Kleisli dfx)) = Kleisli (Compose . liftM xgc . dfx)
yon (Kleisli dfgc) = Procompose (Kleisli id) (Kleisli (getCompose . dfgc))
cokleislis :: Functor f
=> Iso (Procompose (Cokleisli f ) (Cokleisli g ) d c )
(Procompose (Cokleisli f') (Cokleisli g') d' c')
(Cokleisli (Compose f g ) d c )
(Cokleisli (Compose f' g') d' c')
cokleislis = dimap hither (fmap yon) where
hither (Procompose (Cokleisli gxc) (Cokleisli fdx)) = Cokleisli (gxc . fmap fdx . getCompose)
yon (Cokleisli dgfc) = Procompose (Cokleisli (dgfc . Compose)) (Cokleisli id)
newtype Rift p q a b = Rift { runRift :: forall x. p b x -> q a x }
instance ProfunctorFunctor (Rift p) where
promap f (Rift g) = Rift (f . g)
instance Category p => ProfunctorComonad (Rift p) where
proextract (Rift f) = f id
produplicate (Rift f) = Rift $ \p -> Rift $ \q -> f (q . p)
instance (Profunctor p, Profunctor q) => Profunctor (Rift p q) where
dimap ca bd f = Rift (lmap ca . runRift f . lmap bd)
lmap ca f = Rift (lmap ca . runRift f)
rmap bd f = Rift (runRift f . lmap bd)
bd #. f = Rift (\p -> runRift f (p .# bd))
f .# ca = Rift (\p -> runRift f p .# ca)
instance Profunctor p => Functor (Rift p q a) where
fmap bd f = Rift (runRift f . lmap bd)
instance p ~ q => Category (Rift p q) where
id = Rift id
Rift f . Rift g = Rift (g . f)
decomposeRift :: Procompose p (Rift p q) :-> q
decomposeRift (Procompose p (Rift pq)) = pq p
instance ProfunctorAdjunction (Procompose p) (Rift p) where
counit (Procompose p (Rift pq)) = pq p
unit q = Rift $ \p -> Procompose p q