module Cat.Diagram.Equaliser.Joint {o ℓ} (C : Precategory o ℓ) where
open Functor
open Cat C
open _=>_
Joint equalisers🔗
The joint equaliser of a family of parallel maps is a straightforward generalisation of the notion of equaliser to more than two maps. The universal property is straightforward to state: the joint equaliser of the is an arrow satisfying which is universal with this property.
record is-joint-equaliser {ℓ'} {I : Type ℓ'} {E x y} (F : I → Hom x y) (equ : Hom E x) : Type (o ⊔ ℓ ⊔ ℓ') where
field
: ∀ {i j} → F i ∘ equ ≡ F j ∘ equ
equal : ∀ {E'} {e' : Hom E' x} (eq : ∀ i j → F i ∘ e' ≡ F j ∘ e') → Hom E' E
universal : ∀ {E'} {e' : Hom E' x} {eq : ∀ i j → F i ∘ e' ≡ F j ∘ e'} → equ ∘ universal eq ≡ e'
factors
unique: ∀ {E'} {e' : Hom E' x} {eq : ∀ i j → F i ∘ e' ≡ F j ∘ e'} {o : Hom E' E}
→ equ ∘ o ≡ e'
→ o ≡ universal eq
unique₂: ∀ {E'} {e' : Hom E' x} {o1 o2 : Hom E' E}
→ (∀ i j → F i ∘ e' ≡ F j ∘ e')
→ equ ∘ o1 ≡ e'
→ equ ∘ o2 ≡ e'
→ o1 ≡ o2
= unique {eq = eq} p ∙ sym (unique q) unique₂ eq p q
A simple calculation tells us that joint equalisers are monic, much like binary equalisers:
: is-monic equ
is-joint-equaliser→is-monic = unique₂ (λ i j → extendl equal) refl (sym x) is-joint-equaliser→is-monic g h x
record Joint-equaliser {ℓ'} {I : Type ℓ'} {x y} (F : I → Hom x y) : Type (o ⊔ ℓ ⊔ ℓ') where
field
{apex} : Ob
: Hom apex x
equ : is-joint-equaliser F equ
has-is-je open is-joint-equaliser has-is-je public
open is-joint-equaliser
Computation🔗
Joint equalisers are also limits. We can define the figure shape that they are limits over as a straightforward generalisation of the parallel-arrows category, where there is an arbitrary set of arrows between the two objects.
module _ {ℓ'} {I : Type ℓ'} ⦃ _ : H-Level I 2 ⦄ {x y} (F : I → Hom x y) where
private module P = Precategory
private
: Precategory _ _
shape .P.Ob = Bool
shape .P.Hom false false = Lift ℓ' ⊤
shape .P.Hom false true = I
shape .P.Hom true false = Lift ℓ' ⊥
shape .P.Hom true true = Lift ℓ' ⊤ shape
Giving this the structure of a category is trivial: other than the parallel arrows, there is nothing to compose with.
.P.Hom-set true true = hlevel 2
shape .P.Hom-set true false = hlevel 2
shape .P.Hom-set false true = hlevel 2
shape .P.Hom-set false false = hlevel 2
shape .P.id {true} = _
shape .P.id {false} = _
shape .P._∘_ {true} {true} {true} f g = lift tt
shape .P._∘_ {false} {true} {true} f g = g
shape .P._∘_ {false} {false} {true} f g = f
shape .P._∘_ {false} {false} {false} f g = lift tt
shape .P.idr {true} {true} f = refl
shape .P.idr {false} {true} f = refl
shape .P.idr {false} {false} f = refl
shape .P.idl {true} {true} f = refl
shape .P.idl {false} {true} f = refl
shape .P.idl {false} {false} f = refl
shape .P.assoc {true} {true} {true} {true} f g h = refl
shape .P.assoc {false} {true} {true} {true} f g h = refl
shape .P.assoc {false} {false} {true} {true} f g h = refl
shape .P.assoc {false} {false} {false} {true} f g h = refl
shape .P.assoc {false} {false} {false} {false} f g h = refl shape
The family of arrows
extends straightforwardly to a functor from this shape
category to
: Functor shape C
diagram .F₀ true = y
diagram .F₀ false = x
diagram .F₁ {true} {true} f = id
diagram .F₁ {false} {true} i = F i
diagram .F₁ {false} {false} f = id
diagram .F-id {true} = refl
diagram .F-id {false} = refl
diagram .F-∘ {true} {true} {true} f g = introl refl
diagram .F-∘ {false} {true} {true} f g = introl refl
diagram .F-∘ {false} {false} {true} f g = intror refl
diagram .F-∘ {false} {false} {false} f g = introl refl diagram
If the family is pointed, and the diagram
has a limit, then this limit is a
joint equaliser of the given arrows. The requirement for a point in the
family ensures that we’re not taking the joint equaliser of no
arrows, which would be a product. Finally, since
joint equalisers are unique, this construction is invariant under the
chosen point; it would thus suffice for the family to be inhabited
instead.
: ∀ {L} {l} → I → is-limit diagram L l → is-joint-equaliser F (l .η false)
is-limit→joint-equaliser {L} {l} ix lim = je where
is-limit→joint-equaliser module l = is-limit lim
: is-joint-equaliser F (l .η false)
je .equal = sym (l .is-natural false true _) ∙ l .is-natural false true _
je .universal {E'} {e'} eq = l.universal
je (λ { true → F ix ∘ e' ; false → e' })
λ { {true} {true} f → eliml refl
; {false} {true} f → eq f ix
; {false} {false} f → eliml refl }
.factors = l.factors _ _
je .unique p = l.unique _ _ _ λ where
je → ap₂ _∘_ (intror refl ∙ l .is-natural false true ix) refl ∙ pullr p
true → p
false
open Joint-equaliser
: I → Limit diagram → Joint-equaliser F
Limit→Joint-equaliser .apex = Limit.apex lim
Limit→Joint-equaliser ix lim .equ = Limit.cone lim .η false
Limit→Joint-equaliser ix lim .has-is-je = is-limit→joint-equaliser ix (Limit.has-limit lim) Limit→Joint-equaliser ix lim