module Cat.Displayed.TwoSided.Discrete where

Discrete two-sided fibrations🔗

Much like how discrete fibrations are presheaves, a discrete two-sided fibration is a displayed presentation of a profunctor.

A displayed category is a discrete two-sided fibration if:

  record is-discrete-two-sided-fibration : Type (oa  ℓa  ob  ℓb  oe  ℓe) where
  1. For every the type is a set.
    field
      fibre-set :  a b  is-set (Ob[ a , b ])
  1. For every and there exists a unique pair that fits into the diagram below.

This condition provides us with a source of cartesian lifts, and ensures that the pullback of along the functor is a discrete fibration for every In more intuitive terms, this means that is a sort of “presheaf in ”, as we can contravariantly reindex along morphisms in

    field
      cart-lift
        :  {a₁ a₂ : A.Ob} {b : B.Ob}
         (f : A.Hom a₁ a₂)
         (y' : Ob[ a₂ , b ])
         is-contr (Σ[ x'  Ob[ a₁ , b ] ] Hom[ f , B.id ] x' y')
  1. For every and there exists a unique pair that fit into the following diagram.

This gives us a source of cocartesian lifts, and ensures that the pullback of along the functor is a discrete opfibration.

    field
      cocart-lift
        :  {a : A.Ob} {b₁ b₂ : B.Ob}
         (f : B.Hom b₁ b₂)
         (x' : Ob[ a , b₁ ])
         is-contr (Σ[ y'  Ob[ a , b₂ ] ] Hom[ A.id , f ] x' y')
  1. For every there exists a vertical map that causes the following diagram to commute.

This condition is a bit opaque, and is best understood from the indexed point of view. From this perspective, our previous 2 conditions ensure that is separately functorial in and there is no way to commute the two reindexing functors! To get something that is jointly functorial, we need to assert the existence of some extra lifts that allow us more room to manuever.

    field
      vert-lift
        :  {a₁ a₂ b₁ b₂ x y}
         {u : A.Hom a₁ a₂} {v : B.Hom b₁ b₂}
         (f : Hom[ u , v ] x y)
         Hom[ A.id , B.id ] (v ^! x) (u ^* y)

      factors
        :  {a₁ a₂ b₁ b₂ x y}
         {u : A.Hom a₁ a₂} {v : B.Hom b₁ b₂}
         (f : Hom[ u , v ] x y)
         f ≡[ A.intror (A.idl _) ,ₚ B.insertl (B.idl _) ] (π* u y ∘' vert-lift f ∘' ι! v x)

In particular, the existence of such vertical lifts ensure that the for every the lifts and coincide.

    same-lift
      :  {a₁ a₂ b₁ b₂ x' y'} {u : A.Hom a₁ a₂} {v : B.Hom b₁ b₂}
       (f : Hom[ u , v ] x' y')
       u ^* y'  v ^! x'

First, note that it suffices to construct a map as the space of lifts of along is contractible. The above axiom ensures that this map exists!

    same-lift {x' = x'} {y' = y'} {u = u} {v = v} f =
       ap fst $ is-contr→is-prop (cart-lift A.id (u ^* y'))
         (u ^* y' , id')
         (v ^! x' , vert-lift f)

Moreover, the factorisation condition ensures that every hom set forms a proposition.

    Hom[]-is-prop
      :  {a₁ a₂ b₁ b₂ x' y'} {u : A.Hom a₁ a₂} {v : B.Hom b₁ b₂}
       is-prop (Hom[ u , v ] x' y')

Let be a pair of morphisms. Both maps factor as and so it suffices to show that

    Hom[]-is-prop {x' = x'} {y' = y'} {u = u} {v = v} f' g' =
      cast[] $
        f'                                     ≡[]⟨ factors f' ≡[]
        π* u y' ∘'  vert-lift f'  ∘' ι! v x' ≡[]⟨ ap! vert-lift-eq ≡[]
        π* u y' ∘' vert-lift g' ∘' ι! v x'     ≡[]˘⟨ factors g' ≡[]˘
        g'                                     

The type of objects is a set, so it further suffices to prove that which follows immediately from uniqueness of lifts.

      where
        vert-lift-eq : vert-lift f'  vert-lift g'
        vert-lift-eq =
          Σ-inj-set (fibre-set _ _) $
          is-contr→is-prop (cart-lift A.id (u ^* y'))
            (v ^! x' , vert-lift f')
            (v ^! x' , vert-lift g')

An alternative view is that these final conditions ensure that morphisms are equivalent to proofs that

    opaque
      discrete-two-sided-hom
        :  {a₁ a₂ b₁ b₂ x' y'}
         (u : A.Hom a₁ a₂) (v : B.Hom b₁ b₂)
         (u ^* y')  (v ^! x')
         Hom[ u , v ] x' y'
      discrete-two-sided-hom {x' = x'} {y' = y'} u v p =
        hom[ A.elimr (A.idr _) ,ₚ B.cancell (B.idl _) ] $
          π* u y' ∘' subst  v!x  Hom[ A.id , B.id ] v!x (u ^* y')) p id' ∘' ι! v x'

    discrete-two-sided-hom-is-equiv
      :  {a₁ a₂ b₁ b₂ x' y'}
       (u : A.Hom a₁ a₂) (v : B.Hom b₁ b₂)
       is-equiv (discrete-two-sided-hom {x' = x'} {y' = y'} u v)
    discrete-two-sided-hom-is-equiv u v =
      is-iso→is-equiv $
      iso same-lift
         _  Hom[]-is-prop _ _)
         _  fibre-set _ _ _ _ _ _)

Functoriality🔗

Note that the action is functorial on the fibres of that are vertical over as lifts are unique.

    ^*-∘
      :  {a₁ a₂ a₃ : A.Ob} {b : B.Ob}
       (u : A.Hom a₂ a₃) (v : A.Hom a₁ a₂)
       (y' : Ob[ a₃ , b ])
       (u A.∘ v) ^* y'  (v ^* (u ^* y'))
    ^*-∘ u v y' =
      ap fst $ cart-lift (u A.∘ v) y' .paths $
        v ^* (u ^* y') ,
        hom[ refl ,ₚ B.idl _ ] (π* u y' ∘' π* v (u ^* y'))

    ^*-id
      :  {a b} {x' : Ob[ a , b ]}
       A.id ^* x'  x'
    ^*-id {x' = x'} =
      ap fst $ cart-lift A.id x' .paths (x' , id')

Dually, the action is functorial on the fibres of that are vertical over

    ^!-∘
      :  {a : A.Ob} {b₁ b₂ b₃ : B.Ob}
       (u : B.Hom b₂ b₃) (v : B.Hom b₁ b₂)
       (x' : Ob[ a , b₁ ])
       (u B.∘ v) ^! x'  (u ^! (v ^! x'))
    ^!-∘ u v x' =
      ap fst $ cocart-lift (u B.∘ v) x' .paths $
        u ^! (v ^! x') , hom[ A.idr _ ,ₚ refl ] (ι! u (v ^! x') ∘' ι! v x')

    ^!-id
      :  {a b} {x' : Ob[ a , b ]}
       B.id ^! x'  x'
    ^!-id {x' = x'} =
      ap fst $ cocart-lift B.id x' .paths (x' , id')

Moreover, we also have an interchange law that lets us relate the contravariant and covariant actions on fibres.

    ^*-^!-comm
      :  {a₁ a₂ : A.Ob} {b₁ b₂ : B.Ob}
       (u : A.Hom a₁ a₂) (v : B.Hom b₁ b₂)
       (x' : Ob[ a₂ , b₁ ])
       (u ^* (v ^! x'))  (v ^! (u ^* x'))
    ^*-^!-comm u v x' =
      same-lift (hom[ A.idl u ,ₚ B.idr v ] (ι! v x' ∘' π* u x'))

Invertible maps🔗

Every morphism in a discrete two-sided fibration living over an invertible pair of morphisms is itself invertible.

    all-invertible[]
      :  {a₁ a₂ b₁ b₂ x' y'} {u : A.Hom a₁ a₂} {v : B.Hom b₁ b₂}
       (f : Hom[ u , v ] x' y')
       (uv⁻¹ : A×B.is-invertible (u , v))
       is-invertible[ uv⁻¹ ] f

Let be a map displayed over a pair of invertible maps

    all-invertible[] {a₁} {a₂} {b₁} {b₂} {x'} {y'} {u} {v} f uv⁻¹ = f⁻¹ where
      module uv⁻¹ = A×B.is-invertible uv⁻¹
      open is-invertible[_]

      u⁻¹ : A.Hom _ _
      u⁻¹ = uv⁻¹.inv .fst

      v⁻¹ : B.Hom _ _
      v⁻¹ = uv⁻¹.inv .snd

Since each of our is a proposition, to construct an inverse it suffices to build a map This, in turn, reduces to showing which follows from some tedious functoriality algebra.

      f⁻¹ : is-invertible[ uv⁻¹ ] f
      f⁻¹ .inv' =
        discrete-two-sided-hom u⁻¹ v⁻¹ $
          u⁻¹ ^* x'                    ≡˘⟨ ap (u⁻¹ ^*_) ^!-id ≡˘
          u⁻¹ ^* ( B.id  ^! x')      ≡⟨ ap! (sym (ap snd $ uv⁻¹.invr)) 
          u⁻¹ ^* ((v⁻¹ B.∘ v) ^! x')   ≡⟨ ap (u⁻¹ ^*_) (^!-∘ v⁻¹ v x') 
          u⁻¹ ^* (v⁻¹ ^!  v ^! x' )  ≡⟨ ap! (sym (same-lift f)) 
          u⁻¹ ^* (v⁻¹ ^! (u ^* y'))    ≡˘⟨ ap (u⁻¹ ^*_) (^*-^!-comm u v⁻¹ y') ≡˘
          u⁻¹ ^* (u ^* (v⁻¹ ^! y'))    ≡˘⟨ ^*-∘ u u⁻¹ (v⁻¹ ^! y') ≡˘
           u A.∘ u⁻¹  ^* (v⁻¹ ^! y') ≡⟨ ap! (ap fst $ uv⁻¹.invl) 
          A.id ^* (v⁻¹ ^! y')          ≡⟨ ^*-id 
          v⁻¹ ^! y' 
      f⁻¹ .inverses' .Inverses[_].invl' =
        is-prop→pathp  _  Hom[]-is-prop) _ _
      f⁻¹ .inverses' .Inverses[_].invr' =
        is-prop→pathp  _  Hom[]-is-prop) _ _

Cartesian and cocartesian maps🔗

Every map that is is cartesian; and, dually, every map that is is cocartesian.

    vertical-cartesian
      :  {a₁ a₂ b x' y'} {u : A.Hom a₁ a₂}
       (f : Hom[ u , B.id {b} ] x' y')
       is-cartesian E (u , B.id) f

    vertical-cocartesian
      :  {a b₁ b₂ x' y'} {v : B.Hom b₁ b₂}
       (f : Hom[ A.id {a} , v ] x' y')
       is-cocartesian E (A.id , v) f

The proof is a bit more functoriality algebra.

    vertical-cartesian {x' = x'} {y'} {u} f .is-cartesian.universal {_} {a'} (v , w) h =
      discrete-two-sided-hom v w $
        v ^* x'            ≡˘⟨ ap (v ^*_) ^!-id ≡˘
        v ^* (B.id ^! x')  ≡˘⟨ ap (v ^*_) (same-lift f) ≡˘
        v ^* (u ^* y')     ≡˘⟨ ^*-∘ u v y' ≡˘
        (u A.∘ v) ^* y'    ≡⟨ same-lift h 
        (B.id B.∘ w) ^! a' ≡⟨ ap (_^! a') (B.idl w) 
        w ^! a'            
    vertical-cartesian {x' = x'} {y'} {u} f .is-cartesian.commutes _ _ =
      Hom[]-is-prop _ _
    vertical-cartesian {x' = x'} {y'} {u} f .is-cartesian.unique _ _ =
      Hom[]-is-prop _ _
The cocartesian case is formally dual, so we omit the details.
    vertical-cocartesian {x' = x'} {y'} {v} f .is-cocartesian.universal {_} {a'} (u , w) h =
      discrete-two-sided-hom u w $
        u ^* a'            ≡˘⟨ ap (_^* a') (A.idr _) ≡˘
        (u A.∘ A.id) ^* a' ≡⟨ same-lift h 
        (w B.∘ v) ^! x'    ≡⟨ ^!-∘ w v x' 
        w ^! (v ^! x')     ≡˘⟨ ap (w ^!_) (same-lift f) ≡˘
        w ^! (A.id ^* y')  ≡⟨ ap (w ^!_) ^*-id 
        w ^! y'            
    vertical-cocartesian {x' = x'} {y'} {v} f .is-cocartesian.commutes _ _ =
      Hom[]-is-prop _ _
    vertical-cocartesian {x' = x'} {y'} {v} f .is-cocartesian.unique _ _ =
      Hom[]-is-prop _ _

Discrete two-sided fibrations are two-sided fibrations🔗

Every discrete two-sided fibration is a two-sided fibration.

  discrete-two-sided-fibration→two-sided-fibration
    : is-discrete-two-sided-fibration E
     Two-sided-fibration E

This is essentially a triviality at this point: every map is cocartesian, and every map is cartesian, and all requisite lifts exit.

  discrete-two-sided-fibration→two-sided-fibration E-dfib = E-fib where
    open is-discrete-two-sided-fibration E-dfib
    open Two-sided-fibration
    open Cocartesian-lift
    open Cartesian-lift

    E-fib : Two-sided-fibration E
    E-fib .cart-lift u y' .x' = u ^* y'
    E-fib .cart-lift u y' .lifting = π* u y'
    E-fib .cart-lift u y' .cartesian = vertical-cartesian (π* u y')
    E-fib .cocart-lift v x' .y' = v ^! x'
    E-fib .cocart-lift v x' .lifting = ι! v x'
    E-fib .cocart-lift v x' .cocartesian = vertical-cocartesian (ι! v x')
    E-fib .cart-beck-chevalley _ _ _ _ = vertical-cartesian _
    E-fib .cocart-beck-chevalley _ _ _ _ = vertical-cocartesian _