module Cat.Diagram.Limit.Product {o h} (C : Precategory o h) where

Products are limitsπŸ”—

We establish the correspondence between binary products and limits over the functor out of the two-object category which maps to and to

The two-way correspondence between products and terminal cones is simple enough to establish by appropriately shuffling the data.

is-product→is-limit
  : βˆ€ {x} {F : Functor 2-object-category C} {eps : Const x => F}
  β†’ is-product C (eps .Ξ· true) (eps .Ξ· false)
  β†’ is-limit {C = C} F x eps
is-product→is-limit {x = x} {F} {eps} is-prod =
  to-is-limitp ml Ξ» where
    {true} β†’ refl
    {false} β†’ refl
  where
    module is-prod = is-product is-prod
    open make-is-limit

    ml : make-is-limit F x
    ml .ψ j = eps .η j
    ml .commutes f = sym (eps .is-natural _ _ _) βˆ™ idr _
    ml .universal eps _ = is-prod.⟨ eps true , eps false ⟩is-prod.
    ml .factors {true} eps _ = is-prod.Ο€β‚βˆ˜βŸ¨βŸ©
    ml .factors {false} eps _ = is-prod.Ο€β‚‚βˆ˜βŸ¨βŸ©
    ml .unique eps p other q = is-prod.unique (q true) (q false)

is-limit→is-product
  : βˆ€ {a b} {K : Functor ⊀Cat C}
  β†’ {eps : K F∘ !F => 2-object-diagram a b}
  β†’ is-ran !F (2-object-diagram a b) K eps
  β†’ is-product C (eps .Ξ· true) (eps .Ξ· false)
is-limit→is-product {a} {b} {K} {eps} lim = prod where
  module lim = is-limit lim

  D : Functor 2-object-category C
  D = 2-object-diagram a b

  pair
    : βˆ€ {y} β†’ Hom y a β†’ Hom y b
    β†’ βˆ€ (j : Bool) β†’ Hom y (D .Fβ‚€ j)
  pair p1 p2 true = p1
  pair p1 p2 false = p2

  pair-commutes
    : βˆ€ {y} {p1 : Hom y a} {p2 : Hom y b}
    β†’ {i j : Bool}
    β†’ (p : i ≑ j)
    β†’ D .F₁ p ∘ pair p1 p2 i ≑ pair p1 p2 j
  pair-commutes {p1 = p1} {p2 = p2} =
      J (Ξ» _ p β†’ D .F₁ p ∘ pair p1 p2 _ ≑ pair p1 p2 _)
        (eliml (D .F-id))

  prod : is-product C (eps .Ξ· true) (eps .Ξ· false)
  prod .⟨_,_⟩ f g = lim.universal (pair f g) pair-commutes
  prod .Ο€β‚βˆ˜βŸ¨βŸ© {_} {p1'} {p2'} = lim.factors (pair p1' p2') pair-commutes
  prod .Ο€β‚‚βˆ˜βŸ¨βŸ© {_} {p1'} {p2'} = lim.factors (pair p1' p2') pair-commutes
  prod .unique {other = other} p q = lim.unique _ _ other Ξ» where
    true β†’ p
    false β†’ q

Productβ†’Limit : βˆ€ {F : Functor 2-object-category C} β†’ Product C (F # true) (F # false) β†’ Limit F
Product→Limit prod = to-limit (is-product→is-limit {eps = 2-object-nat-trans _ _} (has-is-product prod))

Limitβ†’Product : βˆ€ {a b} β†’ Limit (2-object-diagram a b) β†’ Product C a b
Limit→Product lim .apex = Limit.apex lim
Limitβ†’Product lim .π₁ = Limit.cone lim .Ξ· true
Limit→Product lim .π₂ = Limit.cone lim .η false
Limit→Product lim .has-is-product =
  is-limit→is-product (Limit.has-limit lim)

Indexed products as limitsπŸ”—

In the particular case where is a groupoid, e.g.Β because it arises as the space of objects of a univalent category, an indexed product for is the same thing as a limit over considered as a functor We can not lift this restriction: If is not a groupoid, then its path spaces are not necessarily sets, and so the Disc construction does not apply to it.

module _ {β„“} {I : Type β„“} (i-is-grpd : is-groupoid I) (F : I β†’ Ob) where
  open _=>_

  Projβ†’Cone : βˆ€ {x} β†’ (βˆ€ i β†’ Hom x (F i))
            β†’ Const x => Disc-adjunct {C = C} {iss = i-is-grpd} F
  Proj→Cone π .η i = π i
  Proj→Cone π .is-natural i j p =
    J (Ξ» j p β†’  Ο€ j ∘ id ≑ subst (Hom (F i) βŠ™ F) p id ∘ Ο€ i)
      (idr _ βˆ™ introl (transport-refl id))
      p

  is-indexed-product→is-limit
    : βˆ€ {x} {Ο€ : βˆ€ i β†’ Hom x (F i)}
    β†’ is-indexed-product C F Ο€
    → is-limit (Disc-adjunct F) x (Proj→Cone π)
  is-indexed-product→is-limit {x = x} {π} ip =
    to-is-limitp ml refl
    where
      module ip = is-indexed-product ip
      open make-is-limit

      ml : make-is-limit (Disc-adjunct F) x
      ml .ψ j = Ο€ j
      ml .commutes {i} {j} p =
        J (Ξ» j p β†’ subst (Hom (F i) βŠ™ F) p id ∘ Ο€ i ≑ Ο€ j)
          (eliml (transport-refl _))
          p
      ml .universal eps p = ip.tuple eps
      ml .factors eps p = ip.commute
      ml .unique eps p other q = ip.unique eps q

  is-limit→is-indexed-product
    : βˆ€ {K : Functor ⊀Cat C}
    β†’ {eps : K F∘ !F => Disc-adjunct {iss = i-is-grpd} F}
    β†’ is-ran !F (Disc-adjunct F) K eps
    β†’ is-indexed-product C F (eps .Ξ·)
  is-limit→is-indexed-product {K = K} {eps} lim = ip where
    module lim = is-limit lim
    open is-indexed-product

    ip : is-indexed-product C F (eps .Ξ·)
    ip .tuple k =
      lim.universal k
        (J (Ξ» j p β†’ subst (Hom (F _) βŠ™ F) p id ∘ k _ ≑ k j)
           (eliml (transport-refl _)))
    ip .commute =
      lim.factors _ _
    ip .unique k comm =
      lim.unique _ _ _ comm

  IP→Limit : Indexed-product C F → Limit {C = C} (Disc-adjunct {iss = i-is-grpd} F)
  IP→Limit ip =
    to-limit (is-indexed-product→is-limit has-is-ip)
    where open Indexed-product ip

  Limit→IP : Limit {C = C} (Disc-adjunct {iss = i-is-grpd} F) → Indexed-product C F
  Limit→IP lim .Indexed-product.ΠF = _
  Limit→IP lim .Indexed-product.π = _
  Limit→IP lim .Indexed-product.has-is-ip =
    is-limit→is-indexed-product (Limit.has-limit lim)