\import Algebra.Meta \import Category \import Equiv \import Function.Meta \import Logic.Meta \import Meta \import Paths \import Paths.Meta \class Functor (C D : Precat) (\classifying F : C -> D) { | Func {X Y : C} : Hom X Y -> Hom (F X) (F Y) | Func-id {X : C} : Func (id X) = id (F X) | Func-o {X Y Z : C} {g : Hom Y Z} {f : Hom X Y} : Func (g ∘ f) = Func g ∘ Func f \func op : Functor C.op D.op F \cowith | Func f => Func f | Func-id => Func-id | Func-o => Func-o \func Func-iso (e : Iso {C}) : Iso {D} {F e.dom} {F e.cod} (Func e) \cowith | hinv => Func e.hinv | hinv_f => inv Func-o *> pmap Func e.hinv_f *> Func-id | f_hinv => inv Func-o *> pmap Func e.f_hinv *> Func-id } \func Id {C : Precat} : Functor C C \cowith | F X => X | Func h => h | Func-id => idp | Func-o => idp \func Comp {C D E : Precat} (G : Functor D E) (F : Functor C D) : Functor C E \cowith | F X => G (F X) | Func f => G.Func (F.Func f) | Func-id => pmap G.Func F.Func-id *> G.Func-id | Func-o => pmap G.Func F.Func-o *> G.Func-o \func Const {C D : Precat} (d : D) : Functor C D \cowith | F _ => d | Func _ => id d | Func-id => idp | Func-o => inv id-left \where { \func natTrans {C D : Precat} {d d' : D} (f : Hom d d') : NatTrans {C} (Const d) (Const d') \cowith | trans _ => f | natural g => id-right *> inv id-left } \record NatTrans \plevels obj >= hom >= iobj >= ihom {C : Precat \levels (iobj,ihom) _} {D : Precat \levels (obj,hom) _} (F G : Functor C D) { | \coerce trans (X : C) : Hom (F X) (G X) | natural {X Y : C} (f : Hom X Y) : trans Y ∘ F.Func f = G.Func f ∘ trans X \func op : NatTrans G.op F.op \cowith | trans => trans | natural f => inv (natural f) \lemma iso (e : \Pi {X : C} -> Iso (trans X)) : NatTrans G F (\lam X => e.hinv) \cowith | natural f => e.isMono $ rewrite (inv o-assoc, e.f_hinv, id-left, inv o-assoc, natural f, o-assoc, e.f_hinv, id-right) idp } \where { \func Comp-left {C D E : Precat} (a : NatTrans {D} {E}) (H : Functor C D) : NatTrans (Comp a.F H) (Comp a.G H) \cowith | trans x => a (H x) | natural f => a.natural (H.Func f) \func Comp-right {C D E : Precat} (H : Functor D E) (a : NatTrans {C} {D}) : NatTrans (Comp H a.F) (Comp H a.G) \cowith | trans x => H.Func (a x) | natural f => inv H.Func-o *> pmap H.Func (a.natural f) *> H.Func-o } \instance FunctorPrecat {C D : SmallPrecat} : Precat (Functor C D) | Hom => NatTrans | id F => \new NatTrans { | trans X => id (F X) | natural f => id-left *> inv id-right } | o b a => \new NatTrans { | trans X => b X ∘ a X | natural f => run { rewrite (o-assoc, natural {a} f), rewriteI o-assoc, rewrite (natural {b} f), o-assoc } } | id-left => exts (\lam X => id-left) | id-right => exts (\lam X => id-right) | o-assoc => exts (\lam X => o-assoc) \instance FunctorCat {C : SmallPrecat} {D : SmallCat} : Cat (Functor C D) | Precat => FunctorPrecat | univalence => Cat.makeUnivalence $ later \lam e => (exts (\lam X => D.isotoid (mapIso e X), \lam {X} {Y} h => Cat.transport_Hom_iso (mapIso e X) (mapIso e Y) (natural h)), simp_coe $ simp_coe \lam X => Cat.transport_iso (mapIso e X)) \where { \func mapIso {C D : SmallPrecat} (e : Iso {FunctorPrecat {C} {D}}) (X : C) : Iso {D} \cowith | dom => e.dom X | cod => e.cod X | f => e.f X | hinv => e.hinv X | hinv_f => path (\lam i => trans {e.hinv_f @ i} X) | f_hinv => path (\lam i => trans {e.f_hinv @ i} X) } \instance FamPrecat {J : \Type} (D : Precat) : Precat (J -> D) | Hom F G => \Pi {j : J} -> Hom (F j) (G j) | id F {j} => id (F j) | o g f {j} => g ∘ f | id-left => ext (\lam {j} => id-left) | id-right => ext (\lam {j} => id-right) | o-assoc => ext (\lam {j} => o-assoc) \instance FamCat {J : \Type} (D : Cat) : Cat (J -> D) | Precat => FamPrecat D | univalence => Cat.makeUnivalence $ later \lam e => (ext \lam j => D.isotoid (mapIso e j), simp_coe \lam {j} => Cat.transport_iso (mapIso e j)) \where { \func mapIso {J : \Type} {D : Precat} (e : Iso {FamPrecat {J} D}) (j : J) : Iso {D} \cowith | dom => e.dom j | cod => e.cod j | f => e.f | hinv => e.hinv | hinv_f => path (e.hinv_f @ __) | f_hinv => path (e.f_hinv @ __) } \class FaithfulFunctor \extends Functor { | isFaithful {X Y : C} {f g : Hom X Y} : Func f = Func g -> f = g \func op : FaithfulFunctor \cowith | Functor => Functor.op | isFaithful p => isFaithful p } \class FullFunctor \extends Functor { | isFull {X Y : C} (f : Hom (F X) (F Y)) : ∃ (g : Hom X Y) (Func g = f) \func op : FullFunctor \cowith | Functor => Functor.op | isFull f => isFull f } \class FullyFaithfulFunctor \extends FullFunctor, FaithfulFunctor { | isFullyFaithful {X Y : C} : Equiv (Func {_} {X} {Y}) | isFull f => isSurjMap {ESEquiv.fromEquiv isFullyFaithful} f | isFaithful p => isFullyFaithful.isInj p \func op : FullyFaithfulFunctor \cowith | Functor => Functor.op | isFullyFaithful => isFullyFaithful \func inverse {X Y : C} (f : Hom (F X) (F Y)) : Hom X Y => isFullyFaithful.ret f \lemma inverse-left {X Y : C} {f : Hom X Y} : inverse (Func f) = f => isFullyFaithful.ret_f f \lemma inverse-right {X Y : C} {f : Hom (F X) (F Y)} : Func (inverse f) = f => isFullyFaithful.f_ret f \lemma inverse-id {x : C} : inverse (id (F x)) = id x => pmap inverse (inv Func-id) *> inverse-left \lemma inverse-o {x y z : C} {g : Hom (F y) (F z)} {f : Hom (F x) (F y)} : inverse (g ∘ f) = inverse g ∘ inverse f => inv (pmap inverse Func-o *> cong inverse-right inverse-right) *> inverse-left }