\import Category
\import Category.Adjoint
\import Category.Comma
\import Category.Functor
\import Category.Limit
\import Equiv
\import Function.Meta
\import Logic.Unique
\import Logic
\import Meta
\import Paths
\import Paths.Meta
\func comma-precat {C D : Precat} (L : Functor D C) (b : C) => commaPrecat {D} {TrivialCat} {C} L (Const b)
\func comma-cat {C : Precat} {D : Cat} (L : Functor D C) (b : C) => commaCat {D} {TrivialCat} {C} L (Const b)
\class Coreflection {C D : Precat} (L : Functor D C) (B : C) {
| \classifying Coreflected : D
| corefl-map : Hom (L Coreflected) B
\property isCoreflection {Z : D} : Equiv {Hom Z Coreflected} {Hom (L Z) B} (\lam x => corefl-map ∘ L.Func x)
\func to-comma : comma-precat L B => (Coreflected, (), corefl-map)
\func coreflection-map (x : comma-precat L B) : Hom {comma-precat L B} x to-comma
| (x, s, d) => (isCoreflection.ret d, id {TrivialCat} s, rewrite id-left $ isCoreflection.f_ret d)
\func to-comma-terminal : terminal-obj (comma-precat L B) => isTerminal {comma-precat L B} to-comma
(\lam (p, s, q) => Contr.make (coreflection-map (p, s, q))
(\lam a => exts (inv $ Equiv.adjoint $ a.3 *> id-left, cases a.2 \with {
| Graph.empty p1 => idp
| Graph.cons e x => absurd e
}))
)
}
\where {
\func from-comma-terminal {C D : Precat} {L : Functor D C} {b : C} (terminal : terminal-obj (comma-precat L b))
: Coreflection L b => \new Coreflection {
| Coreflected => terminal.apex.1
| corefl-map => terminal.apex.3
| isCoreflection {z} => \new QEquiv {
| ret g => (terminalMap' {comma-precat L b} {terminal} {z, (), g}).1
| f_sec y => (terminalMap' {comma-precat L b} {terminal} {z, (), y}).3 *> id-left
| ret_f x =>
\let x-comma : comma-precat L b => (z, (), terminal.apex.3 ∘ L.Func x)
| x-map : Hom {comma-precat L b} x-comma terminal.apex => (x, id {TrivialCat} (), inv id-left)
\in
path (\lam i => ((inv $ terminal-unique' {comma-precat L b} {terminal} {x-comma} {x-map}) @ i).1)
}
}
\func terminal-in-comma {C D : Precat} (L : Functor D C) (B : C)
: Section {Coreflection L B} {terminal-obj (comma-precat L B)} => \new Section {
| f coref => Coreflection.to-comma-terminal {coref}
| ret => Coreflection.from-comma-terminal
| ret_f _ => idp
} \where {
\func to-comma-isInj (x y : Coreflection L B) (eq : Coreflection.to-comma-terminal {x} = Coreflection.to-comma-terminal {y})
: x = y =>
inv (ret_f {terminal-in-comma L B} x) *> pmap (ret {terminal-in-comma L B}) eq *> ret_f {terminal-in-comma L B} y
}
\sfunc isProp {C : Precat} {D : Cat} {L : Functor D C} {B : C} (x y : Coreflection L B) : x = y
=> terminal-in-comma.to-comma-isInj x y (terminal-prop {comma-cat L B} _ _)
}
\class RightAdjointCoreflection \extends Functor {
| L : Functor D C
\field coreflection (Z : C) : Coreflection {C} {D} L Z
| F X => coreflection X
| Func {X} {_} f => Equiv.ret {isCoreflection} (f ∘ corefl-map {coreflection X})
| Func-id {_} => unfold $ rewrite id-left $ inv $ Equiv.adjoint $ unfold $ rewrite (Func-id {L}, id-right) idp
| Func-o {_} {Y} {Z} {_} {_} => run {
unfold,
inv,
Equiv.adjoint,
unfold,
rewrite (Func-o {L}),
rewriteI o-assoc ,
rewrite (Equiv.f_ret {isCoreflection {coreflection Z}}),
rewrite o-assoc ,
rewrite (Equiv.f_ret {isCoreflection {coreflection Y}}),
inv o-assoc
}
\use \func eval-trans : NatTrans (Comp L \this) Id \cowith {
| trans c => corefl-map {coreflection c}
| natural _ => unfold $ Equiv.f_ret {isCoreflection} _
}
\use \func is-adjoint-counit {X : D} {Y : C} : Equiv {Hom X (F Y)} {Hom (L X) Y} (eval-trans Y ∘ L.Func __)
=> isCoreflection
}
\where {
\use \coerce toAdjoint (F : RightAdjointCoreflection) : RightAdjointCounit \cowith
| Functor => F
| LAdj => F.L
| epsilon => F.eval-trans
| epsilon-adjoint => F.is-adjoint-counit
\use \coerce fromAdjoint (F : RightAdjoint) : RightAdjointCoreflection F.C F.D F.LAdj \cowith
| coreflection Z => \new Coreflection {
| Coreflected => F Z
| corefl-map => F.epsilon Z
| isCoreflection => symQEquiv F.eta_epsilon-equiv
}
\sfunc isProp {C : Precat} {D : Cat} (L : Functor D C) (adj1 adj2 : RightAdjointCoreflection C D L) : adj1 = adj2 \elim adj1, adj2
| (coref1), (coref2) => exts (\lam Z => Coreflection.isProp (coreflection {coref1} Z) (coreflection {coref2} Z))
}