module Cat.Diagram.Equaliser.Joint {o β„“} (C : Precategory o β„“) where

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
    equal     : βˆ€ {i j} β†’ F i ∘ equ ≑ F j ∘ equ
    universal : βˆ€ {E'} {e' : Hom E' x} (eq : βˆ€ i j β†’ F i ∘ e' ≑ F j ∘ e') β†’ Hom E' E
    factors   : βˆ€ {E'} {e' : Hom E' x} {eq : βˆ€ i j β†’ F i ∘ e' ≑ F j ∘ e'} β†’ equ ∘ universal eq ≑ e'
    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

A simple calculation tells us that joint equalisers are monic, much like binary equalisers:

  is-joint-equaliser→is-monic : is-monic equ
  is-joint-equaliser→is-monic g h x = unique₂ (λ i j → extendl equal) refl (sym x)

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
    shape : 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 β„“' ⊀
Giving this the structure of a category is trivial: other than the parallel arrows, there is nothing to compose with.
    shape .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

The family of arrows extends straightforwardly to a functor from this shape category to

    diagram : 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

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.

  is-limitβ†’joint-equaliser : βˆ€ {L} {l} β†’ I β†’ is-limit diagram L l β†’ is-joint-equaliser F (l .Ξ· false)
  is-limit→joint-equaliser {L} {l} ix lim = je where
    module l = is-limit lim
    je : 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
      (Ξ» { true β†’ F ix ∘ e' ; false β†’ e' })
      Ξ» { {true}  {true}  f β†’ eliml refl
        ; {false} {true}  f β†’ eq f ix
        ; {false} {false} f β†’ eliml refl }
    je .factors = l.factors _ _
    je .unique p = l.unique _ _ _ Ξ» where
      true  β†’ apβ‚‚ _∘_ (intror refl βˆ™ l .is-natural false true ix) refl βˆ™ pullr p
      false β†’ p

  open Joint-equaliser

  Limit→Joint-equaliser : I → Limit diagram → Joint-equaliser F
  Limit→Joint-equaliser ix lim .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)