module Prelude.Category.Span where
open import Prelude.Equality
open import Prelude.Category
open import Prelude.Category.Isomorphism
open import Prelude.Category.Isomorphism.Functor
open import Prelude.Category.Slice
open import Level
open import Function using (_∘_)
open import Data.Product using (Σ; Σ-syntax; _,_; proj₁; _×_)
open import Relation.Binary using (module Setoid)
open import Relation.Binary.PropositionalEquality using (_≡_; refl)
open Functor
record Span {ℓ₀ ℓ₁ ℓ₂ : Level} (C : Category {ℓ₀} {ℓ₁} {ℓ₂}) (L R : Category.Object C) : Set (ℓ₀ ⊔ ℓ₁) where
constructor span
open Category C
field
M : Object
l : M ==> L
r : M ==> R
record SpanMorphism {ℓ₀ ℓ₁ ℓ₂ : Level} (C : Category {ℓ₀} {ℓ₁} {ℓ₂}) (L R : Category.Object C) (s t : Span C L R) : Set (ℓ₁ ⊔ ℓ₂) where
constructor spanMorphism
open Category C
field
m : Span.M s ==> Span.M t
triangle-l : Span.l t · m ≈ Span.l s
triangle-r : Span.r t · m ≈ Span.r s
SpanCategory : {ℓ₀ ℓ₁ ℓ₂ : Level} (C : Category {ℓ₀} {ℓ₁} {ℓ₂}) (L R : Category.Object C) → Category
SpanCategory C L R =
record { Object = Span C L R
; Morphism = λ s t → toSetoid (Morphism (Span.M s) (Span.M t)) (SpanMorphism.m {_} {_} {_} {C} {L} {R})
; _·_ = λ f g → spanMorphism (SpanMorphism.m f · SpanMorphism.m g)
(two-triangles C L (sliceMorphism (SpanMorphism.m f) (SpanMorphism.triangle-l f))
(sliceMorphism (SpanMorphism.m g) (SpanMorphism.triangle-l g)))
(two-triangles C R (sliceMorphism (SpanMorphism.m f) (SpanMorphism.triangle-r f))
(sliceMorphism (SpanMorphism.m g) (SpanMorphism.triangle-r g)))
; id = λ {s} → spanMorphism id (id-r (Span.l s)) (id-r (Span.r s))
; id-l = λ f → id-l (SpanMorphism.m f)
; id-r = λ f → id-r (SpanMorphism.m f)
; assoc = λ f g h → assoc (SpanMorphism.m f) (SpanMorphism.m g) (SpanMorphism.m h)
; cong-l = λ h → cong-l (SpanMorphism.m h)
; cong-r = λ h → cong-r (SpanMorphism.m h) }
where open Category C
SpanU : {ℓ₀ ℓ₁ ℓ₂ : Level} {C : Category {ℓ₀} {ℓ₁} {ℓ₂}} {L R : Category.Object C} → Functor (SpanCategory C L R) C
SpanU {C = C} =
record { object = Span.M
; morphism = SpanMorphism.m
; ≈-respecting = Function.id
; id-preserving = λ {s} → Setoid.refl (Category.Morphism C (Span.M s) (Span.M s))
; comp-preserving = λ {s} {t} {u} f g → Setoid.refl (Category.Morphism C (Span.M s) (Span.M u)) }
SpanFlip : {ℓ₀ ℓ₁ ℓ₂ : Level} {C : Category {ℓ₀} {ℓ₁} {ℓ₂}} {L R : Category.Object C} → Functor (SpanCategory C L R) (SpanCategory C R L)
SpanFlip {C = C} =
record { object = λ s → span (Span.M s) (Span.r s) (Span.l s)
; morphism = λ f → spanMorphism (SpanMorphism.m f) (SpanMorphism.triangle-r f) (SpanMorphism.triangle-l f)
; ≈-respecting = Function.id
; id-preserving = λ {s} → Setoid.refl (Category.Morphism C (Span.M s) (Span.M s))
; comp-preserving = λ {s} {t} {u} f g → Setoid.refl (Category.Morphism C (Span.M s) (Span.M u)) }
SpanUL : {ℓ₀ ℓ₁ ℓ₂ : Level} {C : Category {ℓ₀} {ℓ₁} {ℓ₂}} {L R : Category.Object C} → Functor (SpanCategory C L R) (SliceCategory C L)
SpanUL {C = C} =
record { object = λ s → slice (Span.M s) (Span.l s)
; morphism = λ f → sliceMorphism (SpanMorphism.m f) (SpanMorphism.triangle-l f)
; ≈-respecting = Function.id
; id-preserving = λ {s} → Setoid.refl (Category.Morphism C (Span.M s) (Span.M s))
; comp-preserving = λ {s} {t} {u} f g → Setoid.refl (Category.Morphism C (Span.M s) (Span.M u)) }
SpanUR : {ℓ₀ ℓ₁ ℓ₂ : Level} {C : Category {ℓ₀} {ℓ₁} {ℓ₂}} {L R : Category.Object C} → Functor (SpanCategory C L R) (SliceCategory C R)
SpanUR = SpanUL ⋆ SpanFlip
SpanMap : {ℓ₀ ℓ₁ ℓ₂ ℓ₃ ℓ₄ ℓ₅ : Level} {C : Category {ℓ₀} {ℓ₁} {ℓ₂}} {D : Category {ℓ₃} {ℓ₄} {ℓ₅}} (F : Functor C D) →
{L R : Category.Object C} → Functor (SpanCategory C L R) (SpanCategory D (object F L) (object F R))
SpanMap F =
record { object = λ { (span M l r) → span (object F M) (morphism F l) (morphism F r) }
; morphism = λ f → spanMorphism (morphism F (SpanMorphism.m f))
(SliceMorphism.triangle (morphism (SliceMap F) (morphism SpanUL f)))
(SliceMorphism.triangle (morphism (SliceMap F) (morphism SpanUR f)))
; ≈-respecting = ≈-respecting F
; id-preserving = id-preserving F
; comp-preserving = λ f g → comp-preserving F (SpanMorphism.m f) (SpanMorphism.m g) }
span-mid-iso : {ℓ₀ ℓ₁ ℓ₂ : Level} {C : Category {ℓ₀} {ℓ₁} {ℓ₂}} {L R : Category.Object C} →
(s : Span C L R) (X : Category.Object C) (i : Iso C (Span.M s) X) → Σ (Span C L R) (Iso (SpanCategory C L R) s)
span-mid-iso {C = C} {L} {R} (span M l r) X i =
span X (l · Iso.from i) (r · Iso.from i) ,
record { to = spanMorphism (Iso.to i)
(Setoid.trans (Morphism M L) (assoc l (Iso.from i) (Iso.to i))
(Setoid.trans (Morphism M L) (cong-l l (Iso.from-to-inverse i)) (id-r l)))
(Setoid.trans (Morphism M R) (assoc r (Iso.from i) (Iso.to i))
(Setoid.trans (Morphism M R) (cong-l r (Iso.from-to-inverse i)) (id-r r)))
; from = spanMorphism (Iso.from i) (Setoid.refl (Morphism X L)) (Setoid.refl (Morphism X R))
; from-to-inverse = Iso.from-to-inverse i
; to-from-inverse = Iso.to-from-inverse i }
where open Category C
Product : {ℓ₀ ℓ₁ ℓ₂ : Level} (C : Category {ℓ₀} {ℓ₁} {ℓ₂}) (L R : Category.Object C) → Span C L R → Set (ℓ₀ ⊔ ℓ₁ ⊔ ℓ₂)
Product C L R = Terminal (SpanCategory C L R)
product-iso : {ℓ₀ ℓ₁ ℓ₂ : Level} (C : Category {ℓ₀} {ℓ₁} {ℓ₂}) (L R : Category.Object C) (s t : Span C L R) →
Product C L R s → Product C L R t → Iso C (Span.M s) (Span.M t)
product-iso C L R s t prod-s prod-t = iso-preserving SpanU (terminal-iso (SpanCategory C L R) s t prod-s prod-t)
Product-preserving :
{ℓ₀ ℓ₁ ℓ₂ ℓ₃ ℓ₄ ℓ₅ : Level} {C : Category {ℓ₀} {ℓ₁} {ℓ₂}} {D : Category {ℓ₃} {ℓ₄} {ℓ₅}} → (F : Functor C D) → Set (ℓ₀ ⊔ ℓ₁ ⊔ ℓ₂ ⊔ ℓ₃ ⊔ ℓ₄ ⊔ ℓ₅)
Product-preserving {C = C} {D = D} F =
(L R : Category.Object C) (s : Span C L R) (p : Product C L R s) → Product D (object F L) (object F R) (object (SpanMap F) s)