{-# OPTIONS --without-K --safe #-}
module Categories.Functor.Construction.Limit where
open import Function using (_$_)
open import Categories.Adjoint
open import Categories.Adjoint.Equivalence
open import Categories.Adjoint.Compose
open import Categories.Adjoint.Properties
open import Categories.Category
open import Categories.Category.Construction.Cones
open import Categories.Category.Complete
open import Categories.Category.Cocomplete
open import Categories.Category.Construction.Functors
open import Categories.Functor
open import Categories.Functor.Construction.Diagonal
open import Categories.Functor.Construction.Constant
open import Categories.NaturalTransformation renaming (id to idN)
open import Categories.NaturalTransformation.NaturalIsomorphism using (_≃_; module ≃)
open import Categories.Diagram.Cone.Properties
open import Categories.Diagram.Duality
import Categories.Diagram.Limit as Lim
import Categories.Diagram.Cone as Con
import Categories.Morphism.Reasoning as MR
module _ {o ℓ e o′ ℓ′ e′} (C : Category o ℓ e) (Com : Complete o′ ℓ′ e′ C) {J : Category o′ ℓ′ e′} where
private
module C = Category C
module J = Category J
open C
open HomReasoning
open Lim.Limit
open Con.Cone⇒ renaming (commute to ⇒-commute)
open MR C
K⇒lim : ∀ {F G : Functor J C} (α : NaturalTransformation F G) (K : Con.Cone F) →
Cones G [ nat-map-Cone α K , limit (Com G) ]
K⇒lim {G = G} α K = rep-cone (Com G) (nat-map-Cone α K)
lim⇒lim : ∀ {F G : Functor J C} (α : NaturalTransformation F G) →
Cones G [ nat-map-Cone α (limit (Com F)) , limit (Com G) ]
lim⇒lim {F} α = K⇒lim α (limit (Com F))
id-Cone : ∀ X → Con.Cone {C = C} {J = J} (const X)
id-Cone X = record
{ apex = record
{ ψ = λ _ → C.id
; commute = λ _ → C.identity²
}
}
X⇒limΔ : ∀ X → Cones (const {C = J} X) [ id-Cone X , limit (Com (const X)) ]
X⇒limΔ X = rep-cone (Com (const X)) _
LimitF : Functor (Functors J C) C
LimitF = record
{ F₀ = λ F → apex (Com F)
; F₁ = λ {F G} α → arr (lim⇒lim α)
; identity = λ {F} → terminal.!-unique (Com F) $ record
{ arr = C.id
; commute = id-comm
}
; homomorphism = λ {F G H} {α β} →
let module α = NaturalTransformation α
module β = NaturalTransformation β
in terminal.!-unique₂ (Com H) {_} {terminal.! (Com H)}
{record { commute = λ {j} → begin
proj (Com H) j ∘ arr (lim⇒lim β) ∘ arr (lim⇒lim α) ≈⟨ pullˡ (⇒-commute (lim⇒lim β)) ⟩
(β.η j ∘ proj (Com G) j) ∘ arr (lim⇒lim α) ≈⟨ assoc ⟩
β.η j ∘ proj (Com G) j ∘ arr (lim⇒lim α) ≈⟨ pushʳ (⇒-commute (lim⇒lim α)) ⟩
(β.η j ∘ α.η j) ∘ proj (Com F) j ∎ }}
; F-resp-≈ = λ {F G} {α β} eq → terminal.!-unique (Com G) $ record
{ commute = ⇒-commute (lim⇒lim β) ○ ∘-resp-≈ˡ (⟺ eq)
}
}
Δ⊣LimitF : ΔF J ⊣ LimitF
Δ⊣LimitF = record
{ unit = ntHelper record
{ η = λ X → rep (Com (const X)) (id-Cone X)
; commute = λ {X Y} f → terminal.!-unique₂ (Com (const Y))
{record
{ apex = record
{ ψ = λ _ → f
; commute = λ _ → C.identityˡ
}
}}
{record
{ commute = cancelˡ (⇒-commute (X⇒limΔ Y))
}}
{record
{ commute =
⇒-commute (Cones (const Y) [ lim⇒lim (constNat f)
∘ nat-map-Cone⇒ (constNat f) (terminal.! (Com (const X)) {id-Cone X}) ])
○ identityʳ
}}
}
; counit = ntHelper record
{ η = counit-nat
; commute = λ α → ⇒-commute (lim⇒lim α)
}
; zig = λ {X} → ⇒-commute (X⇒limΔ X)
; zag = λ {F} →
let apF = apex (Com F)
align : Cones F [ limit (Com F) , nat-map-Cone (counit-nat F) (id-Cone apF) ]
align = record
{ arr = C.id
; commute = identityʳ ○ identityʳ
}
limF⇒limF : Cones F [ limit (Com F) , limit (Com F) ]
limF⇒limF = Cones F [ Cones F [ lim⇒lim (counit-nat F)
∘ nat-map-Cone⇒ (counit-nat F) (terminal.! (Com (const apF))) ]
∘ align ]
in terminal.!-unique₂ (Com F)
{limit (Com F)}
{record { commute = ∘-resp-≈ʳ (⟺ identityʳ) ○ ⇒-commute limF⇒limF }}
{record { commute = identityʳ }}
}
where counit-nat : (F : Functor J C) → NaturalTransformation (const (apex (Com F))) F
counit-nat F = ntHelper record
{ η = proj (Com F)
; commute = λ f → identityʳ ○ ⟺ (limit-commute (Com F) f)
}
module _ {o ℓ e o′ ℓ′ e′} (C : Category o ℓ e) (Coc : Cocomplete o′ ℓ′ e′ C) {J : Category o′ ℓ′ e′} where
private
module C = Category C
module J = Category J
open C
open MR C
Com : Complete o′ ℓ′ e′ C.op
Com F = Colimit⇒coLimit C (Coc (Functor.op F))
LF : Functor (Functors J.op op) C.op
LF = LimitF C.op Com {J.op}
ColimitF : Functor (Functors J C) C
ColimitF = Functor.op LF ∘F opF⇐
ColimitF⊣Δ : ColimitF ⊣ ΔF J
ColimitF⊣Δ = ⊣×≃⇒⊣ helper ≃.refl ΔF≃
where Δ⊣LimitFᵒᵖ : ΔF J.op ⊣ LF
Δ⊣LimitFᵒᵖ = Δ⊣LimitF op Com {J.op}
opF⊣ : opF⇐ {A = J} {B = C} ⊣ opF⇒
opF⊣ = ⊣Equivalence.R⊣L (Functorsᵒᵖ-equiv J C)
helper : ColimitF ⊣ opF⇒ ∘F Functor.op (ΔF J.op)
helper = opF⊣ ∘⊣ Adjoint.op Δ⊣LimitFᵒᵖ
ΔF≃ : opF⇒ ∘F Functor.op (ΔF J.op) ≃ ΔF J
ΔF≃ = record
{ F⇒G = record
{ η = λ _ → idN
; commute = λ _ → id-comm-sym
; sym-commute = λ _ → id-comm
}
; F⇐G = record
{ η = λ _ → idN
; commute = λ _ → id-comm-sym
; sym-commute = λ _ → id-comm
}
; iso = λ X → record
{ isoˡ = identity²
; isoʳ = identity²
}
}