191 lines
6.8 KiB
Agda
191 lines
6.8 KiB
Agda
{-# OPTIONS --cubical --caching #-}
|
||
module Cat.Category.Product where
|
||
|
||
open import Cat.Prelude as P hiding (_×_ ; fst ; snd)
|
||
open import Cat.Equivalence
|
||
|
||
open import Cat.Category
|
||
|
||
module _ {ℓa ℓb : Level} (ℂ : Category ℓa ℓb) where
|
||
open Category ℂ
|
||
|
||
module _ (A B : Object) where
|
||
record RawProduct : Set (ℓa ⊔ ℓb) where
|
||
-- no-eta-equality
|
||
field
|
||
object : Object
|
||
fst : ℂ [ object , A ]
|
||
snd : ℂ [ object , B ]
|
||
|
||
record IsProduct (raw : RawProduct) : Set (ℓa ⊔ ℓb) where
|
||
open RawProduct raw public
|
||
field
|
||
ump : ∀ {X : Object} (f : ℂ [ X , A ]) (g : ℂ [ X , B ])
|
||
→ ∃![ f×g ] (ℂ [ fst ∘ f×g ] ≡ f P.× ℂ [ snd ∘ f×g ] ≡ g)
|
||
|
||
-- | Arrow product
|
||
_P[_×_] : ∀ {X} → (π₁ : ℂ [ X , A ]) (π₂ : ℂ [ X , B ])
|
||
→ ℂ [ X , object ]
|
||
_P[_×_] π₁ π₂ = P.fst (ump π₁ π₂)
|
||
|
||
record Product : Set (ℓa ⊔ ℓb) where
|
||
field
|
||
raw : RawProduct
|
||
isProduct : IsProduct raw
|
||
|
||
open IsProduct isProduct public
|
||
|
||
record HasProducts : Set (ℓa ⊔ ℓb) where
|
||
field
|
||
product : ∀ (A B : Object) → Product A B
|
||
|
||
_×_ : Object → Object → Object
|
||
A × B = Product.object (product A B)
|
||
|
||
-- | Parallel product of arrows
|
||
--
|
||
-- The product mentioned in awodey in Def 6.1 is not the regular product of
|
||
-- arrows. It's a "parallel" product
|
||
module _ {A A' B B' : Object} where
|
||
open Product using (_P[_×_])
|
||
open Product (product A B) hiding (_P[_×_]) renaming (fst to fst ; snd to snd)
|
||
_|×|_ : ℂ [ A , A' ] → ℂ [ B , B' ] → ℂ [ A × B , A' × B' ]
|
||
f |×| g = product A' B'
|
||
P[ ℂ [ f ∘ fst ]
|
||
× ℂ [ g ∘ snd ]
|
||
]
|
||
|
||
module _ {ℓa ℓb : Level} {ℂ : Category ℓa ℓb}
|
||
(let module ℂ = Category ℂ) {𝒜 ℬ : ℂ.Object} where
|
||
private
|
||
module _ (raw : RawProduct ℂ 𝒜 ℬ) where
|
||
private
|
||
open Category ℂ hiding (raw)
|
||
module _ (x y : IsProduct ℂ 𝒜 ℬ raw) where
|
||
private
|
||
module x = IsProduct x
|
||
module y = IsProduct y
|
||
|
||
module _ {X : Object} (f : ℂ [ X , 𝒜 ]) (g : ℂ [ X , ℬ ]) where
|
||
module _ (f×g : Arrow X y.object) where
|
||
help : isProp (∀{y} → (ℂ [ y.fst ∘ y ] ≡ f) P.× (ℂ [ y.snd ∘ y ] ≡ g) → f×g ≡ y)
|
||
help = propPiImpl (λ _ → propPi (λ _ → arrowsAreSets _ _))
|
||
|
||
res = ∃-unique (x.ump f g) (y.ump f g)
|
||
|
||
prodAux : x.ump f g ≡ y.ump f g
|
||
prodAux = lemSig ((λ f×g → propSig (propSig (arrowsAreSets _ _) λ _ → arrowsAreSets _ _) (λ _ → help f×g))) _ _ res
|
||
|
||
propIsProduct' : x ≡ y
|
||
propIsProduct' i = record { ump = λ f g → prodAux f g i }
|
||
|
||
propIsProduct : isProp (IsProduct ℂ 𝒜 ℬ raw)
|
||
propIsProduct = propIsProduct'
|
||
|
||
Product≡ : {x y : Product ℂ 𝒜 ℬ} → (Product.raw x ≡ Product.raw y) → x ≡ y
|
||
Product≡ {x} {y} p i = record { raw = p i ; isProduct = q i }
|
||
where
|
||
q : (λ i → IsProduct ℂ 𝒜 ℬ (p i)) [ Product.isProduct x ≡ Product.isProduct y ]
|
||
q = lemPropF propIsProduct p
|
||
|
||
open P
|
||
open import Cat.Categories.Span
|
||
|
||
open Category (span ℂ 𝒜 ℬ)
|
||
|
||
lemma : Terminal ≃ Product ℂ 𝒜 ℬ
|
||
lemma = fromIsomorphism Terminal (Product ℂ 𝒜 ℬ) (f , g , inv)
|
||
where
|
||
f : Terminal → Product ℂ 𝒜 ℬ
|
||
f ((X , x0 , x1) , uniq) = p
|
||
where
|
||
rawP : RawProduct ℂ 𝒜 ℬ
|
||
rawP = record
|
||
{ object = X
|
||
; fst = x0
|
||
; snd = x1
|
||
}
|
||
-- open RawProduct rawP renaming (fst to x0 ; snd to x1)
|
||
module _ {Y : ℂ.Object} (p0 : ℂ [ Y , 𝒜 ]) (p1 : ℂ [ Y , ℬ ]) where
|
||
uy : isContr (Arrow (Y , p0 , p1) (X , x0 , x1))
|
||
uy = uniq {Y , p0 , p1}
|
||
open Σ uy renaming (fst to Y→X ; snd to contractible)
|
||
open Σ Y→X renaming (fst to p0×p1 ; snd to cond)
|
||
ump : ∃![ f×g ] (ℂ [ x0 ∘ f×g ] ≡ p0 P.× ℂ [ x1 ∘ f×g ] ≡ p1)
|
||
ump = p0×p1 , cond , λ {f} cond-f → cong fst (contractible (f , cond-f))
|
||
isP : IsProduct ℂ 𝒜 ℬ rawP
|
||
isP = record { ump = ump }
|
||
p : Product ℂ 𝒜 ℬ
|
||
p = record
|
||
{ raw = rawP
|
||
; isProduct = isP
|
||
}
|
||
g : Product ℂ 𝒜 ℬ → Terminal
|
||
g p = 𝒳 , t
|
||
where
|
||
open Product p renaming (object to X ; fst to x₀ ; snd to x₁) using ()
|
||
module p = Product p
|
||
module isp = IsProduct p.isProduct
|
||
𝒳 : Object
|
||
𝒳 = X , x₀ , x₁
|
||
module _ {𝒴 : Object} where
|
||
open Σ 𝒴 renaming (fst to Y)
|
||
open Σ (snd 𝒴) renaming (fst to y₀ ; snd to y₁)
|
||
ump = p.ump y₀ y₁
|
||
open Σ ump renaming (fst to f')
|
||
open Σ (snd ump) renaming (fst to f'-cond)
|
||
𝒻 : Arrow 𝒴 𝒳
|
||
𝒻 = f' , f'-cond
|
||
contractible : (f : Arrow 𝒴 𝒳) → 𝒻 ≡ f
|
||
contractible ff@(f , f-cond) = res
|
||
where
|
||
k : f' ≡ f
|
||
k = snd (snd ump) f-cond
|
||
prp : (a : ℂ.Arrow Y X) → isProp
|
||
( (ℂ [ x₀ ∘ a ] ≡ y₀)
|
||
× (ℂ [ x₁ ∘ a ] ≡ y₁)
|
||
)
|
||
prp f f0 f1 = Σ≡
|
||
(ℂ.arrowsAreSets _ _ (fst f0) (fst f1))
|
||
(ℂ.arrowsAreSets _ _ (snd f0) (snd f1))
|
||
h :
|
||
( λ i
|
||
→ ℂ [ x₀ ∘ k i ] ≡ y₀
|
||
× ℂ [ x₁ ∘ k i ] ≡ y₁
|
||
) [ f'-cond ≡ f-cond ]
|
||
h = lemPropF prp k
|
||
res : (f' , f'-cond) ≡ (f , f-cond)
|
||
res = Σ≡ k h
|
||
t : IsTerminal 𝒳
|
||
t {𝒴} = 𝒻 , contractible
|
||
ve-re : ∀ x → g (f x) ≡ x
|
||
ve-re x = Propositionality.propTerminal _ _
|
||
re-ve : ∀ p → f (g p) ≡ p
|
||
re-ve p = Product≡ e
|
||
where
|
||
module p = Product p
|
||
-- RawProduct does not have eta-equality.
|
||
e : Product.raw (f (g p)) ≡ Product.raw p
|
||
RawProduct.object (e i) = p.object
|
||
RawProduct.fst (e i) = p.fst
|
||
RawProduct.snd (e i) = p.snd
|
||
inv : AreInverses f g
|
||
inv = funExt ve-re , funExt re-ve
|
||
|
||
propProduct : isProp (Product ℂ 𝒜 ℬ)
|
||
propProduct = equivPreservesNType {n = ⟨-1⟩} lemma Propositionality.propTerminal
|
||
|
||
module _ {ℓa ℓb : Level} {ℂ : Category ℓa ℓb} {A B : Category.Object ℂ} where
|
||
open Category ℂ
|
||
private
|
||
module _ (x y : HasProducts ℂ) where
|
||
private
|
||
module x = HasProducts x
|
||
module y = HasProducts y
|
||
|
||
productEq : x.product ≡ y.product
|
||
productEq = funExt λ A → funExt λ B → propProduct _ _
|
||
|
||
propHasProducts : isProp (HasProducts ℂ)
|
||
propHasProducts x y i = record { product = productEq x y i }
|