open import Cat.Prelude

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

CoequalisersπŸ”—

The coequaliser of two maps f,g:A→Bf, g : A \to B (if it exists), represents the largest quotient object of BB that identifies ff and gg.

record is-coequaliser {E} (f g : Hom A B) (coeq : Hom B E) : Type (o βŠ” β„“) where
  field
    coequal    : coeq ∘ f ≑ coeq ∘ g
    coequalise : βˆ€ {F} {eβ€² : Hom B F} (p : eβ€² ∘ f ≑ eβ€² ∘ g) β†’ Hom E F
    universal  : βˆ€ {F} {eβ€² : Hom B F} {p : eβ€² ∘ f ≑ eβ€² ∘ g}
               β†’ coequalise p ∘ coeq ≑ eβ€²

    unique     : βˆ€ {F} {eβ€² : Hom B F} {p : eβ€² ∘ f ≑ eβ€² ∘ g} {colim : Hom E F}
               β†’ eβ€² ≑ colim ∘ coeq
               β†’ colim ≑ coequalise p

  uniqueβ‚‚
    : βˆ€ {F} {eβ€² : Hom B F} {p : eβ€² ∘ f ≑ eβ€² ∘ g} {colim' colim'' : Hom E F}
    β†’ eβ€² ≑ colim' ∘ coeq
    β†’ eβ€² ≑ colim'' ∘ coeq
    β†’ colim' ≑ colim''
  uniqueβ‚‚ {p = p} q r = unique {p = p} q βˆ™ sym (unique r)

  id-coequalise : id ≑ coequalise coequal
  id-coequalise = unique (sym (idl _))

There is also a convenient bundling of an coequalising arrow together with its codomain:

record Coequaliser (f g : Hom A B) : Type (o βŠ” β„“) where
  field
    {coapex}  : Ob
    coeq      : Hom B coapex
    has-is-coeq : is-coequaliser f g coeq

  open is-coequaliser has-is-coeq public

Coequalisers are epicπŸ”—

Dually to the situation with [equalisers], coequaliser arrows are always epic:

is-coequaliser→is-epic
  : βˆ€ {E} (coequ : Hom A E)
  β†’ is-coequaliser f g coequ
  β†’ is-epic coequ
is-coequaliser→is-epic {f = f} {g = g} equ equalises h i p =
  h                            β‰‘βŸ¨ unique (sym p) βŸ©β‰‘
  coequalise (extendr coequal) β‰‘Λ˜βŸ¨ unique refl βŸ©β‰‘Λ˜
  i                            ∎
  where open is-coequaliser equalises

coequaliser-unique
  : βˆ€ {E Eβ€²} {c1 : Hom A E} {c2 : Hom A Eβ€²}
  β†’ is-coequaliser f g c1
  β†’ is-coequaliser f g c2
  β†’ E β‰… Eβ€²
coequaliser-unique {c1 = c1} {c2} co1 co2 =
  make-iso
    (co1 .coequalise {eβ€² = c2} (co2 .coequal))
    (co2 .coequalise {eβ€² = c1} (co1 .coequal))
    (uniqueβ‚‚ co2 {p = co2 .coequal} (sym (pullr (co2 .universal) βˆ™ co1 .universal)) (introl refl))
    (uniqueβ‚‚ co1 {p = co1 .coequal} (sym (pullr (co1 .universal) βˆ™ co2 .universal)) (introl refl))
  where open is-coequaliser