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 (:-)