{-# OPTIONS --without-K --safe #-} module Cats.Category.Constructions.Initial where open import Data.Product using (proj₁ ; proj₂) open import Level open import Cats.Category.Base import Cats.Category.Constructions.Iso as Iso import Cats.Category.Constructions.Unique as Unique module Build {lo la l≈} (Cat : Category lo la l≈) where open Category Cat open Iso.Build Cat open Unique.Build Cat IsInitial : Obj → Set (lo ⊔ la ⊔ l≈) IsInitial ⊥ = ∀ X → ∃! ⊥ X record HasInitial : Set (lo ⊔ la ⊔ l≈) where field ⊥ : Obj isInitial : IsInitial ⊥ ¡ : ∀ X → ⊥ ⇒ X ¡ X = ∃!′.arr (isInitial X) ¡-unique : ∀ {X} (f : ⊥ ⇒ X) → ¡ X ≈ f ¡-unique {X} f = ∃!′.unique (isInitial X) _ ⊥⇒-unique : ∀ {X} (f g : ⊥ ⇒ X) → f ≈ g ⊥⇒-unique f g = ≈.trans (≈.sym (¡-unique f)) (¡-unique g) ⊥-unique : ∀ {X} → IsInitial X → X ≅ ⊥ ⊥-unique {X} init = record { forth = init ⊥ .∃!′.arr ; back = ¡ X ; back-forth = ≈.trans (≈.sym (init X .∃!′.unique _)) (init X .∃!′.unique _) ; forth-back = ⊥⇒-unique _ _ } initial-unique : ∀ {X Y} → IsInitial X → IsInitial Y → X ≅ Y initial-unique X-init Y-init = HasInitial.⊥-unique (record { isInitial = Y-init }) X-init open Build public using (HasInitial) private open module Build′ {lo la l≈} {C : Category lo la l≈} = Build C public using (IsInitial ; initial-unique)