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 to written 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 to written 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 is monic, then 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 is epic, then 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 is a section of another morphism when The intuition for this name is that picks out a cross-section of from For instance, 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 has a section, then 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 is a retract of another morphism when 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 has a retract, then 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 and are inverses when we have and both equal to the identity. A map is invertible (or is an isomorphism) when there exists a for which and are inverses. An isomorphism is a choice of map 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 with two inverses and then not only are 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-∘ : {a b c : Ob} {f : Hom b c} {f⁻¹ : Hom c b} {g : Hom a b} {g⁻¹ : Hom b a}
           β†’ Inverses f f⁻¹ β†’ Inverses g g⁻¹ β†’ Inverses (f ∘ g) (g⁻¹ ∘ f⁻¹)
Inverses-∘ {f = f} {f⁻¹} {g} {g⁻¹} finv ginv = record { invl = l ; invr = r } where
  module finv = Inverses finv
  module ginv = Inverses ginv

  abstract
    l : (f ∘ g) ∘ g⁻¹ ∘ f⁻¹ ≑ id
    l = (f ∘ g) ∘ g⁻¹ ∘ f⁻¹ β‰‘βŸ¨ cat! C βŸ©β‰‘
        f ∘ (g ∘ g⁻¹) ∘ f⁻¹ β‰‘βŸ¨ (Ξ» i β†’ f ∘ ginv.invl i ∘ f⁻¹) βŸ©β‰‘
        f ∘ id ∘ f⁻¹        β‰‘βŸ¨ cat! C βŸ©β‰‘
        f ∘ f⁻¹             β‰‘βŸ¨ finv.invl βŸ©β‰‘
        id                  ∎

    r : (g⁻¹ ∘ f⁻¹) ∘ f ∘ g ≑ id
    r = (g⁻¹ ∘ f⁻¹) ∘ f ∘ g β‰‘βŸ¨ cat! C βŸ©β‰‘
        g⁻¹ ∘ (f⁻¹ ∘ f) ∘ g β‰‘βŸ¨ (Ξ» i β†’ g⁻¹ ∘ finv.invr i ∘ g) βŸ©β‰‘
        g⁻¹ ∘ id ∘ g        β‰‘βŸ¨ cat! C βŸ©β‰‘
        g⁻¹ ∘ g             β‰‘βŸ¨ ginv.invr βŸ©β‰‘
        id                  ∎

_∘Iso_ : βˆ€ {a b c : Ob} β†’ b β‰… c β†’ a β‰… b β†’ a β‰… c
(f ∘Iso g) .to = f .to ∘ g .to
(f ∘Iso g) .from = g .from ∘ f .from
(f ∘Iso g) .inverses = Inverses-∘ (f .inverses) (g .inverses)

_βˆ™Iso_ : βˆ€ {a b c : Ob} β†’ a β‰… b β†’ b β‰… c β†’ a β‰… c
f βˆ™Iso g = g ∘Iso f

infixr 40 _∘Iso_ _βˆ™Iso_
infixr 41 _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-∘ f-inv.inverses g-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
make-inverses : {f : Hom a b} {g : Hom b a} β†’ f ∘ g ≑ id β†’ g ∘ f ≑ id β†’ Inverses f g
make-inverses p q .invl = p
make-inverses p q .invr = q

make-invertible : {f : Hom a b} β†’ (g : Hom b a) β†’ f ∘ g ≑ id β†’ g ∘ f ≑ id β†’ is-invertible f
make-invertible g p q .is-invertible.inv = g
make-invertible g p q .is-invertible.inverses .invl = p
make-invertible g p q .is-invertible.inverses .invr = q

make-iso : (f : Hom a b) (g : Hom b a) β†’ f ∘ g ≑ id β†’ g ∘ f ≑ id β†’ a β‰… b
make-iso f g p q ._β‰…_.to = f
make-iso f g p q ._β‰…_.from = g
make-iso f g p q ._β‰…_.inverses .Inverses.invl = p
make-iso f g p q ._β‰…_.inverses .Inverses.invr = q

inversesβ†’invertible : βˆ€ {f : Hom a b} {g : Hom b a} β†’ Inverses f g β†’ is-invertible f
inverses→invertible x .is-invertible.inv = _
inverses→invertible x .is-invertible.inverses = x

invertible→iso : (f : Hom a b) → is-invertible f → a ≅ b
invertible→iso f x =
  record
    { to       = f
    ; from     = x .is-invertible.inv
    ; inverses = x .is-invertible.inverses
    }

is-invertible-inverse
  : {f : Hom a b} (g : is-invertible f) β†’ is-invertible (g .is-invertible.inv)
is-invertible-inverse g =
  record { inv = _ ; inverses = record { invl = invr g ; invr = invl g } }
  where open Inverses (g .is-invertible.inverses)

iso→invertible : (i : a ≅ b) → is-invertible (i ._≅_.to)
iso→invertible i = record { inv = i ._≅_.from ; inverses = i ._≅_.inverses }

private
  β‰…-pathp-internal
    : (p : a ≑ c) (q : b ≑ d)
    β†’ {f : a β‰… b} {g : c β‰… d}
    β†’ PathP (Ξ» i β†’ Hom (p i) (q i)) (f ._β‰…_.to) (g ._β‰…_.to)
    β†’ PathP (Ξ» i β†’ Hom (q i) (p i)) (f ._β‰…_.from) (g ._β‰…_.from)
    β†’ PathP (Ξ» i β†’ p i β‰… q i) f g
  β‰…-pathp-internal p q r s i .to = r i
  β‰…-pathp-internal p q r s i .from = s i
  β‰…-pathp-internal p q {f} {g} r s i .inverses =
    is-prop→pathp (λ j → Inverses-are-prop {f = r j} {g = s j})
      (f .inverses) (g .inverses) i

abstract
  inverse-unique
    : {x y : Ob} (p : x ≑ y) {b d : Ob} (q : b ≑ d) (f : x β‰… b) (g : y β‰… d)
    β†’ PathP (Ξ» i β†’ Hom (p i) (q i)) (f .to) (g .to)
    β†’ PathP (Ξ» i β†’ Hom (q i) (p i)) (f .from) (g .from)
  inverse-unique =
    J' (Ξ» a c p β†’ βˆ€ {b d} (q : b ≑ d) (f : a β‰… b) (g : c β‰… d)
      β†’ PathP (Ξ» i β†’ Hom (p i) (q i)) (f .to) (g .to)
      β†’ PathP (Ξ» i β†’ Hom (q i) (p i)) (f .from) (g .from))
      Ξ» x β†’ J' (Ξ» b d q β†’ (f : x β‰… b) (g : x β‰… d)
                β†’ PathP (Ξ» i β†’ Hom x (q i)) (f .to) (g .to)
                β†’ PathP (Ξ» i β†’ Hom (q i) x) (f .from) (g .from))
            Ξ» y f g p β†’
              f .from                     β‰‘Λ˜βŸ¨ ap (f .from ∘_) (g .invl) βˆ™ idr _ βŸ©β‰‘Λ˜
              f .from ∘ g .to ∘ g .from   β‰‘βŸ¨ assoc _ _ _ βŸ©β‰‘
              (f .from ∘ g .to) ∘ g .from β‰‘βŸ¨ ap (_∘ g .from) (ap (f .from ∘_) (sym p) βˆ™ f .invr) βˆ™ idl _ βŸ©β‰‘
              g .from                     ∎

β‰…-pathp
  : (p : a ≑ c) (q : b ≑ d) {f : a β‰… b} {g : c β‰… d}
  β†’ PathP (Ξ» i β†’ Hom (p i) (q i)) (f ._β‰…_.to) (g ._β‰…_.to)
  β†’ PathP (Ξ» i β†’ p i β‰… q i) f g
β‰…-pathp p q {f = f} {g = g} r = β‰…-pathp-internal p q r (inverse-unique p q f g r)

β‰…-pathp-from
  : (p : a ≑ c) (q : b ≑ d) {f : a β‰… b} {g : c β‰… d}
  β†’ PathP (Ξ» i β†’ Hom (q i) (p i)) (f ._β‰…_.from) (g ._β‰…_.from)
  β†’ PathP (Ξ» i β†’ p i β‰… q i) f g
β‰…-pathp-from p q {f = f} {g = g} r = β‰…-pathp-internal p q (inverse-unique q p (f Iso⁻¹) (g Iso⁻¹) r) r

β‰…-path : {f g : a β‰… b} β†’ f ._β‰…_.to ≑ g ._β‰…_.to β†’ f ≑ g
β‰…-path = β‰…-pathp refl refl

β‰…-path-from : {f g : a β‰… b} β†’ f ._β‰…_.from ≑ g ._β‰…_.from β†’ f ≑ g
β‰…-path-from = β‰…-pathp-from refl refl

β‰…-is-contr : (βˆ€ {a b} β†’ is-contr (Hom a b)) β†’ is-contr (a β‰… b)
β‰…-is-contr hom-contr .centre =
  make-iso (hom-contr .centre) (hom-contr .centre)
    (is-contr→is-prop hom-contr _ _)
    (is-contr→is-prop hom-contr _ _)
β‰…-is-contr hom-contr .paths f = β‰…-path (hom-contr .paths (f .to))

β‰…-is-prop : (βˆ€ {a b} β†’ is-prop (Hom a b)) β†’ is-prop (a β‰… b)
β‰…-is-prop hom-prop f g = β‰…-path (hom-prop (f .to) (g .to))

β†ͺ-pathp
  : {a : I β†’ Ob} {b : I β†’ Ob} {f : a i0 β†ͺ b i0} {g : a i1 β†ͺ b i1}
  β†’ PathP (Ξ» i β†’ Hom (a i) (b i)) (f .mor) (g .mor)
  β†’ PathP (Ξ» i β†’ a i β†ͺ b i) f g
β†ͺ-pathp {a = a} {b} {f} {g} pa = go where
  go : PathP (Ξ» i β†’ a i β†ͺ b i) f g
  go i .mor = pa i
  go i .monic {c = c} =
    is-prop→pathp
      (Ξ» i β†’ Ξ -is-hlevel {A = Hom c (a i)} 1
       Ξ» g β†’ Ξ -is-hlevel {A = Hom c (a i)} 1
       Ξ» h β†’ fun-is-hlevel {A = pa i ∘ g ≑ pa i ∘ h} 1
              (Hom-set c (a i) g h))
      (f .monic)
      (g .monic)
      i

β† -pathp
  : {a : I β†’ Ob} {b : I β†’ Ob} {f : a i0 β†  b i0} {g : a i1 β†  b i1}
  β†’ PathP (Ξ» i β†’ Hom (a i) (b i)) (f .mor) (g .mor)
  β†’ PathP (Ξ» i β†’ a i β†  b i) f g
β† -pathp {a = a} {b} {f} {g} pa = go where
  go : PathP (Ξ» i β†’ a i β†  b i) f g
  go i .mor = pa i
  go i .epic {c = c} =
    is-prop→pathp
      (Ξ» i β†’ Ξ -is-hlevel {A = Hom (b i) c} 1
       Ξ» g β†’ Ξ -is-hlevel {A = Hom (b i) c} 1
       Ξ» h β†’ fun-is-hlevel {A = g ∘ pa i ≑ h ∘ pa i} 1
              (Hom-set (b i) c g h))
      (f .epic)
      (g .epic)
      i

Isomorphisms enjoy a 2-out-of-3 property: if any 2 of and 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

Using our lemmas about section/retraction pairs from before, we can show that if is a monic retract, then 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 is invertible, then both pre and post-composition with 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