chapter \The identity type\ text \ The identity type, the higher groupoid structure of types, and type families as fibrations. \ theory Identity imports Spartan begin axiomatization Id :: \o \ o \ o \ o\ and refl :: \o \ o\ and IdInd :: \o \ (o \ o \ o \ o) \ (o \ o) \ o \ o \ o \ o\ syntax "_Id" :: \o \ o \ o \ o\ ("(2_ =\<^bsub>_\<^esub>/ _)" [111, 0, 111] 110) translations "a =\<^bsub>A\<^esub> b" \ "CONST Id A a b" axiomatization where \ \Here `A: U i` comes last because A is often implicit\ IdF: "\a: A; b: A; A: U i\ \ a =\<^bsub>A\<^esub> b: U i" and IdI: "a: A \ refl a: a =\<^bsub>A\<^esub> a" and IdE: "\ p: a =\<^bsub>A\<^esub> b; a: A; b: A; \x y p. \p: x =\<^bsub>A\<^esub> y; x: A; y: A\ \ C x y p: U i; \x. x: A \ f x: C x x (refl x) \ \ IdInd A (fn x y p. C x y p) (fn x. f x) a b p: C a b p" and Id_comp: "\ a: A; \x y p. \x: A; y: A; p: x =\<^bsub>A\<^esub> y\ \ C x y p: U i; \x. x: A \ f x: C x x (refl x) \ \ IdInd A (fn x y p. C x y p) (fn x. f x) a a (refl a) \ f a" lemmas [form] = IdF and [intro, intros] = IdI and [elim "?p" "?a" "?b"] = IdE and [comp] = Id_comp and [refl] = IdI section \Path induction\ \ \With `p: x = y` in the context the invokation `eq p` is essentially `elim p x y`, with some extra bits before and after.\ method_setup eq = \Args.term >> (fn tm => K (CONTEXT_METHOD ( CHEADGOAL o SIDE_CONDS ( CONTEXT_SUBGOAL (fn (goal, i) => fn cst as (ctxt, st) => let val facts = Proof_Context.facts_of ctxt val prems = Logic.strip_assums_hyp goal val template = \<^const>\has_type\ $ tm $ (\<^const>\Id\ $ Var (("*?A", 0), \<^typ>\o\) $ Var (("*?x", 0), \<^typ>\o\) $ Var (("*?y", 0), \<^typ>\o\)) val types = map (Thm.prop_of o #1) (Facts.could_unify facts template) @ filter (fn prem => Term.could_unify (template, prem)) prems |> map Lib.type_of_typing in case types of (Const (\<^const_name>\Id\, _) $ _ $ x $ y) :: _ => elim_ctac [tm, x, y] i cst | _ => no_ctac cst end)))))\ section \Symmetry and transitivity\ Lemma (derive) pathinv: assumes "A: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "y =\<^bsub>A\<^esub> x" by (eq p) intro lemma pathinv_comp [comp]: assumes "x: A" "A: U i" shows "pathinv A x x (refl x) \ refl x" unfolding pathinv_def by reduce Lemma (derive) pathcomp: assumes "A: U i" "x: A" "y: A" "z: A" "p: x =\<^bsub>A\<^esub> y" "q: y =\<^bsub>A\<^esub> z" shows "x =\<^bsub>A\<^esub> z" apply (eq p) focus prems vars x p apply (eq p) apply intro done done lemma pathcomp_comp [comp]: assumes "a: A" "A: U i" shows "pathcomp A a a a (refl a) (refl a) \ refl a" unfolding pathcomp_def by reduce section \Notation\ definition Id_i (infix "=" 110) where [implicit]: "Id_i x y \ x =\<^bsub>?\<^esub> y" definition pathinv_i ("_\" [1000]) where [implicit]: "pathinv_i p \ pathinv ? ? ? p" definition pathcomp_i (infixl "\" 121) where [implicit]: "pathcomp_i p q \ pathcomp ? ? ? ? p q" translations "x = y" \ "x =\<^bsub>A\<^esub> y" "p\" \ "CONST pathinv A x y p" "p \ q" \ "CONST pathcomp A x y z p q" section \Calculational reasoning\ congruence "x = y" rhs y lemmas [sym] = pathinv[rotated 3] and [trans] = pathcomp[rotated 4] section \Basic propositional equalities\ Lemma (derive) refl_pathcomp: assumes "A: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "(refl x) \ p = p" apply (eq p) apply (reduce; intro) done Lemma (derive) pathcomp_refl: assumes "A: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "p \ (refl y) = p" apply (eq p) apply (reduce; intro) done definition [implicit]: "ru p \ pathcomp_refl ? ? ? p" definition [implicit]: "lu p \ refl_pathcomp ? ? ? p" translations "CONST ru p" \ "CONST pathcomp_refl A x y p" "CONST lu p" \ "CONST refl_pathcomp A x y p" Lemma lu_refl [comp]: assumes "A: U i" "x: A" shows "lu (refl x) \ refl (refl x)" unfolding refl_pathcomp_def by reduce Lemma ru_refl [comp]: assumes "A: U i" "x: A" shows "ru (refl x) \ refl (refl x)" unfolding pathcomp_refl_def by reduce Lemma (derive) inv_pathcomp: assumes "A: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "p\ \ p = refl y" by (eq p) (reduce; intro) Lemma (derive) pathcomp_inv: assumes "A: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "p \ p\ = refl x" by (eq p) (reduce; intro) Lemma (derive) pathinv_pathinv: assumes "A: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "p\\ = p" by (eq p) (reduce; intro) Lemma (derive) pathcomp_assoc: assumes "A: U i" "x: A" "y: A" "z: A" "w: A" "p: x =\<^bsub>A\<^esub> y" "q: y =\<^bsub>A\<^esub> z" "r: z =\<^bsub>A\<^esub> w" shows "p \ (q \ r) = p \ q \ r" apply (eq p) focus prems vars x p apply (eq p) focus prems vars x p apply (eq p) apply (reduce; intro) done done done section \Functoriality of functions\ Lemma (derive) ap: assumes "A: U i" "B: U i" "x: A" "y: A" "f: A \ B" "p: x =\<^bsub>A\<^esub> y" shows "f x = f y" by (eq p) intro definition ap_i ("_[_]" [1000, 0]) where [implicit]: "ap_i f p \ ap ? ? ? ? f p" translations "f[p]" \ "CONST ap A B x y f p" Lemma ap_refl [comp]: assumes "f: A \ B" "x: A" "A: U i" "B: U i" shows "f[refl x] \ refl (f x)" unfolding ap_def by reduce Lemma (derive) ap_pathcomp: assumes "A: U i" "B: U i" "x: A" "y: A" "z: A" "f: A \ B" "p: x =\<^bsub>A\<^esub> y" "q: y =\<^bsub>A\<^esub> z" shows "f[p \ q] = f[p] \ f[q]" apply (eq p) focus prems vars x p apply (eq p) apply (reduce; intro) done done Lemma (derive) ap_pathinv: assumes "A: U i" "B: U i" "x: A" "y: A" "f: A \ B" "p: x =\<^bsub>A\<^esub> y" shows "f[p\] = f[p]\" by (eq p) (reduce; intro) text \The next two proofs currently use some low-level rewriting.\ Lemma (derive) ap_funcomp: assumes "A: U i" "B: U i" "C: U i" "x: A" "y: A" "f: A \ B" "g: B \ C" "p: x =\<^bsub>A\<^esub> y" shows "(g \ f)[p] = g[f[p]]" apply (eq p) \ by reduce \ by reduce intro done Lemma (derive) ap_id: assumes "A: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "(id A)[p] = p" apply (eq p) \ by reduce \ by reduce intro done section \Transport\ Lemma (derive) transport: assumes "A: U i" "\x. x: A \ P x: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "P x \ P y" by (eq p) intro definition transport_i ("trans") where [implicit]: "trans P p \ transport ? P ? ? p" translations "trans P p" \ "CONST transport A P x y p" Lemma transport_comp [comp]: assumes "a: A" "A: U i" "\x. x: A \ P x: U i" shows "trans P (refl a) \ id (P a)" unfolding transport_def by reduce \ \TODO: Build transport automation!\ Lemma use_transport: assumes "p: y =\<^bsub>A\<^esub> x" "u: P x" "x: A" "y: A" "A: U i" "\x. x: A \ P x: U i" shows "trans P p\ u: P y" unfolding transport_def pathinv_def by typechk method transport uses eq = (rule use_transport[OF eq]) Lemma (derive) transport_left_inv: assumes "A: U i" "\x. x: A \ P x: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "(trans P p\) \ (trans P p) = id (P x)" by (eq p) (reduce; refl) Lemma (derive) transport_right_inv: assumes "A: U i" "\x. x: A \ P x: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "(trans P p) \ (trans P p\) = id (P y)" by (eq p) (reduce; intro) Lemma (derive) transport_pathcomp: assumes "A: U i" "\x. x: A \ P x: U i" "x: A" "y: A" "z: A" "u: P x" "p: x =\<^bsub>A\<^esub> y" "q: y =\<^bsub>A\<^esub> z" shows "trans P q (trans P p u) = trans P (p \ q) u" apply (eq p) focus prems vars x p apply (eq p) apply (reduce; intro) done done Lemma (derive) transport_compose_typefam: assumes "A: U i" "B: U i" "\x. x: B \ P x: U i" "f: A \ B" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" "u: P (f x)" shows "trans (fn x. P (f x)) p u = trans P f[p] u" by (eq p) (reduce; intro) Lemma (derive) transport_function_family: assumes "A: U i" "\x. x: A \ P x: U i" "\x. x: A \ Q x: U i" "f: \x: A. P x \ Q x" "x: A" "y: A" "u: P x" "p: x =\<^bsub>A\<^esub> y" shows "trans Q p ((f x) u) = (f y) (trans P p u)" by (eq p) (reduce; intro) Lemma (derive) transport_const: assumes "A: U i" "B: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "\b: B. trans (fn _. B) p b = b" by (intro, eq p) (reduce; intro) definition transport_const_i ("trans'_const") where [implicit]: "trans_const B p \ transport_const ? B ? ? p" translations "trans_const B p" \ "CONST transport_const A B x y p" Lemma transport_const_comp [comp]: assumes "x: A" "b: B" "A: U i" "B: U i" shows "trans_const B (refl x) b\ refl b" unfolding transport_const_def by reduce Lemma (derive) pathlift: assumes "A: U i" "\x. x: A \ P x: U i" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" "u: P x" shows " = " by (eq p) (reduce; intro) definition pathlift_i ("lift") where [implicit]: "lift P p u \ pathlift ? P ? ? p u" translations "lift P p u" \ "CONST pathlift A P x y p u" Lemma pathlift_comp [comp]: assumes "u: P x" "x: A" "\x. x: A \ P x: U i" "A: U i" shows "lift P (refl x) u \ refl " unfolding pathlift_def by reduce Lemma (derive) pathlift_fst: assumes "A: U i" "\x. x: A \ P x: U i" "x: A" "y: A" "u: P x" "p: x =\<^bsub>A\<^esub> y" shows "fst[lift P p u] = p" apply (eq p) \ by reduce \ by reduce intro done section \Dependent paths\ Lemma (derive) apd: assumes "A: U i" "\x. x: A \ P x: U i" "f: \x: A. P x" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "trans P p (f x) = f y" by (eq p) (reduce; intro) definition apd_i ("apd") where [implicit]: "apd f p \ Identity.apd ? ? f ? ? p" translations "apd f p" \ "CONST Identity.apd A P f x y p" Lemma dependent_map_comp [comp]: assumes "f: \x: A. P x" "x: A" "A: U i" "\x. x: A \ P x: U i" shows "apd f (refl x) \ refl (f x)" unfolding apd_def by reduce Lemma (derive) apd_ap: assumes "A: U i" "B: U i" "f: A \ B" "x: A" "y: A" "p: x =\<^bsub>A\<^esub> y" shows "apd f p = trans_const B p (f x) \ f[p]" by (eq p) (reduce; intro) section \Whiskering\ Lemma (derive) right_whisker: assumes "A: U i" "a: A" "b: A" "c: A" shows "\p: a = b; q: a = b; r: b = c; \: p =\<^bsub>a = b\<^esub> q\ \ p \ r = q \ r" \ \TODO: In the above we need to annotate the type of \ with the type `a = b` in order for the `eq` method to work correctly. This should be fixed with a pre-proof elaborator.\ apply (eq r) focus prems vars x s t proof - have "t \ refl x = t" by (rule pathcomp_refl) also have ".. = s" by fact also have ".. = s \ refl x" by (rule pathcomp_refl[symmetric]) finally show "{}" by this qed done Lemma (derive) left_whisker: assumes "A: U i" "a: A" "b: A" "c: A" shows "\p: b = c; q: b = c; r: a = b; \: p =\<^bsub>b = c\<^esub> q\ \ r \ p = r \ q" apply (eq r) focus prems prms vars x s t proof - have "refl x \ t = t" by (rule refl_pathcomp) also have ".. = s" by fact also have ".. = refl x \ s" by (rule refl_pathcomp[symmetric]) finally show "{}" by this qed done definition right_whisker_i (infix "\\<^sub>r\<^bsub>_\<^esub>" 121) where [implicit]: "\ \\<^sub>r\<^bsub>a\<^esub> r \ right_whisker ? a ? ? ? ? r \" definition left_whisker_i (infix "\\<^sub>l\<^bsub>_\<^esub>" 121) where [implicit]: "r \\<^sub>l\<^bsub>c\<^esub> \ \ left_whisker ? ? ? c ? ? r \" translations "\ \\<^sub>r\<^bsub>a\<^esub> r" \ "CONST right_whisker A a b c p q r \" "r \\<^sub>l\<^bsub>c\<^esub> \" \ "CONST left_whisker A a b c p q r \" Lemma whisker_refl [comp]: assumes "A: U i" "a: A" "b: A" shows "\p: a = b; q: a = b; \: p =\<^bsub>a = b\<^esub> q\ \ \ \\<^sub>r\<^bsub>a\<^esub> (refl b) \ ru p \ \ \ (ru q)\" unfolding right_whisker_def by reduce Lemma refl_whisker [comp]: assumes "A: U i" "a: A" "b: A" shows "\p: a = b; q: a = b; \: p = q\ \ (refl a) \\<^sub>l\<^bsub>b\<^esub> \ \ (lu p) \ \ \ (lu q)\" unfolding left_whisker_def by reduce method left_whisker = (rule left_whisker) method right_whisker = (rule right_whisker) section \Horizontal path-composition\ text \Conditions under which horizontal path-composition is defined.\ locale horiz_pathcomposable = fixes i A a b c p q r s assumes assums: "A: U i" "a: A" "b: A" "c: A" "p: a =\<^bsub>A\<^esub> b" "q: a =\<^bsub>A\<^esub> b" "r: b =\<^bsub>A\<^esub> c" "s: b =\<^bsub>A\<^esub> c" begin Lemma (derive) horiz_pathcomp: notes assums shows "\\: p = q; \: r = s\ \ ?prf \ \: p \ r = q \ s" proof (rule pathcomp) show "\: p = q \ p \ r = q \ r" by right_whisker show "\: r = s \ .. = q \ s" by left_whisker qed typechk text \A second horizontal composition:\ Lemma (derive) horiz_pathcomp': notes assums shows "\\: p = q; \: r = s\ \ ?prf \ \: p \ r = q \ s" proof (rule pathcomp) show "\: r = s \ p \ r = p \ s" by left_whisker show "\: p = q \ .. = q \ s" by right_whisker qed typechk notation horiz_pathcomp (infix "\" 121) notation horiz_pathcomp' (infix "\''" 121) Lemma (derive) horiz_pathcomp_eq_horiz_pathcomp': notes assums shows "\\: p = q; \: r = s\ \ \ \ \ = \ \' \" unfolding horiz_pathcomp_def horiz_pathcomp'_def apply (eq \, eq \) focus vars p apply (eq p) focus vars _ q by (eq q) (reduce; refl) done done end section \Loop space\ definition \ where "\ A a \ a =\<^bsub>A\<^esub> a" definition \2 where "\2 A a \ \ (\ A a) (refl a)" Lemma \2_alt_def: "\2 A a \ refl a = refl a" unfolding \2_def \_def . section \Eckmann-Hilton\ context fixes i A a assumes "A: U i" "a: A" begin interpretation \2: horiz_pathcomposable i A a a a "refl a" "refl a" "refl a" "refl a" by unfold_locales typechk+ notation \2.horiz_pathcomp (infix "\" 121) notation \2.horiz_pathcomp' (infix "\''" 121) Lemma (derive) pathcomp_eq_horiz_pathcomp: assumes "\: \2 A a" "\: \2 A a" shows "\ \ \ = \ \ \" unfolding \2.horiz_pathcomp_def using assms[unfolded \2_alt_def] proof (reduce, rule pathinv) \ \Propositional equality rewriting needs to be improved\ have "{} = refl (refl a) \ \" by (rule pathcomp_refl) also have ".. = \" by (rule refl_pathcomp) finally have eq\: "{} = \" by this have "{} = refl (refl a) \ \" by (rule pathcomp_refl) also have ".. = \" by (rule refl_pathcomp) finally have eq\: "{} = \" by this have "refl (refl a) \ \ \ refl (refl a) \ (refl (refl a) \ \ \ refl (refl a)) = \ \ {}" by right_whisker (rule eq\) also have ".. = \ \ \" by left_whisker (rule eq\) finally show "{} = \ \ \" by this qed Lemma (derive) pathcomp_eq_horiz_pathcomp': assumes "\: \2 A a" "\: \2 A a" shows "\ \' \ = \ \ \" unfolding \2.horiz_pathcomp'_def using assms[unfolded \2_alt_def] proof reduce have "{} = refl (refl a) \ \" by (rule pathcomp_refl) also have ".. = \" by (rule refl_pathcomp) finally have eq\: "{} = \" by this have "{} = refl (refl a) \ \" by (rule pathcomp_refl) also have ".. = \" by (rule refl_pathcomp) finally have eq\: "{} = \" by this have "refl (refl a) \ \ \ refl (refl a) \ (refl (refl a) \ \ \ refl (refl a)) = \ \ {}" by right_whisker (rule eq\) also have ".. = \ \ \" by left_whisker (rule eq\) finally show "{} = \ \ \" by this qed Lemma (derive) eckmann_hilton: assumes "\: \2 A a" "\: \2 A a" shows "\ \ \ = \ \ \" using assms[unfolded \2_alt_def] proof - have "\ \ \ = \ \ \" by (rule pathcomp_eq_horiz_pathcomp) also have [simplified comp]: ".. = \ \' \" by (transport eq: \2.horiz_pathcomp_eq_horiz_pathcomp') refl also have ".. = \ \ \" by (rule pathcomp_eq_horiz_pathcomp') finally show "\ \ \ = \ \ \" by this (reduce add: \2.horiz_pathcomp_def \2.horiz_pathcomp'_def)+ qed end end