module Cat.Functor.Final where

Final functors🔗

A final functor expresses an equivalence of diagram schemata for the purposes of computing colimits: if is final, then colimits for are equivalent to colimits for A terminological warning: in older literature (e.g. (Borceux 1994) and (Adamek and Rosicky 1994)), these functors are called cofinal, but we stick with terminology from the nLab here.

Finality has an elementary characterisation: we define a functor to be final if, for every the comma category is connected. That is, unpacking, the following data: for every object an object and a map and for every span

a finite zigzag of morphisms from to inducing a chain of commuting triangles from to For example, in the case of a “cospan” zigzag

  is-final : Type (o ⊔ ℓ ⊔ o' ⊔ ℓ')
  is-final = ∀ d → is-connected-cat (d ↙ F)

The utility of this definition comes, as mentioned, from the ability to move (colimiting) cocones back and forth between a diagram and its restriction to the domain category If we have a cocone then precomposition with the map (where comes from the finality of defines a cocone

However, since the comma category is merely inhabited, we need to make sure that this extension is independent of the choice of and This follows from naturality of the cocone and by connectedness of as expressed by the commutativity of the following diagram:

    module _ {coapex} (cone : D F∘ F => Const coapex) where
      extend : ∀ d → Ob (d ↙ F) → ℰ.Hom (D.₀ d) coapex
      extend d f = cone .η (f .y) ℰ.∘ D.₁ (f .map)

          : ∀ d {f g : Ob (d ↙ F)} (h : ↓Hom _ _ f g)
          → extend d f ≡ extend d g
        extend-const1 d {f} {g} h =
          cone .η _ ℰ.∘ D.₁ (f .map)                        ≡˘⟹ cone .is-natural _ _ _ ∙ ℰ.idl _ ℰ.⟩∘⟚refl âŸ©â‰ĄË˜
          (cone .η _ ℰ.∘ D.₁ (F.₁ (h .ÎČ))) ℰ.∘ D.₁ (f .map) ≡⟹ D.pullr refl âŸ©â‰Ą
          cone .η _ ℰ.∘ D.₁ ⌜ F.₁ (h .ÎČ) 𝒟.∘ f .map ⌝       ≡⟹ ap! (sym (h .sq) ∙ 𝒟.idr _) âŸ©â‰Ą
          cone .η _ ℰ.∘ D.₁ (g .map)                        ∎

          : ∀ d (f g : Ob (d ↙ F))
          → extend d f ≡ extend d g
        extend-const d f g = case fin.zigzag d f g of
          Meander-rec-≡ (el! _) (extend d) (extend-const1 d)

In order to make reasoning easier, we define the extended cocone simultaneously with an elimination principle for its components.

      extend-cocone : D => Const coapex
        : ∀ d {ℓ} (P : ℰ.Hom (D.₀ d) coapex → Type ℓ)
        → (∀ f → is-prop (P f))
        → (∀ f → P (extend d f))
        → P (extend-cocone .η d)

      extend-cocone .η d = ∄-∄-rec-set (hlevel 2)
        (extend d) (extend-const d) (fin.point d)

      extend-cocone .is-natural x y f = extend-cocone-elim x
        (λ ex → extend-cocone .η y ℰ.∘ D.₁ f ≡ ex)
        (λ _ → hlevel 1)
        (λ ex → extend-cocone-elim y
          (λ ey → ey ℰ.∘ D.₁ f ≡ extend x ex)
          (λ _ → hlevel 1)
          λ ey → ℰ.pullr (sym (D.F-∘ _ _))
               ∙ sym (extend-const x ex (↓obj (ey .map 𝒟.∘ f))))
        ∙ sym (ℰ.idl _)

In the other direction, suppose that we have a cocone — inserting in the appropriate places makes a cocone

    restrict-cocone : ∀ {coapex} → D => Const coapex → D F∘ F => Const coapex
    restrict-cocone K .η x = K .η (F.₀ x)
    restrict-cocone K .is-natural x y f = K .is-natural (F.₀ x) (F.₀ y) (F.₁ f)

A computation using connectedness of the comma categories shows that these formulae are mutually inverse:

    open is-iso
    extend-cocone-is-iso : ∀ {coapex} → is-iso (extend-cocone {coapex})
    extend-cocone-is-iso .inv = restrict-cocone
    extend-cocone-is-iso .rinv K = ext λ o →
      extend-cocone-elim (restrict-cocone K) o
        (λ ex → ex ≡ K .η o)
        (λ _ → hlevel 1)
        λ _ → K .is-natural _ _ _ ∙ ℰ.idl _
    extend-cocone-is-iso .linv K = ext λ o →
      extend-cocone-elim K (F.₀ o)
        (λ ex → ex ≡ K .η o)
        (λ _ → hlevel 1)
        λ f → extend-const K (F.₀ o) f (↓obj 𝒟.id) ∙ D.elimr refl

The most important conclusion that we get is the following: If you can show that the restricted cocone is a colimit, then the original cocone was a colimit, too! We’ll do this in two steps: first, show that the extension of a colimiting cocone is a colimit. Then, using the fact that restrict-cocone is an equivalence, we’ll be able to fix up the polarity mismatch.

      : ∀ {coapex} (K : D F∘ F => Const coapex)
      → is-colimit (D F∘ F) coapex K
      → is-colimit D coapex (extend-cocone K)
The proof of the auxiliary lemma is a direct computation, so we’ll leave it in this <details> tag for the curious reader only.
    extend-is-colimit {coapex} K colim =
      to-is-colimitp mc refl
      module extend-is-colimit where
        module colim = is-colimit colim
        open make-is-colimit

        mc : make-is-colimit D coapex
        mc .ψ x = extend-cocone K .η x
        mc .commutes f = extend-cocone K .is-natural _ _ _ ∙ ℰ.idl _
        mc .universal eps p =
          colim.universal (λ j → eps (F.₀ j)) λ f → p (F.₁ f)
        mc .factors {j} eps p =
          extend-cocone-elim K j
            (λ ex → mc .universal eps p ℰ.∘ ex ≡ eps j)
            (λ _ → hlevel 1)
            λ f → ℰ.pulll (colim.factors _ _) ∙ p (f .map)
        mc .unique eps p other q =
          colim.unique _ _ _ λ j →
            sym (ℰ.refl⟩∘⟚ extend-cocone-is-iso .linv K ηₚ j)
            ∙ q (F.₀ j)
      : ∀ {coapex}
      → (K : D => Const coapex)
      → is-colimit (D F∘ F) coapex (restrict-cocone K)
      → is-colimit D coapex K
    is-colimit-restrict {coapex} K colim =
        ( (restrict-cocone K) colim)
        (extend-cocone-is-iso .rinv K ηₚ _)
        where open is-iso


Final functors between pregroupoids have a very simple characterisation: they are the full, essentially surjective functors. In this case, there is a direct connection with homotopy type theory: groupoids are 1-types, comma categories are fibres of over and so finality says that is a connected map.

Essential surjectivity on objects pretty much exactly says that each comma category is inhabited. To see that fullness implies the existence of zigzags, meditate on the following diagram:

  module _ (𝒞-grpd : is-pregroupoid 𝒞) (𝒟-grpd : is-pregroupoid 𝒟) where
    full+eso→final : is-full F → is-eso F → is-final
    full+eso→final full eso d .zigzag f g = do
      z , p ← full (g .map 𝒟.∘ 𝒟-grpd (f .map) .inv)
      pure $ zig
        (↓hom {ÎČ = z}
          (𝒟.idr _ ∙ sym (𝒟.rswizzle p (𝒟-grpd (f .map) .invr))))
      where open 𝒟.is-invertible
    full+eso→final full eso d .point =
      ∄-∄-map (λ e → ↓obj (𝒟.from (e .snd))) (eso d)

For the other direction, given observe that connectedness of the comma category gives us a zigzag between and but since is a pregroupoid we can evaluate this zigzag to a single morphism such that

    final→full+eso : is-final → is-full F × is-eso F
    final→full+eso fin .fst {x} {y} f = do
      zs ← fin (F.₀ x) .zigzag (↓obj 𝒟.id) (↓obj f)
      let z = Free-groupoid-counit
            (↓-is-pregroupoid _ _ ⊀Cat-is-pregroupoid 𝒞-grpd)
            .F₁ zs
      pure (z .ÎČ , sym (𝒟.idr _) ∙ sym (z .sq) ∙ 𝒟.idr _)
    final→full+eso fin .snd d = do
      fd ← fin d .point
      pure (fd .y , 𝒟.invertible→iso (fd .map) (𝒟-grpd _) 𝒟.Iso⁻Âč)

Another general class of final functors is given by right adjoint functors. This follows directly from the characterisation of right adjoints in terms of free objects: since the comma categories have initial objects, they are connected.

  : ∀ {o ℓ o' ℓ'} {𝒞 : Precategory o ℓ} {𝒟 : Precategory o' ℓ'}
  → {L : Functor 𝒞 𝒟} {R : Functor 𝒟 𝒞} (L⊣R : L ⊣ R)
  → is-final R
right-adjoint-is-final L⊣R c =
  initial→connected  (left-adjoint→universal-maps L⊣R c)

In particular, the inclusion of a terminal object into a category is a final functor. This means that the colimit of any diagram over a shape category with a terminal object is simply the value of the diagram on the terminal object.

  : ∀ {o ℓ} {𝒞 : Precategory o ℓ}
  → (top : 𝒞 .Ob) (term : is-terminal 𝒞 top)
  → is-final (const! {A = 𝒞} top)
terminal→inclusion-is-final top term = right-adjoint-is-final
  (terminal→inclusion-is-right-adjoint _ top term)

Closure under composition🔗

We now prove that final functors are closed under composition.

First, given an object we get a map using the finality of and a map using the finality of which we can compose into an object of

  F∘-is-final : is-final (G F∘ F)
  F∘-is-final c .point = do
    g ← gf.point c
    f ← ff.point (g .y)
    pure (g ↙> f)

Now, given a span finality of gives us a zigzag between and in but we need a zigzag between and in Thus we have to refine our zigzag step by step, using the finality of

  F∘-is-final c .zigzag f g = do
    gz ← gf.zigzag c (↓obj (f .map)) (↓obj (g .map))
    fz ← refine gz (↓obj 𝒟.id) (↓obj 𝒟.id)
    pure (subst₂ (Meander (c ↙ G F∘ F)) ↙>-id ↙>-id fz)

We start by defining a congruence on the objects of whereby and are related if, for any extensions and there merely exists a zigzag between the corresponding objects of

      R : Congruence (Ob (c ↙ G)) _
      R ._∌_ f g =
        ∀ (f' : Ob (f .y ↙ F)) (g' : Ob (g .y ↙ F))
        → ∄ Meander (c ↙ G F∘ F) (f ↙> f') (g ↙> g') ∄
      R .has-is-prop _ _ = hlevel 1

That this is a congruence is easily checked using the finality of

      R .reflᶜ {f} f' g' =
        Free-groupoid-map (↙-compose f) .F₁ <$> ff.zigzag (f .y) f' g'
      R ._∙ᶜ_ {f} {g} {h} fg gh f' h' = do
        g' ← ff.point (g .y)
        ∄-∄-map₂ _++_ (gh g' h') (fg f' g')
      R .symᶜ fg g' f' = ∄-∄-map (reverse _) (fg f' g')

Using the universal mapping property of the free groupoid into congruences, we conclude by showing that any two arrows connected by a morphism are related, which again involves the connectedness of

      refine1 : ∀ {f g} → Hom (c ↙ G) f g → R ._∌_ f g
      refine1 {f} {g} h f' g' = do
        z ← ff.zigzag (f .y) f' (↓obj (g' .map 𝒟.∘ h .ÎČ))
          z' : Meander (c ↙ G F∘ F) _ _
          z' = Free-groupoid-map (↙-compose f) .F₁ z
          fixup : f ↙> ↓obj (g' .map 𝒟.∘ h .ÎČ) ≡ g ↙> g'
          fixup = ext $ refl ,ₚ G.pushl refl ∙ (ℰ.refl⟩∘⟚ sym (h .sq) ∙ ℰ.idr _)
        pure (subst (Meander (c ↙ G F∘ F) (f ↙> f')) fixup z')

      refine : ∀ {f g} → Meander (c ↙ G) f g → R ._∌_ f g
      refine = Meander-rec-congruence R refine1