\import Category
\import Category.Functor
\import Equiv
\import Function.Meta
\import Meta
\import Paths
\import Paths.Meta
\class RightAdjoint \extends Functor {
| LAdj : Functor D C
| eta : NatTrans Id (Comp \this LAdj)
\field isAdjoint {X : D} {Y : C} : Equiv {Hom (LAdj X) Y} {Hom X (F Y)} (Func __ ∘ eta X)
\func epsilon : NatTrans (Comp LAdj \this) Id \cowith
| trans X => isAdjoint.ret (id _)
| natural f => isAdjoint.isInj $ unfold $ rewrite (Func-o, Func-o, o-assoc, o-assoc, isAdjoint.f_ret, id-right, inv (eta.natural _), inv o-assoc, isAdjoint.f_ret) id-left
\lemma eta_epsilon-left (Y : C) : Func (epsilon Y) ∘ eta (F Y) = id (F Y)
=> isAdjoint.f_ret _
\lemma eta_epsilon-right (X : D) : epsilon (LAdj X) ∘ LAdj.Func (eta X) = id (LAdj X)
=> isAdjoint.isInj $ unfold $ rewrite (Func-id, Func-o, o-assoc, inv (eta.natural _), inv o-assoc, isAdjoint.f_ret) idp
\lemma adjoint_epsilon {X : D} {Y : C} (f : Hom X (F Y)) : isAdjoint.ret f = epsilon Y ∘ LAdj.Func f
=> isAdjoint.isInj $ unfold $ isAdjoint.f_ret _ *> rewrite (Func-o, o-assoc, inv (eta.natural _), inv o-assoc, isAdjoint.f_ret, id-left) idp
\lemma eta_eps_equiv {X : D} {Y : C} : QEquiv {Hom (LAdj X) Y} {Hom X (F Y)} (Func __ ∘ eta X) (epsilon Y ∘ LAdj.Func __) \cowith
| ret_f f => inv (adjoint_epsilon _) *> isAdjoint.ret_f _
| f_sec g => rewriteI adjoint_epsilon (isAdjoint.f_ret _)
} \where {
\func rightFactor {C D E : Precat} (G1 : FullyFaithfulFunctor D E) (G2 : Functor E D) (adj : RightAdjoint { | Functor => Comp G1 G2 }) : RightAdjoint \cowith
| Functor => G2
| LAdj => Comp adj.LAdj G1
| eta {
| trans Y => G1.inverse (adj.eta (G1 Y))
| natural h => run {
G1.isFullyFaithful.isInj,
repeat {2} (rewrite G1.Func-o),
repeat {2} (rewrite G1.inverse-right),
adj.eta.natural (G1.Func h)
}
}
| isAdjoint => \new QEquiv {
| ret h => adj.isAdjoint.ret (G1.Func h)
| ret_f h => rewrite (G1.Func-o, G1.inverse-right) (adj.isAdjoint.ret_f _)
| f_sec h => run {
G1.isFullyFaithful.isInj,
rewrite (G1.Func-o, G1.inverse-right),
adj.isAdjoint.f_ret _
}
}
}
\class CatEquiv \extends FullyFaithfulFunctor, RightAdjoint {
\field eta-iso {X : D} : Iso (eta X)
\field epsilon-iso {Y : C} : Iso (epsilon Y)
| isFullyFaithful => TwoOutOfThree.rightFactor _ (symQEquiv isAdjoint) $ transport (QEquiv __) (ext \lam h => inv (adjoint_epsilon _ *> epsilon.natural h)) epsilon-iso.-o_Equiv
\func op : CatEquiv \cowith
| Functor => Functor.op
| LAdj => LAdj.op
| eta => NatTrans.op {eta.iso eta-iso}
| isAdjoint {X} {Y} => \new QEquiv {
| ret g => LAdj.Func g ∘ epsilon-iso.hinv
| ret_f f => run {
rewrite LAdj.Func-o,
rewriteEq (inv (natural {epsilon.iso epsilon-iso} f)),
inv,
Iso.adjoint {LAdj.Func-iso eta-iso},
epsilon-iso.adjoint,
rewriteEq (eta_epsilon-right X),
id-left
}
| f_sec => unfold \lam g => run {
rewrite Func-o,
rewriteEq (natural {eta.iso eta-iso} g),
inv,
Iso.adjoint' {Func-iso epsilon-iso},
eta-iso.adjoint',
rewriteEq (eta_epsilon-left Y),
id-right
}
}
| eta-iso => eta-iso.op.reverse
| epsilon-iso => unfold $ rewrite (LAdj.Func-id,id-left) epsilon-iso.op.reverse
\func reverse : CatEquiv \cowith
| Functor => LAdj
| LAdj => \this
| eta => epsilon.iso epsilon-iso
| isAdjoint => \new QEquiv {
| ret h => eta-iso.hinv ∘ Func h
| ret_f h => rewrite (Func-o, inv o-assoc, natural {eta.iso eta-iso}, o-assoc) $
pmap (h ∘) (pmap (`∘ _) (inv (Iso.adjoint' (eta_epsilon-left _) *> id-left )) *> f_hinv {Functor.Func-iso epsilon-iso}) *> id-right
| f_sec h => rewrite (LAdj.Func-o, o-assoc, inv (natural {epsilon.iso epsilon-iso} _), inv o-assoc) $
pmap (`∘ h) (pmap (_ ∘) (inv (epsilon-iso.adjoint (eta_epsilon-right _) *> id-right)) *> hinv_f {LAdj.Func-iso eta-iso}) *> id-left
}
| eta-iso => epsilon-iso.reverse
| epsilon-iso => unfold $ rewrite (Func-id,id-right) eta-iso.reverse
}