module Cat.Morphism {o h} (C : Precategory o h) where

Morphisms🔗

This module defines the three most important classes of morphisms that can be found in a category: monomorphisms, epimorphisms, and isomorphisms.

Monos🔗

A morphism is said to be monic when it is left-cancellable. A monomorphism from AA to BB, written ABA \hookrightarrow B, is a monic morphism.

is-monic : Hom a b  Type _
is-monic {a = a} f =  {c}  (g h : Hom c a)  f ∘ g ≡ f ∘ h  g ≡ h

is-monic-is-prop :  {a b} (f : Hom a b)  is-prop (is-monic f)
is-monic-is-prop f x y i {c} g h p = Hom-set _ _ _ _ (x g h p) (y g h p) i

record __ (a b : Ob) : Type (o ⊔ h) where
  field
    mor   : Hom a b
    monic : is-monic mor

open __ public

Conversely, a morphism is said to be epic when it is right-cancellable. An epimorphism from AA to BB, written ABA \twoheadrightarrow B, is an epic morphism.

Epis🔗

is-epic : Hom a b  Type _
is-epic {b = b} f =  {c}  (g h : Hom b c)  g ∘ f ≡ h ∘ f  g ≡ h

is-epic-is-prop :  {a b} (f : Hom a b)  is-prop (is-epic f)
is-epic-is-prop f x y i {c} g h p = Hom-set _ _ _ _ (x g h p) (y g h p) i

record __ (a b : Ob) : Type (o ⊔ h) where
  field
    mor  : Hom a b
    epic : is-epic mor

open __ public

The identity morphism is monic and epic.

id-monic :  {a}  is-monic (id {a})
id-monic g h p = sym (idl _) ·· p ·· idl _

id-epic :  {a}  is-epic (id {a})
id-epic g h p = sym (idr _) ·· p ·· idr _

Both monos and epis are closed under composition.

monic-∘
  :  {a b c} {f : Hom b c} {g : Hom a b}
   is-monic f
   is-monic g
   is-monic (f ∘ g)
monic-∘ fm gm a b α = gm _ _ (fm _ _ (assoc _ _ _ ·· α ·· sym (assoc _ _ _)))

epic-∘
  :  {a b c} {f : Hom b c} {g : Hom a b}
   is-epic f
   is-epic g
   is-epic (f ∘ g)
epic-∘ fe ge a b α = fe _ _ (ge _ _ (sym (assoc _ _ _) ·· α ·· (assoc _ _ _)))

_∘Mono_ :  {a b c}  b ↪ c  a ↪ b  a ↪ c
(f ∘Mono g) .mor = f .mor ∘ g .mor
(f ∘Mono g) .monic = monic-∘ (f .monic) (g .monic)

_∘Epi_ :  {a b c}  b ↠ c  a ↠ b  a ↠ c
(f ∘Epi g) .mor = f .mor ∘ g .mor
(f ∘Epi g) .epic = epic-∘ (f .epic) (g .epic)

If fgf \circ g is monic, then gg must also be monic.

monic-cancell
  :  {a b c} {f : Hom b c} {g : Hom a b}
   is-monic (f ∘ g)
   is-monic g
monic-cancell {f = f} fg-monic h h' p = fg-monic h h' $
  sym (assoc _ _ _) ·· ap (f ∘_) p ·· assoc _ _ _

Dually, if fgf \circ g is epic, then ff must also be epic.

epic-cancelr
  :  {a b c} {f : Hom b c} {g : Hom a b}
   is-epic (f ∘ g)
   is-epic f
epic-cancelr {g = g} fg-epic h h' p = fg-epic h h' $
  assoc _ _ _ ·· ap (_∘ g) p ·· sym (assoc _ _ _)

Postcomposition with a mono is an embedding.

monic-postcomp-embedding
  :  {a b c} {f : Hom b c}
   is-monic f
   is-embedding {A = Hom a b} (f ∘_)
monic-postcomp-embedding monic =
  injective→is-embedding (Hom-set _ _) _ (monic _ _)

Likewise, precomposition with an epi is an embedding.

epic-precomp-embedding
  :  {a b c} {f : Hom a b}
   is-epic f
   is-embedding {A = Hom b c} (_∘ f)
epic-precomp-embedding epic =
  injective→is-embedding (Hom-set _ _) _ (epic _ _)

Sections🔗

A morphism s:BAs : B \to A is a section of another morphism r:ABr : A \to B when rs=idr \cdot s = id. The intuition for this name is that ss picks out a cross-section of aa from bb. For instance, rr could map animals to their species; a section of this map would have to pick out a canonical representative of each species from the set of all animals.

_section-of_ : (s : Hom b a) (r : Hom a b)  Type _
s section-of r = r ∘ s ≡ id

section-of-is-prop
  :  {s : Hom b a} {r : Hom a b}
   is-prop (s section-of r)
section-of-is-prop = Hom-set _ _ _ _

record has-section (r : Hom a b) : Type h where
  constructor make-section
  field
    section : Hom b a
    is-section : section section-of r

open has-section public

id-has-section :  {a}  has-section (id {a})
id-has-section .section = id
id-has-section .is-section = idl _

section-of-∘
  :  {a b c} {f : Hom c b} {g : Hom b c} {h : Hom b a} {i : Hom a b}
   f section-of g  h section-of i
   (h ∘ f) section-of (g ∘ i)
section-of-∘ {f = f} {g = g} {h = h} {i = i} fg-sect hi-sect =
  (g ∘ i) ∘ h ∘ f ≡⟨ cat! C ⟩
  g ∘ (i ∘ h) ∘ f ≡⟨ ap  ϕ  g ∘ ϕ ∘ f) hi-sect ⟩
  g ∘ id ∘ f      ≡⟨ ap (g ∘_) (idl _)
  g ∘ f           ≡⟨ fg-sect ⟩
  id ∎

section-∘
  :  {a b c} {f : Hom b c} {g : Hom a b}
   has-section f  has-section g  has-section (f ∘ g)
section-∘ f-sect g-sect .section = g-sect .section ∘ f-sect .section
section-∘ {f = f} {g = g} f-sect g-sect .is-section =
  section-of-∘ (f-sect .is-section) (g-sect .is-section)

If ff has a section, then ff is epic.

has-section→epic
  :  {a b} {f : Hom a b}
   has-section f
   is-epic f
has-section→epic {f = f} f-sect g h p =
  g                         ≡˘⟨ idr _
  g ∘ id                    ≡˘⟨ ap (g ∘_) (f-sect .is-section)
  g ∘ f ∘ f-sect .section   ≡⟨ assoc _ _ _
  (g ∘ f) ∘ f-sect .section ≡⟨ ap (_∘ f-sect .section) p ⟩
  (h ∘ f) ∘ f-sect .section ≡˘⟨ assoc _ _ _
  h ∘ f ∘ f-sect .section   ≡⟨ ap (h ∘_) (f-sect .is-section)
  h ∘ id                    ≡⟨ idr _
  h ∎

Retracts🔗

A morphism r:ABr : A \to B is a retract of another morphism s:BAs : B \to A when rs=idr \cdot s = id. Note that this is the same equation involved in the definition of a section; retracts and sections always come in pairs. If sections solve a sort of “curation problem” where we are asked to pick out canonical representatives, then retracts solve a sort of “classification problem”.

_retract-of_ : (r : Hom a b) (s : Hom b a)  Type _
r retract-of s = r ∘ s ≡ id

retract-of-is-prop
  :  {s : Hom b a} {r : Hom a b}
   is-prop (r retract-of s)
retract-of-is-prop = Hom-set _ _ _ _

record has-retract (s : Hom b a) : Type h where
  constructor make-retract
  field
    retract : Hom a b
    is-retract : retract retract-of s

open has-retract public

id-has-retract :  {a}  has-retract (id {a})
id-has-retract .retract = id
id-has-retract .is-retract = idl _

retract-of-∘
  :  {a b c} {f : Hom c b} {g : Hom b c} {h : Hom b a} {i : Hom a b}
   f retract-of g  h retract-of i
   (h ∘ f) retract-of (g ∘ i)
retract-of-∘ fg-ret hi-ret = section-of-∘ hi-ret fg-ret

retract-∘
  :  {a b c} {f : Hom b c} {g : Hom a b}
   has-retract f  has-retract g
   has-retract (f ∘ g)
retract-∘ f-ret g-ret .retract = g-ret .retract ∘ f-ret .retract
retract-∘ f-ret g-ret .is-retract =
  retract-of-∘ (f-ret .is-retract) (g-ret .is-retract)

If ff has a retract, then ff is monic.

has-retract→monic
  :  {a b} {f : Hom a b}
   has-retract f
   is-monic f
has-retract→monic {f = f} f-ret g h p =
  g                        ≡˘⟨ idl _
  id ∘ g                   ≡˘⟨ ap (_∘ g) (f-ret .is-retract)
  (f-ret .retract ∘ f) ∘ g ≡˘⟨ assoc _ _ _
  f-ret .retract ∘ (f ∘ g) ≡⟨ ap (f-ret .retract ∘_) p ⟩
  f-ret .retract ∘ f ∘ h   ≡⟨ assoc _ _ _
  (f-ret .retract ∘ f) ∘ h ≡⟨ ap (_∘ h) (f-ret .is-retract)
  id ∘ h                   ≡⟨ idl _
  h                        ∎

A section that is also epic is a retract.

section-of+epic→retract-of
  :  {a b} {s : Hom b a} {r : Hom a b}
   s section-of r
   is-epic s
   s retract-of r
section-of+epic→retract-of {s = s} {r = r} sect epic =
  epic (s ∘ r) id $
    (s ∘ r) ∘ s ≡˘⟨ assoc s r s ⟩
    s ∘ (r ∘ s) ≡⟨ ap (s ∘_) sect ⟩
    s ∘ id      ≡⟨ idr _
    s           ≡˘⟨ idl _
    id ∘ s      ∎

Dually, a retract that is also monic is a section.

retract-of+monic→section-of
  :  {a b} {s : Hom b a} {r : Hom a b}
   r retract-of s
   is-monic r
   r section-of s
retract-of+monic→section-of {s = s} {r = r} ret monic =
  monic (s ∘ r) id $
    r ∘ s ∘ r   ≡⟨ assoc r s r ⟩
    (r ∘ s) ∘ r ≡⟨ ap (_∘ r) ret ⟩
    id ∘ r      ≡⟨ idl _
    r           ≡˘⟨ idr _
    r ∘ id      ∎

Isos🔗

Maps f:ABf : A \to B and g:BAg : B \to A are inverses when we have fgf \circ g and gfg \circ f both equal to the identity. A map f:ABf : A \to B is invertible (or is an isomorphism) when there exists a gg for which ff and gg are inverses. An isomorphism ABA \cong B is a choice of map ABA \to B, together with a specified inverse.

record Inverses (f : Hom a b) (g : Hom b a) : Type h where
  field
    invl : f ∘ g ≡ id
    invr : g ∘ f ≡ id

open Inverses

record is-invertible (f : Hom a b) : Type h where
  field
    inv : Hom b a
    inverses : Inverses f inv

  open Inverses inverses public

  op : is-invertible inv
  op .inv = f
  op .inverses .Inverses.invl = invr inverses
  op .inverses .Inverses.invr = invl inverses

record __ (a b : Ob) : Type h where
  field
    to       : Hom a b
    from     : Hom b a
    inverses : Inverses to from

  open Inverses inverses public

open __ public

A given map is invertible in at most one way: If you have f:ABf : A \to B with two inverses g:BAg : B \to A and h:BAh : B \to A, then not only are g=hg = h equal, but the witnesses of these equalities are irrelevant.

Inverses-are-prop :  {f : Hom a b} {g : Hom b a}  is-prop (Inverses f g)
Inverses-are-prop x y i .Inverses.invl = Hom-set _ _ _ _ (x .invl) (y .invl) i
Inverses-are-prop x y i .Inverses.invr = Hom-set _ _ _ _ (x .invr) (y .invr) i

is-invertible-is-prop :  {f : Hom a b}  is-prop (is-invertible f)
is-invertible-is-prop {a = a} {b = b} {f = f} g h = p where
  module g = is-invertible g
  module h = is-invertible h

  g≡h : g.inv ≡ h.inv
  g≡h =
    g.inv             ≡⟨ sym (idr _) ∙ ap₂ __ refl (sym h.invl)
    g.inv ∘ f ∘ h.inv ≡⟨ assoc _ _ _ ·· ap₂ __ g.invr refl ·· idl _
    h.inv             ∎

  p : g ≡ h
  p i .is-invertible.inv = g≡h i
  p i .is-invertible.inverses =
    is-prop→pathp  i  Inverses-are-prop {g = g≡h i}) g.inverses h.inverses i

We note that the identity morphism is always iso, and that isos compose:

id-invertible :  {a}  is-invertible (id {a})
id-invertible .is-invertible.inv = id
id-invertible .is-invertible.inverses .invl = idl id
id-invertible .is-invertible.inverses .invr = idl id

id-iso : a ≅ a
id-iso .to = id
id-iso .from = id
id-iso .inverses .invl = idl id
id-iso .inverses .invr = idl id

Isomorphism = __

Inverses-∘ : {f : Hom a b} {f⁻¹ : Hom b a} {g : Hom b c} {g⁻¹ : Hom c b}
            Inverses f f⁻¹  Inverses g g⁻¹  Inverses (g ∘ f) (f⁻¹ ∘ g⁻¹)
Inverses-∘ {f = f} {f⁻¹} {g} {g⁻¹} finv ginv = record { invl = l ; invr = r } where
  module finv = Inverses finv
  module ginv = Inverses ginv

  abstract
    l : (g ∘ f) ∘ f⁻¹ ∘ g⁻¹ ≡ id
    l = (g ∘ f) ∘ f⁻¹ ∘ g⁻¹ ≡⟨ cat! C ⟩
        g ∘ (f ∘ f⁻¹) ∘ g⁻¹ ≡⟨  i  g ∘ finv.invl i ∘ g⁻¹)
        g ∘ id ∘ g⁻¹        ≡⟨ cat! C ⟩
        g ∘ g⁻¹             ≡⟨ ginv.invl ⟩
        id                  ∎

    r : (f⁻¹ ∘ g⁻¹) ∘ g ∘ f ≡ id
    r = (f⁻¹ ∘ g⁻¹) ∘ g ∘ f ≡⟨ cat! C ⟩
        f⁻¹ ∘ (g⁻¹ ∘ g) ∘ f ≡⟨  i  f⁻¹ ∘ ginv.invr i ∘ f)
        f⁻¹ ∘ id ∘ f        ≡⟨ cat! C ⟩
        f⁻¹ ∘ f             ≡⟨ finv.invr ⟩
        id                  ∎

_∘Iso_ : a ≅ b  b ≅ c  a ≅ c
(f ∘Iso g) .to = g .to ∘ f .to
(f ∘Iso g) .from = f .from ∘ g .from
(f ∘Iso g) .inverses = Inverses-∘ (f .inverses) (g .inverses)

infixr 40 _∘Iso_

invertible-∘
  :  {f : Hom b c} {g : Hom a b}
   is-invertible f  is-invertible g
   is-invertible (f ∘ g)
invertible-∘ f-inv g-inv = record
  { inv = g-inv.inv ∘ f-inv.inv
  ; inverses = Inverses-∘ g-inv.inverses f-inv.inverses
  }
  where
    module f-inv = is-invertible f-inv
    module g-inv = is-invertible g-inv

_invertible⁻¹
  :  {f : Hom a b}  (f-inv : is-invertible f)
   is-invertible (is-invertible.inv f-inv)
_invertible⁻¹ {f = f} f-inv .is-invertible.inv = f
_invertible⁻¹ f-inv .is-invertible.inverses .invl =
  is-invertible.invr f-inv
_invertible⁻¹ f-inv .is-invertible.inverses .invr =
  is-invertible.invl f-inv

_Iso⁻¹ : a ≅ b  b ≅ a
(f Iso⁻¹) .to = f .from
(f Iso⁻¹) .from = f .to
(f Iso⁻¹) .inverses .invl = f .inverses .invr
(f Iso⁻¹) .inverses .invr = f .inverses .invl

Isomorphisms enjoy a 2-out-of-3 property: if any 2 of ff, gg, and fgf \circ g are isomorphisms, then so is the third.

inverses-cancell
  :  {f : Hom b c} {g : Hom a b} {g⁻¹ : Hom b a} {fg⁻¹ : Hom c a}
   Inverses g g⁻¹  Inverses (f ∘ g) fg⁻¹
   Inverses f (g ∘ fg⁻¹)

inverses-cancelr
  :  {f : Hom b c} {f⁻¹ : Hom c b} {g : Hom a b} {fg⁻¹ : Hom c a}
   Inverses f f⁻¹  Inverses (f ∘ g) fg⁻¹
   Inverses g (fg⁻¹ ∘ f)

invertible-cancell
  :  {f : Hom b c} {g : Hom a b}
   is-invertible g  is-invertible (f ∘ g)
   is-invertible f

invertible-cancelr
  :  {f : Hom b c} {g : Hom a b}
   is-invertible f  is-invertible (f ∘ g)
   is-invertible g
We are early into our bootstrapping process for category theory, so the proofs of these lemmas are quite low-level, and thus omitted.
inverses-cancell g-inv fg-inv .invl =
  assoc _ _ _ ∙ fg-inv .invl
inverses-cancell g-inv fg-inv .invr =
  sym (idr _)
  ∙ ap₂ __ refl (sym (g-inv .invl))
  ∙ assoc _ _ _
  ∙ ap₂ __
    (sym (assoc _ _ _)
    ∙ sym (assoc _ _ _)
    ∙ ap₂ __ refl (fg-inv .invr)
    ∙ idr _)
    refl
  ∙ g-inv .invl

inverses-cancelr f-inv fg-inv .invl =
  sym (idl _)
  ∙ ap₂ __ (sym (f-inv .invr)) refl
  ∙ sym (assoc _ _ _)
  ∙ ap₂ __ refl
    (assoc _ _ _
    ∙ assoc _ _ _
    ∙ ap₂ __ (fg-inv .invl) refl
    ∙ idl _)
  ∙ f-inv .invr
inverses-cancelr f-inv fg-inv .invr =
  sym (assoc _ _ _) ∙ fg-inv .invr

invertible-cancell g-inv fg-inv =
  inverses→invertible $
  inverses-cancell
    (g-inv .is-invertible.inverses)
    (fg-inv .is-invertible.inverses)

invertible-cancelr f-inv fg-inv =
  inverses→invertible $
  inverses-cancelr
    (f-inv .is-invertible.inverses)
    (fg-inv .is-invertible.inverses)

We also note that invertible morphisms are both epic and monic.

invertible→monic : is-invertible f  is-monic f
invertible→monic {f = f} invert g h p =
  g             ≡˘⟨ idl g ⟩
  id ∘ g        ≡˘⟨ ap (_∘ g) (is-invertible.invr invert)
  (inv ∘ f) ∘ g ≡˘⟨ assoc inv f g ⟩
  inv ∘ (f ∘ g) ≡⟨ ap (inv ∘_) p ⟩
  inv ∘ (f ∘ h) ≡⟨ assoc inv f h ⟩
  (inv ∘ f) ∘ h ≡⟨ ap (_∘ h) (is-invertible.invr invert)
  id ∘ h        ≡⟨ idl h ⟩
  h ∎
  where
    open is-invertible invert

invertible→epic : is-invertible f  is-epic f
invertible→epic {f = f} invert g h p =
  g             ≡˘⟨ idr g ⟩
  g ∘ id        ≡˘⟨ ap (g ∘_) (is-invertible.invl invert)
  g ∘ (f ∘ inv) ≡⟨ assoc g f inv ⟩
  (g ∘ f) ∘ inv ≡⟨ ap (_∘ inv) p ⟩
  (h ∘ f) ∘ inv ≡˘⟨ assoc h f inv ⟩
  h ∘ (f ∘ inv) ≡⟨ ap (h  ∘_) (is-invertible.invl invert)
  h ∘ id        ≡⟨ idr h ⟩
  h ∎
  where
    open is-invertible invert

iso→monic : (f : a ≅ b)  is-monic (f .to)
iso→monic f = invertible→monic (iso→invertible f)

iso→epic : (f : a ≅ b)  is-epic (f .to)
iso→epic f = invertible→epic (iso→invertible f)

Furthermore, isomorphisms also yield section/retraction pairs.

inverses→to-has-section
  :  {f : Hom a b} {g : Hom b a}
   Inverses f g  has-section f
inverses→to-has-section {g = g} inv .section = g
inverses→to-has-section inv .is-section = Inverses.invl inv

inverses→from-has-section
  :  {f : Hom a b} {g : Hom b a}
   Inverses f g  has-section g
inverses→from-has-section {f = f} inv .section = f
inverses→from-has-section inv .is-section = Inverses.invr inv

inverses→to-has-retract
  :  {f : Hom a b} {g : Hom b a}
   Inverses f g  has-retract f
inverses→to-has-retract {g = g} inv .retract = g
inverses→to-has-retract inv .is-retract = Inverses.invr inv

inverses→from-has-retract
  :  {f : Hom a b} {g : Hom b a}
   Inverses f g  has-retract g
inverses→from-has-retract {f = f} inv .retract = f
inverses→from-has-retract inv .is-retract = Inverses.invl inv

iso→to-has-section : (f : a ≅ b)  has-section (f .to)
iso→to-has-section f .section = f .from
iso→to-has-section f .is-section = f .invl

iso→from-has-section : (f : a ≅ b)  has-section (f .from)
iso→from-has-section f .section = f .to
iso→from-has-section f .is-section = f .invr

iso→to-has-retract : (f : a ≅ b)  has-retract (f .to)
iso→to-has-retract f .retract = f .from
iso→to-has-retract f .is-retract = f .invr

iso→from-has-retract : (f : a ≅ b)  has-retract (f .from)
iso→from-has-retract f .retract = f .to
iso→from-has-retract f .is-retract = f .invl

Using our lemmas about section/retraction pairs from before, we can show that if ff is a monic retract, then ff is an iso.

retract-of+monic→inverses
  :  {a b} {s : Hom b a} {r : Hom a b}
   r retract-of s
   is-monic r
   Inverses r s
retract-of+monic→inverses ret monic .invl = ret
retract-of+monic→inverses ret monic .invr =
  retract-of+monic→section-of ret monic

We also have a dual result for sections and epis.

section-of+epic→inverses
  :  {a b} {s : Hom b a} {r : Hom a b}
   s retract-of r
   is-epic r
   Inverses r s
section-of+epic→inverses sect epic .invl =
  section-of+epic→retract-of sect epic
section-of+epic→inverses sect epic .invr = sect

Hom-sets between isomorphic objects are equivalent. Crucially, this allows us to use univalence to transport properties between hom-sets.

iso→hom-equiv
  :  {a a' b b'}  a ≅ a'  b ≅ b'
   Hom a b ≃ Hom a' b'
iso→hom-equiv f g = Iso→Equiv $
   h  g .to ∘ h ∘ f .from) ,
  iso  h  g .from ∘ h ∘ f .to )
     h 
      g .to(g .from ∘ h ∘ f .to) ∘ f .from   ≡⟨ cat! C ⟩
      (g .to ∘ g .from) ∘ h ∘ (f .to ∘ f .from) ≡⟨ ap₂  l r  l ∘ h ∘ r) (g .invl) (f .invl)
      id ∘ h ∘ id                               ≡⟨ cat! C ⟩
      h ∎)
     h 
      g .from ∘ (g .to ∘ h ∘ f .from) ∘ f .to   ≡⟨ cat! C ⟩
      (g .from ∘ g .to) ∘ h ∘ (f .from ∘ f .to) ≡⟨ ap₂  l r  l ∘ h ∘ r) (g .invr) (f .invr)
      id ∘ h ∘ id                               ≡⟨ cat! C ⟩
      h ∎)

If ff is invertible, then both pre and post-composition with ff are equivalences.

invertible-precomp-equiv
  :  {a b c} {f : Hom a b}
   is-invertible f
   is-equiv {A = Hom b c} (_∘ f)
invertible-precomp-equiv {f = f} f-inv = is-iso→is-equiv $
  iso  h  h ∘ f-inv.inv)
     h  sym (assoc _ _ _) ·· ap (h ∘_) f-inv.invr ·· idr h)
     h  sym (assoc _ _ _) ·· ap (h ∘_) f-inv.invl ·· idr h)
  where module f-inv = is-invertible f-inv

invertible-postcomp-equiv
  :  {a b c} {f : Hom b c}
   is-invertible f
   is-equiv {A = Hom a b} (f ∘_)
invertible-postcomp-equiv {f = f} f-inv = is-iso→is-equiv $
  iso  h  f-inv.inv ∘ h)
     h  assoc _ _ _ ·· ap (_∘ h) f-inv.invl ·· idl h)
     h  assoc _ _ _ ·· ap (_∘ h) f-inv.invr ·· idl h)
  where module f-inv = is-invertible f-inv