{-# OPTIONS --without-K --safe #-}
open import Categories.Category.Core using (Category)
open import Categories.Category.CartesianClosed using (CartesianClosed; module CartesianMonoidalClosed)
module Categories.Category.CartesianClosed.Properties {o ℓ e} {𝒞 : Category o ℓ e} (𝓥 : CartesianClosed 𝒞) where
open import Level
open import Data.Product using (Σ; _,_; Σ-syntax; proj₁; proj₂)
open import Categories.Adjoint.Properties using (lapc)
open import Categories.Category.BinaryProducts using (BinaryProducts)
open import Categories.Category.Cartesian using (Cartesian)
open import Categories.Category.Monoidal.Closed using (Closed)
open import Categories.Diagram.Colimit using (Colimit)
open import Categories.Diagram.Empty 𝒞 using (empty)
open import Categories.Functor using (Functor; _∘F_)
open import Categories.Morphism.Reasoning 𝒞 using (pullˡ)
open import Categories.Object.Initial 𝒞 using (Initial; IsInitial)
open import Categories.Object.Initial.Colimit 𝒞 using (⊥⇒colimit; colimit⇒⊥)
open import Categories.Object.StrictInitial 𝒞 using (IsStrictInitial)
open import Categories.Object.Terminal using (Terminal)
open Category 𝒞
open CartesianClosed 𝓥 using (_^_; eval′; cartesian)
open Cartesian cartesian using (products; terminal)
open CartesianMonoidalClosed 𝒞 𝓥 using (closedMonoidal)
open BinaryProducts products
open Terminal terminal using (⊤)
open HomReasoning
private
module closedMonoidal = Closed closedMonoidal
PointSurjective : ∀ {A X Y : Obj} → (X ⇒ Y ^ A) → Set (ℓ ⊔ e)
PointSurjective {A = A} {X = X} {Y = Y} ϕ =
∀ (f : A ⇒ Y) → Σ[ x ∈ ⊤ ⇒ X ] (∀ (a : ⊤ ⇒ A) → eval′ ∘ first ϕ ∘ ⟨ x , a ⟩ ≈ f ∘ a)
lawvere-fixed-point : ∀ {A B : Obj} → (ϕ : A ⇒ B ^ A) → PointSurjective ϕ → (f : B ⇒ B) → Σ[ s ∈ ⊤ ⇒ B ] f ∘ s ≈ s
lawvere-fixed-point {A = A} {B = B} ϕ surjective f = g ∘ x , g-fixed-point
where
g : A ⇒ B
g = f ∘ eval′ ∘ ⟨ ϕ , id ⟩
x : ⊤ ⇒ A
x = proj₁ (surjective g)
g-surjective : eval′ ∘ first ϕ ∘ ⟨ x , x ⟩ ≈ g ∘ x
g-surjective = proj₂ (surjective g) x
lemma : ∀ {A B C D} → (f : B ⇒ C) → (g : B ⇒ D) → (h : A ⇒ B) → (f ⁂ g) ∘ ⟨ h , h ⟩ ≈ ⟨ f , g ⟩ ∘ h
lemma f g h = begin
(f ⁂ g) ∘ ⟨ h , h ⟩ ≈⟨ ⁂∘⟨⟩ ⟩
⟨ f ∘ h , g ∘ h ⟩ ≈˘⟨ ⟨⟩∘ ⟩
⟨ f , g ⟩ ∘ h ∎
g-fixed-point : f ∘ (g ∘ x) ≈ g ∘ x
g-fixed-point = begin
f ∘ g ∘ x ≈˘⟨ refl⟩∘⟨ g-surjective ⟩
f ∘ eval′ ∘ first ϕ ∘ ⟨ x , x ⟩ ≈⟨ refl⟩∘⟨ refl⟩∘⟨ lemma ϕ id x ⟩
f ∘ eval′ ∘ ⟨ ϕ , id ⟩ ∘ x ≈⟨ ∘-resp-≈ʳ sym-assoc ○ sym-assoc ⟩
(f ∘ eval′ ∘ ⟨ ϕ , id ⟩) ∘ x ≡⟨⟩
g ∘ x ∎
initial→product-initial : ∀ {⊥ A} → IsInitial ⊥ → IsInitial (⊥ × A)
initial→product-initial {⊥} {A} i = initial.⊥-is-initial
where colim : Colimit (empty o ℓ e)
colim = ⊥⇒colimit record { ⊥ = ⊥ ; ⊥-is-initial = i }
colim' : Colimit (-× A ∘F (empty o ℓ e))
colim' = lapc closedMonoidal.adjoint (empty o ℓ e) colim
initial : Initial
initial = colimit⇒⊥ colim'
module initial = Initial initial
open IsStrictInitial using (is-initial; is-strict)
initial→strict-initial : ∀ {⊥} → IsInitial ⊥ → IsStrictInitial ⊥
initial→strict-initial i .is-initial = i
initial→strict-initial {⊥} i .is-strict f = record
{ from = f
; to = !
; iso = record
{ isoˡ = begin
! ∘ f ≈˘⟨ refl⟩∘⟨ project₁ ⟩
! ∘ π₁ ∘ ⟨ f , id ⟩ ≈⟨ pullˡ (initial-product.!-unique₂ (! ∘ π₁) π₂) ⟩
π₂ ∘ ⟨ f , id ⟩ ≈⟨ project₂ ⟩
id ∎
; isoʳ = !-unique₂ (f ∘ !) id
}
}
where open IsInitial i
module initial-product {A} =
IsInitial (initial→product-initial {⊥} {A} i)