packages feed

extended-categories-0.2.0: Product.hs

module Product where

import qualified Prelude as P
import Data.Constraint hiding ((***), (&&&))
import Data.Proxy
import Data.Tagged

import Category
import Category.Product
import Functor
import Functor.Product
import NatTr
import Adjoint
import Terminal
import Universal
import Monoidal

data ProductF (c :: o -> o -> *) where ProductF :: ProductCategory c => ProductF c
class Adjoint c (c :><: c) (Diag c) (ProductF c) => ProductCategory c
type Product c a b = FMap (ProductF c) '(a, b)

proj1 :: forall (c :: o -> o -> *). ProductCategory c => NatTr (c :><: c) c (ProductF c) (Proj1 c c)
proj1 = idR . compFL counit . assocR . compFR retractProj1Inv . idLInv

proj2 :: forall (c :: o -> o -> *). ProductCategory c => NatTr (c :><: c) c (ProductF c) (Proj2 c c)
proj2 = idR . compFL counit . assocR . compFR retractProj2Inv . idLInv

(&&&) :: forall c a b1 b2. ProductCategory c => c a b1 -> c a b2 -> c a (Product c b1 b2)
f &&& g | Dict <- observeObjects f = proxy phiL (Proxy :: Proxy '(Diag c, ProductF c)) (f :><: g)

(***) :: forall c a1 a2 b1 b2. ProductCategory c => c a1 b1 -> c a2 b2 -> c (Product c a1 a2) (Product c b1 b2)
f *** g = proxy morphMap (Proxy :: Proxy (ProductF c)) (f :><: g)

instance (ProductCategory c, Terminal c) => Monoidal c (ProductF c) where
    type I (ProductF c) = T c

instance Functor (ProductF (->)) ('KProxy :: KProxy ((*,*) -> *)) where
    type Domain (ProductF (->)) = (->) :><: (->)
    type Codomain (ProductF (->)) = (->)
    type FMap (ProductF (->)) '(a, b) = (a, b)
    morphMap = Tagged (\(f :><: g) -> (f . appNat proj1) &&& (g . appNat proj2))

instance Adjoint (->) ((->) :><: (->)) (Diag (->)) (ProductF (->)) where
    leftAdjunct = NatTr (Tagged (\(f :><: g) z -> (f z, g z)))
    rightAdjunct = NatTr (Tagged (\f -> (P.fst . f) :><: (P.snd . f)))

instance ProductCategory (->)

instance Functor (ProductF (:-)) ('KProxy :: KProxy ((Constraint, Constraint) -> Constraint)) where
    type Domain (ProductF (:-)) = (:-) :><: (:-)
    type Codomain (ProductF (:-)) = (:-)
    type FMap (ProductF (:-)) '((a :: Constraint), (b :: Constraint)) = ((a, b) :: Constraint)
    morphMap = Tagged (\(f :><: g) -> (f . appNat proj1) &&& (g . appNat proj2))

instance Adjoint (:-) ((:-) :><: (:-)) (Diag (:-)) (ProductF (:-)) where
    leftAdjunct = NatTr (Tagged (\(f :><: g) -> Sub (Dict \\ f \\ g)))
    rightAdjunct = NatTr (Tagged (\f -> (Sub (Dict \\ f) :><: Sub (Dict \\ f))))

instance ProductCategory (:-)