module Cat.Functor.Kan.Duality whereprivate
  variable
    o ā : Level
    C C' D : Precategory o āDuality for Kan extensionsš
Left Kan extensions are dual to right Kan extensions. This is straightforward enough to prove, but does involve some bureaucracy involving opposite categories.
module _ (p : Functor C C') (F : Functor C D) where
  open Ran
  open Lan
  open is-ran
  open is-lan
  open _=>_
  co-unitācounit
    : ā {G : Functor (C' ^op) (D ^op)}
    ā Functor.op F => G Fā Functor.op p
    ā unopF G Fā p => F
  co-unitācounit α = record { opN α }
  co-unitācounit
    : ā {G : Functor C' D}
    ā G Fā p => F
    ā Functor.op F => Functor.op G Fā Functor.op p
  co-unitācounit α = record { opN α }
  counitāco-unit
    : ā {G : Functor (C' ^op) (D ^op)}
    ā G Fā Functor.op p => Functor.op F
    ā F => unopF G Fā p
  counitāco-unit α = record { opN α }
  counitāco-unit
    : ā {G : Functor C' D}
    ā F => G Fā p
    ā Functor.op G Fā Functor.op p => Functor.op F
  counitāco-unit α = record { opN α }  is-co-lan'āis-ran
    : ā {G : Functor (C' ^op) (D ^op)} {eta : Functor.op F => G Fā Functor.op p}
    ā is-lan (Functor.op p) (Functor.op F) G eta
    ā is-ran p F (unopF G) (co-unitācounit eta)
  is-co-lan'āis-ran {G = G} {eta = eta} is-lan = ran where
    module lan = is-lan is-lan
    ran : is-ran p F (unopF G) (co-unitācounit eta)
    ran .Ļ {M = M} α = record { opN (lan.Ļ Ī±') } where
      α' : Functor.op F => Functor.op M Fā Functor.op p
      α' = record { opN α }
    ran .Ļ-comm = ext (lan.Ļ-comm Ī·ā_)
    ran .Ļ-uniq {M = M} {Ļ' = Ļ'} p = ext Ī» x ā
      lan.Ļ-uniq {Ļ' = dualise! Ļ'} (reext! p) Ī·ā x  -- This is identical to is-co-lan'āis-ran, but we push the Functor.op
  -- into the is-lan, which is what you want when not dealing with Lan.
  is-co-lanāis-ran
    : {G : Functor C' D} {eps : G Fā p => F}
    ā is-lan (Functor.op p) (Functor.op F) (Functor.op G) (co-unitācounit eps)
    ā is-ran p F G eps
  is-co-lanāis-ran {G = G} {eps} lan = ran where
    module lan = is-lan lan
    ran : is-ran p F G eps
    ran .Ļ {M = M} α = record { opN (lan.Ļ Ī±') } where
      α' : (Functor.op F => Functor.op M Fā Functor.op p)
      α' = record { _=>_ (_=>_.op α) }
    ran .Ļ-comm = ext (lan.Ļ-comm Ī·ā_)
    ran .Ļ-uniq {M = M} {Ļ' = Ļ'} p = ext Ī» x ā
      lan.Ļ-uniq {Ļ' = dualise! Ļ'} (reext! p) Ī·ā x
  is-ranāis-co-lan
    : ā {Ext : Functor C' D} {eta : Ext Fā p => F}
    ā is-ran p F Ext eta
    ā is-lan (Functor.op p) (Functor.op F) (Functor.op Ext) (co-unitācounit eta)
  is-ranāis-co-lan {Ext = Ext} is-ran = lan where
    module ran = is-ran is-ran
    lan : is-lan (Functor.op p) (Functor.op F) (Functor.op Ext) _
    lan .Ļ {M = M} α = Ļ' where
      α' : (unopF M Fā p => F)
      α' = record { opN α }
      Ļ' : (Functor.op Ext => M)
      Ļ' = record { opN (ran.Ļ Ī±') }
    lan .Ļ-comm = ext (ran.Ļ-comm Ī·ā_)
    lan .Ļ-uniq {M = M} {Ļ' = Ļ'} p = ext Ī» x ā
      ran.Ļ-uniq {Ļ' = dualise! Ļ'} (reext! p) Ī·ā x
  Co-lanāRan : Lan (Functor.op p) (Functor.op F) ā Ran p F
  Co-lanāRan lan .Ext     = unopF (lan .Ext)
  Co-lanāRan lan .eps     = co-unitācounit (lan .eta)
  Co-lanāRan lan .has-ran = is-co-lan'āis-ran (lan .has-lan)
  RanāCo-lan : Ran p F ā Lan (Functor.op p) (Functor.op F)
  RanāCo-lan ran .Ext = Functor.op (ran .Ext)
  RanāCo-lan ran .eta = co-unitācounit (ran .eps)
  RanāCo-lan ran .has-lan = is-ranāis-co-lan (ran .has-ran)
  is-co-ran'āis-lan
    : {G : Functor (C' ^op) (D ^op)} {eps : G Fā Functor.op p => Functor.op F}
    ā is-ran (Functor.op p) (Functor.op F) G eps
    ā is-lan p F (unopF G) (counitāco-unit eps)
  is-co-ran'āis-lan {G = G} {eps} is-ran = lan where
    module ran = is-ran is-ran
    lan : is-lan p F (unopF G) (counitāco-unit eps)
    lan .Ļ {M = M} β = record { opN (ran.Ļ Ī²') } where
      β' : Functor.op M Fā Functor.op p => Functor.op F
      β' = record { opN β }
    lan .Ļ-comm = ext (ran.Ļ-comm Ī·ā_)
    lan .Ļ-uniq {M = M} {Ļ' = Ļ'} p = ext Ī» x ā
      ran.Ļ-uniq {Ļ' = dualise! Ļ'} (reext! p) Ī·ā x
  is-co-ranāis-lan
    : ā {G : Functor C' D} {eta}
    ā is-ran (Functor.op p) (Functor.op F) (Functor.op G) (counitāco-unit eta)
    ā is-lan p F G eta
  is-co-ranāis-lan {G = G} {eta} is-ran = lan where
    module ran = is-ran is-ran
    lan : is-lan p F G eta
    lan .Ļ {M = M} β = record { opN (ran.Ļ Ī²') } where
      β' : Functor.op M Fā Functor.op p => Functor.op F
      β' = record { opN β }
    lan .Ļ-comm = ext (ran.Ļ-comm Ī·ā_)
    lan .Ļ-uniq {M = M} {Ļ' = Ļ'} p = ext Ī» x ā
      ran.Ļ-uniq {Ļ' = dualise! Ļ'} (reext! p) Ī·ā x
  is-lanāis-co-ran
    : ā {G : Functor C' D} {eps : F => G Fā p}
    ā is-lan p F G eps
    ā is-ran (Functor.op p) (Functor.op F) (Functor.op G) (counitāco-unit eps)
  is-lanāis-co-ran {G = G} is-lan = ran where
    module lan = is-lan is-lan
    ran : is-ran (Functor.op p) (Functor.op F) (Functor.op G) _
    ran .Ļ {M = M} β = Ļ' where
      β' : F => unopF M Fā p
      β' = record { opN β }
      Ļ' : M => Functor.op G
      Ļ' = record { opN (lan.Ļ Ī²') }
    ran .Ļ-comm = ext (lan.Ļ-comm Ī·ā_)
    ran .Ļ-uniq {M = M} {Ļ' = Ļ'} p = ext Ī» x ā
      lan.Ļ-uniq {Ļ' = dualise! Ļ'} (reext! p) Ī·ā x
  Co-ranāLan : Ran (Functor.op p) (Functor.op F) ā Lan p F
  Co-ranāLan ran .Ext = unopF (ran .Ext)
  Co-ranāLan ran .eta = counitāco-unit (ran .eps)
  Co-ranāLan ran .has-lan = is-co-ran'āis-lan (ran .has-ran)
  LanāCo-ran : Lan p F ā Ran (Functor.op p) (Functor.op F)
  LanāCo-ran lan .Ext = Functor.op (lan .Ext)
  LanāCo-ran lan .eps = counitāco-unit (lan .eta)
  LanāCo-ran lan .has-ran = is-lanāis-co-ran (lan .has-lan)