Last active
December 7, 2016 13:07
-
-
Save mathink/27b1a8150a118affc1296790673114d9 to your computer and use it in GitHub Desktop.
Coq で圏論 2016 年 12 月 ver.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Set Implicit Arguments. | |
Unset Strict Implicit. | |
Unset Printing Implicit Defensive. | |
Set Reversible Pattern Implicit. | |
Generalizable All Variables. | |
Set Primitive Projections. | |
Set Universe Polymorphism. | |
(* cmorphisms... *) | |
Require Export Coq.Program.Basics Coq.Program.Tactics Coq.Setoids.Setoid Coq.Classes.Morphisms. | |
Obligation Tactic := (try split); program_simpl; try now auto. | |
(** * 0. Setoid and Map **) | |
Structure Setoid: Type := | |
{ | |
setoid_carrier:> Type; | |
setoid_equal: setoid_carrier -> setoid_carrier -> Prop; | |
setoid_prf:> Equivalence setoid_equal | |
}. | |
Existing Instance setoid_prf. | |
Notation "[ 'Setoid' 'by' P 'on' A ]" := (@Build_Setoid A P _). | |
Notation "[ 'Setoid' 'by' P ]" := [Setoid by P on _]. | |
Notation "(== 'in' A )" := (setoid_equal A). | |
Notation "x == y 'in' A" := (setoid_equal A x y) (at level 70, y at next level, no associativity). | |
Notation "(==)" := (== in _). | |
Notation "x == y" := (x == y in _) (at level 70, no associativity). | |
Program Definition eq_setoid (X: Type) := | |
[Setoid by @eq X]. | |
Program Definition function (X Y: Type): Setoid := | |
[Setoid by `(forall x, f x = g x) on X -> Y]. | |
Next Obligation. | |
intros f g h Heqfg Heqgh x. | |
now rewrite Heqfg. | |
Qed. | |
Class IsMap {X Y: Setoid}(f: X -> Y) := | |
{ | |
map_proper:> Proper ((==) ==> (==)) f | |
}. | |
Structure Map (X Y: Setoid): Type := | |
{ | |
map_fun:> X -> Y; | |
map_prf:> IsMap map_fun | |
}. | |
Existing Instance map_prf. | |
Notation "[ 'Map' 'by' f ]" := (@Build_Map _ _ f _). | |
Notation "[ x 'in' X :-> m ]" := [Map by fun (x: X) => m]. | |
Notation "[ x :-> m ]" := ([ x in _ :-> m]). | |
Program Definition Map_compose (X Y Z: Setoid)(f: Map X Y)(g: Map Y Z): Map X Z := | |
[ x :-> g (f x)]. | |
Next Obligation. | |
intros x y Heq; simpl. | |
now rewrite Heq. | |
Qed. | |
Program Definition Map_id (X: Setoid): Map X X := | |
[ x :-> x ]. | |
Program Definition Map_setoid (X Y: Setoid): Setoid := | |
[Setoid by `(forall x, f x == g x) on Map X Y]. | |
Next Obligation. | |
intros f g h Heqfg Heqgh x. | |
now rewrite Heqfg. | |
Qed. | |
Canonical Structure Map_setoid. | |
(** * 1. Category, Functor, Natural Transformation **) | |
(** ** 1.1 Category **) | |
(** *** 1.1.1 Definition **) | |
Class IsCategory | |
(obj: Type) | |
(hom: obj -> obj -> Setoid) | |
(comp: forall {X Y Z: obj}, hom X Y -> hom Y Z -> hom X Z) | |
(id: forall (X: obj), hom X X) := | |
{ | |
cat_comp_proper:> | |
forall (X Y Z: obj), | |
Proper ((==) ==> (==) ==> (==)) (@comp X Y Z); | |
cat_comp_assoc: | |
forall X Y Z W (f: hom X Y)(g: hom Y Z)(h: hom Z W), | |
comp f (comp g h) == comp (comp f g) h; | |
cat_comp_id_dom: | |
forall X Y (f: hom X Y), | |
comp (id X) f == f; | |
cat_comp_id_cod: | |
forall X Y (f: hom X Y), | |
comp f (id Y) == f | |
}. | |
Hint Resolve cat_comp_assoc cat_comp_id_dom cat_comp_id_cod. | |
Structure Category := | |
{ | |
cat_obj:> Type; | |
cat_hom:> cat_obj -> cat_obj -> Setoid; | |
cat_comp: | |
forall (X Y Z: cat_obj), | |
cat_hom X Y -> cat_hom Y Z -> cat_hom X Z; | |
cat_id: forall X: cat_obj, cat_hom X X; | |
cat_prf:> IsCategory cat_comp cat_id | |
}. | |
Existing Instance cat_prf. | |
Notation "[ 'Category' 'by' hom 'with' comp , id ]" := | |
(@Build_Category _ hom comp id _). | |
Notation "[ 'Category' 'by' hom 'with' 'comp' := comp 'with' 'id' := id ]" := | |
[Category by hom with comp , id]. | |
Notation "g \o{ C } f" := (@cat_comp C _ _ _ f g) (at level 60, right associativity). | |
Notation "g \o f" := (g \o{_} f) (at level 60, right associativity) . | |
Notation "Id_{ C } X" := (@cat_id C X) (at level 20, no associativity). | |
Notation "'Id' X" := (Id_{_} X) (at level 30, right associativity). | |
Definition domain {C: Category}{X Y: C}(f: C X Y) := X. | |
Definition codomain {C: Category}{X Y: C}(f: C X Y) := Y. | |
(** isomorphic **) | |
Definition isomorphic (C: Category)(X Y: C) := | |
exists (f: C X Y)(g: C Y X), | |
(g \o f == Id X) /\ (f \o g == Id Y). | |
Program Definition isomorphic_setoid (C: Category) := | |
[Setoid by isomorphic C on C]. | |
Next Obligation. | |
- intros X. | |
exists (Id X), (Id X); split. | |
+ now rewrite cat_comp_id_dom. | |
+ now rewrite cat_comp_id_cod. | |
- intros X Y [f [g [Heqfg Heqgf]]]. | |
now exists g, f. | |
- intros X Y Z [f [f' [Heqf Heqf']]] [g [g' [Heqg Heqg']]]. | |
exists (g \o f), (f' \o g'); split. | |
+ rewrite cat_comp_assoc, <- (cat_comp_assoc f), Heqg. | |
now rewrite cat_comp_id_cod, Heqf. | |
+ rewrite cat_comp_assoc, <- (cat_comp_assoc g'), Heqf'. | |
now rewrite cat_comp_id_cod, Heqg'. | |
Qed. | |
Notation "X === Y 'in' C" := (X == Y in (isomorphic_setoid C)) (at level 70, no associativity, Y at next level). | |
Notation "X === Y" := (X === Y in _) (at level 70, no associativity). | |
(** *** 1.1.2 Examples **) | |
(** Category of Type **) | |
Program Definition Types := | |
[Category by function | |
with (fun X Y Z f g x => g (f x)), | |
(fun X x => x)]. | |
Next Obligation. | |
intros f f' Heqf g g' Heqg x; simpl. | |
now rewrite Heqf, Heqg. | |
Qed. | |
(** Category of Setoid **) | |
Program Definition Setoids := | |
[Category by Map_setoid with Map_compose, Map_id]. | |
Next Obligation. | |
intros f f' Heqf g g' Heqg x; simpl. | |
now rewrite (Heqf x), (Heqg (f' x)). | |
Qed. | |
Canonical Structure Setoids. | |
(** Discrete category **) | |
Program Definition Prop_setoid (P: Prop) := | |
[Setoid by (fun _ _ => True) on P]. | |
Program Definition DiscreteCategory (X: Setoid): Category := | |
[Category by `(Prop_setoid (x == y)) with _,_]. | |
Next Obligation. | |
revert H H0. | |
now apply transitivity. | |
Qed. | |
(** Dual category **) | |
Program Definition DualCategory (C: Category): Category := | |
[Category by (fun X Y => C Y X) | |
with (fun X Y Z (f: C Y X)(g: C Z Y) => f \o g), | |
(fun X => Id X)]. | |
Next Obligation. | |
- now intros f f' Heqf g g' Heqg; rewrite Heqf, Heqg. | |
- now rewrite cat_comp_assoc. | |
- now rewrite cat_comp_id_cod. | |
- now rewrite cat_comp_id_dom. | |
Qed. | |
Notation "C ^op" := (DualCategory C) (at level 0, format "C ^op"). | |
(** ** 1.2 Functor **) | |
(** *** 1.2.1 Definition **) | |
Class IsFunctor (C D: Category) | |
(fobj: C -> D) | |
(fmap: forall {X Y: C}, C X Y -> D (fobj X) (fobj Y)) := | |
{ | |
fmap_subst:> | |
forall X Y: C, Proper ((==) ==> (==)) (@fmap X Y); | |
fmap_comp: | |
forall (X Y Z: C)(f: C X Y)(g: C Y Z), | |
fmap (g \o{C} f) == fmap g \o{D} fmap f; | |
fmap_id: | |
forall X: C, fmap (Id X) == Id (fobj X) | |
}. | |
Structure Functor (C D: Category): Type := | |
{ | |
fun_obj:> C -> D; | |
fmap: forall {X Y: C}, C X Y -> D (fun_obj X) (fun_obj Y); | |
fun_prf:> IsFunctor (@fmap) | |
}. | |
Existing Instance fun_prf. | |
Notation "C --> D" := (Functor C D). | |
Arguments fmap_comp {C D fobj fmap F}{X Y Z}(f g): rename, clear implicits. | |
Arguments fmap_id {C D fobj fmap F}(X): rename, clear implicits. | |
Notation "[ 'Functor' 'by' fmap 'with' fobj ; C 'to' D ]" := (@Build_Functor C D fobj fmap _). | |
Notation "[ 'Functor' 'by' fmap 'with' fobj ]" := [Functor by fmap with fobj ; _ to _]. | |
Notation "[ 'Functor' 'by' fmap ]" := [Functor by fmap with _]. | |
Notation "[ 'Functor' 'by' f :-> Ff 'with' X :-> FX ; C 'to' D ]" := [Functor by (fun _ _ f => Ff) with (fun X => FX) ; C to D]. | |
Notation "[ 'Functor' 'by' f :-> Ff 'with' X :-> FX ]" := [Functor by f :-> Ff with X :-> FX ; _ to _]. | |
Notation "[ 'Functor' 'by' f :-> Ff ; C 'to' D ]" := | |
[Functor by f :-> Ff with _ :-> _ ; _ to _]. | |
Notation "[ 'Functor' 'by' f :-> Ff ]" := [Functor by f :-> Ff with _ :-> _ ; _ to _]. | |
Program Definition Functor_compose (C D E: Category)(F: C --> D)(G: D --> E): C --> E := | |
[Functor by f :-> fmap G (fmap F f)]. | |
Next Obligation. | |
- intros f f' Heqf; simpl. | |
now rewrite Heqf. | |
- now rewrite !(fmap_comp _). | |
- now rewrite !(fmap_id _). | |
Qed. | |
Program Definition Functor_id (C: Category): C --> C := | |
[Functor by f :-> f]. | |
(** *** 1.2.2 Category of Category **) | |
(** homogenous equality on Hom **) | |
Inductive hom_eq (C : Category)(X Y: C)(f: C X Y): | |
forall (Z W: C), C Z W -> Prop := | |
hom_eq_def: | |
forall (g: C X Y), f == g -> hom_eq f g. | |
Notation "f =H g 'in' C" := (@hom_eq C _ _ f _ _ g) (at level 70, g at next level). | |
Infix "=H" := hom_eq (at level 70, only parsing). | |
Lemma hom_eq_refl: | |
forall (C: Category)(df cf: C)(bf: C df cf), | |
bf =H bf. | |
Proof. | |
intros C df cf bf; apply hom_eq_def; reflexivity. | |
Qed. | |
Lemma hom_eq_sym: | |
forall (C: Category) | |
(df cf: C)(bf: C df cf) | |
(dg cg: C)(bg: C dg cg), | |
bf =H bg -> bg =H bf. | |
Proof. | |
intros C df cf bf dg cg bg [g Heq]. | |
apply hom_eq_def; apply symmetry; assumption. | |
Qed. | |
Lemma hom_eq_trans: | |
forall (C : Category) | |
(df cf: C)(bf: C df cf) | |
(dg cg: C)(bg: C dg cg) | |
(dh ch: C)(bh: C dh ch), | |
bf =H bg -> bg =H bh -> bf =H bh. | |
Proof. | |
intros C df cf bf dg cg bg dh ch bh [g Heqg] [h Heqh]. | |
apply hom_eq_def. | |
transitivity g; assumption. | |
Qed. | |
Program Definition Functor_setoid (C D: Category): Setoid := | |
[Setoid by `(forall (X Y: C)(f: C X Y), fmap F f =H fmap G f) on C --> D]. | |
Next Obligation. | |
- intros F G Heq X Y f. | |
now apply hom_eq_sym, Heq. | |
- intros F G H HeqFG HeqGH X Y f. | |
eapply hom_eq_trans. | |
+ now apply HeqFG. | |
+ now apply HeqGH. | |
Qed. | |
Canonical Structure Functor_setoid. | |
Program Definition Cat: Category := | |
[Category by Functor_setoid with Functor_compose, Functor_id]. | |
Next Obligation. | |
rename X into C, Y into D, Z into E. | |
intros F F' HeqF G G' HeqG X Y f; simpl in *. | |
destruct (HeqF _ _ f). | |
destruct (HeqG _ _ g). | |
apply hom_eq_def. | |
now rewrite H, H0. | |
Qed. | |
Canonical Structure Cat. | |
(** *** 1.2.3 Examples **) | |
(* constant functor *) | |
Program Definition constant_functor (C D: Category)(d: D): C --> D := | |
[Functor by f :-> Id d with c :-> d]. | |
Next Obligation. | |
now rewrite cat_comp_id_dom. | |
Qed. | |
Notation "[ * 'in' D |-> c 'in' C ]" := (constant_functor D C c). | |
(** Hom(X,-): C -> Setoids **) | |
Program Definition covariant_hom_functor (C: Category)(X: C) | |
: C --> Setoids := | |
[Functor by (fun (Y Z: C)(g: C Y Z) => [ f in C X Y :-> g \o f]) | |
with (fun Y => C X Y)]. | |
Next Obligation. | |
now intros f f' Heq; rewrite Heq. | |
Qed. | |
Next Obligation. | |
- rename X0 into Y, Y into Z. | |
intros g g' Heqg f; simpl. | |
now rewrite Heqg. | |
- now rewrite cat_comp_assoc. | |
- now rewrite cat_comp_id_cod. | |
Qed. | |
Notation "'Hom' ( X , -)" := (covariant_hom_functor _ X). | |
(** Hom(-,Y): C^op -> Setoids **) | |
Program Definition contravariant_hom_functor (C: Category)(Y: C) | |
: C^op --> Setoids := | |
[Functor by (fun (X W: C)(f: C W X) => | |
[g in C X Y :-> g \o f] ) | |
with (fun X => C X Y)]. | |
Next Obligation. | |
now intros g g' Heq; rewrite Heq. | |
Qed. | |
Next Obligation. | |
- rename Y0 into W. | |
intros f f' Heqf g; simpl. | |
now rewrite Heqf. | |
- now rewrite cat_comp_assoc. | |
- now rewrite cat_comp_id_dom. | |
Qed. | |
Notation "'Hom' (- , Y )" := (contravariant_hom_functor _ Y). | |
(** ** 1.3 Natural Transformation **) | |
(** *** 1.3.1 Definition **) | |
Class IsNatrans | |
(C D: Category) | |
(F G: C --> D) | |
(natrans: forall (X: C), D (F X) (G X)) := | |
{ | |
natrans_naturality: | |
forall (X Y: C)(f: C X Y), | |
natrans Y \o fmap F f == fmap G f \o natrans X | |
}. | |
Structure Natrans {C D: Category}(F G: C --> D): Type := | |
{ | |
natrans:> forall X: C, D (F X) (G X); | |
natrans_prf:> IsNatrans natrans | |
}. | |
Existing Instance natrans_prf. | |
Notation "F ==> G" := (Natrans F G). | |
Notation "[ X 'in' T :=> f 'from' F 'to' G ]" := (@Build_Natrans _ _ F G (fun X: T => f) _). | |
Notation "[ X :=> f 'from' F 'to' G ]" := [X in _ :=> f from F to G]. | |
Notation "[ X 'in' T :=> f ]" := [X in T :=> f from _ to _]. | |
Notation "[ X :=> f ]" := ([ X in _ :=> f]). | |
Program Definition Natrans_compose (C D: Category)(F G H: C --> D)(S: F ==> G)(T: G ==> H): F ==> H := | |
[X :=> T X \o S X]. | |
Next Obligation. | |
now rewrite cat_comp_assoc, (natrans_naturality (IsNatrans := S)), <- cat_comp_assoc, (natrans_naturality (IsNatrans:=T)), cat_comp_assoc. | |
Qed. | |
Program Definition Natrans_id (C D: Category)(F: C --> D): Natrans F F := | |
[X :=> Id (F X)]. | |
Next Obligation. | |
now rewrite cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Program Definition Natrans_dom_compose (B C D: Category)(E: B --> C)(F G: C --> D)(S: F ==> G): (F \o E) ==> (G \o E) := | |
[X :=> S (E X)]. | |
Next Obligation. | |
now rewrite natrans_naturality. | |
Qed. | |
Notation "S o> E" := (Natrans_dom_compose E S) (at level 50, left associativity). | |
Program Definition Natrans_cod_compose (C D E: Category)(F G: C --> D)(H: D --> E)(S: F ==> G): (H \o F) ==> (H \o G) := | |
[X :=> fmap H (S X)]. | |
Next Obligation. | |
now rewrite <- !(fmap_comp _), natrans_naturality. | |
Qed. | |
Notation "H <o S" := (Natrans_cod_compose H S) (at level 50, left associativity). | |
Program Definition Natrans_hcompose | |
(C D E: Category) | |
(F G: C --> D)(H K: D --> E) | |
(S: F ==> G)(T: H ==> K) | |
: (H \o F) ==> (K \o G) := | |
[ X :=> fmap K (S X) \o T (F X) ]. | |
Next Obligation. | |
rewrite cat_comp_assoc, natrans_naturality, <- !cat_comp_assoc. | |
rewrite <- !(fmap_comp ). | |
now rewrite <- (natrans_naturality (IsNatrans:=S)). | |
Qed. | |
Notation "T <o> S" := (Natrans_hcompose S T) (at level 60, right associativity). | |
Program Definition Natrans_setoid (C D: Category)(F G: C --> D): Setoid := | |
[Setoid by (fun (S T: F ==> G) => forall X, S X == T X)]. | |
Next Obligation. | |
intros S T U HeqST HeqTU X. | |
now rewrite (HeqST X), (HeqTU X). | |
Qed. | |
Canonical Structure Natrans_setoid. | |
Program Definition Fun (C D: Category): Category := | |
[Category by (@Natrans_setoid C D) | |
with (@Natrans_compose C D), (@Natrans_id C D)]. | |
Next Obligation. | |
- rename X into F, Y into G, Z into H. | |
intros S S' HeqS T T' HeqT X; simpl. | |
now rewrite HeqS, HeqT. | |
- now rewrite cat_comp_assoc. | |
- now rewrite cat_comp_id_dom. | |
-now rewrite cat_comp_id_cod. | |
Qed. | |
Canonical Structure Fun. | |
Notation "D ^ C" := (Fun C D). | |
(** ** 1.4 Yoneda Lemma **) | |
Program Definition yoneda_map (C: Category)(X: C)(F: C --> Setoids) | |
: Map (Natrans_setoid Hom(X,-) F) (F X) := | |
[ S in Natrans Hom(X,-) F :-> S X (Id X) ]. | |
Program Definition inv_yoneda_map (C: Category)(X: C)(F: C --> Setoids) | |
: Map (F X) (Natrans_setoid Hom(X,-) F) := | |
[ x in F X :-> [ Y in C :=> [ f in C X Y :-> fmap F f x ]]]. | |
Next Obligation. | |
intros f f' Heq. | |
now apply (fmap_subst (IsFunctor:=F) Heq x). | |
Qed. | |
Next Obligation. | |
now rewrite (fmap_comp (F:=F) _ _ x). | |
Qed. | |
Next Obligation. | |
now intros x y Heq Y f; simpl; rewrite Heq. | |
Qed. | |
(* Yoneda Lemma *) | |
Definition injective (X Y: Setoid)(f: Map X Y) := | |
forall x y, f x == f y -> x == y. | |
Definition surjective (X Y: Setoid)(f: Map X Y) := | |
forall (y: Y), exists x: X, f x == y. | |
Definition bijective (X Y: Setoid)(f: Map X Y) := | |
injective f /\ surjective f. | |
Definition equiv (X Y: Setoid) := | |
exists f: Map X Y, bijective f. | |
Theorem yoneda_lemma: | |
forall (C: Category)(X: C)(F: C --> Setoids), | |
equiv ((Setoids^C) Hom(X,-) F) (F X). | |
Proof. | |
intros; exists (yoneda_map X F). | |
unfold bijective, injective, surjective; split; simpl. | |
- intros S T Heq Y f. | |
generalize (natrans_naturality (IsNatrans:=S) f (Id X)); simpl. | |
rewrite cat_comp_id_dom; intros H; rewrite H; clear H. | |
generalize (natrans_naturality (IsNatrans:=T) f (Id X)); simpl. | |
rewrite cat_comp_id_dom; intros H; rewrite H; clear H. | |
now rewrite Heq. | |
- intros x. | |
exists (inv_yoneda_map X F x); simpl. | |
now rewrite (fmap_id (F:=F) X x). | |
Qed. | |
(** * 2. Universal Property **) | |
(** ** 2.1 Initial and Terminal **) | |
(** *** 2.1.1 Definitions **) | |
Class IsInitial (C: Category) | |
(obj: C) | |
(univ: forall X: C, C obj X) := | |
{ | |
initial_uniqueness: | |
forall (X: C)(f: C obj X), | |
f == univ X | |
}. | |
Structure Initial (C: Category) := | |
{ | |
initial_obj:> C; | |
initial_univ: forall X: C, C initial_obj X; | |
initial_prf:> IsInitial initial_univ | |
}. | |
Existing Instance initial_prf. | |
Notation "[ 'Initial' i 'by' univ ]" := (@Build_Initial _ i univ _). | |
Notation "[ 'Initial' 'by' univ ]" := [Initial _ by univ]. | |
Class IsTerminal (C: Category) | |
(obj: C) | |
(univ: forall X: C, C X obj) := | |
{ | |
terminal_uniqueness: | |
forall (X: C)(f: C X obj), | |
f == univ X | |
}. | |
Structure Terminal (C: Category) := | |
{ | |
terminal_obj:> C; | |
terminal_univ: forall X: C, C X terminal_obj; | |
terminal_prf:> IsTerminal terminal_univ | |
}. | |
Existing Instance terminal_prf. | |
Notation "[ 'Terminal' t 'by' univ ]" := (@Build_Terminal _ t univ _). | |
Notation "[ 'Terminal' 'by' univ ]" := [Terminal _ by univ]. | |
(** *** 2.1.2 Isomorphic **) | |
Lemma initial_isomorphic: | |
forall (C: Category)(i i': Initial C), | |
i === i' in C. | |
Proof. | |
intros C i i'; simpl; unfold isomorphic. | |
exists (initial_univ i i'), (initial_univ i' i); split. | |
- rewrite (initial_uniqueness (Id i)). | |
now apply initial_uniqueness. | |
- rewrite (initial_uniqueness (Id i')). | |
now apply initial_uniqueness. | |
Qed. | |
Lemma terminal_isomorphic: | |
forall (C: Category)(t t': Terminal C), | |
t === t' in C. | |
Proof. | |
intros C t t'; simpl; unfold isomorphic. | |
exists (terminal_univ t' t), (terminal_univ t t'); split. | |
- rewrite (terminal_uniqueness (Id t)). | |
now apply terminal_uniqueness. | |
- rewrite (terminal_uniqueness (Id t')). | |
now apply terminal_uniqueness. | |
Qed. | |
(** *** 2.1.3 Duality **) | |
Program Definition terminal_from_initial (C: Category)(i: Initial C): Terminal C^op := | |
[Terminal by (initial_univ i)]. | |
Next Obligation. | |
now apply initial_uniqueness. | |
Qed. | |
Program Definition initial_from_terminal (C: Category)(t: Terminal C): Initial C^op := | |
[Initial by (terminal_univ t)]. | |
Next Obligation. | |
now apply terminal_uniqueness. | |
Qed. | |
(** *** 2.1.3 Examples **) | |
(** Initial of Types, Setoids, Cat **) | |
Inductive empty := . | |
Program Definition initial_of_Types: Initial Types := | |
[Initial empty by (fun (X: Type)(e: empty) => match e with end)]. | |
Program Definition empty_setoid: Setoid := | |
[Setoid by (fun e e' => match e, e' with end) on empty]. | |
Program Definition initial_of_Setoids: Initial Setoids := | |
[Initial empty_setoid | |
by (fun (X: Setoid) => [e in empty :-> match e with end])]. | |
Program Definition Zero: Category := | |
[Category by (fun (e e': empty) => match e, e' with end) | |
with (fun X Y Z f g => match X with end), | |
(fun X => match X with end)]. | |
Program Definition FromZero (C: Category): Zero --> C := | |
[Functor by (fun X Y f => match X with end) | |
with (fun (X: empty) => match X with end)]. | |
Program Definition initial_of_Cat: Initial Cat := | |
[Initial Zero by @FromZero]. | |
(** Terminal of Types, Setoids, Cat **) | |
Inductive unit := tt. | |
Program Definition terminal_of_Types: Terminal Types := | |
[Terminal unit by (fun (X: Type)(_: X) => tt)]. | |
Next Obligation. | |
now destruct (f x). | |
Qed. | |
Program Definition unit_setoid: Setoid := | |
[Setoid by (fun x y => True) on unit]. | |
Program Definition terminal_of_Setoids: Terminal Setoids := | |
[Terminal unit_setoid by (fun (X: Setoid) => [_ in X :-> tt])]. | |
Program Definition One: Category := | |
[Category by (fun _ _ => unit_setoid) | |
with (fun X Y Z f g => match X, Y, Z with tt, tt, tt => tt end), | |
(fun X => match X with tt => tt end)]. | |
Canonical Structure One. | |
Program Definition ToOne (C: Category): C --> One := | |
[Functor by f :-> Id tt with X :-> tt]. | |
Program Definition terminal_of_Cat: Terminal Cat := | |
[Terminal One by @ToOne]. | |
Next Obligation. | |
rename X into C, f into F, X0 into X, f0 into f. | |
destruct (fmap F f), (F X), (F Y). | |
now apply hom_eq_refl. | |
Qed. | |
(** ** 2.2 Product **) | |
(** *** 2.2.1 Definitions **) | |
Class IsProduct (C: Category)(X Y: C) | |
(P: C)(pi1: C P X)(pi2: C P Y) | |
(univ: forall (Z: C), C Z X -> C Z Y -> C Z P) := | |
{ | |
product_universality_1: | |
forall (Z: C)(p1: C Z X)(p2: C Z Y), | |
(p1 == pi1 \o univ Z p1 p2); | |
product_universality_2: | |
forall (Z: C)(p1: C Z X)(p2: C Z Y), | |
(p2 == pi2 \o univ Z p1 p2); | |
product_uniqueness: | |
forall (Z: C)(p1: C Z X)(p2: C Z Y)(u: C Z P), | |
(p1 == pi1 \o u) -> | |
(p2 == pi2 \o u) -> | |
u == univ Z p1 p2 | |
}. | |
Structure Product (C: Category)(X Y: C) := | |
{ | |
product_obj:> C; | |
product_proj1: C product_obj X; | |
product_proj2: C product_obj Y; | |
product_univ: forall (Z: C), C Z X -> C Z Y -> C Z product_obj; | |
product_prf:> IsProduct product_proj1 product_proj2 (@product_univ) | |
}. | |
Existing Instance product_prf. | |
Notation "[ 'Product' P 'by' univ 'with' pi1 , pi2 ]" := | |
(@Build_Product _ _ _ P pi1 pi2 univ _). | |
Notation "[ 'Product' 'by' univ 'with' pi1 , pi2 ]" := | |
[Product _ by univ with pi1, pi2]. | |
Notation "[ f , g 'to' P ]" := (product_univ P f g). | |
Notation "pi1_{ P }" := (product_proj1 P) (at level 0, no associativity, format "pi1_{ P }"). | |
Notation "pi2_{ P }" := (product_proj2 P) (at level 0, no associativity, format "pi2_{ P }"). | |
Program Instance product_univ_proper (C: Category)(X Y: C) | |
(prod: Product C X Y) | |
(Z: C) | |
: Proper ((== in C Z X) ==> (== in C Z Y) ==> (==)) | |
(@product_univ _ _ _ prod Z). | |
Next Obligation. | |
intros f f' Heqf g g' Heqg. | |
apply (product_uniqueness (IsProduct:=prod)(p1:=f')(p2:=g')(u:=[f , g to prod])). | |
- rewrite <- Heqf. | |
now apply (product_universality_1 (IsProduct:=prod) f g). | |
- rewrite <- Heqg. | |
now apply (product_universality_2 (IsProduct:=prod) f g). | |
Qed. | |
Definition product_map (C: Category)(prod: forall (X Y: C), Product C X Y) | |
(X X' Y Y': C)(f: C X Y)(g: C X' Y') | |
: C (prod X X') (prod Y Y') := | |
[f \o pi1_{prod X X'} , g \o pi2_{prod X X'} to (prod Y Y')]. | |
Notation "[ f \* g 'with' prod ]" := (product_map prod f g). | |
Program Instance product_map_proper | |
(C: Category)(prod: forall (X Y: C), Product C X Y) | |
(X X' Y Y': C) | |
: Proper ((==) ==> (==) ==> (==)) (@product_map _ prod X X' Y Y'). | |
Next Obligation. | |
intros f f' Heqf g g' Heqg. | |
unfold product_map. | |
now rewrite Heqf, Heqg. | |
Qed. | |
Lemma product_map_compose: | |
forall (C: Category)(prod: forall (X Y: C), Product C X Y) | |
(X X' Y Y' Z Z': C) | |
(f: C X Y)(g: C Y Z) | |
(f': C X' Y')(g': C Y' Z'), | |
[(g \o f) \* (g' \o f') with prod] == | |
[g \* g' with prod] \o [ f \* f' with prod]. | |
Proof. | |
intros. | |
unfold product_map. | |
symmetry. | |
apply (product_uniqueness (IsProduct:=prod Z Z')). | |
- rewrite <- cat_comp_assoc. | |
rewrite <- (product_universality_1 (IsProduct:=prod Z Z') _ _). | |
rewrite !cat_comp_assoc. | |
now rewrite <- (product_universality_1 (IsProduct:=prod Y Y') _ _). | |
- rewrite <- cat_comp_assoc. | |
rewrite <- (product_universality_2 (IsProduct:=prod Z Z') _ _). | |
rewrite !cat_comp_assoc. | |
now rewrite <- (product_universality_2 (IsProduct:=prod Y Y') _ _). | |
Qed. | |
Lemma product_map_id: | |
forall (C: Category)(prod: forall (X Y: C), Product C X Y) | |
(X X': C), | |
[Id X \* Id X' with prod] == Id (prod X X'). | |
Proof. | |
intros. | |
unfold product_map. | |
rewrite !cat_comp_id_cod. | |
symmetry. | |
now apply (product_uniqueness (IsProduct:=prod X X')); | |
rewrite !cat_comp_id_dom. | |
Qed. | |
(** *** 2.2.2 Isomorphic **) | |
Lemma product_isomorphic: | |
forall (C: Category)(X Y: C)(P Q: Product C X Y), | |
P === Q in C. | |
Proof. | |
intros; simpl; unfold isomorphic. | |
exists [pi1_{P}, pi2_{P} to Q], [pi1_{Q}, pi2_{Q} to P]; split. | |
- rewrite (product_uniqueness (p1:=pi1_{P})(p2:=pi2_{P})(u:=Id P)); | |
try now rewrite cat_comp_id_dom. | |
apply product_uniqueness. | |
+ rewrite <- cat_comp_assoc. | |
rewrite <- (product_universality_1 (IsProduct:=P)). | |
now rewrite <- (product_universality_1 (IsProduct:=Q)). | |
+ rewrite <- cat_comp_assoc. | |
rewrite <- (product_universality_2 (IsProduct:=P)). | |
now rewrite <- (product_universality_2 (IsProduct:=Q)). | |
- rewrite (product_uniqueness (p1:=pi1_{Q})(p2:=pi2_{Q})(u:=Id Q)); | |
try now rewrite cat_comp_id_dom. | |
apply product_uniqueness. | |
+ rewrite <- cat_comp_assoc. | |
rewrite <- (product_universality_1 (IsProduct:=Q)). | |
now rewrite <- (product_universality_1 (IsProduct:=P)). | |
+ rewrite <- cat_comp_assoc. | |
rewrite <- (product_universality_2 (IsProduct:=Q)). | |
now rewrite <- (product_universality_2 (IsProduct:=P)). | |
Qed. | |
(** *** 2.2.3 Examples **) | |
Record product (A B: Type): Type := | |
pair_of { fst: A; snd: B }. | |
Notation "( x , y )" := (pair_of x y) (format "( x , y )"). | |
Notation "p .1" := (fst p) (at level 5, left associativity, format "p .1"). | |
Notation "p .2" := (snd p) (at level 5, left associativity, format "p .2"). | |
Program Definition product_of_types (X Y: Type) | |
: Product Types X Y := | |
[Product (product X Y) by (fun P f g x => (f x, g x)) | |
with @fst X Y, @snd X Y]. | |
Next Obligation. | |
generalize (H x), (H0 x). | |
now destruct (u x); simpl; intros; subst. | |
Qed. | |
Program Definition product_setoid (X Y: Setoid): Setoid := | |
[Setoid by `((p.1 == q.1) /\ (p.2 == q.2)) on product X Y]. | |
Next Obligation. | |
repeat split; program_simpl; try now auto. | |
- now rewrite H. | |
- now rewrite H2. | |
Qed. | |
Program Instance fst_proper (X Y: Setoid) | |
: Proper ((== in product_setoid X Y) ==> (== in X)) (@fst X Y). | |
Program Instance snd_proper (X Y: Setoid) | |
: Proper ((== in product_setoid X Y) ==> (== in Y)) (@snd X Y). | |
Program Instance pair_of_proper (X Y: Setoid) | |
: Proper ((== in X) ==> (== in Y) ==> (== in product_setoid X Y)) (@pair_of X Y). | |
Program Definition product_of_Setoids (X Y: Setoid) | |
: Product Setoids X Y := | |
[Product (product_setoid X Y) | |
by (fun P f g => [x :-> (f x, g x)]) | |
with [Map by @fst X Y], | |
[Map by @snd X Y]]. | |
Next Obligation. | |
now intros p q Heq; simpl; rewrite Heq. | |
Qed. | |
Program Definition product_category (C D: Category): Category := | |
[Category by (fun X Y => product_setoid (C X.1 Y.1) (D X.2 Y.2)) | |
with (fun X Y Z f g => (g.1 \o f.1, g.2 \o f.2)), | |
(fun X => (Id X.1, Id X.2))]. | |
Next Obligation. | |
- repeat split; program_simpl; try now auto. | |
+ now rewrite H, H0. | |
+ now rewrite H1, H2. | |
- now rewrite !cat_comp_assoc. | |
- now rewrite !cat_comp_id_dom. | |
- now rewrite !cat_comp_id_cod. | |
Qed. | |
Program Definition functor_for_product_of_Cat (C D: Category) | |
(B: Category)(F: B --> C)(G: B --> D) | |
: B --> (product_category C D) := | |
[Functor by f :-> (fmap F f, fmap G f) | |
with b :-> (F b, G b)]. | |
Next Obligation. | |
- now intros f g Heq; simpl; rewrite Heq. | |
- now rewrite !fmap_comp. | |
- now rewrite !fmap_id. | |
Qed. | |
Program Definition product_of_Cat (C D: Category) | |
: Product Cat C D := | |
[Product (product_category C D) | |
by (@functor_for_product_of_Cat C D) | |
with [Functor by fg :-> fg.1 with XY :-> XY.1], | |
[Functor by fg :-> fg.2 with XY :-> XY.2]]. | |
Next Obligation. | |
generalize (H _ _ f), (H0 _ _ f); clear H H0; intros H1 H2. | |
destruct (fmap u f); simpl in *. | |
destruct (u X), (u Y); simpl in *. | |
destruct H1, H2. | |
now apply hom_eq_def; rewrite H, H0. | |
Qed. | |
(** ** 2.3 Coproduct **) | |
(** *** 2.3.1 Definitions **) | |
Class IsCoproduct (C: Category)(X Y: C) | |
(CP: C)(in1: C X CP)(in2: C Y CP) | |
(univ: forall (Z: C), C X Z -> C Y Z -> C CP Z) := | |
{ | |
coproduct_universality_1: | |
forall (Z: C)(i1: C X Z)(i2: C Y Z), | |
(i1 == univ Z i1 i2 \o in1); | |
coproduct_universality_2: | |
forall (Z: C)(i1: C X Z)(i2: C Y Z), | |
(i2 == univ Z i1 i2 \o in2); | |
coproduct_uniqueness: | |
forall (Z: C)(i1: C X Z)(i2: C Y Z)(u: C CP Z), | |
(i1 == u \o in1) -> | |
(i2 == u \o in2) -> | |
u == univ Z i1 i2 | |
}. | |
Structure Coproduct (C: Category)(X Y: C) := | |
{ | |
coproduct_obj:> C; | |
coproduct_inj1: C X coproduct_obj; | |
coproduct_inj2: C Y coproduct_obj; | |
coproduct_univ: forall (Z: C), C X Z -> C Y Z -> C coproduct_obj Z; | |
coproduct_prf:> IsCoproduct coproduct_inj1 coproduct_inj2 (@coproduct_univ) | |
}. | |
Existing Instance coproduct_prf. | |
Notation "[ 'Coproduct' P 'by' univ 'with' in1 , in2 ]" := | |
(@Build_Coproduct _ _ _ P in1 in2 univ _). | |
Notation "[ 'Coproduct' 'by' univ 'with' in1 , in2 ]" := | |
[Coproduct _ by univ with in1, in2]. | |
Notation "[ f , g 'from' P ]" := (coproduct_univ P f g). | |
Notation "in1_{ P }" := (coproduct_inj1 P) (at level 0, no associativity, format "in1_{ P }"). | |
Notation "in2_{ P }" := (coproduct_inj2 P) (at level 0, no associativity, format "in2_{ P }"). | |
Program Instance coproduct_univ_proper (C: Category)(X Y: C) | |
(cp: Coproduct C X Y) | |
(Z: C) | |
: Proper ((== in C X Z) ==> (== in C Y Z) ==> (==)) | |
(@coproduct_univ _ _ _ cp Z). | |
Next Obligation. | |
intros f f' Heqf g g' Heqg. | |
apply coproduct_uniqueness. | |
- rewrite <- Heqf. | |
now apply coproduct_universality_1. | |
- rewrite <- Heqg. | |
now apply coproduct_universality_2. | |
Qed. | |
Definition coproduct_map (C: Category) | |
(coprod: forall (X Y: C), Coproduct C X Y) | |
(X X' Y Y': C)(f: C X Y)(g: C X' Y') | |
: C (coprod X X') (coprod Y Y') := | |
[in1_{coprod Y Y'} \o f, in2_{coprod Y Y'} \o g from (coprod X X')]. | |
Notation "[ f \+ g 'with' coprod ]" := (coproduct_map coprod f g). | |
Program Instance coproduct_map_proper | |
(C: Category)(coprod: forall (X Y: C), Coproduct C X Y) | |
(X X' Y Y': C) | |
: Proper ((==) ==> (==) ==> (==)) (@coproduct_map _ coprod X X' Y Y'). | |
Next Obligation. | |
intros f f' Heqf g g' Heqg. | |
unfold coproduct_map. | |
now rewrite Heqf, Heqg. | |
Qed. | |
Lemma coproduct_map_compose: | |
forall (C: Category)(coprod: forall (X Y: C), Coproduct C X Y) | |
(X X' Y Y' Z Z': C) | |
(f: C X Y)(g: C Y Z) | |
(f': C X' Y')(g': C Y' Z'), | |
[(g \o f) \+ (g' \o f') with coprod] == | |
[g \+ g' with coprod] \o [ f \+ f' with coprod]. | |
Proof. | |
intros. | |
unfold coproduct_map. | |
symmetry. | |
apply coproduct_uniqueness. | |
- rewrite cat_comp_assoc. | |
rewrite <- (coproduct_universality_1 _ _). | |
rewrite <- !cat_comp_assoc. | |
now rewrite <- (coproduct_universality_1 _ _). | |
- rewrite cat_comp_assoc. | |
rewrite <- (coproduct_universality_2 _ _). | |
rewrite <- !cat_comp_assoc. | |
now rewrite <- (coproduct_universality_2 _ _). | |
Qed. | |
Lemma coproduct_map_id: | |
forall (C: Category)(coprod: forall (X Y: C), Coproduct C X Y) | |
(X X': C), | |
[Id X \+ Id X' with coprod] == Id (coprod X X'). | |
Proof. | |
intros. | |
unfold coproduct_map. | |
rewrite !cat_comp_id_dom. | |
symmetry. | |
now apply (coproduct_uniqueness); rewrite !cat_comp_id_cod. | |
Qed. | |
(** *** 2.3.2 Isomorphic **) | |
Lemma coproduct_isomorphic: | |
forall (C: Category)(X Y: C)(P Q: Coproduct C X Y), | |
P === Q in C. | |
Proof. | |
intros; simpl; unfold isomorphic. | |
exists [in1_{Q}, in2_{Q} from P], [in1_{P}, in2_{P} from Q]; split. | |
- rewrite (coproduct_uniqueness (i1:=in1_{P})(i2:=in2_{P})(u:=Id P)); | |
try now rewrite cat_comp_id_cod. | |
apply coproduct_uniqueness. | |
+ rewrite cat_comp_assoc. | |
rewrite <- (coproduct_universality_1 (IsCoproduct:=P)). | |
now rewrite <- (coproduct_universality_1 (IsCoproduct:=Q)). | |
+ rewrite cat_comp_assoc. | |
rewrite <- (coproduct_universality_2 (IsCoproduct:=P)). | |
now rewrite <- (coproduct_universality_2 (IsCoproduct:=Q)). | |
- rewrite (coproduct_uniqueness (i1:=in1_{Q})(i2:=in2_{Q})(u:=Id Q)); | |
try now rewrite cat_comp_id_cod. | |
apply coproduct_uniqueness. | |
+ rewrite cat_comp_assoc. | |
rewrite <- (coproduct_universality_1 (IsCoproduct:=Q)). | |
now rewrite <- (coproduct_universality_1 (IsCoproduct:=P)). | |
+ rewrite cat_comp_assoc. | |
rewrite <- (coproduct_universality_2 (IsCoproduct:=Q)). | |
now rewrite <- (coproduct_universality_2 (IsCoproduct:=P)). | |
Qed. | |
(** *** 2.3.3 Examples **) | |
Inductive coproduct (A B: Type): Type := | |
| inj1: A -> coproduct A B | |
| inj2: B -> coproduct A B. | |
Program Definition coproduct_of_Types (X Y: Type) | |
: Coproduct Types X Y := | |
[Coproduct (coproduct X Y) | |
by (fun P f g xy => match xy with | |
| inj1 _ x => f x | |
| inj2 _ y => g y | |
end) | |
with @inj1 X Y, @inj2 X Y]. | |
Next Obligation. | |
destruct x as [x | y]. | |
- now rewrite H. | |
- now rewrite H0. | |
Qed. | |
Program Definition coproduct_setoid (X Y: Setoid) := | |
[Setoid by (fun a b => match a, b with | |
| inj1 _ x, inj1 _ x' => x == x' in X | |
| inj2 _ y, inj2 _ y' => y == y' in Y | |
| _, _ => False | |
end)]. | |
Next Obligation. | |
- now intros [x | y]. | |
- now intros [x | y] [x' | y']. | |
- intros [x | y] [x' | y'] [x'' | y'']; try contradiction; | |
now apply transitivity. | |
Qed. | |
Program Instance inj1_proper (X Y: Setoid) | |
: Proper ((== in X) ==> (== in coproduct_setoid X Y)) (@inj1 X Y). | |
Program Instance inj2_proper (X Y: Setoid) | |
: Proper ((== in Y) ==> (== in coproduct_setoid X Y)) (@inj2 X Y). | |
Program Definition coproduct_of_Setoids (X Y: Setoid) | |
: Coproduct Setoids X Y := | |
[Coproduct (coproduct_setoid X Y) | |
by (fun P f g => [xy :-> match xy with | |
| inj1 _ x => f x | |
| inj2 _ y => g y | |
end]) | |
with [Map by @inj1 X Y], | |
[Map by @inj2 X Y]]. | |
Next Obligation. | |
intros [x | y] [x' | y']; try contradiction; now apply map_proper. | |
Qed. | |
Next Obligation. | |
destruct x as [x | y]; symmetry. | |
- now apply H. | |
- now apply H0. | |
Qed. | |
Definition coproduct_hom (C D: Category)(X Y: coproduct C D): Setoid := | |
match X, Y with | |
| inj1 _ X, inj1 _ Y => C X Y | |
| inj2 _ X, inj2 _ Y => D X Y | |
| _, _ => empty_setoid | |
end. | |
Program Definition coproduct_category (C D: Category): Category := | |
[Category by (@coproduct_hom C D) | |
with (fun X Y Z f g => _), | |
(fun X => match X with | |
| inj1 _ X => Id X | |
| inj2 _ X => Id X | |
end)]. | |
Next Obligation. | |
destruct X as [X | X], Y as [Y | Y], Z as [Z | Z]; simpl in *; | |
try contradiction. | |
- exact (g \o f). | |
- exact (g \o f). | |
Defined. | |
Next Obligation. | |
- now destruct X as [X | X], Y as [Y | Y], Z as [Z | Z]; | |
intros f f' Heqf g g' Heqg; simpl in *; | |
try contradiction; rewrite Heqf, Heqg. | |
- destruct X as [X | X], Y as [Y | Y], Z as [Z | Z], W as [W | W]; | |
simpl in *; try contradiction; | |
now rewrite !cat_comp_assoc. | |
- destruct X as [X | X], Y as [Y | Y]; | |
simpl in *; try contradiction; | |
now rewrite cat_comp_id_dom. | |
- destruct X as [X | X], Y as [Y | Y]; | |
simpl in *; try contradiction; | |
now rewrite cat_comp_id_cod. | |
Qed. | |
Definition fobj_for_coproduct_of_Cat (C D: Category) | |
(E: Category)(F: C --> E)(G:D --> E) | |
: coproduct_category C D -> E := | |
fun X => match X with | |
| inj1 _ X => F X | |
| inj2 _ X => G X | |
end. | |
Program Definition functor_for_coproduct_of_Cat (C D: Category) | |
(E: Category)(F: C --> E)(G:D --> E) | |
: (coproduct_category C D) --> E := | |
let fobj := fobj_for_coproduct_of_Cat F G in | |
[Functor by (fun X Y => | |
match X as X', Y as Y' return | |
(coproduct_category C D) X' Y' -> | |
E (fobj X') | |
(fobj Y') with | |
| inj1 _ X, inj1 _ Y => fun f => fmap F f | |
| inj2 _ X, inj2 _ Y => fun f => fmap G f | |
| _, _ => fun f => match f with end | |
end)]. | |
Next Obligation. | |
- now destruct X as [X | X], Y as [Y | Y]; | |
intros f f' Heq; simpl in *; | |
try contradiction; rewrite Heq. | |
- now destruct X as [X | X], Y as [Y | Y], Z as [Z | Z]; simpl in *; | |
try contradiction; rewrite fmap_comp. | |
- now destruct X; simpl; rewrite fmap_id. | |
Qed. | |
Program Definition coproduct_of_Cat (C D: Category) | |
: Coproduct Cat C D := | |
[Coproduct (coproduct_category C D) | |
by @functor_for_coproduct_of_Cat C D | |
with [Functor by f :-> f with X :-> inj1 D X], | |
[Functor by f :-> f with X :-> inj2 C X]]. | |
Next Obligation. | |
- destruct X as [X | X], Y as [Y | Y]; simpl in *; | |
try contradiction; apply hom_eq_sym. | |
+ now apply H. | |
+ now apply H0. | |
Qed. | |
(** ** 2.4 Equalizer **) | |
(** *** 2.4.1 Definition **) | |
Class IsEqualizer (C: Category)(X Y: C)(f g: C X Y) | |
(Eq: C) | |
(eq: C Eq X) | |
(univ: forall {Z: C}{k: C Z X}, | |
f \o k == g \o k -> C Z Eq) := | |
{ | |
equalize: f \o eq == g \o eq; | |
equalizer_universality: forall Z (k: C Z X)(Heq: f \o k == g \o k), | |
eq \o (univ Heq) == k; | |
equalizer_uniqueness: forall Z (k: C Z X)(Heq: f \o k == g \o k)(u: C Z Eq), | |
eq \o u == k -> u == univ Heq | |
}. | |
Structure Equalizer (C: Category)(X Y: C)(f g: C X Y) := | |
{ | |
equalizer_obj: C; | |
equalizer_map:> C equalizer_obj X; | |
equalizer_univ: forall (Z: C)(k: C Z X), f \o k == g \o k -> C Z equalizer_obj; | |
equalizer_prf:> IsEqualizer equalizer_map equalizer_univ | |
}. | |
Existing Instance equalizer_prf. | |
Notation "[ 'Equalizer' 'of' f , g 'by' univ 'with' map 'from' Eq 'in' C ]" := | |
(@Build_Equalizer C _ _ f g Eq map univ _). | |
Notation "[ 'Equalizer' 'of' f , g 'by' univ 'with' map ]" := | |
[Equalizer of f,g by univ with map from _ in _]. | |
Notation "[ 'Equalizer' 'by' univ 'with' map ]" := | |
[Equalizer of _,_ by univ with map]. | |
Notation "[ 'Equalizer' 'by' univ ]" := [Equalizer by univ with _]. | |
Lemma equalizer_univ_subst | |
(C: Category)(X Y: C)(f g: C X Y) | |
(eq: Equalizer f g) | |
(Z: C)(k k': C Z X) | |
(Heq: f \o k == g \o k) | |
(Heq': f \o k' == g \o k'): | |
k == k' -> | |
equalizer_univ eq Heq == equalizer_univ eq Heq'. | |
Proof. | |
intros Heqk. | |
apply equalizer_uniqueness; symmetry; rewrite <- Heqk. | |
now rewrite equalizer_universality. | |
Qed. | |
(** *** 2.4.2 Isomorphic **) | |
Lemma equalizer_isomorphic: | |
forall (C: Category)(X Y: C)(f g: C X Y) | |
(eq eq': Equalizer f g), | |
equalizer_obj eq === equalizer_obj eq' in C. | |
Proof. | |
intros; simpl; unfold isomorphic. | |
exists (equalizer_univ eq' (equalize (IsEqualizer:=eq))), | |
(equalizer_univ eq (equalize (IsEqualizer:=eq'))); split. | |
- rewrite (equalizer_uniqueness (equalize (IsEqualizer:=eq)) (u:=Id (equalizer_obj eq))); [| now rewrite cat_comp_id_dom]. | |
apply equalizer_uniqueness. | |
now rewrite <- cat_comp_assoc, !equalizer_universality. | |
- rewrite (equalizer_uniqueness (equalize (IsEqualizer:=eq')) (u:=Id (equalizer_obj eq'))); [| now rewrite cat_comp_id_dom]. | |
apply equalizer_uniqueness. | |
now rewrite <- cat_comp_assoc, !equalizer_universality. | |
Qed. | |
(** *** 2.4.3 Example **) | |
(** Equalizer of Setoids **) | |
Class IsPredicate (X: Setoid)(P: X -> Prop) := | |
{ | |
predicate_proper:> Proper ((== in X) ==> iff) P | |
}. | |
Structure Predicate (X: Setoid) := | |
{ | |
predicate:> X -> Prop; | |
predicate_prf:> IsPredicate X predicate | |
}. | |
Existing Instance predicate_prf. | |
Notation "[ 'Predicate' 'by' P 'on' X ]" := (@Build_Predicate X P _). | |
Notation "[ 'Predicate' 'by' P ]" := [Predicate by P on _]. | |
Inductive SubSetoid_type (X: Setoid)(P: Predicate X) := | |
| subsetoid_def (x: X)(Hp: P x). | |
Notation "[ x 'satisfies' P 'on' X ]" := (@subsetoid_def X P x _). | |
Notation "[ x 'satisfies' P ]" := [x satisfies P on _]. | |
Definition elem {X: Setoid}{P: Predicate X}(x: SubSetoid_type P): X := | |
match x with | |
| @subsetoid_def _ _ x _ => x | |
end. | |
Program Definition SubSetoid (X: Setoid)(P: Predicate X) := | |
[Setoid by `(elem x == elem y) on SubSetoid_type P]. | |
Next Obligation. | |
- now intros [x Hx] [y Hy] [z Hz]; transitivity y. | |
Qed. | |
Notation "{{ x 'in' X | P }}" := (SubSetoid [Predicate by fun x => P on X]). | |
Program Definition elem_map (X: Setoid)(P: Predicate X) | |
: Map (SubSetoid P) X := | |
[Map by @elem _ P]. | |
Program Definition equalize_predicate (X Y: Setoid)(f g: Map X Y) := | |
[Predicate by `(f x == g x) on X]. | |
Next Obligation. | |
now intros x y Heq; rewrite Heq. | |
Qed. | |
Program Definition equalizer_of_Setoids (X Y: Setoid)(f g: Map X Y) | |
: Equalizer (C:=Setoids) f g:= | |
[Equalizer of f, g | |
by (fun Z k H => [z :-> subsetoid_def (H z)]) | |
with elem_map _ from {{x in X | f x == g x }} | |
in Setoids]. | |
Next Obligation. | |
now intros x y Heq; rewrite Heq. | |
Qed. | |
Next Obligation. | |
intros x y Heq. | |
unfold elem. | |
now rewrite Heq. | |
Qed. | |
Next Obligation. | |
destruct x; unfold elem. | |
now apply Hp. | |
Qed. | |
(** ** 2.5 Coequalizer **) | |
(** *** 2.5.1 Definition **) | |
Class IsCoequalizer (C: Category)(X Y: C)(f g: C X Y) | |
(Coeq: C) | |
(coeq: C Y Coeq) | |
(univ: forall {Z: C}{h: C Y Z}, | |
h \o f == h \o g -> C Coeq Z) := | |
{ | |
coequalize: coeq \o f == coeq \o g; | |
coequalizer_universality: forall Z (h: C Y Z)(Heq: h \o f == h \o g), | |
(univ Heq) \o coeq == h; | |
coequalizer_uniqueness: forall Z (h: C Y Z)(Heq: h \o f == h \o g)(u: C Coeq Z), | |
u \o coeq == h -> u == univ Heq | |
}. | |
Structure Coequalizer (C: Category)(X Y: C)(f g: C X Y) := | |
{ | |
coequalizer_obj: C; | |
coequalizer_map:> C Y coequalizer_obj; | |
coequalizer_univ: forall (Z: C)(h:C Y Z), h \o f == h \o g -> C coequalizer_obj Z; | |
coequalizer_prf:> IsCoequalizer coequalizer_map coequalizer_univ | |
}. | |
Existing Instance coequalizer_prf. | |
Notation "[ 'Coequalizer' 'of' f , g 'by' univ 'with' map 'to' Coeq 'in' C ]" := | |
(@Build_Coequalizer C _ _ f g Coeq map univ _). | |
Notation "[ 'Coequalizer' 'of' f , g 'by' univ 'with' map ]" := | |
[Coequalizer of f,g by univ with map to _ in _]. | |
Notation "[ 'Coequalizer' 'by' univ 'with' map ]" := | |
[Coequalizer of _,_ by univ with map]. | |
Notation "[ 'Coequalizer' 'by' univ ]" := [Coequalizer by univ with _]. | |
Lemma coequalizer_univ_subst | |
(C: Category)(X Y: C)(f g: C X Y) | |
(coeq: Coequalizer f g) | |
(Z: C)(h h': C Y Z) | |
(Heq: h \o f == h \o g) | |
(Heq': h' \o f == h' \o g): | |
h == h' -> | |
coequalizer_univ coeq Heq == coequalizer_univ coeq Heq'. | |
Proof. | |
intros Heqh. | |
apply coequalizer_uniqueness; symmetry; rewrite <- Heqh. | |
now rewrite coequalizer_universality. | |
Qed. | |
(** *** 2.5.2 Isomorphic **) | |
Lemma coequalizer_isomorphic: | |
forall (C: Category)(X Y: C)(f g: C X Y) | |
(eq eq': Coequalizer f g), | |
coequalizer_obj eq === coequalizer_obj eq' in C. | |
Proof. | |
intros; simpl; unfold isomorphic. | |
exists (coequalizer_univ eq (coequalize (IsCoequalizer:=eq'))), (coequalizer_univ eq' (coequalize (IsCoequalizer:=eq))); split. | |
- rewrite (coequalizer_uniqueness (coequalize (IsCoequalizer:=eq)) (u:=Id (coequalizer_obj eq))); [| now rewrite cat_comp_id_cod]. | |
apply coequalizer_uniqueness. | |
now rewrite cat_comp_assoc, !coequalizer_universality. | |
- rewrite (coequalizer_uniqueness (coequalize (IsCoequalizer:=eq')) (u:=Id (coequalizer_obj eq'))); [| now rewrite cat_comp_id_cod]. | |
apply coequalizer_uniqueness. | |
now rewrite cat_comp_assoc, !coequalizer_universality. | |
Qed. | |
(** *** 2.5.3 Example **) | |
(** Coequalizer of Setoids **) | |
Class IsRelation (X: Setoid)(R: X -> X -> Prop) := | |
{ | |
relation_proper:> Proper ((== in X) ==> (== in X) ==> iff) R | |
}. | |
Structure Relation (X: Setoid) := | |
{ | |
relation_rel:> X -> X -> Prop; | |
relation_prf:> IsRelation X relation_rel | |
}. | |
Existing Instance relation_prf. | |
Notation "[ 'Rel' 'by' rel 'on' X ]" := (@Build_Relation X rel _). | |
Inductive EquivClosure (A: Setoid)(R: Relation A): A -> A -> Prop := | |
| eqcl_base: forall a b, R a b -> EquivClosure R a b | |
| eqcl_refl: forall a b: A, a == b -> EquivClosure R a b | |
| eqcl_sym: forall a b: A, EquivClosure R a b -> EquivClosure R b a | |
| eqcl_trans: forall a b c, EquivClosure R a b -> EquivClosure R b c -> EquivClosure R a c. | |
Program Instance EquivClosure_Equivalence (A: Setoid)(R: Relation A) | |
: Equivalence (EquivClosure R). | |
Next Obligation. | |
now intros x; apply eqcl_refl. | |
Qed. | |
Next Obligation. | |
now intros x y; apply eqcl_sym. | |
Qed. | |
Next Obligation. | |
now intros x y z; apply eqcl_trans. | |
Qed. | |
Program Definition EqCl (X: Setoid)(R: Relation X) := | |
[Rel by EquivClosure R on X]. | |
Next Obligation. | |
split; intros. | |
- revert y y0 H H0. | |
induction H1; intros. | |
+ apply eqcl_base. | |
now rewrite <- H0, <- H1. | |
+ rewrite H0, H1 in H. | |
now apply eqcl_refl. | |
+ now apply eqcl_sym, IHEquivClosure. | |
+ apply eqcl_trans with b. | |
* now apply IHEquivClosure1. | |
* now apply IHEquivClosure2. | |
- rename x into y, y into x, x0 into y0, y0 into x0. | |
revert y y0 H H0. | |
induction H1; intros. | |
+ apply eqcl_base. | |
now rewrite H0, H1. | |
+ rewrite <- H0, <- H1 in H. | |
now apply eqcl_refl. | |
+ now apply eqcl_sym, IHEquivClosure. | |
+ apply eqcl_trans with b. | |
* now apply IHEquivClosure1. | |
* now apply IHEquivClosure2. | |
Qed. | |
Program Definition QuotientSetoid (X: Setoid)(R: Relation X) | |
(Heq: Equivalence R) := | |
[Setoid by R on X]. | |
Inductive coequalize_pair (X Y: Setoid)(f g: Map X Y): Y -> Y -> Prop := | |
| coequalize_pair_def: forall (x: X)(y y': Y), | |
f x == y -> g x == y' -> | |
coequalize_pair f g y y'. | |
Program Definition coequalize_pair_relation (X Y: Setoid)(f g: Map X Y) := | |
[Rel by coequalize_pair f g on Y]. | |
Next Obligation. | |
split; intros. | |
- destruct H1. | |
apply coequalize_pair_def with x. | |
+ now rewrite H in H1. | |
+ now rewrite H0 in H2. | |
- destruct H1. | |
apply coequalize_pair_def with x1. | |
+ now rewrite H. | |
+ now rewrite H0. | |
Qed. | |
Program Definition coequalizer_of_Setoids (X Y: Setoid)(f g: Map X Y) := | |
[Coequalizer of f, g | |
by (fun z h H => [ y :-> h y]) | |
with [y :-> y] | |
to QuotientSetoid (EqCl (coequalize_pair_relation f g)) (EquivClosure_Equivalence Y (coequalize_pair_relation f g)) | |
in Setoids]. | |
Next Obligation. | |
intros y y' Heq. | |
now apply eqcl_refl. | |
Qed. | |
Next Obligation. | |
intros y y' Hr. | |
induction Hr. | |
- destruct H0. | |
rewrite <- H0, <- H1. | |
now rewrite (H x). | |
- now rewrite H0. | |
- now symmetry. | |
- now transitivity (h b). | |
Qed. | |
Next Obligation. | |
now apply eqcl_base, coequalize_pair_def with x. | |
Qed. | |
(** ** 2.6 Exponential **) | |
(** *** 2.6.1 Definition **) | |
Class IsExponential | |
(C: Category) | |
(prod: forall (X Y: C), Product C X Y) | |
(Y Z: C) | |
(exp: C)(ev: C (prod exp Y) Z) | |
(univ: forall (X: C)(g: C (prod X Y) Z), C X exp) := | |
{ | |
exp_universality: | |
forall (X: C)(g: C (prod X Y) Z), | |
g == ev \o [univ X g \* Id Y with prod]; | |
exp_uniqueness: | |
forall (X: C)(g: C (prod X Y) Z)(u: C X exp), | |
g == ev \o [u \* Id Y with prod] -> | |
u == univ X g | |
}. | |
Structure Exponential | |
(C: Category)(prod: forall (X Y: C), Product C X Y) | |
(Y Z: C) := | |
{ | |
exp_obj:> C; | |
exp_eval: C (prod exp_obj Y) Z; | |
exp_univ: forall (X: C), C (prod X Y) Z -> C X exp_obj; | |
exp_prf:> IsExponential exp_eval exp_univ | |
}. | |
Existing Instance exp_prf. | |
Notation "[ 'Exp' exp 'by' univ 'with' eval ]" := | |
(@Build_Exponential _ _ _ _ exp eval univ _). | |
Notation "[ 'Exp' 'by' univ 'with' eval ]" := | |
[Exp _ by univ with eval]. | |
Notation "[ 'curry' f 'to' exp ]" := (exp_univ exp f) (f at next level). | |
Program Instance exponential_univ_proper | |
(C: Category) | |
(prod: forall (X Y: C), Product C X Y) | |
(Y Z: C) | |
(exp: Exponential prod Y Z) | |
(X: C) | |
: Proper ((==) ==> (==)) (@exp_univ _ prod _ _ exp X). | |
Next Obligation. | |
intros f g Heq. | |
apply (exp_uniqueness (IsExponential:=exp)). | |
rewrite <- Heq. | |
now apply (exp_universality (IsExponential:=exp)). | |
Qed. | |
(** *** 2.6.2 Isomorphic **) | |
Lemma exponential_isomorphic: | |
forall (C: Category) | |
(prod: forall (X Y: C), Product C X Y) | |
(Y Z: C)(exp exp': Exponential prod Y Z), | |
exp === exp' in C. | |
Proof. | |
intros; simpl; unfold isomorphic. | |
exists [curry (exp_eval exp) to exp'], [curry (exp_eval exp') to exp]; split. | |
- rewrite (exp_uniqueness (g:=exp_eval exp)(u:=Id exp)). | |
+ apply exp_uniqueness. | |
rewrite <- (cat_comp_id_dom (Id Y)), product_map_compose. | |
now rewrite <- cat_comp_assoc, <- !exp_universality. | |
+ now rewrite product_map_id, cat_comp_id_dom. | |
- rewrite (exp_uniqueness (g:=exp_eval exp')(u:=Id exp')). | |
+ apply exp_uniqueness. | |
rewrite <- (cat_comp_id_dom (Id Y)), product_map_compose. | |
now rewrite <- cat_comp_assoc, <- !exp_universality. | |
+ now rewrite product_map_id, cat_comp_id_dom. | |
Qed. | |
(** *** 2.6.3 Examples **) | |
Program Definition exponential_of_Setoids (Y Z: Setoids) | |
: Exponential (C:=Setoids) product_of_Setoids Y Z := | |
[Exp (Setoids Y Z) | |
by (fun (X: Setoid) f => [x :-> [y :-> f (x, y)]]) | |
with [gy :-> gy.1 gy.2]]. | |
Next Obligation. | |
intros [g y] [g' y'] [Heqg Heqy]; simpl in *. | |
now rewrite Heqy, Heqg. | |
Qed. | |
Next Obligation. | |
now intros y y' Heq; rewrite Heq. | |
Qed. | |
Next Obligation. | |
now intros x x' Heq y; simpl; rewrite Heq. | |
Qed. | |
Next Obligation. | |
rename g into f, u into g, x0 into y. | |
now rewrite (H (x, y)). | |
Qed. | |
(** * 3. Limit and Colimit **) | |
(** ** 3.1 Limit **) | |
(** *** 3.1.1 Definition **) | |
Class IsCone | |
(J C: Category) | |
(D: J --> C) | |
(apex: C) | |
(gen: forall i, C apex (D i)) := | |
{ | |
cone_commute: | |
forall i j (u: J i j), | |
fmap D u \o gen i == gen j | |
}. | |
Structure Cone (J C: Category)(D: J --> C): Type := | |
{ | |
cone_apex:> C; | |
cone_gen:> forall i, C cone_apex (D i); | |
cone_prf:> IsCone cone_gen | |
}. | |
Existing Instance cone_prf. | |
Notation "[ 'Cone' 'of' D 'by' gen 'from' apex ]" := (@Build_Cone _ _ D apex gen _). | |
Notation "[ 'Cone' 'by' gen 'from' apex ]" := [Cone of _ by gen from apex]. | |
Notation "[ 'Cone' 'by' gen ]" := [Cone by gen from _]. | |
Notation "[ 'Cone' 'by' i :-> f 'from' apex ]" := [Cone by (fun i => f) from apex]. | |
Notation "[ 'Cone' 'by' i :-> f ]" := [Cone by i :-> f from _]. | |
Class IsLimit (J C: Category)(D: J --> C) | |
(obj: Cone D) | |
(univ: forall c: Cone D, C c obj) := | |
{ | |
limit_universality: | |
forall (c: Cone D)(i: J), | |
obj i \o univ c == c i; | |
limit_uniqueness: | |
forall (c: Cone D)(u: C c obj), | |
(forall i: J, obj i \o u == c i) -> | |
u == univ c | |
}. | |
Structure Limit (J C: Category)(D: J --> C) := | |
{ | |
limit_obj:> Cone D; | |
limit_univ: forall c: Cone D, C c limit_obj; | |
limit_prf:> IsLimit limit_univ | |
}. | |
Existing Instance limit_prf. | |
Notation "[ 'Limit' obj 'by' univ 'of' D ]" := (@Build_Limit _ _ D obj univ _). | |
Notation "[ 'Limit' 'by' univ 'of' D ]" := [Limit _ by univ of D]. | |
Notation "[ 'Limit' obj 'by' univ ]" := [Limit obj by univ of _]. | |
Notation "[ 'Limit' 'by' univ ]" := [Limit by univ of _]. | |
(** *** 3.1.2 Isomorphic **) | |
Lemma limit_isomorphic: | |
forall (J C: Category)(D: J --> C) | |
(lim lim': Limit D), | |
lim === lim' in C. | |
Proof. | |
intros; simpl; unfold isomorphic. | |
exists (limit_univ lim' lim), (limit_univ lim lim'); split. | |
- rewrite (limit_uniqueness (u:=Id lim)). | |
+ apply limit_uniqueness; intros i. | |
now rewrite <- cat_comp_assoc, !limit_universality. | |
+ now intros i; rewrite cat_comp_id_dom. | |
- rewrite (limit_uniqueness (u:=Id lim')). | |
+ apply limit_uniqueness; intros i. | |
now rewrite <- cat_comp_assoc, !limit_universality. | |
+ now intros i; rewrite cat_comp_id_dom. | |
Qed. | |
(** *** 3.1.3 Terminality of Limit **) | |
Class IsConeMap | |
(J C: Category) | |
(D: J --> C) | |
(c d: Cone D) | |
(map: C c d) := | |
{ | |
cone_map_commute: | |
forall i: J, | |
d i \o map == c i | |
}. | |
Structure ConeMap | |
(J C: Category) | |
(D: J --> C) | |
(c d: Cone D) := | |
{ | |
cone_map_map:> C c d; | |
cone_map_prf:> IsConeMap cone_map_map | |
}. | |
Existing Instance cone_map_prf. | |
Notation "[ 'ConeMap' 'by' f ]" := (@Build_ConeMap _ _ _ _ _ f _). | |
Program Definition ConeMap_compose (J C: Category)(D: J --> C)(c d e: Cone D)(f: ConeMap c d)(g: ConeMap d e) | |
: ConeMap c e := | |
[ConeMap by g \o f]. | |
Next Obligation. | |
now rewrite <- cat_comp_assoc, !cone_map_commute. | |
Qed. | |
Program Definition ConeMap_id (J C: Category)(D: J --> C)(c: Cone D): ConeMap c c := | |
[ConeMap by Id c]. | |
Next Obligation. | |
now rewrite cat_comp_id_dom. | |
Qed. | |
Program Definition ConeMap_setoid (J C: Category)(D: J --> C)(c d: Cone D): Setoid := | |
[Setoid by `(f == g) on ConeMap c d]. | |
Next Obligation. | |
now intros f g h Heqfg Heqgh; rewrite Heqfg, Heqgh. | |
Qed. | |
Program Definition Cones (J C: Category)(D: J --> C): Category := | |
[Category by @ConeMap_setoid J C D | |
with @ConeMap_compose J C D, | |
@ConeMap_id J C D]. | |
Next Obligation. | |
- rename X into c, Y into d, Z into e. | |
intros f f' Heqf g g' Heqg; simpl in *. | |
now rewrite Heqf, Heqg. | |
- now rewrite cat_comp_assoc. | |
- now rewrite cat_comp_id_dom. | |
- now rewrite cat_comp_id_cod. | |
Qed. | |
Program Definition limit_by_terminal_of_cones | |
(J C: Category)(D: J --> C)(t: Terminal (Cones D)): Limit D := | |
[Limit by terminal_univ t]. | |
Next Obligation. | |
- now apply (cone_map_commute (IsConeMap:=terminal_univ t c)). | |
- now apply (terminal_uniqueness (IsTerminal:=t) (X:=c) (Build_ConeMap (Build_IsConeMap H))). | |
Qed. | |
(** ** 3.2 Colimit **) | |
(** *** 3.2.1 Definition **) | |
Class IsCocone | |
(J C: Category)(D: J --> C) | |
(apex: C) | |
(gen: forall i: J, C (D i) apex) := | |
{ | |
cocone_commute: | |
forall (i j: J)(u: J i j), | |
gen j \o fmap D u == gen i | |
}. | |
Structure Cocone (J C: Category)(D: J --> C): Type := | |
{ | |
cocone_apex:> C; | |
cocone_gen:> forall i: J, C (D i) cocone_apex; | |
cocone_prf:> IsCocone cocone_gen | |
}. | |
Existing Instance cocone_prf. | |
Notation "[ 'Cocone' 'of' D 'by' gen 'to' apex ]" := (@Build_Cocone _ _ D apex gen _). | |
Notation "[ 'Cocone' 'by' gen 'to' apex ]" := [Cocone of _ by gen to apex]. | |
Notation "[ 'Cocone' 'by' gen ]" := [Cocone by gen to _]. | |
Notation "[ 'Cocone' 'by' i :-> f 'to' apex ]" := [Cocone by (fun i => f) to apex]. | |
Notation "[ 'Cocone' 'by' i :-> f ]" := [Cocone by i :-> f to _]. | |
Class IsColimit (J C: Category)(D: J --> C) | |
(obj: Cocone D) | |
(univ: forall c: Cocone D, C obj c) := | |
{ | |
colimit_universality: | |
forall (c: Cocone D)(i: J), | |
univ c \o obj i == c i; | |
colimit_uniqueness: | |
forall (c: Cocone D)(u: C obj c), | |
(forall i: J, u \o obj i == c i) -> | |
u == univ c | |
}. | |
Structure Colimit (J C: Category)(D: J --> C) := | |
{ | |
colimit_obj:> Cocone D; | |
colimit_univ: forall c: Cocone D, C colimit_obj c; | |
colimit_prf:> IsColimit colimit_univ | |
}. | |
Existing Instance colimit_prf. | |
Notation "[ 'Colimit' obj 'by' univ 'of' D ]" := (@Build_Colimit _ _ D obj univ _). | |
Notation "[ 'Colimit' 'by' univ 'of' D ]" := [Colimit _ by univ of D]. | |
Notation "[ 'Colimit' obj 'by' univ ]" := [Colimit obj by univ of _]. | |
Notation "[ 'Colimit' 'by' univ ]" := [Colimit by univ of _]. | |
(** *** 3.1.2 Isomorphic **) | |
Lemma colimit_isomorphic: | |
forall (J C: Category)(D: J --> C) | |
(colim colim': Colimit D), | |
colim === colim' in C. | |
Proof. | |
intros; simpl; unfold isomorphic. | |
exists (colimit_univ colim colim'), (colimit_univ colim' colim); split. | |
- rewrite (colimit_uniqueness (u:=Id colim)). | |
+ apply colimit_uniqueness; intros i. | |
now rewrite cat_comp_assoc, !colimit_universality. | |
+ now intros i; rewrite cat_comp_id_cod. | |
- rewrite (colimit_uniqueness (u:=Id colim')). | |
+ apply colimit_uniqueness; intros i. | |
now rewrite cat_comp_assoc, !colimit_universality. | |
+ now intros i; rewrite cat_comp_id_cod. | |
Qed. | |
(** *** 3.2.3 Initiality of Colimit **) | |
Class IsCoconeMap | |
(J C: Category)(D: J --> C) | |
(c d: Cocone D) | |
(map: C c d) := | |
{ | |
cocone_map_commute: | |
forall i: J, | |
map \o c i == d i | |
}. | |
Structure CoconeMap (J C: Category)(D: J --> C)(c d: Cocone D) := | |
{ | |
cocone_map_map:> C c d; | |
cocone_map_prf:> IsCoconeMap cocone_map_map | |
}. | |
Existing Instance cocone_map_prf. | |
Notation "[ 'CoconeMap' 'by' f ]" := | |
(@Build_CoconeMap _ _ _ _ _ f _). | |
Program Definition CoconeMap_compose (J C: Category)(D: J --> C)(c d e: Cocone D)(f: CoconeMap c d)(g: CoconeMap d e) | |
: CoconeMap c e := | |
[CoconeMap by g \o f]. | |
Next Obligation. | |
now rewrite cat_comp_assoc, !cocone_map_commute. | |
Qed. | |
Program Definition CoconeMap_id (J C: Category)(D: J --> C)(c: Cocone D): CoconeMap c c := | |
[CoconeMap by Id c]. | |
Next Obligation. | |
now rewrite cat_comp_id_cod. | |
Qed. | |
Program Definition CoconeMap_setoid (J C: Category)(D: J --> C)(c d: Cocone D): Setoid := | |
[Setoid by `(f == g) on CoconeMap c d]. | |
Next Obligation. | |
now intros f g h Heqfg Heqgh; rewrite Heqfg, Heqgh. | |
Qed. | |
Program Definition Cocones (J C: Category)(D: J --> C): Category := | |
[Category by @CoconeMap_setoid J C D | |
with (@CoconeMap_compose J C D), | |
(@CoconeMap_id J C D)]. | |
Next Obligation. | |
rename X into c, Y into d, Z into e. | |
intros f f' Heqf g g' Heqg; simpl in *. | |
now rewrite Heqf, Heqg. | |
now rewrite cat_comp_assoc. | |
now rewrite cat_comp_id_dom. | |
now rewrite cat_comp_id_cod. | |
Qed. | |
Program Definition colimit_by_initial_of_cocones (J C: Category)(D: J --> C)(i: Initial (Cocones D)): Colimit D := | |
[Colimit (initial_obj i) by initial_univ i]. | |
Next Obligation. | |
- now apply cocone_map_commute. | |
- apply Build_IsCoconeMap in H. | |
now apply (initial_uniqueness (IsInitial:=i)(X:=c)[CoconeMap by u]). | |
Qed. | |
(** * 4. Adjunction **) | |
(** ** 4.1 Definition **) | |
(* 随伴 *) | |
Class IsAdjunction | |
(C D: Category)(F: C --> D)(G: D --> C) | |
(lr: forall {c: C}{d: D}, Map (D (F c) d) (C c (G d))) | |
(rl: forall {c: C}{d: D}, Map (C c (G d)) (D (F c) d)) := | |
{ | |
adj_iso_lr_rl: | |
forall (c: C)(d: D)(f: D (F c) d), | |
rl (lr f) == f; | |
adj_iso_rl_lr: | |
forall (c: C)(d: D)(g: C c (G d)), | |
lr (rl g) == g; | |
adj_lr_naturality: | |
forall (c c': C)(d d': D)(f : C c' c)(g: D d d')(h: D (F c) d), | |
lr (g \o h \o fmap F f) == fmap G g \o lr h \o f; | |
adj_rl_naturality: | |
forall (c c': C)(d d': D)(f : C c' c)(g: D d d')(h: C c (G d)), | |
rl (fmap G g \o h \o f) == g \o rl h \o fmap F f | |
}. | |
Structure Adjunction (C D: Category)(F: C --> D)(G: D --> C) := | |
{ | |
adj_lr: forall {c: C}{d: D}, Map (D (F c) d) (C c (G d)); | |
adj_rl: forall {c: C}{d: D}, Map (C c (G d)) (D (F c) d); | |
prf:> IsAdjunction (@adj_lr) (@adj_rl) | |
}. | |
Existing Instance prf. | |
Notation "F -| G ; C <--> D" := (Adjunction (C:=C) (D:=D) F G) (at level 40, no associativity). | |
Notation "F -| G" := (F -| G ; _ <--> _) (at level 40, no associativity). | |
Notation "[ 'Adj' 'of' F , G 'by' lr , rl ]" := | |
(@Build_Adjunction _ _ F G lr rl _). | |
Notation "[ 'Adj' 'by' lr , rl ]" := [Adj of _, _ by lr, rl]. | |
Notation "[ F -| G 'by' lr , rl ]" := [Adj of F,G by lr,rl]. | |
(** unit of adjunction **) | |
Program Definition adj_unit | |
(C D: Category)(F: C --> D)(G: D --> C)(adj: F -| G) | |
: (Id C) ==> (G \o F) := | |
[ c :=> adj_lr adj (Id (F c))]. | |
Next Obligation. | |
rewrite <- cat_comp_id_cod. | |
rewrite <- (fmap_id (F Y)). | |
rewrite <- adj_lr_naturality. | |
rewrite !cat_comp_id_cod. | |
symmetry. | |
rewrite <- cat_comp_id_dom, cat_comp_assoc. | |
rewrite <- adj_lr_naturality. | |
now rewrite cat_comp_id_cod, fmap_id, cat_comp_id_dom. | |
Qed. | |
(** counit of adjunction *) | |
Program Definition adj_counit | |
(C D: Category)(F: C --> D)(G: D --> C)(adj: F -| G): | |
(F \o G) ==> (Id D) := | |
[d :=> adj_rl adj (Id (G d))]. | |
Next Obligation. | |
intros; simpl. | |
rewrite <- cat_comp_id_cod. | |
rewrite <- adj_rl_naturality. | |
rewrite fmap_id, cat_comp_id_cod. | |
symmetry. | |
rewrite <- cat_comp_id_dom, <- fmap_id, cat_comp_assoc. | |
rewrite <- adj_rl_naturality. | |
now rewrite !cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
(* Adjunction by unit and counit *) | |
Program Definition Natrans_id_dom (C D: Category)(F: C --> D): (F \o Id C) ==> F := | |
[X :=> fmap F (Id X)]. | |
Next Obligation. | |
now rewrite !fmap_id, cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Notation "[ * \o '1' ==> * ]" := (Natrans_id_dom _). | |
Program Definition Natrans_id_dom_inv (C D: Category)(F: C --> D): F ==> (F \o Id C) := | |
[X :=> fmap F (Id X)]. | |
Next Obligation. | |
now rewrite !fmap_id, cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Notation "[ * ==> * \o '1' ]" := (Natrans_id_dom_inv _). | |
Program Definition Natrans_id_cod (C D: Category)(F: C --> D): (Id D \o F) ==> F := | |
[X :=> Id (F X)]. | |
Next Obligation. | |
now rewrite cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Notation "[ '1' \o * ==> * ]" := (Natrans_id_cod _). | |
Program Definition Natrans_id_cod_inv (C D: Category)(F: C --> D): F ==> (Id D \o F) := | |
[X :=> Id (F X)]. | |
Next Obligation. | |
now rewrite cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Notation "[ * ==> '1' \o * ]" := (Natrans_id_cod_inv _). | |
Program Definition Natrans_assoc (B C D E: Category)(F: B --> C)(G: C --> D)(H: D --> E): (H \o (G \o F)) ==> ((H \o G) \o F) := | |
[ X in B :=> Id (H (G (F X)))]. | |
Next Obligation. | |
now rewrite cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Notation Nassoc := (Natrans_assoc _ _ _). | |
Program Definition Natrans_assoc_inv (B C D E: Category)(F: B --> C)(G: C --> D)(H: D --> E): ((H \o G) \o F) ==> (H \o (G \o F)) := | |
[ X in B :=> Id (H (G (F X)))]. | |
Next Obligation. | |
now rewrite cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Notation Nassoc_inv := (Natrans_assoc_inv _ _ _). | |
Definition adj_triangle | |
(C D: Category) | |
(F: C --> D)(G: D --> C) | |
(au: (Id C) ==> (G \o F)) | |
(ac: (F \o G) ==> (Id D)) := | |
([1 \o * ==> *] | |
\o (ac o> F) | |
\o Nassoc | |
\o (F <o au) | |
\o [* ==> * \o 1] | |
== Id F | |
in Natrans_setoid _ _) (* acF \o Fau == Id_F *) | |
/\ | |
([* \o 1 ==> *] | |
\o (G <o ac) | |
\o Nassoc_inv | |
\o (au o> G) | |
\o [* ==> 1 \o *] | |
== Id G | |
in Natrans_setoid _ _). (* Gac \o auG == Id_G *) | |
Lemma adj_satisfies_triangle: | |
forall (C D: Category)(F: C --> D)(G: D --> C)(adj: F -| G), | |
adj_triangle (adj_unit adj) (adj_counit adj). | |
Proof. | |
intros; split; simpl; [intro c | intro d]; | |
rewrite fmap_id, ?cat_comp_id_dom, ?cat_comp_id_cod. | |
- rewrite <- cat_comp_id_cod, <- adj_rl_naturality. | |
rewrite fmap_id, !cat_comp_id_cod. | |
now rewrite adj_iso_lr_rl. | |
- rewrite <- cat_comp_id_dom, cat_comp_assoc, <- adj_lr_naturality. | |
rewrite fmap_id, !cat_comp_id_dom. | |
now rewrite adj_iso_rl_lr. | |
Qed. | |
Program Definition Adjunction_by_unit_and_counit | |
(C D: Category) | |
(F: C --> D)(G: D --> C) | |
(au: (Id C) ==> (G \o F)) | |
(ac: (F \o G) ==> (Id D)) | |
(Hadj: adj_triangle au ac) | |
: F -| G := | |
[Adj by (fun c d => [g in D (F c) d :-> fmap G g \o au c]), | |
(fun c d => [f in C c (G d) :-> ac d \o fmap F f])]. | |
Next Obligation. | |
now intros g g' Heq; rewrite Heq. | |
Qed. | |
Next Obligation. | |
now intros f f' Heq; rewrite Heq. | |
Qed. | |
Next Obligation. | |
- rewrite fmap_comp, <- cat_comp_assoc. | |
rewrite (natrans_naturality (IsNatrans:=ac) f); simpl. | |
rewrite cat_comp_assoc. | |
destruct Hadj as [HF HG]. | |
generalize (HF c); simpl. | |
rewrite fmap_id, !cat_comp_id_cod, !cat_comp_id_dom. | |
now intros H; rewrite H, cat_comp_id_dom. | |
- rewrite fmap_comp, cat_comp_assoc. | |
rewrite <- (natrans_naturality (IsNatrans:=au) g); simpl. | |
rewrite <- cat_comp_assoc. | |
destruct Hadj as [HF HG]. | |
generalize (HG d); simpl. | |
rewrite fmap_id, !cat_comp_id_cod, !cat_comp_id_dom. | |
now intros H; rewrite H, cat_comp_id_cod. | |
- rewrite !fmap_comp, !cat_comp_assoc. | |
now rewrite (natrans_naturality (IsNatrans:=au) f). | |
- rewrite !fmap_comp, <- !cat_comp_assoc. | |
now rewrite (natrans_naturality (IsNatrans:=ac) g). | |
Qed. | |
(** ** 4.2 Examples **) | |
(** *** 4.2.1 -*Y -| (-)^Y **) | |
Program Definition Product_2_functor (C: Category) | |
(prod: forall X Y: C, Product C X Y) | |
(Y: C) | |
: C --> C := | |
[Functor by (fun (W X: C)(f: C W X) => [f \* Id _ with prod ]) | |
with `(prod X Y) ]. | |
Next Obligation. | |
- rename X into W, Y0 into X. | |
intros f f' Heq. | |
now rewrite Heq. | |
- rename X into V, Y0 into W, Z into X. | |
now rewrite <- product_map_compose, cat_comp_id_dom. | |
- now apply product_map_id. | |
Qed. | |
Program Definition Exponential_functor | |
(C: Category)(prod: forall (X Y: C), Product C X Y) | |
(exp: forall (Y Z: C), Exponential prod Y Z) | |
(X: C) | |
: C --> C := | |
[Functor by (fun (Y Z: C)(g: C Y Z) => [curry (g \o exp_eval (exp X Y)) to (exp X Z)]) with `(exp X Y)]. | |
Next Obligation. | |
- rename X0 into Y, Y into Z. | |
now intros g g' Heq; rewrite Heq. | |
- rename X0 into Y, Y into Z, Z into W. | |
symmetry. | |
apply exp_uniqueness. | |
rewrite <- (cat_comp_id_dom (Id X)). | |
rewrite product_map_compose. | |
rewrite <- cat_comp_assoc. | |
rewrite <- (exp_universality (IsExponential:=exp X W)). | |
rewrite !cat_comp_assoc. | |
now rewrite <- (exp_universality (IsExponential:=exp X Z)). | |
- rename X0 into Y. | |
symmetry. | |
apply exp_uniqueness. | |
now rewrite product_map_id, cat_comp_id_cod, cat_comp_id_dom. | |
Qed. | |
Program Definition prod_exp_adjunction | |
(C: Category) | |
(prod: forall (X Y: C), Product C X Y) | |
(exp: forall (Y Z: C), Exponential prod Y Z) | |
(Y: C) | |
: Product_2_functor prod Y -| Exponential_functor exp Y := | |
[Adj by (fun X Z => [f in C (prod X Y) Z :-> [curry f to exp Y Z]]), | |
(fun X Z => [f in C X (exp Y Z) :-> exp_eval (exp Y Z) \o [f \* Id Y with prod]])]. | |
Next Obligation. | |
now intros f f' Heq; rewrite Heq. | |
Qed. | |
Next Obligation. | |
now intros f f' Heq; rewrite Heq. | |
Qed. | |
Next Obligation. | |
- rename c into X, d into Z. | |
now rewrite <- (exp_universality (IsExponential:=exp Y Z)). | |
- rename c into X, d into Z. | |
symmetry. | |
now apply exp_uniqueness. | |
- rename c' into W, c into X, d into Z, d' into Z'. | |
symmetry. | |
apply exp_uniqueness. | |
rewrite <- (cat_comp_id_dom (Id Y)) at 2. | |
rewrite product_map_compose. | |
rewrite <- (cat_comp_assoc _ _ (exp_eval _)), <- exp_universality. | |
rewrite !cat_comp_assoc. | |
rewrite <- (cat_comp_id_dom (Id Y)) at 2. | |
rewrite product_map_compose. | |
now rewrite <- (cat_comp_assoc _ _ (exp_eval _)), <- exp_universality. | |
- rename c' into W, c into X, d into Z, d' into Z'. | |
rewrite !cat_comp_assoc. | |
rewrite <- product_map_compose, cat_comp_id_dom. | |
rewrite <- (cat_comp_id_dom (Id Y)) at 1. | |
rewrite product_map_compose. | |
now rewrite <- cat_comp_assoc, <- exp_universality, cat_comp_assoc. | |
Qed. | |
(** *** 4.2.2 Colimit -| Diagonal -| Limit **) | |
Program Definition Diagonal_functor (J C: Category) | |
: C --> (C^J) := | |
[Functor by f :-> [X in J :=> f] | |
with X :-> [ * in J |-> X in C ]]. | |
Next Obligation. | |
now rewrite cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Program Definition Colimit_functor (J C: Category)(colim: forall (D: J --> C), Colimit D) | |
: (C^J) --> C := | |
[Functor by (fun D D' S => colimit_univ (colim D) [Cocone by i :-> (colim D') i \o S i] ) | |
with `(colim D)]. | |
Next Obligation. | |
rewrite cat_comp_assoc, natrans_naturality. | |
rewrite <- cat_comp_assoc. | |
now rewrite (cocone_commute (IsCocone:=colim D')). | |
Qed. | |
Next Obligation. | |
- rename X into D, Y into D'. | |
intros S T Heq; simpl. | |
apply (colimit_uniqueness (IsColimit:=colim D)(c:=[ Cocone by i :-> (colim D') i \o T i])(u:=colimit_univ (colim D) [ Cocone by i :-> (colim D') i \o S i])); simpl. | |
intros j; simpl. | |
rewrite <- (Heq j). | |
now rewrite (colimit_universality (IsColimit:=colim D)[Cocone by i :-> colim D' i \o S i]). | |
- rename X into D, Y into D', Z into D''. | |
rename f into S, g into T. | |
symmetry. | |
apply (colimit_uniqueness (IsColimit:=colim D)(c:=[ Cocone by i :-> (colim D'') i \o T i \o S i])). | |
simpl; intros i. | |
rewrite cat_comp_assoc. | |
rewrite (colimit_universality (IsColimit:=colim D)[ Cocone by i :-> (colim D') i \o S i]); simpl. | |
rewrite <- cat_comp_assoc. | |
rewrite (colimit_universality (IsColimit:=colim D')[ Cocone by i :-> (colim D'') i \o T i]); simpl. | |
now rewrite cat_comp_assoc. | |
- symmetry. | |
rename X into D. | |
apply (colimit_uniqueness (IsColimit:=colim D)(c:=[ Cocone by i :-> (colim D) i \o Id (D i)])); simpl. | |
intros i. | |
now rewrite cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Program Definition colimit_diag_adjunction | |
(J C: Category) | |
(colim: forall (D: J --> C), Colimit D) | |
: Colimit_functor colim -| Diagonal_functor J C := | |
[Adj by (fun D c => [f :-> [i in J :=> f \o colim D i]]), | |
(fun D c => [g :-> colimit_univ (colim D) [Cocone by g to c]])]. | |
Next Obligation. | |
rename X into i, Y into j, f0 into u. | |
rewrite cat_comp_assoc, (cocone_commute (IsCocone:=colim D)). | |
now rewrite cat_comp_id_cod. | |
Qed. | |
Next Obligation. | |
intros f g Heq i; simpl. | |
now rewrite Heq. | |
Qed. | |
Next Obligation. | |
rewrite (natrans_naturality (IsNatrans:=g)); simpl. | |
now rewrite cat_comp_id_cod. | |
Qed. | |
Next Obligation. | |
intros S T Heq; simpl. | |
apply (colimit_uniqueness (IsColimit:=colim D)(c:=[Cocone by T to c])(u:=colimit_univ (colim D) [Cocone by S to c])); simpl. | |
intros i. | |
rewrite <- (Heq i). | |
now rewrite (colimit_universality (IsColimit:=colim D) [Cocone by S to c]). | |
Qed. | |
Next Obligation. | |
- symmetry. | |
now apply (colimit_uniqueness (IsColimit:=colim c)(c:=[Cocone by i :-> f \o (colim c) i])); simpl. | |
- now rewrite (colimit_universality (IsColimit:=colim c) [Cocone by g to d]). | |
- rewrite !cat_comp_assoc. | |
now rewrite (colimit_universality (IsColimit:=colim c')[Cocone by i :-> (colim c) i \o f i]). | |
- rename c into D, c' into D', d into c, d' into c', f into S, g into f, h into T. | |
symmetry. | |
apply (colimit_uniqueness (IsColimit:=colim D')(c:=[ Cocone by X :-> f \o T X \o S X])); simpl. | |
intros i. | |
rewrite cat_comp_assoc. | |
apply cat_comp_proper; try now idtac. | |
rewrite cat_comp_assoc. | |
rewrite (colimit_universality (IsColimit:=colim D')[ Cocone by i :-> (colim D) i \o S i]); simpl. | |
rewrite <- cat_comp_assoc. | |
now rewrite (colimit_universality (IsColimit:=colim D) [ Cocone by T to c]); simpl. | |
Qed. | |
Program Definition Limit_functor (J C: Category)(lim: forall (D: J --> C), Limit D) | |
: (C^J) --> C := | |
[Functor by (fun D D' S => limit_univ (lim D') [Cone by i :-> S i \o (lim D) i] ) | |
with `(lim D)]. | |
Next Obligation. | |
rewrite <- cat_comp_assoc, <- natrans_naturality. | |
rewrite cat_comp_assoc. | |
now rewrite (cone_commute (IsCone:=lim D)). | |
Qed. | |
Next Obligation. | |
- rename X into D, Y into D'. | |
intros S T Heq; simpl. | |
apply (limit_uniqueness (IsLimit:=lim D')(c:=[ Cone by i :-> T i \o (lim D) i])(u:=limit_univ (lim D') [ Cone by i :-> S i \o (lim D) i])); simpl. | |
intros j; simpl. | |
rewrite <- (Heq j). | |
now rewrite (limit_universality (IsLimit:=lim D')[Cone by i :-> S i \o lim D i]). | |
- rename X into D, Y into D', Z into D''. | |
rename f into S, g into T. | |
symmetry. | |
apply (limit_uniqueness (IsLimit:=lim D'')(c:=[ Cone by i :-> (T i \o S i) \o (lim D i)])). | |
simpl; intros i. | |
rewrite <- cat_comp_assoc. | |
rewrite (limit_universality (IsLimit:=lim D'')[ Cone by i :-> T i \o (lim D') i]); simpl. | |
rewrite cat_comp_assoc. | |
rewrite (limit_universality (IsLimit:=lim D')[ Cone by i :-> S i \o (lim D) i]); simpl. | |
now rewrite cat_comp_assoc. | |
- symmetry. | |
rename X into D. | |
apply (limit_uniqueness (IsLimit:=lim D)(c:=[ Cone by i :-> Id (D i) \o (lim D) i])); simpl. | |
intros i. | |
now rewrite cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Program Definition diag_limit_adjunction | |
(J C: Category) | |
(lim: forall (D: J --> C), Limit D) | |
: Diagonal_functor J C -| Limit_functor lim := | |
[Adj by (fun c D => [g :-> limit_univ (lim D) [Cone by g from c]]), | |
(fun c D => [f :-> [i in J :=> lim D i \o f]])]. | |
Next Obligation. | |
rewrite <- (natrans_naturality (IsNatrans:=g)); simpl. | |
now rewrite cat_comp_id_dom. | |
Qed. | |
Next Obligation. | |
intros S T Heq; simpl. | |
apply (limit_uniqueness (IsLimit:=lim D)(c:=[Cone by T from c])(u:=limit_univ (lim D) [Cone by S from c])); simpl. | |
intros i. | |
rewrite <- (Heq i). | |
now rewrite (limit_universality (IsLimit:=lim D) [Cone by S from c]). | |
Qed. | |
Next Obligation. | |
rename X into i, Y into j, f0 into u. | |
rewrite <- cat_comp_assoc, (cone_commute (IsCone:=lim D)). | |
now rewrite cat_comp_id_dom. | |
Qed. | |
Next Obligation. | |
intros f g Heq i; simpl. | |
now rewrite Heq. | |
Qed. | |
Next Obligation. | |
- now rewrite (limit_universality (IsLimit:=lim d)[Cone by f from c]). | |
- symmetry. | |
now apply (limit_uniqueness (IsLimit:=lim d)(c:=[Cone by i :-> (lim d) i \o g])); simpl. | |
- rename d into D, d' into D', g into S, h into T. | |
symmetry. | |
apply (limit_uniqueness (IsLimit:=lim D')(c:=[ Cone by X :-> S X \o T X \o f])); simpl. | |
intros i. | |
rewrite <- !cat_comp_assoc. | |
apply cat_comp_proper; try now idtac. | |
rewrite (limit_universality (IsLimit:=lim D')[ Cone by i :-> S i \o (lim D) i]); simpl. | |
rewrite cat_comp_assoc. | |
now rewrite (limit_universality (IsLimit:=lim D) [ Cone by T from c]); simpl. | |
- rewrite <- !cat_comp_assoc. | |
now rewrite (limit_universality (IsLimit:=lim d')[Cone by i :-> g i \o (lim d) i]). | |
Qed. | |
(** ** 4.3 naturality of adjunction **) | |
Program Definition prod_functor (C D C' D': Category)(F: C --> D)(F': C' --> D'): (product_category C C') --> (product_category D D') := | |
[ F \* F' with product_of_Cat]. | |
Notation "[ F 'xF' G ]" := (prod_functor F G). | |
Program Definition hom_functor (C: Category): (product_category C^op C) --> Setoids := | |
[Functor by fh :-> [ g :-> fh.2 \o{C} g \o{C} fh.1] | |
with XY :-> C XY.1 XY.2]. | |
Next Obligation. | |
now intros g g' Heq; rewrite Heq. | |
Qed. | |
Next Obligation. | |
intros f f' [Heqf1 Heqf2] g; simpl. | |
- now rewrite Heqf1, Heqf2. | |
- now rewrite !cat_comp_assoc. | |
- now rewrite cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Notation "'HomF' C" := (hom_functor C) (at level 40, no associativity). | |
Program Definition op_functor (C D: Category)(F: C --> D) | |
: C^op --> D^op := | |
[Functor by f :-> fmap F f ]. | |
Next Obligation. | |
- now apply fmap_subst. | |
- now apply fmap_comp. | |
- now apply fmap_id. | |
Qed. | |
Notation "F ^opF" := (op_functor F) (at level 0, format "F ^opF"). | |
(** | |
#$Hom_D(-,-)\circ F\times Id_D$# | |
**) | |
Definition adj_lrF (C D: Category)(F: C --> D): (product_category C^op D) --> Setoids := | |
hom_functor D \o [F^opF xF (Id D)]. | |
(** | |
#$Hom_C(-,-)\circ Id_{C^op}\times G$# | |
**) | |
Definition adj_rlF (C D: Category)(G: D --> C): (product_category C^op D) --> Setoids := | |
hom_functor C \o [(Id C^op) xF G]. | |
Program Definition adj_lr_Natrans | |
(C D: Category)(F: C --> D)(G: D --> C)(adj: F -| G) | |
: (adj_lrF F) ==> (adj_rlF G):= | |
[ cd :=> let (c,d) := cd in adj_lr adj (c:=c)(d:=d)]. | |
Next Obligation. | |
now rewrite adj_lr_naturality. | |
Qed. | |
Program Definition adj_rl_Natrans | |
(C D: Category)(F: C --> D)(G: D --> C)(adj: F -| G) | |
: (adj_rlF G) ==> (adj_lrF F):= | |
[ cd :=> let (c,d) := cd in adj_rl adj (c:=c)(d:=d)]. | |
Next Obligation. | |
now rewrite adj_rl_naturality. | |
Qed. | |
(** * 5. Kan extension **) | |
(** ** 5.1 Left Kan extension **) | |
(** *** 5.1.1 Definition **) | |
Class IsLan | |
(C D E: Category) | |
(F: C --> E)(K: C --> D) | |
(lanF: D --> E) | |
(lanN: F ==> (lanF \o K)) | |
(lanU: forall {S: D --> E}, | |
F ==> (S \o K) -> lanF ==> S) := | |
{ | |
lan_universality: | |
forall (S: D --> E)(e: F ==> (S \o K)), | |
(lanU e o> K) \o{Fun _ _} lanN == e; | |
lan_uniqueness: | |
forall (S: D --> E)(e: F ==> (S \o K))(u: lanF ==> S), | |
(u o> K) \o{Fun _ _} lanN == e -> u == lanU e | |
}. | |
Structure Lan (C D E: Category)(F: C --> E)(K: C --> D): Type := | |
{ | |
lanF: D --> E; | |
lanN: F ==> (lanF \o K); | |
lanU: forall {S: D --> E}, | |
F ==> (S \o K) -> lanF ==> S; | |
lan_prf:> IsLan lanN (@lanU) | |
}. | |
Notation "[ 'Lan' 'of' F 'along' K 'by' lanU 'with' lanF , lanN ]" := | |
(@Build_Lan _ _ _ F K lanF lanN lanU _). | |
Notation "[ 'Lan' 'by' lanU 'with' lanF , lanN ]" := | |
[Lan of _ along _ by lanU with lanF, lanN]. | |
(** *** 5.1.2 Lan and Colimit **) | |
Program Definition colimit_from_lan | |
(C D: Category) | |
(F: C --> D) | |
(lan: Lan F (ToOne C)) | |
: Colimit F := | |
[Colimit [Cocone by (lanN lan) to (lanF lan tt)] | |
by `(lanU lan (S:=constant_functor One D (c: Cocone F)) [i :=> c i] tt) ]. | |
Next Obligation. | |
rewrite (natrans_naturality (IsNatrans:=lanN lan)); simpl. | |
now rewrite (fmap_id (F:=lanF lan) tt), cat_comp_id_cod. | |
Qed. | |
Next Obligation. | |
now rewrite cocone_commute, cat_comp_id_cod. | |
Qed. | |
Next Obligation. | |
generalize (lan_universality (IsLan:=lan)(S:=[* in One |-> c in D])); simpl. | |
intros H; apply H. | |
generalize (lan_uniqueness (IsLan:=lan)(S:=[* in One |-> c in D])); simpl. | |
intros Huniq; eapply (Huniq _ [x :=> match x with | |
| tt => u | |
end | |
from (lanF lan) to [* in One |-> c in D]]); simpl. | |
now apply H. | |
Grab Existential Variables. | |
split. | |
intros [] [] []; simpl. | |
now rewrite (fmap_id (F:=lanF lan)), cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Program Definition lan_from_colimit | |
(C D: Category) | |
(F: C --> D) | |
(colim: Colimit F) | |
: Lan F (ToOne C) := | |
[Lan by (fun S (e: F ==> (S \o ToOne C)) => | |
[ x :=> match x with | |
| tt => colimit_univ colim [Cocone by e to S tt] | |
end]) | |
with [Functor by f :-> Id colim], [ c in C :=> colim c]]. | |
Next Obligation. | |
now rewrite cat_comp_id_dom. | |
Qed. | |
Next Obligation. | |
now rewrite cocone_commute, cat_comp_id_cod. | |
Qed. | |
Next Obligation. | |
rewrite (natrans_naturality (IsNatrans:=e)); simpl. | |
now rewrite (fmap_id (F:=S) tt), cat_comp_id_cod. | |
Qed. | |
Next Obligation. | |
destruct X, Y, f. | |
now rewrite cat_comp_id_dom, (fmap_id (F:=S) tt), cat_comp_id_cod. | |
Qed. | |
Next Obligation. | |
generalize (colimit_universality (IsColimit:=colim)); simpl. | |
intros H; apply (H [Cocone by e to S tt] X). | |
destruct X. | |
generalize (colimit_uniqueness (IsColimit:=colim)); intros Huniq. | |
now apply (Huniq [Cocone by e to S tt]), H. | |
Qed. | |
(** equivalence **) | |
Program Definition Cocone_setoid {J C: Category}(D: J --> C): Setoid := | |
[Setoid by `(forall i, c i =H d i) on Cocone D]. | |
Next Obligation. | |
- intros c d Heq i. | |
now apply hom_eq_sym, Heq. | |
- intros c d e Heqcd Heqde i. | |
now eapply hom_eq_trans; [apply Heqcd | apply Heqde]. | |
Qed. | |
Program Definition Colimit_setoid {J C: Category}(D: J --> C): Setoid := | |
[Setoid by `(forall c, colimit_univ colim c =H colimit_univ colim' c) on Colimit D]. | |
Next Obligation. | |
- intros c d Heq i. | |
now apply hom_eq_sym, Heq. | |
- intros c d e Heqcd Heqde i. | |
now eapply hom_eq_trans; [apply Heqcd | apply Heqde]. | |
Qed. | |
Program Definition Lan_setoid (C D E: Category)(F: C --> E)(K: C --> D) := | |
[Setoid by (fun (lan lan': Lan F K) => forall x, lanN lan x =H lanN lan' x ) on Lan F K]. | |
Next Obligation. | |
- intros lan lan' Heq c; apply hom_eq_sym, Heq. | |
- intros lan lan' lan'' Heq Heq' c. | |
now eapply hom_eq_trans; [apply Heq | apply Heq']. | |
Qed. | |
Lemma lan_from_colimit_from_lan: | |
forall (C D: Category) | |
(F: C --> D) | |
(lan: Lan F (ToOne C)), | |
lan == lan_from_colimit (colimit_from_lan lan) | |
in Lan_setoid F (ToOne C). | |
Proof. | |
now simpl. | |
Qed. | |
Lemma colimit_from_lan_from_colimit: | |
forall (C D: Category) | |
(F: C --> D) | |
(colim: Colimit F), | |
colim === colimit_from_lan (lan_from_colimit colim). | |
Proof. | |
intros; apply colimit_isomorphic. | |
Qed. | |
(** ** 5.2 Right Kan extension **) | |
(** *** 5.2.1 Definition **) | |
Class IsRan | |
(C D E: Category) | |
(F: C --> E)(K: C --> D) | |
(ranF: D --> E) | |
(ranN: (ranF \o K) ==> F) | |
(ranU: forall {S: D --> E}, | |
(S \o K) ==> F -> S ==> ranF) := | |
{ | |
ran_universality: | |
forall (S: D --> E)(e: (S \o K) ==> F), | |
ranN \o{Fun _ _} (ranU e o> K) == e; | |
ran_uniqueness: | |
forall (S: D --> E)(e: (S \o K) ==> F)(u: S ==> ranF), | |
ranN \o{Fun _ _} (u o> K) == e -> u == ranU e | |
}. | |
Structure Ran (C D E: Category)(F: C --> E)(K: C --> D): Type := | |
{ | |
ranF: D --> E; | |
ranN: (ranF \o K) ==> F; | |
ranU: forall {S: D --> E}, | |
(S \o K) ==> F -> S ==> ranF; | |
ran_prf:> IsRan ranN (@ranU) | |
}. | |
Notation "[ 'Ran' 'of' F 'along' K 'by' ranU 'with' ranF , ranN ]" := | |
(@Build_Ran _ _ _ F K ranF ranN ranU _). | |
Notation "[ 'Ran' 'of' F 'along' K 'by' ranU ]" := | |
[Ran of F along K by ranU with _, _]. | |
Notation "[ 'Ran' 'by' ranU 'with' ranF , ranN ]" := | |
[Ran of _ along _ by ranU with ranF, ranN]. | |
Notation "[ 'Ran' 'by' ranU ]" := [Ran by ranU with _,_]. | |
(** *** 5.2.2 Ran and Limit **) | |
Program Definition limit_from_ran | |
(C D: Category) | |
(F: C --> D) | |
(ran: Ran F (ToOne C)) | |
: Limit F := | |
[Limit [Cone by (ranN ran) from (ranF ran tt)] | |
by `(ranU ran (S:=[* in One |-> (c: Cone F) in D]) [i :=> c i] tt) ]. | |
Next Obligation. | |
rewrite <- (natrans_naturality (IsNatrans:=ranN ran)); simpl. | |
now rewrite (fmap_id (F:=ranF ran) tt), cat_comp_id_dom. | |
Qed. | |
Next Obligation. | |
now rewrite cone_commute, cat_comp_id_dom. | |
Qed. | |
Next Obligation. | |
generalize (ran_universality (IsRan:=ran)(S:=[* in One |-> c in D ])); simpl. | |
intros H; apply H. | |
generalize (ran_uniqueness (IsRan:=ran)(S:=[* in One |-> c in D ])); simpl. | |
intros Huniq; eapply (Huniq _ [x :=> match x with | |
| tt => u | |
end | |
from [* in One |-> c in D] to (ranF ran)]); simpl. | |
now apply H. | |
Grab Existential Variables. | |
split. | |
intros [] [] []; simpl. | |
now rewrite (fmap_id (F:=ranF ran)), cat_comp_id_dom, cat_comp_id_cod. | |
Qed. | |
Program Definition ran_from_limit | |
(C D: Category) | |
(F: C --> D) | |
(lim: Limit F) | |
: Ran F (ToOne C) := | |
[Ran by (fun S (e: (S \o ToOne C) ==> F) => | |
[ x :=> match x with | |
| tt => limit_univ lim [Cone by e from S tt] | |
end]) | |
with [Functor by f :-> Id lim], [ c in C :=> lim c]]. | |
Next Obligation. | |
now rewrite cat_comp_id_dom. | |
Qed. | |
Next Obligation. | |
now rewrite cone_commute, cat_comp_id_dom. | |
Qed. | |
Next Obligation. | |
rewrite <- (natrans_naturality (IsNatrans:=e)); simpl. | |
now rewrite (fmap_id (F:=S) tt), cat_comp_id_dom. | |
Qed. | |
Next Obligation. | |
destruct X, Y, f. | |
now rewrite cat_comp_id_cod, (fmap_id (F:=S) tt), cat_comp_id_dom. | |
Qed. | |
Next Obligation. | |
- generalize (limit_universality (IsLimit:=lim)); simpl. | |
now intros H; apply (H [Cone by e from S tt] X). | |
- destruct X. | |
generalize (limit_uniqueness (IsLimit:=lim)); intros Huniq. | |
now apply (Huniq [Cone by e from S tt]), H. | |
Qed. | |
(** ** 5.3 Adjunction and Kan extension **) | |
(** *** 5.3.1 Concepts **) | |
Class PreserveLan | |
{C D E E': Category}{F: C --> E}{K: C --> D} | |
(lan: Lan F K) | |
(L: E --> E') | |
(new: forall (S: D --> E'), | |
(L \o F) ==> (S \o K) -> | |
(L \o lanF lan) ==> S) := | |
preserve_lan: | |
IsLan (lanF:=L \o lanF lan) (Nassoc \o (L <o lanN lan)) (@new). | |
(** left adjoint preserve lan **) | |
Program Instance left_adjoint_preserve_lan | |
(C D E E': Category) | |
(F: C --> E)(K: C --> D)(lan: Lan F K) | |
(L: E --> E')(R: E' --> E)(adj: L -| R) | |
: PreserveLan | |
(fun S e => | |
[ 1 \o * ==> * ] | |
\o (adj_counit adj o> S) | |
\o Nassoc | |
\o (L <o (lanU lan | |
(Nassoc | |
\o (R <o e) | |
\o Nassoc_inv | |
\o (adj_unit adj o> F) | |
\o [ * ==> 1 \o * ])))). | |
Next Obligation. | |
- simpl; intros. | |
rewrite !cat_comp_id_cod, !cat_comp_assoc, <- fmap_comp; simpl. | |
generalize (lan_universality | |
(IsLan:=lan) | |
(Nassoc \o (R <o e) \o Nassoc_inv \o (adj_unit adj o> F) \o [ * ==> 1 \o * ]) X); simpl. | |
intro H; rewrite H; simpl. | |
rewrite cat_comp_id_cod, cat_comp_id_dom. | |
rewrite <- cat_comp_id_cod. | |
rewrite <- adj_rl_naturality. | |
rewrite fmap_id, !cat_comp_id_cod. | |
rewrite <- (cat_comp_id_dom (fmap R _ \o _)), cat_comp_assoc. | |
rewrite adj_rl_naturality. | |
now rewrite adj_iso_lr_rl, fmap_id, !cat_comp_id_dom. | |
- simpl; intros. | |
symmetry. | |
rewrite !cat_comp_id_cod, <- cat_comp_id_cod. | |
rewrite <- adj_rl_naturality. | |
rewrite fmap_id, !cat_comp_id_cod. | |
generalize (lan_uniqueness | |
(IsLan:=lan) | |
(e:=Nassoc \o (R <o e) \o Nassoc_inv \o (adj_unit adj o> F) \o Natrans_id_cod_inv F) | |
(u:=(R <o u) \o Nassoc_inv \o{Fun _ _} (adj_unit adj o> lanF lan) \o{Fun _ _} [* ==> 1 \o * ])); | |
simpl; intros Heq. | |
rewrite <- Heq. | |
+ rewrite cat_comp_id_cod. | |
rewrite adj_rl_naturality. | |
now rewrite fmap_id, cat_comp_id_dom, adj_iso_lr_rl, cat_comp_id_dom. | |
+ intros c. | |
rewrite !cat_comp_id_cod. | |
rewrite <- adj_lr_naturality. | |
rewrite cat_comp_id_cod. | |
rewrite (fmap_id (F:=L)), cat_comp_id_dom. | |
rewrite <- adj_lr_naturality. | |
rewrite (fmap_id (F:=L)), !cat_comp_id_dom. | |
rewrite <- H. | |
rewrite cat_comp_id_cod. | |
rewrite <- (cat_comp_id_cod (u (K c) \o _)). | |
rewrite (adj_lr_naturality (IsAdjunction:=adj) _ _ (u (K c))). | |
now rewrite fmap_id, cat_comp_id_cod. | |
Qed. | |
(** lan from adjunction **) | |
Program Definition lan_from_adjunction | |
(C D: Category) | |
(F: C --> D)(G: D --> C)(adj: F -| G) | |
: Lan (Id C) F := | |
[Lan by (fun S e => ([ * \o 1 ==> *] | |
\o (S <o adj_counit adj) | |
\o Nassoc_inv | |
\o (e o> G) | |
\o [* ==> 1 \o *])) | |
with G, adj_unit adj]. | |
Next Obligation. | |
rewrite <- !cat_comp_assoc. | |
rewrite <- fmap_comp, cat_comp_id_cod, !cat_comp_id_dom. | |
rewrite cat_comp_assoc. | |
generalize (natrans_naturality (IsNatrans:=e) (adj_lr adj (Id F X))); simpl; intros H; rewrite H; clear H. | |
rewrite <- cat_comp_assoc, <- fmap_comp. | |
rewrite <- (cat_comp_id_cod (adj_rl adj _ \o _)). | |
rewrite <- adj_rl_naturality. | |
rewrite !fmap_id, !cat_comp_id_cod. | |
now rewrite adj_iso_lr_rl, fmap_id, cat_comp_id_cod. | |
rewrite fmap_id, !cat_comp_id_cod, cat_comp_id_dom. | |
rewrite <- H. | |
rewrite <- cat_comp_assoc. | |
rewrite <- (natrans_naturality (IsNatrans:=u) ((adj_rl adj) (Id G X))). | |
rewrite cat_comp_assoc. | |
rewrite <- (cat_comp_id_dom (fmap G _ \o _)), cat_comp_assoc. | |
rewrite <- adj_lr_naturality, fmap_id, !cat_comp_id_dom. | |
now rewrite adj_iso_rl_lr, cat_comp_id_dom. | |
Qed. | |
(** ran from adjunction **) | |
Program Definition ran_from_adjunction | |
(C D: Category) | |
(F: C --> D)(G: D --> C)(adj: F -| G) | |
: Ran (Id D) G := | |
[Ran by (fun S e => | |
[1 \o * ==> *] | |
\o (e o> F) | |
\o Nassoc | |
\o (S <o adj_unit adj) | |
\o [* ==> * \o 1]) | |
with F, adj_counit adj]. | |
Next Obligation. | |
rewrite <- fmap_comp, !cat_comp_id_cod, !cat_comp_id_dom. | |
rewrite <- cat_comp_assoc. | |
generalize (natrans_naturality (IsNatrans:=e) (adj_rl adj (Id (G X)))); simpl; intros H; rewrite <- H; clear H. | |
rewrite cat_comp_assoc, <- fmap_comp. | |
rewrite <- (cat_comp_id_dom (_ \o adj_lr adj _)). | |
rewrite cat_comp_assoc, <- adj_lr_naturality. | |
rewrite !fmap_id, !cat_comp_id_dom. | |
now rewrite adj_iso_rl_lr, fmap_id, cat_comp_id_dom. | |
rewrite fmap_id, !cat_comp_id_cod, cat_comp_id_dom. | |
rewrite <- H. | |
rewrite cat_comp_assoc. | |
rewrite (natrans_naturality (IsNatrans:=u) (adj_lr adj (Id (F X)))). | |
rewrite <- cat_comp_assoc. | |
rewrite <- (cat_comp_id_cod (_ \o fmap F _)), <- !cat_comp_assoc. | |
rewrite (cat_comp_assoc (fmap F _)). | |
rewrite <- adj_rl_naturality, fmap_id, !cat_comp_id_cod. | |
now rewrite adj_iso_lr_rl, cat_comp_id_cod. | |
Qed. | |
(** adjunction from lan **) | |
Program Definition counit_from_lan | |
(C D: Category) | |
(F: C --> D)(G: D --> C) | |
(au: (Id C) ==> (G \o F)) | |
(luniv: forall (S: D --> C), | |
(Id C) ==> (S \o F) -> G ==> S) | |
(Hlan: IsLan (lanF:=G) au luniv) | |
(puniv: forall (S: D --> D), | |
(F \o Id C) ==> (S \o F) -> | |
(F \o G) ==> S) | |
(Hp: PreserveLan (lan:=Build_Lan Hlan)(L:=F) puniv) | |
: (F \o G) ==> (Id D) := | |
puniv (Id D) ([* ==> 1 \o *] \o Id F \o [* \o 1 ==> *]). | |
Lemma counit_from_lan_makes_triangle: | |
forall (C D: Category) | |
(F: C --> D)(G: D --> C) | |
(au: (Id C) ==> (G \o F)) | |
(luniv: forall (S: D --> C), | |
(Id C) ==> (S \o F) -> G ==> S) | |
(Hlan: IsLan (lanF:=G) au luniv) | |
(puniv: forall (S: D --> D), | |
(F \o Id C) ==> (S \o F) -> | |
(F \o G) ==> S) | |
(Hp: PreserveLan (lan:=Build_Lan Hlan)(L:=F) puniv), | |
adj_triangle au (puniv (Id D) ([* ==> 1 \o *] \o Id F \o [* \o 1 ==> *])). | |
Proof. | |
intros; split. | |
- simpl; intros c. | |
rewrite !cat_comp_id_cod, fmap_id, cat_comp_id_dom. | |
generalize (lan_universality (IsLan:=Hp) ([ * ==> 1 \o * ] \o Natrans_id F \o [ * \o 1 ==> * ]) c); simpl. | |
rewrite cat_comp_id_cod. | |
intros H; rewrite H. | |
now rewrite !cat_comp_id_cod, fmap_id. | |
- | |
generalize (lan_uniqueness (IsLan:=Hlan)(e:=au)(u:=Id G)). | |
intros H'; rewrite H'; clear H'. | |
+ apply lan_uniqueness. | |
simpl; intros c. | |
rewrite fmap_id, !cat_comp_id_cod, cat_comp_id_dom. | |
rewrite cat_comp_assoc. | |
rewrite (natrans_naturality (IsNatrans:=au) (au c)); simpl. | |
rewrite <- cat_comp_assoc, <- fmap_comp. | |
generalize (lan_universality (IsLan:=Hp) ([ * ==> 1 \o * ] \o Natrans_id F \o [ * \o 1 ==> * ]) c); simpl. | |
rewrite !cat_comp_id_cod. | |
intros H; rewrite H. | |
now rewrite !fmap_id, !cat_comp_id_cod. | |
+ now simpl; intros c; rewrite cat_comp_id_cod. | |
Qed. | |
Definition adjunction_from_lan | |
(C D: Category) | |
(F: C --> D)(G: D --> C) | |
(au: (Id C) ==> (G \o F)) | |
(luniv: forall (S: D --> C), | |
(Id C) ==> (S \o F) -> G ==> S) | |
(Hlan: IsLan (lanF:=G) au luniv) | |
(puniv: forall (S: D --> D), | |
(F \o Id C) ==> (S \o F) -> | |
(F \o G) ==> S) | |
(Hp: PreserveLan (lan:=Build_Lan Hlan)(L:=F) puniv) | |
: F -| G := | |
Adjunction_by_unit_and_counit | |
(counit_from_lan_makes_triangle Hp). | |
(** *** 5.3.2 Lan -| Inverse -| Ran **) | |
Program Definition Inverse_functor | |
(C D: Category)(K: C --> D) | |
(E: Category) | |
: (E^D) --> (E^C) := | |
[Functor by S :-> [c :=> S (K c)] with F :-> F \o K]. | |
Next Obligation. | |
now rewrite <- natrans_naturality. | |
Qed. | |
Next Obligation. | |
rename X into F, Y into G. | |
intros S T Heq c; simpl. | |
now rewrite Heq. | |
Qed. | |
Program Definition Lan_functor | |
(C D: Category)(K: C --> D) | |
(E: Category) | |
(lan: forall (F: C --> E), Lan F K) | |
: (E^C) --> (E^D) := | |
[Functor by (fun F G S => lanU (lan F) (lanN (lan G) \o S)) | |
with `(lanF (lan F))]. | |
Next Obligation. | |
- rename X into F, Y into G. | |
intros S T Heq d. | |
apply (lan_uniqueness (IsLan:=lan F)(e:=lanN (lan G) \o T)). | |
rewrite (lan_universality (IsLan:=lan F)(lanN (lan G) \o S)). | |
now simpl; intros c; rewrite Heq. | |
- rename X into F, Y into G, Z into H, f into S, g into T, X0 into d. | |
symmetry. | |
apply (lan_uniqueness (IsLan:=lan F)(e:=(lanN (lan H) \o T \o S))(u:=(lanU (lan G) (lanN (lan H) \o T))\o (lanU (lan F) (lanN (lan G) \o S)))); simpl; intros c. | |
rewrite cat_comp_assoc. | |
rewrite (lan_universality (IsLan:=lan F)(lanN (lan G) \o S) c). | |
simpl. | |
rewrite <- cat_comp_assoc. | |
rewrite (lan_universality (IsLan:=lan G)(lanN (lan H) \o T) c). | |
simpl. | |
now rewrite cat_comp_assoc. | |
- rename X into F, X0 into d. | |
symmetry. | |
apply (lan_uniqueness (IsLan:=lan F)(e:=(lanN (lan F) \o Natrans_id F))(u:=Natrans_id _)); simpl; intros c. | |
now rewrite cat_comp_id_cod, cat_comp_id_dom. | |
Qed. | |
Program Definition Ran_functor | |
(C D: Category)(K: C --> D) | |
(E: Category) | |
(ran: forall (F: C --> E), Ran F K) | |
: (E^C) --> (E^D) := | |
[Functor by (fun F G S => ranU (ran G) (S \o ranN (ran F))) | |
with `(ranF (ran F))]. | |
Next Obligation. | |
- rename X into F, Y into G. | |
intros S T Heq d. | |
apply (ran_uniqueness (IsRan:=ran G)(e:=T \o ranN (ran F))). | |
rewrite (ran_universality (IsRan:=ran G)(S \o ranN (ran F))). | |
now simpl; intros c; rewrite Heq. | |
- rename X into F, Y into G, Z into H, f into S, g into T, X0 into d. | |
symmetry. | |
apply (ran_uniqueness (IsRan:=ran H)(e:=((T \o S) \o ranN (ran F)))(u:=(ranU (ran H) (T \o ranN (ran G))) \o (ranU (ran G) (S \o ranN (ran F))))); simpl; intros c. | |
rewrite <- cat_comp_assoc. | |
rewrite (ran_universality (IsRan:=ran H)(T \o ranN (ran G)) c). | |
simpl. | |
rewrite cat_comp_assoc. | |
rewrite (ran_universality (IsRan:=ran G)(S \o ranN (ran F)) c). | |
simpl. | |
now rewrite cat_comp_assoc. | |
- rename X into F, X0 into d. | |
symmetry. | |
apply (ran_uniqueness (IsRan:=ran F)(e:=(Natrans_id F \o ranN (ran F)))(u:=Natrans_id _)); simpl; intros c. | |
now rewrite cat_comp_id_cod, cat_comp_id_dom. | |
Qed. | |
(** Lan -| Inverse **) | |
Program Definition lan_inverse_adjunction | |
(C D: Category)(K: C --> D) | |
(E: Category) | |
(lan: forall (F: C --> E), Lan F K) | |
: Lan_functor lan -| Inverse_functor K E := | |
[Adj by (fun (F: C --> E)(G: D --> E) => | |
[S in lanF (lan F) ==> G :-> | |
(S o> K) \o lanN (lan F)]), | |
(fun (F: C --> E)(G: D --> E) => | |
[S in F ==> (G \o K) :-> lanU (lan F) S]) ]. | |
Next Obligation. | |
intros S T Heq c; simpl. | |
now rewrite Heq. | |
Qed. | |
Next Obligation. | |
intros S T Heq d; simpl. | |
apply (lan_uniqueness (IsLan:=lan F)(e:= T)); simpl; intros c. | |
now rewrite (lan_universality (IsLan:=lan F) S c), Heq. | |
Qed. | |
Next Obligation. | |
- rename c into F, d into G, f into S, X into d. | |
symmetry. | |
now apply (lan_uniqueness (IsLan:=lan F)(e:=S o> K \o lanN (lan F))). | |
- rename c into F, d into G, g into T, X into c. | |
now rewrite (lan_universality (IsLan:=lan F) T c). | |
- rename c into F, c' into F', d into G, d' into G', f into S, g into T, h into U, X into c. | |
rewrite !cat_comp_assoc. | |
now rewrite (lan_universality (IsLan:=lan F') (lanN (lan F) \o S) c); simpl. | |
- rename c into F, c' into F', d into G, d' into G', f into S, g into T, h into U, X into d. | |
symmetry. | |
generalize (lan_uniqueness (IsLan:=lan F')); simpl; intros Huniq. | |
eapply (Huniq _ ([c :=> T (K c) from (G \o K) to (G' \o K)] \o U \o S) | |
(T \o (lanU (lan F) U) \o (lanU (lan F') (lanN (lan F) \o S)))); simpl; intros c. | |
rewrite !cat_comp_assoc. | |
rewrite (lan_universality (IsLan:=lan F')(lanN (lan F) \o S) c); simpl. | |
rewrite <- (cat_comp_assoc (S c)). | |
now rewrite (lan_universality (IsLan:=lan F) U c). | |
Qed. | |
(** Inverse -| Ran **) | |
Program Definition ran_inverse_adjunction | |
(C D: Category)(K: C --> D) | |
(E: Category) | |
(ran: forall (F: C --> E), Ran F K) | |
: Inverse_functor K E -| Ran_functor ran := | |
[Adj by (fun (G: D --> E)(F: C --> E) => | |
[S in (G \o K) ==> F :-> ranU (ran F) S]), | |
(fun (G: D --> E)(F: C --> E) => | |
[S in G ==> ranF (ran F) :-> ranN (ran F) \o (S o> K)])]. | |
Next Obligation. | |
intros S T Heq d; simpl. | |
apply (ran_uniqueness (IsRan:=ran F)(e:= T)); simpl; intros c. | |
now rewrite (ran_universality (IsRan:=ran F) S c), Heq. | |
Qed. | |
Next Obligation. | |
intros S T Heq c; simpl. | |
now rewrite Heq. | |
Qed. | |
Next Obligation. | |
- rename c into G, d into F, f into S, X into c. | |
now rewrite (ran_universality (IsRan:=ran F) S c). | |
- rename c into G, d into F, g into S, X into d. | |
symmetry. | |
now apply (ran_uniqueness (IsRan:=ran F)(e:=ranN (ran F) \o (S o> K))). | |
- rename d into F, d' into F', c into G, c' into G', f into T, g into S, h into U, X into d. | |
symmetry. | |
generalize (ran_uniqueness (IsRan:=ran F')); simpl; intros Huniq. | |
eapply (Huniq _ (S \o U \o [c :=> T (K c) from (_ \o _) to (_ \o _)]) | |
((ranU (ran F') (S \o ranN (ran F))) \o (ranU (ran F) U) \o T)); simpl; intros c. | |
rewrite <- !cat_comp_assoc. | |
rewrite (ran_universality (IsRan:=ran F')(S \o ranN (ran F)) c); simpl. | |
rewrite (cat_comp_assoc _ _ (S c)). | |
now rewrite (ran_universality (IsRan:=ran F) U c). | |
- rename d into F, d' into F', c into G, c' into G', f into T, g into S, h into U, X into d. | |
rewrite <- !cat_comp_assoc. | |
now rewrite (ran_universality (IsRan:=ran F') (S \o ranN (ran F)) d); simpl. | |
Qed. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment