module Cat.Bi.Diagram.Monad.Spans {} where

Monads in Spans(Sets)🔗

Let C\mathcal{C} be a strict category. Whatever your favourite strict category might be — it doesn’t matter in this case. Let C0\mathcal{C}_0 denote its set of objects, and write C(x,y)\mathcal{C}(x, y) for its Hom-family. We know that families are equivalently fibrations, so that we may define

C1=x,y:C0C(x,y), \mathcal{C}_1 = \sum_{x, y : \mathcal{C}_0} \mathcal{C}(x, y)\text{,}

and, since the family is valued in Sets\mathbf{Sets} and indexed by a set, so is C1\mathcal{C}_1. We can picture C1\mathcal{C}_1 together with the components of its first projection as a span in the category of sets

Under this presentation, what does the composition operation correspond to? Well, it takes something in the object of composable morphisms, a certain subset of C1×C1\mathcal{C}_1 \times \mathcal{C}_1, and yields a morphism, i.e. something in C1\mathcal{C}_1. Moreover, this commutes with taking source/target: The source of the composition is the source of its first argument, and the target is the target of its second argument. The key observation, that will lead to a new representation of categories, is that the object of composable morphisms is precisely the composition C1C1\mathcal{C}_1 \circ \mathcal{C}_1 in the bicategory Span(Sets)\mathbf{Span}(\mathbf{Sets})!

Phrased like this, we see that the composition map gives an associative and unital procedure for mapping (C1C1)C1(\mathcal{C}_1\mathcal{C}_1) \Rightarrow \mathcal{C}_1 in a certain bicategory — a monad in that bicategory.

Spans[Sets] : Prebicategory _ _ _
Spans[Sets] = Spanᵇ (Sets ) Sets-pullbacks

strict-category→span-monad
  : (C : Precategory  ) (cset : is-set (C .Ob))
   Monad Spans[Sets] (el _ cset)
strict-category→span-monad C cset = m where
  open Monad
  open n-Type (el {n = 2} _ cset) using (H-Level-n-type)
  open Precategory.HLevel-instance C
  module C = Precategory C

  homs : Span (Sets ) (el _ cset) (el _ cset)
  homs .apex = el (Σ[ x  C .Ob ] Σ[ y  C .Ob ] (C .Hom x y)) (hlevel 2)
  homs .left (x , _ , _) = x
  homs .right (_ , y , _) = y

  mult : _ Sb.⇒ _
  mult .map ((x , y , f) , (z , x′ , g) , p) =
    z , y , subst  e  C.Hom e y) p f C.∘ g
  mult .left = refl
  mult .right = refl

  unit : _ Sb.⇒ _
  unit .map x = x , x , C .id
  unit .left = refl
  unit .right = refl

  m : Monad Spans[Sets] (el (C .Ob) cset)
  m .M = homs
  m .μ = mult
  m .η = unit

It is annoying, but entirely straightforward, to verify that the operations mult and unit defined above do constitute a monad in Span(Sets)\mathbf{Span}(\mathbf{Sets}). We omit the verification here and instruct the curious reader to check the proof on GitHub.

  m .μ-assoc = Span-hom-path (Sets ) $ funext λ where
    ((w , x , f) , ((y , z , g) , (a , b , h) , p) , q) 
      J′  w z q   (f : C.Hom w x) {y b} (p : y  b) (g : C .Hom y z)
                      (h : C.Hom a b)
                   (mult Sb.∘ (homs Sb.▶ mult)) .map ((w , x , f) , ((y , z , g) , (a , b , h) , p) , q)
                   (mult Sb.∘ (mult Sb.◀ homs) Sb.∘ Sb.α← homs homs homs) .map ((w , x , f) , ((y , z , g) , (a , b , h) , p) , q))
          w f  J′  y b p  (g : C.Hom y w) (h : C.Hom a b) 
            (mult Sb.∘ (homs Sb.▶ mult)) .map ((w , x , f) , ((y , w , g) , (a , b , h) , p) , refl)
           (mult Sb.∘ (mult Sb.◀ homs) Sb.∘ Sb.α← homs homs homs) .map ((w , x , f) , ((y , w , g) , (a , b , h) , p) , refl))
          λ y g h  Σ-pathp refl (Σ-pathp refl (C.assoc _ _ _
             ap₂ C._∘_ (ap₂ C._∘_ (ap  p  subst  e  C.Hom e x) p f) (hlevel 2 w w _ refl)  transport-refl _)
                                   (ap  p  subst  e  C.Hom e w) p g) (hlevel 2 y y _ refl)  transport-refl _)
                         sym ((ap (subst  e  C.Hom e x) _)
                                  (ap₂ C._∘_ ((ap  p  subst  e  C.Hom e x) p f) (hlevel 2 w w _ refl)  transport-refl _))
                                  refl)  ap  p  subst  e  C.Hom e x) p (f C.∘ g)) (hlevel 2 y y _ refl)  transport-refl _)))
                        refl)))
         q f p g h
  m .μ-unitr = Span-hom-path (Sets ) $ funext λ where
    ((x , y , f) , z , p) 
      J′  x z p  (f : C .Hom x y)  (mult Sb.∘ (homs Sb.▶ unit)) .map ((x , y , f) , z , p)
                                      (x , y , f))
          x f  Σ-pathp refl
            (Σ-pathp refl (ap₂ C._∘_ (ap  p  subst  e  C.Hom e y) p f) (hlevel 2 _ _ _ _)  transport-refl _) refl
                           C.idr _)))
         p f
  m .μ-unitl = Span-hom-path (Sets ) $ funext λ where
    (x , (y , z , f) , p) 
      J′  x z p  (f : C .Hom y z)
            (mult Sb.∘ (unit Sb.◀ homs)) .map (x , (y , z , f) , p)
            (y , z , f))
          x f  Σ-pathp refl
            (Σ-pathp refl (ap₂ C._∘_ (ap  p  subst  e  C.Hom e x) p C.id) (hlevel 2 _ _ _ _)  transport-refl _) refl
                           C.idl _)))
         p f

Conversely, if we have an associative and unital method mapping composable morphisms into morphisms, it stands to reason that we should be able to recover a category. Indeed, we can! The verification is once more annoying, but unsurprising. Since it’s less of a nightmare this time around, we include it in full below.

span-monad→strict-category :  (C : Set )  Monad Spans[Sets] C  Precategory _ _
span-monad→strict-category C monad = precat where
  open Monad monad

  open n-Type C using (H-Level-n-type)
  open n-Type (M .apex) using (H-Level-n-type)

  precat : Precategory _ _
  precat .Ob =  C 
  precat .Hom a b = Σ[ s   M .apex  ] ((M .left s  a) × (M .right s  b))
  precat .Hom-set x y = hlevel 2
  precat .id {x} = η .map x , sym (happly (η .left) x) , sym (happly (η .right) x)
  precat ._∘_ (f , fs , ft) (g , gs , gt) =
      μ .map (f , g , fs  sym gt)
    , sym (happly (μ .left) _)  gs
    , sym (happly (μ .right) _)  ft

The family of morphisms Hom(x,y)\mathbf{Hom}(x,y) of our recovered category is precisely the fibre of (s,t):C1C0×C0(s,t) : \mathcal{C}_1 \to \mathcal{C}_0 \times \mathcal{C}_0 over the pair x,yx, y. The commutativity conditions for 2-cells in Span(Sets)\mathbf{Span}(\mathbf{Sets}) implies that source and target are preserved through composition, and that the identity morphism — that is, the image of xx under the unit map — lies in the fibre over x,xx, x.

The verification follows from the monad laws, and it would be trivial in extensional type theory, but the tradeoff for decidable type-checking is having to munge paths sometimes. This is one of those times:

  precat .idr {x} {y} f = Σ-prop-path  _  hlevel 1)
    ( ap (μ .map) (ap (f .fst ,_) (Σ-prop-path  _  C .is-tr _ _) refl))
     happly (ap map μ-unitr) (f .fst , x , f .snd .fst))
  precat .idl {x} {y} f = Σ-prop-path  _  hlevel 1)
    ( ap (μ .map) (ap (η .map y ,_) (Σ-prop-path  _  C .is-tr _ _) refl))
     happly (ap map μ-unitl) (y , f .fst , sym (f .snd .snd)))
  precat .assoc f g h = Σ-prop-path  _  hlevel 1)
    ( ap (μ .map) (ap (f .fst ,_) (Σ-prop-path  _  hlevel 1)
        (ap (μ .map) (ap (g .fst ,_)
          (Σ-prop-path  _  hlevel 1) (refl {x = h .fst}))))))
    ·· happly (ap map μ-assoc)
        ( f .fst , (g .fst , h .fst , g .snd .fst  sym (h .snd .snd))
        , f .snd .fst  sym (g .snd .snd)
        )
    ·· ap (μ .map) (Σ-pathp (ap (μ .map) (ap (f .fst ,_)
        (Σ-prop-path  _  hlevel 1) refl)))
           (Σ-pathp-dep refl (is-prop→pathp  _  hlevel 1) _ _))))