module Cat.Instances.Slice.Limit where

Arbitrary limits in slices🔗

Suppose we have some really weird diagram in a slice category, like the one below. Well, alright, it’s not that weird, but it’s not a pullback or a terminal object, so we don’t a priori know how to compute its limit in the slice.

The observation that will let us compute a limit for this diagram is inspecting the computation of products in a slice. To compute the product of and we had to pass to a pullback of in — which we had assumed exists. But! Take a look at what that diagram looks like:

We “exploded” a diagram of shape to one of shape This process can be described in a way easier to generalise: We “exploded” our diagram to one indexed by a category which contains contains an extra point, and has a unique map between each object of — we have adjoined a terminal object to our diagram shape.

Generically, if we have a diagram we can “explode” this into a diagram compute the limit in then pass back to the slice category.

    F' : Functor (J ▹) C
    F' = to-slice→from-▹ F

  limit-above→limit-in-slice : Limit F' → Limit F
  limit-above→limit-in-slice lims = to-limit (to-is-limit lim) where
    module lims = Limit lims
    open make-is-limit

    apex : C/o.Ob
    apex = cut (lims.ψ (inr tt))

    nadir : (j : J.Ob) → /-Hom apex (F .F₀ j)
    nadir j .map = lims.ψ (inl j)
    nadir j .com = lims.commutes (lift tt)

    module Cone
      {x : C/o.Ob}
      (eps : (j : J.Ob) → C/o.Hom x (F .F₀ j))
      (p : ∀ {i j : J.Ob} → (f : J.Hom i j) → F .F₁ f C/o.∘ eps i ≡ eps j)
      where

        ϕ : (j : J.Ob ⊎ ⊤) → C.Hom (x .dom) (F' .F₀ j)
        ϕ (inl j) = eps j .map
        ϕ (inr _) = x .map

        ϕ-commutes
          : ∀ {i j : J.Ob ⊎ ⊤}
          → (f : ⋆Hom J ⊤Cat i j)
          → F' .F₁ f C.∘ ϕ i ≡ ϕ j
        ϕ-commutes {inl i} {inl j} (lift f) = ap map (p f)
        ϕ-commutes {inl i} {inr j} (lift f) = eps i .com
        ϕ-commutes {inr i} {inr x} (lift f) = C.idl _

        ϕ-factor
          : ∀ (other : /-Hom x apex)
          → (∀ j → nadir j C/o.∘ other ≡ eps j)
          → (j : J.Ob ⊎ ⊤)
          → lims.ψ j C.∘ other .map ≡ ϕ j
        ϕ-factor other q (inl j)  = ap map (q j)
        ϕ-factor other q (inr tt) = other .com

    lim : make-is-limit F apex
    lim .ψ          = nadir
    lim .commutes f = ext (lims.commutes (lift f))

    lim .universal {x} eps p .map = lims.universal
      (Cone.ϕ eps p) (Cone.ϕ-commutes eps p)
    lim .universal {x} eps p .com = lims.factors _ _

    lim .factors eps p         = ext (lims.factors _ _)
    lim .unique  eps p other q = ext $
      lims.unique _ _ (other .map) (Cone.ϕ-factor eps p other q)

In particular, if a category is complete, then so are its slices:

is-complete→slice-is-complete
  : ∀ {ℓ o o' ℓ'} {C : Precategory o ℓ} {c : ⌞ C ⌟}
  → is-complete o' ℓ' C
  → is-complete o' ℓ' (Slice C c)
is-complete→slice-is-complete lims F = limit-above→limit-in-slice F (lims _)

Connected limits in slices🔗

We can simplify this story for a particular class of limits: the forgetful functor creates connected limits.1 For instance, a pullback in is computed exactly as a pullback in (assuming this pullback exists), ignoring the maps into Contrast this with the fact that colimits in slice categories are all created by the forgetful functor.

To get some intuition for the connectedness requirement, we can think type-theoretically: an object of is, in the internal language of a “type in context ”, while the forgetful functor can be thought of as forming the Then, given a diagram of types in with maps between them over the limit of the induced diagram of closed types consists of a bunch of pairs obeying some relations; but, since the diagram has a connected shape, those relations ensure that all the are equal! Thus, it is enough to compute the limit over and then take the

We start by showing that Forget/ lifts limits: given a diagram in and its limit in the key step is to find a suitable map to promote this to a limit in As hinted above, we can pick any object and set this to the composite since is connected, the choice of doesn’t matter, and there is at least one object by assumption.

  Forget/-lifts-connected-limits
    : is-connected-cat J
    → lifts-limits-of J (Forget/ {C = C} {c = A})
  Forget/-lifts-connected-limits conn {D} L .lifted = to-limit (to-is-limit L')
    where
      module D = Functor D
      module L = Limit L
      module conn = is-connected-groupoid conn

      proj : J.Ob → C.Hom L.apex A
      proj j = D.₀ j .map C.∘ L.ψ j

      proj' : ∥ J.Ob ∥ → C.Hom L.apex A
      proj' = connected-∥-∥-rec! conn proj λ {x} {y} f →
        D.₀ x .map C.∘ L.ψ x                ≡⟨ C.pushl (sym (D.₁ f .com)) ⟩≡
        D.₀ y .map C.∘ D.₁ f .map C.∘ L.ψ x ≡⟨ C.cdr (L.commutes f) ⟩≡
        D.₀ y .map C.∘ L.ψ y                ∎

The rest is an uneventful computation.

      L' : make-is-limit D (cut (proj' conn.point))
      L' .make-is-limit.ψ j .map = L.ψ j
      L' .make-is-limit.ψ j .com = ap proj' (squash (inc _) conn.point)
      L' .make-is-limit.commutes f = ext (L.commutes f)
      L' .make-is-limit.universal eps comm .map =
        L.universal (λ j → eps j .map) λ {x} {y} f → unext (comm f)
      L' .make-is-limit.universal eps comm .com =
        case conn.point return (λ p → proj' p C.∘ _ ≡ _) of λ j →
          C.pullr (L.factors _ _) ∙ eps j .com
      L' .make-is-limit.factors eps comm = ext (L.factors _ _)
      L' .make-is-limit.unique eps comm other fac =
        ext (L.unique _ _ _ λ j → unext (fac j))

  Forget/-lifts-connected-limits conn lim .preserved =
    generalize-limitp (Limit.has-limit lim) refl

Since Forget/ is conservative, we conclude that it creates connected limits.

  Forget/-creates-connected-limits
    : is-connected-cat J
    → creates-limits-of J (Forget/ {C = C} {c = A})
  Forget/-creates-connected-limits conn = conservative+lifts→creates-limits
    Forget/-is-conservative (Forget/-lifts-connected-limits conn)

  1. That is, limits of shape a connected category. This notably includes pullbacks, but not terminal objects or binary products, since their shape categories have respectively 0 and 2 connected components.↩︎