{-# OPTIONS --cubical --safe --postfix-projections #-} open import Prelude hiding (_×_) module Categories.HSets {ℓ : Level} where open import Categories open import Cubical.Foundations.HLevels open import Cubical.Foundations.Equiv open import Cubical.Foundations.Univalence open import Data.Sigma.Properties open import Categories.Product open import Categories.Exponential hSetPreCategory : PreCategory (ℓsuc ℓ) ℓ hSetPreCategory .PreCategory.Ob = hSet _ hSetPreCategory .PreCategory.Hom (X , _) (Y , _) = X → Y hSetPreCategory .PreCategory.Id = id hSetPreCategory .PreCategory.Comp f g = f ∘ g hSetPreCategory .PreCategory.assoc-Comp _ _ _ = refl hSetPreCategory .PreCategory.Comp-Id _ = refl hSetPreCategory .PreCategory.Id-Comp _ = refl hSetPreCategory .PreCategory.Hom-Set {X} {Y} = hLevelPi 2 λ _ → Y .snd open PreCategory hSetPreCategory public _⟨×⟩_ : isSet A → isSet B → isSet (A Prelude.× B) xs ⟨×⟩ ys = isOfHLevelΣ 2 xs (const ys) module _ {X Y : Ob} where iso-iso : (X ≅ Y) ⇔ (fst X ⇔ fst Y) iso-iso .fun (f , g , f∘g , g∘f) = iso f g (λ x i → g∘f i x) (λ x i → f∘g i x) iso-iso .inv (iso f g g∘f f∘g) = f , g , (λ i x → f∘g x i) , (λ i x → g∘f x i) iso-iso .rightInv _ = refl iso-iso .leftInv _ = refl univ⇔ : (X ≡ Y) ⇔ (X ≅ Y) univ⇔ = equivToIso (≃ΣProp≡ (λ _ → isPropIsSet)) ⟨ trans-⇔ ⟩ equivToIso univalence ⟨ trans-⇔ ⟩ sym-⇔ (iso⇔equiv (snd X)) ⟨ trans-⇔ ⟩ sym-⇔ iso-iso hSetCategory : Category (ℓsuc ℓ) ℓ hSetCategory .Category.preCategory = hSetPreCategory hSetCategory .Category.univalent = isoToEquiv univ⇔ hSetProd : HasProducts hSetCategory hSetProd .HasProducts.product X Y .Product.obj = (X .fst Prelude.× Y .fst) , X .snd ⟨×⟩ Y .snd hSetProd .HasProducts.product X Y .Product.proj₁ = fst hSetProd .HasProducts.product X Y .Product.proj₂ = snd hSetProd .HasProducts.product X Y .Product.ump f g .fst z = f z , g z hSetProd .HasProducts.product X Y .Product.ump f g .snd .fst .fst = refl hSetProd .HasProducts.product X Y .Product.ump f g .snd .fst .snd = refl hSetProd .HasProducts.product X Y .Product.ump f g .snd .snd (f≡ , g≡) i x = f≡ (~ i) x , g≡ (~ i) x hSetExp : HasExponentials hSetCategory hSetProd hSetExp X Y .Exponential.obj = (X .fst → Y .fst) , hLevelPi 2 λ _ → Y .snd hSetExp X Y .Exponential.eval (f , x) = f x hSetExp X Y .Exponential.uniq X₁ f .fst = curry f hSetExp X Y .Exponential.uniq X₁ f .snd .fst = refl hSetExp X Y .Exponential.uniq X₁ f .snd .snd {y} x = cong curry (sym x) open import Categories.Pullback hSetHasPullbacks : HasPullbacks hSetCategory hSetHasPullbacks {X = X} {Y = Y} {Z = Z} f g .Pullback.P = ∃[ ab ] (f (fst ab) ≡ g (snd ab)) , isOfHLevelΣ 2 (X .snd ⟨×⟩ Y .snd) λ xy → isProp→isSet (Z .snd (f (xy .fst)) (g (xy .snd))) hSetHasPullbacks f g .Pullback.p₁ ((x , _) , _) = x hSetHasPullbacks f g .Pullback.p₂ ((_ , y) , _) = y hSetHasPullbacks f g .Pullback.commute = funExt snd hSetHasPullbacks f g .Pullback.ump {A = A} h₁ h₂ p .fst x = (h₁ x , h₂ x) , λ i → p i x hSetHasPullbacks f g .Pullback.ump {A = A} h₁ h₂ p .snd .fst .fst = refl hSetHasPullbacks f g .Pullback.ump {A = A} h₁ h₂ p .snd .fst .snd = refl hSetHasPullbacks {Z = Z} f g .Pullback.ump {A = A} h₁ h₂ p .snd .snd {i} (p₁e , p₂e) = funExt (λ x → ΣProp≡ (λ _ → Z .snd _ _) λ j → p₁e (~ j) x , p₂e (~ j) x) hSetTerminal : Terminal hSetTerminal .fst = Lift _ ⊤ , isProp→isSet λ _ _ → refl hSetTerminal .snd .fst x .lower = tt hSetTerminal .snd .snd y = funExt λ _ → refl hSetInitial : Initial hSetInitial .fst = Lift _ ⊥ , λ () hSetInitial .snd .fst () hSetInitial .snd .snd y i () open import HITs.PropositionalTruncation open import Categories.Coequalizer ∃!′ : (A : Type a) → (A → Type b) → Type (a ℓ⊔ b) ∃!′ A P = ∥ Σ A P ∥ Prelude.× AtMostOne P lemma23 : ∀ {p} {P : A → hProp p} → ∃!′ A (fst ∘ P) → Σ A (fst ∘ P) lemma23 {P = P} (x , y) = rec (λ xs ys → ΣProp≡ (snd ∘ P) (y (xs .fst) (ys .fst) (xs .snd) (ys .snd))) id x module _ {A : Type a} {P : A → Type b} (R : ∀ x → P x → hProp c) where uniqueChoice : (Π[ x ⦂ A ] (∃!′ (P x) (λ u → R x u .fst))) → Σ[ f ⦂ Π[ x ⦂ A ] P x ] Π[ x ⦂ A ] (R x (f x) .fst) uniqueChoice H = fst ∘ mid , snd ∘ mid where mid : Π[ x ⦂ A ] Σ[ u ⦂ P x ] (R x u .fst) mid x = lemma23 {P = R x} (H x) open import HITs.PropositionalTruncation.Sugar module CoeqProofs {X Y : Ob} (f : X ⟶ Y) where KernelPair : Pullback hSetCategory {X = X} {Z = Y} {Y = X} f f KernelPair = hSetHasPullbacks f f Im : Ob Im = ∃[ b ] ∥ fiber f b ∥ , isOfHLevelΣ 2 (Y .snd) λ _ → isProp→isSet squash im : X ⟶ Im im x = f x , ∣ x , refl ∣ open Pullback KernelPair lem : ∀ {H : Ob} (h : X ⟶ H) → h ∘ p₁ ≡ h ∘ p₂ → Σ[ f ⦂ (Im ⟶ H) ] Π[ x ⦂ Im .fst ] (∀ y → im y ≡ x → h y ≡ f x) lem {H = H} h eq = uniqueChoice R prf where R : Im .fst → H .fst → hProp _ R w x .fst = ∀ y → im y ≡ w → h y ≡ x R w x .snd = hLevelPi 1 λ _ → hLevelPi 1 λ _ → H .snd _ _ prf : Π[ x ⦂ Im .fst ] ∃!′ (H .fst) (λ u → ∀ y → im y ≡ x → h y ≡ u) prf (xy , p) .fst = (λ { (z , r) → h z , λ y imy≡xyp → cong (_$ ((y , z) , cong fst imy≡xyp ; sym r)) eq }) ∥$∥ p prf (xy , p) .snd x₁ x₂ Px₁ Px₂ = rec (H .snd x₁ x₂) (λ { (z , zs) → sym (Px₁ z (ΣProp≡ (λ _ → squash) zs)) ; Px₂ z (ΣProp≡ (λ _ → squash) zs) } ) p lem₂ : ∀ (H : Ob) (h : X ⟶ H) (i : Im ⟶ H) (x : Im .fst) (hi : h ≡ i ∘ im) (eq : h ∘ p₁ ≡ h ∘ p₂) → i x ≡ lem {H = H} h eq .fst x lem₂ H h i x hi eq = rec (H .snd _ _) (λ { (y , ys) → (cong i (ΣProp≡ (λ _ → squash) (sym ys)) ; sym (cong (_$ y) hi)) ; lem {H = H} h eq .snd x y (ΣProp≡ (λ _ → squash) ys) }) (x .snd) hSetCoeq : Coequalizer hSetCategory {X = P} {Y = X} p₁ p₂ hSetCoeq .Coequalizer.obj = Im hSetCoeq .Coequalizer.arr = im hSetCoeq .Coequalizer.equality = funExt λ x → ΣProp≡ (λ _ → squash) λ i → commute i x hSetCoeq .Coequalizer.coequalize {H = H} {h = h} eq = lem {H = H} h eq .fst hSetCoeq .Coequalizer.universal {H = H} {h = h} {eq = eq} = funExt λ x → lem {H = H} h eq .snd (im x) x refl hSetCoeq .Coequalizer.unique {H = H} {h = h} {i = i} {eq = eq} prf = funExt λ x → lem₂ H h i x prf eq open CoeqProofs using (hSetCoeq) public module PullbackSurjProofs {X Y : Ob} (f : X ⟶ Y) (fSurj : Surjective f) where KernelPair : Pullback hSetCategory {X = X} {Z = Y} {Y = X} f f KernelPair = hSetHasPullbacks f f open Pullback KernelPair p₁surj : Surjective p₁ p₁surj y = ∣ ((y , y) , refl) , refl ∣ p₂surj : Surjective p₂ p₂surj y = ∣ ((y , y) , refl) , refl ∣ open import Relation.Binary open import Cubical.HITs.SetQuotients module _ {A : Type a} {R : A → A → Type b} {C : Type c} (isSetC : isSet C) (f : A → C) (coh : ∀ x y → R x y → f x ≡ f y) where recQuot : A / R → C recQuot [ a ] = f a recQuot (eq/ a b r i) = coh a b r i recQuot (squash/ xs ys x y i j) = isSetC (recQuot xs) (recQuot ys) (cong recQuot x) (cong recQuot y) i j open import Path.Reasoning module ExtactProofs {X : Ob} {R : X .fst → X .fst → hProp ℓ} (symR : Symmetric (λ x y → R x y .fst)) (transR : Transitive (λ x y → R x y .fst)) (reflR : Reflexive (λ x y → R x y .fst)) where ℛ : X .fst → X .fst → Type ℓ ℛ x y = R x y .fst Src : Ob Src .fst = ∃[ x,y ] (uncurry ℛ x,y) Src .snd = isOfHLevelΣ 2 (X .snd ⟨×⟩ X .snd) λ _ → isProp→isSet (R _ _ .snd) pr₁ pr₂ : Src ⟶ X pr₁ = fst ∘ fst pr₂ = snd ∘ fst ROb : Ob ROb = X .fst / ℛ , squash/ CR : Coequalizer hSetCategory {X = Src} {Y = X} pr₁ pr₂ CR .Coequalizer.obj = ROb CR .Coequalizer.arr = [_] CR .Coequalizer.equality = funExt λ { ((x , y) , x~y) → eq/ x y x~y} CR .Coequalizer.coequalize {H = H} {h = h} e = recQuot (H .snd) h λ x y x~y → cong (_$ ((x , y) , x~y)) e CR .Coequalizer.universal {H = H} {h = h} {eq = e} = refl CR .Coequalizer.unique {H = H} {h = h} {i = i} {eq = e} p = funExt (elimSetQuotientsProp (λ _ → H .snd _ _) λ x j → p (~ j) x)