{-# LANGUAGE TypeOperators, TypeFamilies, FlexibleInstances, FlexibleContexts, UndecidableInstances, RankNTypes, GADTs, LiberalTypeSynonyms, NoImplicitPrelude #-}
module Data.Category.NaturalTransformation (
(:~>)
, Component
, (!)
, o
, natId
, srcF
, tgtF
, Nat(..)
, Endo
, Presheaves
, Profunctors
, compAssoc
, compAssocInv
, idPrecomp
, idPrecompInv
, idPostcomp
, idPostcompInv
, constPrecompIn
, constPrecompOut
, constPostcompIn
, constPostcompOut
, FunctorCompose(..)
, EndoFunctorCompose
, Precompose
, precompose
, Postcompose
, postcompose
, Wrap(..)
, Apply(..)
, Tuple(..)
) where
import Data.Category
import Data.Category.Functor
import Data.Category.Product
infixl 9 !
type f :~> g = forall c d. (c ~ Dom f, c ~ Dom g, d ~ Cod f, d ~ Cod g) => Nat c d f g
data Nat :: (* -> * -> *) -> (* -> * -> *) -> * -> * -> * where
Nat :: (Functor f, Functor g, c ~ Dom f, c ~ Dom g, d ~ Cod f, d ~ Cod g)
=> f -> g -> (forall z. Obj c z -> Component f g z) -> Nat c d f g
type Component f g z = Cod f (f :% z) (g :% z)
(!) :: (Category c, Category d) => Nat c d f g -> c a b -> d (f :% a) (g :% b)
Nat f _ n ! h = n (tgt h) . f % h
o :: (Category c, Category d, Category e) => Nat d e j k -> Nat c d f g -> Nat c e (j :.: f) (k :.: g)
njk@(Nat j k _) `o` nfg@(Nat f g _) = Nat (j :.: f) (k :.: g) ((njk !) . (nfg !))
natId :: Functor f => f -> Nat (Dom f) (Cod f) f f
natId f = Nat f f (\i -> f % i)
srcF :: Nat c d f g -> f
srcF (Nat f _ _) = f
tgtF :: Nat c d f g -> g
tgtF (Nat _ g _) = g
instance Category d => Category (Nat c d) where
src (Nat f _ _) = natId f
tgt (Nat _ g _) = natId g
Nat _ h ngh . Nat f _ nfg = Nat f h (\i -> ngh i . nfg i)
compAssoc :: (Functor f, Functor g, Functor h, Dom f ~ Cod g, Dom g ~ Cod h)
=> f -> g -> h -> Nat (Dom h) (Cod f) ((f :.: g) :.: h) (f :.: (g :.: h))
compAssoc f g h = Nat ((f :.: g) :.: h) (f :.: (g :.: h)) (\i -> f % g % h % i)
compAssocInv :: (Functor f, Functor g, Functor h, Dom f ~ Cod g, Dom g ~ Cod h)
=> f -> g -> h -> Nat (Dom h) (Cod f) (f :.: (g :.: h)) ((f :.: g) :.: h)
compAssocInv f g h = Nat (f :.: (g :.: h)) ((f :.: g) :.: h) (\i -> f % g % h % i)
idPrecomp :: Functor f => f -> Nat (Dom f) (Cod f) (f :.: Id (Dom f)) f
idPrecomp f = Nat (f :.: Id) f (f %)
idPrecompInv :: Functor f => f -> Nat (Dom f) (Cod f) f (f :.: Id (Dom f))
idPrecompInv f = Nat f (f :.: Id) (f %)
idPostcomp :: Functor f => f -> Nat (Dom f) (Cod f) (Id (Cod f) :.: f) f
idPostcomp f = Nat (Id :.: f) f (f %)
idPostcompInv :: Functor f => f -> Nat (Dom f) (Cod f) f (Id (Cod f) :.: f)
idPostcompInv f = Nat f (Id :.: f) (f %)
constPrecompIn :: Nat j d (f :.: Const j c x) g -> Nat j d (Const j d (f :% x)) g
constPrecompIn (Nat (f :.: Const x) g n) = Nat (Const (f % x)) g n
constPrecompOut :: Nat j d f (g :.: Const j c x) -> Nat j d f (Const j d (g :% x))
constPrecompOut (Nat f (g :.: Const x) n) = Nat f (Const (g % x)) n
constPostcompIn :: Nat j d (Const k d x :.: f) g -> Nat j d (Const j d x) g
constPostcompIn (Nat (Const x :.: _) g n) = Nat (Const x) g n
constPostcompOut :: Nat j d f (Const k d x :.: g) -> Nat j d f (Const j d x)
constPostcompOut (Nat f (Const x :.: _) n) = Nat f (Const x) n
data FunctorCompose (c :: * -> * -> *) (d :: * -> * -> *) (e :: * -> * -> *) = FunctorCompose
instance (Category c, Category d, Category e) => Functor (FunctorCompose c d e) where
type Dom (FunctorCompose c d e) = Nat d e :**: Nat c d
type Cod (FunctorCompose c d e) = Nat c e
type FunctorCompose c d e :% (f, g) = f :.: g
FunctorCompose % (n1 :**: n2) = n1 `o` n2
type Endo k = Nat k k
type EndoFunctorCompose k = FunctorCompose k k k
type Presheaves k = Nat (Op k) (->)
type Profunctors c d = Nat (Op d :**: c) (->)
type Precompose f e = FunctorCompose (Dom f) (Cod f) e :.: Tuple2 (Nat (Cod f) e) (Nat (Dom f) (Cod f)) f
precompose :: (Category e, Functor f) => f -> Precompose f e
precompose f = FunctorCompose :.: tuple2 (natId f)
type Postcompose f c = FunctorCompose c (Dom f) (Cod f) :.: Tuple1 (Nat (Dom f) (Cod f)) (Nat c (Dom f)) f
postcompose :: (Category e, Functor f) => f -> Postcompose f e
postcompose f = FunctorCompose :.: tuple1 (natId f)
data Wrap f h = Wrap f h
instance (Functor f, Functor h) => Functor (Wrap f h) where
type Dom (Wrap f h) = Nat (Cod h) (Dom f)
type Cod (Wrap f h) = Nat (Dom h) (Cod f)
type Wrap f h :% g = f :.: g :.: h
Wrap f h % n = natId f `o` n `o` natId h
data Apply (c1 :: * -> * -> *) (c2 :: * -> * -> *) = Apply
instance (Category c1, Category c2) => Functor (Apply c1 c2) where
type Dom (Apply c1 c2) = Nat c2 c1 :**: c2
type Cod (Apply c1 c2) = c1
type Apply c1 c2 :% (f, a) = f :% a
Apply % (l :**: r) = l ! r
data Tuple (c1 :: * -> * -> *) (c2 :: * -> * -> *) = Tuple
instance (Category c1, Category c2) => Functor (Tuple c1 c2) where
type Dom (Tuple c1 c2) = c1
type Cod (Tuple c1 c2) = Nat c2 (c1 :**: c2)
type Tuple c1 c2 :% a = Tuple1 c1 c2 a
Tuple % f = Nat (tuple1 (src f)) (tuple1 (tgt f)) (\z -> f :**: z)