{-# OPTIONS --without-K --safe #-}
open import Categories.Category hiding (_[_,_])
module Categories.Object.Coproduct {o ℓ e} (𝒞 : Category o ℓ e) where
open import Level
open import Function using (flip; _$_)
open Category 𝒞
open import Categories.Morphism.Reasoning 𝒞
open import Categories.Morphism 𝒞
open HomReasoning
private
variable
A B C D X Y Z : Obj
f g h : A ⇒ B
record Coproduct (A B : Obj) : Set (o ⊔ ℓ ⊔ e) where
infix 10 [_,_]
field
A+B : Obj
i₁ : A ⇒ A+B
i₂ : B ⇒ A+B
[_,_] : A ⇒ C → B ⇒ C → A+B ⇒ C
inject₁ : [ f , g ] ∘ i₁ ≈ f
inject₂ : [ f , g ] ∘ i₂ ≈ g
unique : h ∘ i₁ ≈ f → h ∘ i₂ ≈ g → [ f , g ] ≈ h
g-η : [ f ∘ i₁ , f ∘ i₂ ] ≈ f
g-η = unique Equiv.refl Equiv.refl
η : [ i₁ , i₂ ] ≈ id
η = unique identityˡ identityˡ
[]-cong₂ : ∀ {C} → {f f′ : A ⇒ C} {g g′ : B ⇒ C} → f ≈ f′ → g ≈ g′ → [ f , g ] ≈ [ f′ , g′ ]
[]-cong₂ f≈f′ g≈g′ = unique (inject₁ ○ ⟺ f≈f′) (inject₂ ○ ⟺ g≈g′)
∘-distribˡ-[] : ∀ {f : A ⇒ C} {g : B ⇒ C} {q : C ⇒ D} → q ∘ [ f , g ] ≈ [ q ∘ f , q ∘ g ]
∘-distribˡ-[] = ⟺ $ unique (pullʳ inject₁) (pullʳ inject₂)
record IsCoproduct {A B A+B : Obj} (i₁ : A ⇒ A+B) (i₂ : B ⇒ A+B) : Set (o ⊔ ℓ ⊔ e) where
field
[_,_] : A ⇒ C → B ⇒ C → A+B ⇒ C
inject₁ : [ f , g ] ∘ i₁ ≈ f
inject₂ : [ f , g ] ∘ i₂ ≈ g
unique : h ∘ i₁ ≈ f → h ∘ i₂ ≈ g → [ f , g ] ≈ h
Coproduct⇒IsCoproduct : (c : Coproduct A B) → IsCoproduct (Coproduct.i₁ c) (Coproduct.i₂ c)
Coproduct⇒IsCoproduct c = record
{ [_,_] = [_,_]
; inject₁ = inject₁
; inject₂ = inject₂
; unique = unique
}
where
open Coproduct c
IsCoproduct⇒Coproduct : ∀ {C} {i₁ : A ⇒ C} {i₂ : B ⇒ C} → IsCoproduct i₁ i₂ → Coproduct A B
IsCoproduct⇒Coproduct c = record
{ [_,_] = [_,_]
; inject₁ = inject₁
; inject₂ = inject₂
; unique = unique
}
where
open IsCoproduct c
module _ {A B : Obj} where
open Coproduct {A} {B} renaming ([_,_] to _[_,_])
repack : (p₁ p₂ : Coproduct A B) → A+B p₁ ⇒ A+B p₂
repack p₁ p₂ = p₁ [ i₁ p₂ , i₂ p₂ ]
repack∘ : (p₁ p₂ p₃ : Coproduct A B) → repack p₂ p₃ ∘ repack p₁ p₂ ≈ repack p₁ p₃
repack∘ p₁ p₂ p₃ = ⟺ $ unique p₁
(glueTrianglesˡ (inject₁ p₂) (inject₁ p₁))
(glueTrianglesˡ (inject₂ p₂) (inject₂ p₁))
repack≡id : (p : Coproduct A B) → repack p p ≈ id
repack≡id = η
repack-cancel : (p₁ p₂ : Coproduct A B) → repack p₁ p₂ ∘ repack p₂ p₁ ≈ id
repack-cancel p₁ p₂ = repack∘ p₂ p₁ p₂ ○ repack≡id p₂
up-to-iso : ∀ (p₁ p₂ : Coproduct A B) → Coproduct.A+B p₁ ≅ Coproduct.A+B p₂
up-to-iso p₁ p₂ = record
{ from = repack p₁ p₂
; to = repack p₂ p₁
; iso = record
{ isoˡ = repack-cancel p₂ p₁
; isoʳ = repack-cancel p₁ p₂
}
}
transport-by-iso : ∀ (p : Coproduct A B) → ∀ {X} → Coproduct.A+B p ≅ X → Coproduct A B
transport-by-iso p {X} p≅X = record
{ A+B = X
; i₁ = from ∘ i₁
; i₂ = from ∘ i₂
; [_,_] = λ h₁ h₂ → [ h₁ , h₂ ] ∘ to
; inject₁ = cancelInner isoˡ ○ inject₁
; inject₂ = cancelInner isoˡ ○ inject₂
; unique = λ {_ i l r} pf₁ pf₂ → begin
[ l , r ] ∘ to ≈˘⟨ []-cong₂ pf₁ pf₂ ⟩∘⟨refl ⟩
[ i ∘ from ∘ i₁ , i ∘ from ∘ i₂ ] ∘ to ≈⟨ unique assoc assoc ⟩∘⟨refl ⟩
(i ∘ from) ∘ to ≈⟨ cancelʳ isoʳ ⟩
i ∎
}
where open Coproduct p
open _≅_ p≅X
Reversible : (p : Coproduct A B) → Coproduct B A
Reversible p = record
{ A+B = A+B
; i₁ = i₂
; i₂ = i₁
; [_,_] = flip [_,_]
; inject₁ = inject₂
; inject₂ = inject₁
; unique = flip unique
}
where open Coproduct p
Commutative : (p₁ : Coproduct A B) (p₂ : Coproduct B A) → Coproduct.A+B p₁ ≅ Coproduct.A+B p₂
Commutative p₁ p₂ = up-to-iso p₁ (Reversible p₂)
Associable : ∀ (p₁ : Coproduct X Y) (p₂ : Coproduct Y Z) (p₃ : Coproduct X (Coproduct.A+B p₂)) → Coproduct (Coproduct.A+B p₁) Z
Associable p₁ p₂ p₃ = record
{ A+B = A+B p₃
; i₁ = p₁ [ i₁ p₃ , i₂ p₃ ∘ i₁ p₂ ]
; i₂ = i₂ p₃ ∘ i₂ p₂
; [_,_] = λ f g → p₃ [ f ∘ i₁ p₁ , p₂ [ f ∘ i₂ p₁ , g ] ]
; inject₁ = λ {_ f g} → begin
p₃ [ f ∘ i₁ p₁ , p₂ [ f ∘ i₂ p₁ , g ] ] ∘ p₁ [ i₁ p₃ , i₂ p₃ ∘ i₁ p₂ ] ≈⟨ ∘-distribˡ-[] p₁ ⟩
p₁ [ p₃ [ f ∘ i₁ p₁ , p₂ [ f ∘ i₂ p₁ , g ] ] ∘ i₁ p₃
, p₃ [ f ∘ i₁ p₁ , p₂ [ f ∘ i₂ p₁ , g ] ] ∘ i₂ p₃ ∘ i₁ p₂ ] ≈⟨ []-cong₂ p₁ (inject₁ p₃) (glueTrianglesʳ (inject₂ p₃) (inject₁ p₂)) ⟩
p₁ [ f ∘ i₁ p₁ , f ∘ i₂ p₁ ] ≈⟨ g-η p₁ ⟩
f ∎
; inject₂ = λ {_ f g} → glueTrianglesʳ (inject₂ p₃) (inject₂ p₂)
; unique = λ {_ i f g} pf₁ pf₂ → begin
p₃ [ f ∘ i₁ p₁ , p₂ [ f ∘ i₂ p₁ , g ] ] ≈⟨ []-cong₂ p₃ (∘-resp-≈ˡ (sym pf₁))
([]-cong₂ p₂ (∘-resp-≈ˡ (sym pf₁)) (sym pf₂)) ⟩
(p₃ [ (i ∘ p₁ [ i₁ p₃ , i₂ p₃ ∘ i₁ p₂ ]) ∘ i₁ p₁
, p₂ [ (i ∘ p₁ [ i₁ p₃ , i₂ p₃ ∘ i₁ p₂ ]) ∘ i₂ p₁
, i ∘ i₂ p₃ ∘ i₂ p₂ ] ]) ≈⟨ []-cong₂ p₃ (pullʳ (inject₁ p₁))
([]-cong₂ p₂ (trans (pullʳ (inject₂ p₁)) sym-assoc)
sym-assoc) ⟩
(p₃ [ i ∘ i₁ p₃
, p₂ [ (i ∘ i₂ p₃) ∘ i₁ p₂ , (i ∘ i₂ p₃) ∘ i₂ p₂ ] ]) ≈⟨ []-cong₂ p₃ refl (g-η p₂) ⟩
(p₃ [ i ∘ i₁ p₃ , i ∘ i₂ p₃ ]) ≈⟨ g-η p₃ ⟩
i ∎
}
where
open Coproduct renaming ([_,_] to _[_,_])
open Equiv
Associative : ∀ (p₁ : Coproduct X Y) (p₂ : Coproduct Y Z)
(p₃ : Coproduct X (Coproduct.A+B p₂)) (p₄ : Coproduct (Coproduct.A+B p₁) Z) →
(Coproduct.A+B p₃) ≅ (Coproduct.A+B p₄)
Associative p₁ p₂ p₃ p₄ = up-to-iso (Associable p₁ p₂ p₃) p₄
Mobile : ∀ {A₁ B₁ A₂ B₂} (p : Coproduct A₁ B₁) → A₁ ≅ A₂ → B₁ ≅ B₂ → Coproduct A₂ B₂
Mobile p A₁≅A₂ B₁≅B₂ = record
{ A+B = A+B
; i₁ = i₁ ∘ to A₁≅A₂
; i₂ = i₂ ∘ to B₁≅B₂
; [_,_] = λ h k → [ h ∘ from A₁≅A₂ , k ∘ from B₁≅B₂ ]
; inject₁ = begin
[ _ ∘ from A₁≅A₂ , _ ∘ from B₁≅B₂ ] ∘ i₁ ∘ to A₁≅A₂ ≈⟨ pullˡ inject₁ ⟩
(_ ∘ from A₁≅A₂) ∘ to A₁≅A₂ ≈⟨ cancelʳ (isoʳ A₁≅A₂) ⟩
_ ∎
; inject₂ = begin
[ _ ∘ from A₁≅A₂ , _ ∘ from B₁≅B₂ ] ∘ i₂ ∘ to B₁≅B₂ ≈⟨ pullˡ inject₂ ⟩
(_ ∘ from B₁≅B₂) ∘ to B₁≅B₂ ≈⟨ cancelʳ (isoʳ B₁≅B₂) ⟩
_ ∎
; unique = λ pfˡ pfʳ → unique (switch-fromtoʳ (≅-sym A₁≅A₂) ((assoc ○ pfˡ))) (switch-fromtoʳ (≅-sym B₁≅B₂) ((assoc ○ pfʳ)))
}
where open Coproduct p
open _≅_
open ≅ using () renaming (sym to ≅-sym)