open import Cat.Instances.Functor.Limits
open import Cat.Instances.Sets.Complete
open import Cat.Diagram.Coequaliser
open import Cat.Diagram.Exponential
open import Cat.Diagram.Coproduct
open import Cat.Instances.Functor
open import Cat.Diagram.Pullback
open import Cat.Diagram.Terminal
open import Cat.Diagram.Product
open import Cat.Functor.Adjoint
open import Cat.Instances.Sets
open import Cat.Functor.Hom
open import Cat.Prelude
open import Data.Sum
import Cat.Functor.Bifunctor as Bifunctor
import Cat.Reasoning
module Cat.CartesianClosed.Instances.PSh where
open Functor
open _=>_
open _⊣_
module _ {o ℓ κ} {C : Precategory o ℓ} where
private
module C = Cat.Reasoning C
module PSh = Cat.Reasoning (PSh κ C)
PSh-terminal : Terminal (PSh κ C)
PSh-terminal = record { top = top ; has⊤ = uniq } where
top : Functor (C ^op) (Sets κ)
top .F₀ x = el! (Lift κ ⊤)
top .F₁ _ _ = lift tt
top .F-id = refl
top .F-∘ _ _ = refl
uniq : is-terminal (PSh κ C) top
uniq x .centre .η _ _ = lift tt
uniq x .centre .is-natural _ _ _ = refl
uniq x .paths f = trivial!
PSh-pullbacks
: ∀ {X Y Z} (f : PSh.Hom X Z) (g : PSh.Hom Y Z)
→ Pullback (PSh κ C) f g
PSh-pullbacks {X} {Y} {Z} f g = pb where
module X = Functor X
module Y = Functor Y
module Z = Functor Z
module f = _=>_ f
module g = _=>_ g
open Pullback
open is-pullback
pb-path
: ∀ {i} {x y : Σ[ x ∈ X.₀ i ] Σ[ y ∈ Y.₀ i ] f.η i x ≡ g.η i y}
→ x .fst ≡ y .fst
→ x .snd .fst ≡ y .snd .fst
→ x ≡ y
pb-path p q i .fst = p i
pb-path p q i .snd .fst = q i
pb-path {idx} {x} {y} p q i .snd .snd j =
is-set→squarep (λ _ _ → Z.₀ idx .is-tr)
(ap (f .η idx) p) (x .snd .snd) (y .snd .snd) (ap (g .η idx) q)
i j
pb : Pullback (PSh κ C) f g
pb .apex .F₀ i = el! (Σ[ x ∈ X.₀ i ] Σ[ y ∈ Y.₀ i ] f.η i x ≡ g.η i y)
pb .apex .F₁ {x} {y} h (a , b , p) = X.₁ h a , Y.₁ h b , path where abstract
path : f.η y (X.₁ h a) ≡ g.η y (Y.₁ h b)
path = happly (f.is-natural _ _ _) _
·· (λ i → Z.₁ h (p i))
·· sym (happly (g.is-natural _ _ _) _)
pb .apex .F-id = funext λ (a , b , _) → pb-path (X.F-id $ₚ a) (Y.F-id $ₚ b)
pb .apex .F-∘ f g = funext λ (a , b , _) → pb-path (X.F-∘ f g $ₚ a) (Y.F-∘ f g $ₚ b)
pb .p₁ .η idx (a , b , _) = a
pb .p₁ .is-natural _ _ _ = refl
pb .p₂ .η x (a , b , _) = b
pb .p₂ .is-natural _ _ _ = refl
pb .has-is-pb .square = ext λ _ _ _ p → p
pb .has-is-pb .universal path .η idx arg = _ , _ , unext path _ _
pb .has-is-pb .universal {p₁' = p₁'} {p₂'} path .is-natural x y f = funext λ x →
pb-path (happly (p₁' .is-natural _ _ _) _) (happly (p₂' .is-natural _ _ _) _)
pb .has-is-pb .p₁∘universal = trivial!
pb .has-is-pb .p₂∘universal = trivial!
pb .has-is-pb .unique p q = ext λ _ _ →
pb-path (unext p _ _) (unext q _ _)
PSh-products : (A B : PSh.Ob) → Product (PSh κ C) A B
PSh-products A B = prod where
open Product
open is-product
module A = Functor A
module B = Functor B
prod : Product (PSh _ C) A B
prod .apex .F₀ x = el! (∣ A.₀ x ∣ × ∣ B.₀ x ∣)
prod .apex .F₁ f (x , y) = A.₁ f x , B.₁ f y
prod .apex .F-id i (x , y) = A.F-id i x , B.F-id i y
prod .apex .F-∘ f g i (x , y) = A.F-∘ f g i x , B.F-∘ f g i y
prod .π₁ = NT (λ x → fst) (λ _ _ _ → refl)
prod .π₂ = NT (λ x → snd) (λ _ _ _ → refl)
prod .has-is-product .⟨_,_⟩ f g =
NT (λ i x → f .η i x , g .η i x) λ x y h i a →
f .is-natural x y h i a , g .is-natural x y h i a
prod .has-is-product .π₁∘⟨⟩ = trivial!
prod .has-is-product .π₂∘⟨⟩ = trivial!
prod .has-is-product .unique p q = ext λ i x → unext p i x , unext q i x
{-# TERMINATING #-}
PSh-coproducts : (A B : PSh.Ob) → Coproduct (PSh κ C) A B
PSh-coproducts A B = coprod where
open Coproduct
open is-coproduct
module A = Functor A
module B = Functor B
coprod : Coproduct (PSh _ C) A B
coprod .coapex .F₀ i = el! (∣ A.₀ i ∣ ⊎ ∣ B.₀ i ∣)
coprod .coapex .F₁ h (inl x) = inl (A.₁ h x)
coprod .coapex .F₁ h (inr x) = inr (B.₁ h x)
coprod .coapex .F-id = funext λ where
(inl x) → ap inl (happly A.F-id x)
(inr x) → ap inr (happly B.F-id x)
coprod .coapex .F-∘ f g = funext λ where
(inl x) → ap inl (happly (A.F-∘ f g) x)
(inr x) → ap inr (happly (B.F-∘ f g) x)
coprod .ι₁ .η _ x = inl x
coprod .ι₁ .is-natural x y f i a = inl (A.₁ f a)
coprod .ι₂ .η _ x = inr x
coprod .ι₂ .is-natural x y f i b = inr (B.₁ f b)
coprod .has-is-coproduct .is-coproduct.[_,_] f g .η _ (inl x) = f .η _ x
coprod .has-is-coproduct .is-coproduct.[_,_] f g .η _ (inr x) = g .η _ x
coprod .has-is-coproduct .is-coproduct.[_,_] f g .is-natural x y h = funext λ where
(inl x) → f .is-natural _ _ _ $ₚ _
(inr x) → g .is-natural _ _ _ $ₚ _
coprod .has-is-coproduct .[]∘ι₁ = trivial!
coprod .has-is-coproduct .[]∘ι₂ = trivial!
coprod .has-is-coproduct .unique p q = ext λ where
a (inl x) → unext p a x
a (inr x) → unext q a x
PSh-coequaliser
: ∀ {X Y} (f g : PSh.Hom X Y)
→ Coequaliser (PSh κ C) f g
PSh-coequaliser {X = X} {Y = Y} f g = coequ where
open Coequaliser
open is-coequaliser
module X = Functor X
module Y = Functor Y
incq : ∀ {i} → _ → Coeq (f .η i) (g .η i)
incq = inc
coequ : Coequaliser (PSh _ C) f g
coequ .coapex .F₀ i = el (Coeq (f .η i) (g .η i)) squash
coequ .coapex .F₁ h = Coeq-rec (λ g → inc (Y.₁ h g)) λ x →
inc (Y.₁ h (f .η _ x)) ≡˘⟨ ap incq (happly (f .is-natural _ _ h) x) ⟩
inc (f .η _ _) ≡⟨ glue (X.₁ h x) ⟩
inc (g .η _ _) ≡⟨ ap incq (happly (g .is-natural _ _ h) x) ⟩
inc (Y.₁ h (g .η _ x)) ∎
coequ .coapex .F-id = ext λ _ → ap incq (happly Y.F-id _)
coequ .coapex .F-∘ f g = ext λ _ → ap incq (happly (Y.F-∘ f g) _)
coequ .coeq .η i = incq
coequ .coeq .is-natural x y f = refl
coequ .has-is-coeq .coequal = ext λ i x → glue x
coequ .has-is-coeq .universal {F = F} {e' = e'} p .η x =
Coeq-rec (e' .η x) (p ηₚ x $ₚ_)
coequ .has-is-coeq .universal {F = F} {e' = e'} p .is-natural x y f = ext λ x →
e' .is-natural _ _ _ $ₚ _
coequ .has-is-coeq .factors = trivial!
coequ .has-is-coeq .unique {F = F} p = reext! p
module _ {κ} {C : Precategory κ κ} where
private
module C = Cat.Reasoning C
module PSh = Cat.Reasoning (PSh κ C)
open Binary-products (PSh κ C) (PSh-products {C = C})
PSh[_,_] : PSh.Ob → PSh.Ob → PSh.Ob
PSh[ A , B ] = F module psh-exp where
module A = Functor A
module B = Functor B
F : PSh.Ob
F .F₀ c = el ((よ₀ C c ⊗₀ A) => B) Nat-is-set
F .F₁ f nt .η i (g , x) = nt .η i (f C.∘ g , x)
F .F₁ f nt .is-natural x y g = funext λ o →
ap (nt .η y) (Σ-pathp (C.assoc _ _ _) refl) ∙ happly (nt .is-natural _ _ _) _
F .F-id = ext λ f i g x →
ap (f .η i) (Σ-pathp (C.idl _) refl)
F .F-∘ f g = ext λ h i j x →
ap (h .η i) (Σ-pathp (sym (C.assoc _ _ _)) refl)
{-# DISPLAY psh-exp.F A B = PSh[ A , B ] #-}
PSh-closed : Cartesian-closed (PSh κ C) (PSh-products {C = C}) (PSh-terminal {C = C})
PSh-closed = cc where
cat = PSh κ C
module _ (A : PSh.Ob) where
func : Functor (PSh κ C) (PSh κ C)
func .F₀ = PSh[ A ,_]
func .F₁ f .η i g .η j (h , x) = f .η _ (g .η _ (h , x))
func .F₁ f .η i g .is-natural x y h = funext λ x →
ap (f .η _) (happly (g .is-natural _ _ _) _) ∙ happly (f .is-natural _ _ _) _
func .F₁ nt .is-natural x y f = trivial!
func .F-id = trivial!
func .F-∘ f g = trivial!
adj : Bifunctor.Left ×-functor A ⊣ func
adj .unit .η x .η i a =
NT (λ j (h , b) → x .F₁ h a , b) λ _ _ _ → funext λ _ →
Σ-pathp (happly (x .F-∘ _ _) _) refl
adj .unit .η x .is-natural _ _ _ = ext λ _ _ _ _ → sym (x .F-∘ _ _ # _) , refl
adj .unit .is-natural x y f = ext λ _ _ _ _ _ → sym (f .is-natural _ _ _ $ₚ _) , refl
adj .counit .η _ .η _ x = x .fst .η _ (C.id , x .snd)
adj .counit .η _ .is-natural x y f = funext λ h →
ap (h .fst .η _) (Σ-pathp C.id-comm refl) ∙ happly (h .fst .is-natural _ _ _) _
adj .counit .is-natural x y f = trivial!
adj .zig {A} = ext λ x _ _ → happly (F-id A) _ , refl
adj .zag {A} = ext λ _ x i f g j → x .η i (C.idr f j , g)
cc : Cartesian-closed (PSh κ C) (PSh-products {C = C}) (PSh-terminal {C = C})
cc = product-adjoint→cartesian-closed (PSh κ C)
(PSh-products {C = C}) (PSh-terminal {C = C}) func adj