From a5b6b3bfd85e165c9de8272a911e0eb21e7e9d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20van=20Br=C3=BCgge?= Date: Sun, 14 Feb 2021 13:26:51 +0100 Subject: [PATCH 1/8] Add case expression syntax --- Syntax.thy | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Syntax.thy b/Syntax.thy index 837495b..9be28e7 100644 --- a/Syntax.thy +++ b/Syntax.thy @@ -41,6 +41,13 @@ nominal_datatype "term" = | Lam x::"var" "\" e::"term" binds x in e ("\ _ : _ . _" 50) | TyLam a::"tyvar" "\" e::"term" binds a in e ("\ _ : _ . _" 50) | Let x::"var" "\" "term" e2::"term" binds x in e2 + | Case "term" "alt_list" +and "alt_list" = + ANil +| ACons "alt" "alt_list" +and "alt" = + MatchCtor "ctor_name" tys::"tyvar list" vals::"var list" e::"term" binds tys vals in e +| MatchVar x::"var" e::"term" binds x in e nominal_datatype "binder" = BVar "var" "\" From faf1953d25c3f37a6f11650eee765bfc7bfea638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20van=20Br=C3=BCgge?= Date: Sun, 14 Feb 2021 14:58:38 +0100 Subject: [PATCH 2/8] Adjust substitution functions --- Defs.thy | 206 ++++++++++++++++++++++++++++++++++++-------- Nominal2_Lemmas.thy | 17 ++++ 2 files changed, 187 insertions(+), 36 deletions(-) diff --git a/Defs.thy b/Defs.thy index 64e5533..0e27a8b 100644 --- a/Defs.thy +++ b/Defs.thy @@ -35,9 +35,10 @@ nominal_function head_ctor :: "term \ bool" where | "head_ctor (TApp e _) = head_ctor e" | "head_ctor (Ctor _) = True" | "head_ctor (Let _ _ _ _) = False" +| "head_ctor (Case _ _) = False" proof goal_cases case (3 P x) - then show ?case by (cases x rule: term.exhaust) + then show ?case by (cases x rule: term_alt_list_alt.exhaust(1)) qed (auto simp: eqvt_def head_ctor_graph_aux_def) nominal_termination (eqvt) by lexicographic_order @@ -170,44 +171,111 @@ nominal_function is_value :: "term => bool" where | "is_value (TApp e \) = head_ctor e" | "is_value (Ctor _) = True" | "is_value (Let x \ e1 e2) = False" +| "is_value (Case _ _) = False" proof goal_cases case (3 P x) - then show ?case by (cases x rule: term.exhaust) + then show ?case by (cases x rule: term_alt_list_alt.exhaust(1)) next - case (17 a k e a' k' e') + case (19 a k e a' k' e') obtain c::tyvar where c: "atom c \ (a, e, a', e')" by (rule obtain_fresh) have 1: "is_value_sumC e' = (a' \ c) \ is_value_sumC e'" using permute_boolE permute_boolI by blast have 2: "is_value_sumC e = (a \ c) \ is_value_sumC e" using permute_boolE permute_boolI by blast - from c have "(a \ c) \ e = (a' \ c) \ e'" using 17(5) by simp - then show ?case using 1 2 17(1,2) eqvt_at_def by metis + from c have "(a \ c) \ e = (a' \ c) \ e'" using 19(5) by simp + then show ?case using 1 2 19(1,2) eqvt_at_def by metis qed (auto simp: eqvt_def is_value_graph_aux_def) nominal_termination (eqvt) by lexicographic_order -nominal_function subst_term :: "term => term \ var => term" where +nominal_function (default "case_sum (\x. Inl undefined) (case_sum (\x. Inr (Inl undefined)) (\x. Inr (Inr undefined)))") + subst_term :: "term => term \ var => term" and + subst_alt_list :: "alt_list \ term \ var \ alt_list" and + subst_alt :: "alt \ term \ var \ alt" where + "subst_term (Var y) e x = (if x = y then e else Var y)" | "subst_term (App e1 e2) e x = App (subst_term e1 e x) (subst_term e2 e x)" | "subst_term (TApp e1 \) e x = TApp (subst_term e1 e x) \" | "subst_term (Ctor D) _ _ = Ctor D" +| "subst_term (Case t alts) e x = Case (subst_term t e x) (subst_alt_list alts e x)" | "atom y \ (e, x) \ subst_term (\ y:\. e2) e x = (\ y:\. subst_term e2 e x)" | "atom y \ (e, x) \ subst_term (\ y:k. e2) e x = (\ y:k. subst_term e2 e x)" | "atom y \ (e, x) \ subst_term (Let y \ e1 e2) e x = Let y \ (subst_term e1 e x) (subst_term e2 e x)" + +| "subst_alt_list ANil _ _ = ANil" +| "subst_alt_list (ACons alt alts) e x = ACons (subst_alt alt e x) (subst_alt_list alts e x)" + +| "atom y \ (e, x) \ subst_alt (MatchVar y t) e x = MatchVar y (subst_term t e x)" +| "set (map atom tys @ map atom vals) \* (e, x) \ subst_alt (MatchCtor D tys vals t) e x = MatchCtor D tys vals (subst_term t e x)" proof (goal_cases) - case (3 P x) - then obtain t e y where P: "x = (t, e, y)" by (metis prod.exhaust) + + (* this is adapted and simplified from here: https://www.joachim-breitner.de/thesis/isa/Substitution.thy *) + have eqvt_at_term: "\e y z . eqvt_at subst_term_subst_alt_list_subst_alt_sumC (Inl (e, y, z)) \ eqvt_at (\(a, b, c). subst_term a b c) (e, y, z)" + apply (simp add: eqvt_at_def subst_term_def) + apply rule + apply (subst Projl_permute) + apply (simp add: subst_term_subst_alt_list_subst_alt_sumC_def) + apply (simp add: THE_default_def) + apply (case_tac "Ex1 (subst_term_subst_alt_list_subst_alt_graph (Inl (e, y, z)))") + apply(auto)[2] + apply (erule_tac x="x" in allE) + apply simp + apply(cases rule: subst_term_subst_alt_list_subst_alt_graph.cases) + apply(assumption) + apply blast+ + apply simp + done + +{ case (3 P x) then show ?case - apply (cases t rule: term.strong_exhaust[of _ _ "(e, y)"]) - apply (auto simp: 3) - using 3(5-7) P fresh_star_def by blast+ + proof (cases x) + case (Inl a) + then obtain t e y where P: "a = (t, e, y)" by (metis prod.exhaust) + then show ?thesis using 3(1-5) Inl + proof (cases t rule: term_alt_list_alt.strong_exhaust(1)[of _ _ "(e, y)"]) + case Lam + then show ?thesis using 3(6) Inl P fresh_star_insert by blast + next + case TyLam + then show ?thesis using 3(7) Inl P fresh_star_insert by blast + next + case Let + then show ?thesis using 3(8) Inl P fresh_star_insert by blast + qed auto + next + case outer: (Inr b) + then show ?thesis + proof (cases b) + case (Inl a) + then obtain xs e y where "a = (xs, e, y)" by (metis prod.exhaust) + then show ?thesis using 3(9,10) Inl outer by (cases xs rule: term_alt_list_alt.exhaust(2)) auto + next + case (Inr c) + then obtain m e y where "c = (m, e, y)" by (metis prod.exhaust) + then show ?thesis using 3(11,12) Inr outer fresh_star_insert + apply (cases m rule: term_alt_list_alt.strong_exhaust(3)[of "(e, y)"]) + apply auto + by blast + qed + qed +next + case (54 y e x \ e2 y' e' x' \' e2') + have "(\ y : \ . subst_term e2 e x) = (\ y' : \' . subst_term e2' e' x')" using Abs_sumC[OF 54(5,6) eqvt_at_term[OF 54(1)] eqvt_at_term[OF 54(2)]] 54(7) by fastforce + then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_def, symmetric, unfolded fun_eq_iff]) next - case (26 y e x \ e2 y' e' x' \' e2') - then show ?case using Abs_sumC[OF 26(5,6,1,2)] by fastforce + case (61 y e x k e2 y' e' x' k' e2') + have "(\ y : k . subst_term e2 e x) = (\ y' : k' . subst_term e2' e' x')" using Abs_sumC[OF 61(5,6) eqvt_at_term[OF 61(1)] eqvt_at_term[OF 61(2)]] 61(7) by fastforce + then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_def, symmetric, unfolded fun_eq_iff]) next - case (29 y e x k e2 y' e' x' k' e2') - then show ?case using Abs_sumC[OF 29(5,6,1,2)] by fastforce + case (67 y e x \ e1 e2 y' e' x' \' e1' e2') + have "Let y \ (subst_term e1 e x) (subst_term e2 e x) = Let y' \' (subst_term e1' e' x') (subst_term e2' e' x')" using Abs_sumC[OF 67(9,10) eqvt_at_term[OF 67(2)] eqvt_at_term[OF 67(4)]] 67(11) by fastforce + then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_def, symmetric, unfolded fun_eq_iff]) next - case (31 y e x \ e1 e2 y' e' x' \' e1' e2') - then show ?case using Abs_sumC[OF 31(9,10,2,4)] by fastforce -qed (auto simp: eqvt_def subst_term_graph_aux_def) + case (79 y e x t y' e' x' t') + have "MatchVar y (subst_term t e x) = MatchVar y' (subst_term t' e' x')" using Abs_sumC[OF 79(5,6) eqvt_at_term[OF 79(1)] eqvt_at_term[OF 79(2)]] 79(7) by fastforce + then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_def, symmetric, unfolded fun_eq_iff]) +next + case (81 tys vals e x D t tys' vals' e' x' D' t') + have "MatchCtor D tys vals (subst_term t e x) = MatchCtor D' tys' vals' (subst_term t' e' x')" using Abs_sumC_star[OF 81(5,6) eqvt_at_term[OF 81(1)] eqvt_at_term[OF 81(2)]] 81(7) by fastforce + then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_def, symmetric, unfolded fun_eq_iff]) +} qed (auto simp: eqvt_def subst_term_subst_alt_list_subst_alt_graph_aux_def) nominal_termination (eqvt) by lexicographic_order nominal_function subst_type :: "\ \ \ \ tyvar \ \" where @@ -219,41 +287,107 @@ nominal_function subst_type :: "\ \ \ \ tyvar proof goal_cases case (3 P x) then obtain t \ a where P: "x = (t, \, a)" by (metis prod.exhaust) - then show ?case - apply (cases t rule: \.strong_exhaust[of _ _ "(\, a)"]) - apply (auto simp: 3) - using 3(5) P fresh_star_def by blast + then show ?case proof(cases t rule: \.strong_exhaust[of _ _ "(\, a)"]) + case (TyForall x51 x52 x53) + then show ?thesis using 3(5) P fresh_star_def by blast + qed (auto simp: 3) next case (18 b \ a k \ b' \' a' k' \') then show ?case using Abs_sumC[OF 18(5,6,1,2)] by fastforce qed (auto simp: eqvt_def subst_type_graph_aux_def) nominal_termination (eqvt) by lexicographic_order -nominal_function subst_term_type :: "term \ \ \ tyvar \ term" where +nominal_function (default "case_sum (\x. Inl undefined) (case_sum (\x. Inr (Inl undefined)) (\x. Inr (Inr undefined)))") + subst_term_type :: "term \ \ \ tyvar \ term" and + subst_alt_list_type :: "alt_list \ \ \ tyvar \ alt_list" and + subst_alt_type :: "alt \ \ \ tyvar \ alt" where + "subst_term_type (Var x) _ _ = Var x" | "subst_term_type (Ctor D) _ _ = Ctor D" | "subst_term_type (App e1 e2) \ a = App (subst_term_type e1 \ a) (subst_term_type e2 \ a)" | "subst_term_type (TApp e \2) \ a = TApp (subst_term_type e \ a) (subst_type \2 \ a)" +| "subst_term_type (Case e alts) \ a = Case (subst_term_type e \ a) (subst_alt_list_type alts \ a)" | "atom y \ (\, a) \ subst_term_type (\ y:\'. e2) \ a = (\ y:(subst_type \' \ a). subst_term_type e2 \ a)" | "atom b \ (\, a) \ subst_term_type (\ b:k. e2) \ a = (\ b:k. subst_term_type e2 \ a)" | "atom y \ (\, a) \ subst_term_type (Let y \' e1 e2) \ a = Let y (subst_type \' \ a) (subst_term_type e1 \ a) (subst_term_type e2 \ a)" + +| "subst_alt_list_type ANil _ _ = ANil" +| "subst_alt_list_type (ACons alt alts) \ a = ACons (subst_alt_type alt \ a) (subst_alt_list_type alts \ a)" + +| "atom y \ (\, a) \ subst_alt_type (MatchVar y e) \ a = MatchVar y (subst_term_type e \ a)" +| "set (map atom tys @ map atom vals) \* (\, a) \ subst_alt_type (MatchCtor D tys vals e) \ a = MatchCtor D tys vals (subst_term_type e \ a)" proof goal_cases - case (3 P x) - then obtain t \ a where P: "x = (t, \, a)" by (metis prod.exhaust) + + (* this is adapted and simplified from here: https://www.joachim-breitner.de/thesis/isa/Substitution.thy *) + have eqvt_at_term: "\e y z . eqvt_at subst_term_type_subst_alt_list_type_subst_alt_type_sumC (Inl (e, y, z)) \ eqvt_at (\(a, b, c). subst_term_type a b c) (e, y, z)" + apply (simp add: eqvt_at_def subst_term_type_def) + apply rule + apply (subst Projl_permute) + apply (simp add: subst_term_type_subst_alt_list_type_subst_alt_type_sumC_def) + apply (simp add: THE_default_def) + apply (case_tac "Ex1 (subst_term_type_subst_alt_list_type_subst_alt_type_graph (Inl (e, y, z)))") + apply(auto)[2] + apply (erule_tac x="x" in allE) + apply simp + apply(cases rule: subst_term_type_subst_alt_list_type_subst_alt_type_graph.cases) + apply(assumption) + apply blast+ + apply simp + done + +{ case (3 P x) then show ?case - apply (cases t rule: term.strong_exhaust[of _ _ "(\, a)"]) - using 3 P apply auto[4] - using 3(5,6,7) P fresh_star_def by blast+ + proof (cases x) + case (Inl a) + then obtain t e y where P: "a = (t, e, y)" by (metis prod.exhaust) + then show ?thesis using 3(1-5) Inl + proof (cases t rule: term_alt_list_alt.strong_exhaust(1)[of _ _ "(e, y)"]) + case Lam + then show ?thesis using 3(6) Inl P fresh_star_insert by blast + next + case TyLam + then show ?thesis using 3(7) Inl P fresh_star_insert by blast + next + case Let + then show ?thesis using 3(8) Inl P fresh_star_insert by blast + qed auto + next + case outer: (Inr b) + then show ?thesis + proof (cases b) + case (Inl a) + then obtain xs e y where "a = (xs, e, y)" by (metis prod.exhaust) + then show ?thesis using 3(9,10) Inl outer by (cases xs rule: term_alt_list_alt.exhaust(2)) auto + next + case (Inr c) + then obtain m e y where P: "c = (m, e, y)" by (metis prod.exhaust) + then show ?thesis using Inr outer 3(11,12) + apply (cases m rule: term_alt_list_alt.strong_exhaust(3)[of "(e, y)"]) apply simp + using fresh_star_insert by blast + qed + qed +next + case (54 y \ a \2 e2 y' \' a' \2' e2') + have "(\ y : subst_type \2 \ a . subst_term_type e2 \ a) = (\ y' : subst_type \2' \' a' . subst_term_type e2' \' a')" using Abs_sumC[OF 54(5,6) eqvt_at_term[OF 54(1)] eqvt_at_term[OF 54(2)]] 54(7) by fastforce + then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_type_def, symmetric, unfolded fun_eq_iff]) +next + case (61 b \ a k e2 b' \' a' k' e2') + have "(\ b : k . subst_term_type e2 \ a) = (\ b' : k' . subst_term_type e2' \' a')" using Abs_sumC[OF 61(5,6) eqvt_at_term[OF 61(1)] eqvt_at_term[OF 61(2)]] 61(7) by fastforce + then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_type_def, symmetric, unfolded fun_eq_iff]) next - case (26 y \ a \1 e2 y' \' a' \1' e2') - then show ?case using Abs_sumC[OF 26(5,6,1,2)] by fastforce + case (67 y \ a \2 e1 e2 y' \' a' \2' e1' e2') + have "Let y (subst_type \2 \ a) (subst_term_type e1 \ a) (subst_term_type e2 \ a) = Let y' (subst_type \2' \' a') (subst_term_type e1' \' a') (subst_term_type e2' \' a')" + using Abs_sumC[OF 67(9,10) eqvt_at_term[OF 67(2)] eqvt_at_term[OF 67(4)]] 67(11) by fastforce + then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_type_def, symmetric, unfolded fun_eq_iff]) next - case (29 b \ a k e2 b' \' a' k' e2') - then show ?case using Abs_sumC[OF 29(5,6,1,2)] by fastforce + case (79 y \ a e y' \' a' e') + have "MatchVar y (subst_term_type e \ a) = MatchVar y' (subst_term_type e' \' a')" using Abs_sumC[OF 79(5,6) eqvt_at_term[OF 79(1)] eqvt_at_term[OF 79(2)]] 79(7) by fastforce + then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_type_def, symmetric, unfolded fun_eq_iff]) next - case (31 y \ a \1 e1 e2 y' \' a' \1' e1' e2') - then show ?case using Abs_sumC[OF 31(9,10,2,4)] by fastforce -qed (auto simp: eqvt_def subst_term_type_graph_aux_def) + case (81 tys vals \ a D e tys' vals' \' a' D' e') + have "MatchCtor D tys vals (subst_term_type e \ a) = MatchCtor D' tys' vals' (subst_term_type e' \' a')" using Abs_sumC_star[OF 81(5,6) eqvt_at_term[OF 81(1)] eqvt_at_term[OF 81(2)]] 81(7) by fastforce + then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_type_def, symmetric, unfolded fun_eq_iff]) +} qed (auto simp: eqvt_def subst_term_type_subst_alt_list_type_subst_alt_type_graph_aux_def) nominal_termination (eqvt) by lexicographic_order nominal_function subst_context :: "\ \ \ \ tyvar \ \" where @@ -275,6 +409,6 @@ no_notation inverse_divide (infixl "'/" 70) consts subst :: "'a \ 'b \ 'c \ 'a" ("_[_'/_]" [1000,0,0] 1000) adhoc_overloading - subst subst_term subst_type subst_term_type subst_context + subst subst_term subst_alt_list subst_alt subst_type subst_term_type subst_alt_list_type subst_alt_type subst_context end diff --git a/Nominal2_Lemmas.thy b/Nominal2_Lemmas.thy index 421adae..90f0e8f 100644 --- a/Nominal2_Lemmas.thy +++ b/Nominal2_Lemmas.thy @@ -62,6 +62,19 @@ proof - show ?thesis using 1 2 3 equal by argo qed +lemma Abs_sumC_star: + fixes ys ys'::"atom list" and x x'::"'a::fs" and e e'::"'b::fs" and e2 e2'::"'c::fs" and f::"'c * 'b * 'a \ 'd::fs" + assumes fresh: "set ys \* (e, x)" "set ys' \* (e', x')" + and eqvt_at: "eqvt_at f (e2, e, x)" "eqvt_at f (e2', e', x')" + and equal: "[ys]lst. e2 = [ys']lst. e2'" "x = x'" "e = e'" + shows "[ys]lst. f (e2, e, x) = [ys']lst. f (e2', e', x')" +proof - + have 1: "set ys \* ([ys]lst. f (e2, e, x))" by (simp add: Abs_fresh_star(3)) + have 2: "\p. supp p \* (e, x) \ p \ ([ys]lst. f (e2, e, x)) = [p \ ys]lst. f (p \ e2, e, x)" using eqvt_at(1) by (simp add: eqvt_at_def, simp add: fresh_star_Pair perm_supp_eq) + have 3: "\p. supp p \* (e, x) \ p \ ([ys']lst. f (e2', e, x)) = [p \ ys']lst. f (p \ e2', e, x)" using eqvt_at(2) equal(2,3) by (simp add: eqvt_at_def, simp add: fresh_star_Pair perm_supp_eq) + show ?thesis using Abs_lst_fcb2[where f="\a b c. [a]lst. f (b, e, x)", OF equal(1) 1 fresh(1) _ 2 3] fresh(2) equal(2,3) by simp +qed + lemma Abs_fresh_var: fixes y::"'a::at" and e ::"'b::fs" obtains c::"'a" and e'::"'b" where "([[atom y]]lst. e = [[atom c]]lst. e') \ atom y \ [[atom c]]lst. e'" @@ -79,7 +92,11 @@ lemma Abs_rename_body: shows "(a \ b) \ e1 = e2" by (metis Abs1_eq_iff'(3) Nominal2_Base.swap_self assms flip_commute flip_def fresh_star_zero supp_perm_eq_test) + lemma fresh_filter: "a = b \ atom a \ xs \ atom a \ filter (\x. x \ b) xs" by (induction xs) (auto simp: fresh_Cons fresh_Nil) +lemma Projl_permute: "\y. f = Inl y \ p \ projl f = projl (p \ f)" by auto +lemma Projr_permute: "\y. f = Inr y \ p \ projr f = projr (p \ f)" by auto + end From b6c52e05caebb623073420a767ec1b5a43db63bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20van=20Br=C3=BCgge?= Date: Sun, 14 Feb 2021 20:04:38 +0100 Subject: [PATCH 3/8] Adjust Lemmas --- Lemmas.thy | 185 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 152 insertions(+), 33 deletions(-) diff --git a/Lemmas.thy b/Lemmas.thy index b520a3a..0b8d7b0 100644 --- a/Lemmas.thy +++ b/Lemmas.thy @@ -2,31 +2,104 @@ theory Lemmas imports Syntax Defs begin +lemma fresh_match_Pair: + fixes tys::"tyvar list" and vals::"var list" + assumes "set (map atom tys) \* e" "set (map atom vals) \* e" "set (map atom tys) \* y" "set (map atom vals) \* y" + shows "set (map atom tys @ map atom vals) \* (e, y)" + by (metis assms fresh_star_Pair fresh_star_Un set_append) + +lemma fresh_in_match_var: + fixes x::"var" + assumes "set (map atom tys) \* x" "set (map atom vals) \* x" "atom x \ MatchCtor D tys vals e" + shows "atom x \ e" + using assms fresh_at_base(2) fresh_star_Un fresh_star_def by fastforce + +lemma fresh_in_match_tyvar: + fixes a::"tyvar" + assumes "set (map atom tys) \* a" "set (map atom vals) \* a" "atom a \ MatchCtor D tys vals e" + shows "atom a \ e" + using assms fresh_at_base(2) fresh_star_Un fresh_star_def by fastforce +lemmas fresh_in_match = fresh_in_match_var fresh_in_match_tyvar + +lemma fresh_star_invert: "set (map atom xs) \* a \ atom a \ xs" + unfolding fresh_star_def by (induction xs) (auto simp: fresh_Cons fresh_Nil fresh_at_base(2)) + +lemma match_ctor_eqvt_var: + fixes a c::"var" + assumes "set (map atom tys) \* a" "set (map atom vals) \* a" "set (map atom tys) \* c" "set (map atom vals) \* c" + shows "(a \ c) \ MatchCtor D tys vals e = MatchCtor D tys vals ((a \ c) \ e)" +proof - + from assms(1,3) have 1: "(a \ c) \ tys = tys" using fresh_star_invert flip_fresh_fresh by blast + from assms(2,4) have 2: "(a \ c) \ vals = vals" using fresh_star_invert flip_fresh_fresh by blast + from 1 2 show ?thesis by auto +qed + +lemma match_ctor_eqvt_tyvar: + fixes a c::"tyvar" + assumes "set (map atom tys) \* a" "set (map atom vals) \* a" "set (map atom tys) \* c" "set (map atom vals) \* c" + shows "(a \ c) \ MatchCtor D tys vals e = MatchCtor D tys vals ((a \ c) \ e)" +proof - + from assms(1,3) have 1: "(a \ c) \ tys = tys" using fresh_star_invert flip_fresh_fresh by blast + from assms(2,4) have 2: "(a \ c) \ vals = vals" using fresh_star_invert flip_fresh_fresh by blast + from 1 2 show ?thesis by auto +qed +lemmas match_ctor_eqvt = match_ctor_eqvt_var match_ctor_eqvt_tyvar + (* \ atom x \ t' ; x = y \ atom x \ t \ \ atom x \ t[t'/y] *) -lemma fresh_subst_term: "\ atom x \ e' ; x = y \ atom x \ e \ \ atom x \ subst_term e e' y" - by (nominal_induct e avoiding: x y e' rule: term.strong_induct) auto -lemma fresh_subst_term_tyvar: "\ atom (a::tyvar) \ e' ; atom a \ e \ \ atom a \ subst_term e e' y" - by (nominal_induct e avoiding: y a e' rule: term.strong_induct) auto +lemma fresh_subst_term: + shows "\ atom x \ e' ; x = y \ atom x \ e \ \ atom x \ subst_term e e' y" + and "\ atom x \ e' ; x = y \ atom x \ alts \ \ atom x \ subst_alt_list alts e' y" + and "\ atom x \ e' ; x = y \ atom x \ alt \ \ atom x \ subst_alt alt e' y" +proof (nominal_induct e and alts and alt avoiding: x y e' rule: term_alt_list_alt.strong_induct) + case (MatchCtor D tys vals e) + then have "atom x \ e[e'/y]" using fresh_in_match(1) by blast + then show ?case using fresh_match_Pair[OF MatchCtor(3,6,2,5)] by simp +qed auto +lemma fresh_subst_term_tyvar: + shows "\ atom (a::tyvar) \ e' ; atom a \ e \ \ atom a \ subst_term e e' y" + and "\ atom (a::tyvar) \ e' ; atom a \ alts \ \ atom a \ subst_alt_list alts e' y" + and "\ atom (a::tyvar) \ e' ; atom a \ alt \ \ atom a \ subst_alt alt e' y" +proof (nominal_induct e and alts and alt avoiding: a y e' rule: term_alt_list_alt.strong_induct) + case (MatchCtor D tys vals e) + then have "atom a \ e[e'/y]" using fresh_in_match(2) by blast + then show ?case using fresh_match_Pair[OF MatchCtor(3,6,2,5)] by simp +qed auto lemma fresh_subst_type: "\ atom a \ \ ; a = b \ atom a \ \ \ \ atom a \ subst_type \ \ b" by (nominal_induct \ avoiding: a b \ rule: \.strong_induct) auto -lemma fresh_subst_term_type: "\ atom a \ \ ; a = b \ atom a \ e \ \ atom a \ subst_term_type e \ b" - by (nominal_induct e avoiding: a b \ rule: term.strong_induct) (auto simp: fresh_subst_type) +lemma fresh_subst_term_type: + shows "\ atom a \ \ ; a = b \ atom a \ e \ \ atom a \ subst_term_type e \ b" + and "\ atom a \ \ ; a = b \ atom a \ alts \ \ atom a \ subst_alt_list_type alts \ b" + and "\ atom a \ \ ; a = b \ atom a \ alt \ \ atom a \ subst_alt_type alt \ b" +proof (nominal_induct e and alts and alt avoiding: a b \ rule: term_alt_list_alt.strong_induct) + case (MatchCtor D tys vals e) + then have "atom a \ e[\/b]" using fresh_in_match(2) by blast + then show ?case using fresh_match_Pair[OF MatchCtor(3,6,2,5)] by simp +qed (auto simp: fresh_subst_type) lemma fresh_subst_context_var: "atom x \ \ \ atom (x::var) \ subst_context \ \' a" by (induction \ \' a rule: subst_context.induct) (auto simp: fresh_Cons) lemma fresh_subst_context_tyvar: "\ atom a \ \' ; a = b \ atom a \ \ \ \ atom a \ subst_context \ \' b" by (induction \ \' a rule: subst_context.induct) (auto simp: fresh_Cons fresh_Nil fresh_subst_type) -lemmas fresh_subst = fresh_subst_term fresh_subst_term_tyvar fresh_subst_type fresh_subst_term_type fresh_subst_context_var fresh_subst_context_tyvar +lemmas fresh_subst = fresh_subst_term(1) fresh_subst_term_tyvar(1) fresh_subst_type fresh_subst_term_type(1) fresh_subst_context_var fresh_subst_context_tyvar fresh_subst_term(2,3) fresh_subst_term_tyvar(2,3) fresh_subst_term_type(2,3) (* atom c \ t \ t[t'/x] = ((x \ c) \ t)[t'/c] *) -lemma subst_term_var_name: "atom c \ e \ subst_term e e' x = subst_term ((x \ c) \ e) e' c" -proof (nominal_induct e avoiding: c x e' rule: term.strong_induct) +lemma subst_term_var_name: + shows "atom c \ e \ subst_term e e' x = subst_term ((x \ c) \ e) e' c" + and "atom c \ alts \ subst_alt_list alts e' x = subst_alt_list ((x \ c) \ alts) e' c" + and "atom c \ alt \ subst_alt alt e' x = subst_alt ((x \ c) \ alt) e' c" +proof (nominal_induct e and alts and alt avoiding: c x e' rule: term_alt_list_alt.strong_induct) case (Let y \ e1 e2) then have "(Let y \ e1 e2)[e'/x] = Let y \ e1[e'/x] e2[e'/x]" by auto also have "... = Let y \ ((x \ c) \ e1)[e'/c] ((x \ c) \ e2)[e'/c]" - by (metis Let.hyps(1) Let.hyps(4) Let.hyps(5) Let.prems fresh_at_base(2) list.set(1) list.set(2) singletonD term.fresh(7)) + by (metis Let.hyps(1) Let.hyps(4) Let.hyps(5) Let.prems fresh_at_base(2) list.set(1) list.set(2) singletonD term_alt_list_alt.fresh(7)) also have "... = (Let y \ ((x \ c) \ e1) ((x \ c) \ e2))[e'/c]" by (simp add: Let.hyps(1) Let.hyps(3)) finally show ?case - by (metis Let.hyps(1) Let.hyps(2) flip_fresh_fresh fresh_at_base(2) no_vars_in_ty term.perm_simps(7)) + by (metis Let.hyps(1) Let.hyps(2) flip_fresh_fresh fresh_at_base(2) no_vars_in_ty term_alt_list_alt.perm_simps(7)) +next + case (MatchCtor D tys vals e) + from MatchCtor have "(MatchCtor D tys vals e)[e'/x] = MatchCtor D tys vals e[e'/x]" using fresh_match_Pair[OF MatchCtor(3,6,2,5)] by auto + also have "... = MatchCtor D tys vals ((x \ c) \ e)[e'/c]" using fresh_in_match(1) MatchCtor by metis + also have "... = (MatchCtor D tys vals ((x \ c) \ e))[e'/c]" using fresh_match_Pair[OF MatchCtor(3,6,1,4)] by simp + finally show ?case using match_ctor_eqvt(1)[OF MatchCtor(2,5,1,4)] by presburger qed (auto simp: flip_fresh_fresh fresh_at_base) lemma subst_type_var_name: "atom c \ \ \ subst_type \ \ a = subst_type ((a \ c) \ \) \ c" @@ -38,12 +111,15 @@ proof (nominal_induct \ avoiding: c a \ rule: \.strong_induct) finally show ?case by (metis TyForall.hyps(1) TyForall.hyps(2) \.perm_simps(5) flip_fresh_fresh fresh_at_base(2) no_tyvars_in_kinds) qed (auto simp: fresh_at_base) -lemma subst_term_type_var_name: "atom c \ e \ subst_term_type e \ a = subst_term_type ((a \ c) \ e) \ c" -proof (nominal_induct e avoiding: c a \ rule: term.strong_induct) +lemma subst_term_type_var_name: + shows "atom c \ e \ subst_term_type e \ a = subst_term_type ((a \ c) \ e) \ c" + and "atom c \ alts \ subst_alt_list_type alts \ a = subst_alt_list_type ((a \ c) \ alts) \ c" + and "atom c \ alt \ subst_alt_type alt \ a = subst_alt_type ((a \ c) \ alt) \ c" +proof (nominal_induct e and alts and alt avoiding: c a \ rule: term_alt_list_alt.strong_induct) case (Lam x \1 e) then have "(\ x:\1. e)[\/a] = (\ x:\1[\/a]. e[\/a])" by simp also have "... = (\ x:((a \ c) \ \1)[\/c]. e[\/a])" using subst_type_var_name Lam by force - also have "... = (\ x:((a \ c) \ \1)[\/c]. ((a \ c) \ e)[\/c])" using Lam by (metis fresh_at_base(2) list.set(1) list.set(2) singletonD term.fresh(5)) + also have "... = (\ x:((a \ c) \ \1)[\/c]. ((a \ c) \ e)[\/c])" using Lam by (metis fresh_at_base(2) list.set(1) list.set(2) singletonD term_alt_list_alt.fresh(5)) also have "... = (\ x:((a \ c) \ \1). ((a \ c) \ e))[\/c]" by simp finally show ?case by (simp add: Lam.hyps(2) flip_fresh_fresh) next @@ -51,11 +127,16 @@ next then have "(Let x \1 e1 e2)[\/a] = Let x \1[\/a] e1[\/a] e2[\/a]" by simp also have "... = Let x ((a \ c) \ \1)[\/c] e1[\/a] e2[\/a]" using subst_type_var_name Let by auto also have "... = Let x ((a \ c) \ \1)[\/c] ((a \ c) \ e1)[\/c] ((a \ c) \ e2)[\/c]" - by (metis (mono_tags, lifting) Let.hyps(1) Let.hyps(4) Let.hyps(5) Let.prems fresh_at_base(2) list.set(1) list.set(2) singletonD term.fresh(7)) + by (metis (mono_tags, lifting) Let.hyps(1) Let.hyps(4) Let.hyps(5) Let.prems fresh_at_base(2) list.set(1) list.set(2) singletonD term_alt_list_alt.fresh(7)) also have "... = (Let x ((a \ c) \ \1) ((a \ c) \ e1) ((a \ c) \ e2))[\/c]" by simp finally show ?case by (simp add: flip_fresh_fresh) +next + case (MatchCtor D tys vals e) + have "(MatchCtor D tys vals e)[\/a] = MatchCtor D tys vals e[\/a]" using fresh_match_Pair[OF MatchCtor(3,6,2,5)] by simp + also have "... = MatchCtor D tys vals ((a \ c) \ e)[\/c]" using fresh_in_match(2) MatchCtor by metis + also have "... = (MatchCtor D tys vals ((a \ c) \ e))[\/c]" using fresh_match_Pair[OF MatchCtor(3,6,1,4)] by simp + finally show ?case using match_ctor_eqvt(2)[OF MatchCtor(2,5,1,4)] by presburger qed (auto simp: flip_fresh_fresh fresh_at_base subst_type_var_name) -lemmas subst_var_name = subst_term_var_name subst_type_var_name subst_term_type_var_name lemma subst_context_var_name: "atom c \ \ \ subst_context \ \ a = subst_context ((a \ c) \ \) \ c" proof (induction \ \ a rule: subst_context.induct) @@ -74,14 +155,15 @@ proof (induction \ \ a rule: subst_context.induct) show ?thesis using a b c 1 by argo qed qed (auto simp: flip_fresh_fresh fresh_Cons subst_type_var_name) +lemmas subst_var_name = subst_term_var_name(1) subst_type_var_name subst_term_type_var_name(1) subst_context_var_name subst_term_var_name(2,3) subst_term_type_var_name(2,3) (* [[atom a]]lst. t = [[atom a2]]lst. t2 \ subst t t' a = subst t2 t' a2 *) lemma subst_term_same: "[[atom a]]lst. e = [[atom a']]lst. e' \ subst_term e t a = subst_term e' t a'" - by (metis Abs1_eq_iff(3) flip_commute subst_term_var_name) + by (metis Abs1_eq_iff(3) flip_commute subst_term_var_name(1)) lemma subst_type_same: "[[atom a]]lst. e = [[atom a']]lst. e' \ subst_type e \ a = subst_type e' \ a'" by (metis Abs1_eq_iff(3) flip_commute subst_type_var_name) lemma subst_term_type_same: "[[atom a]]lst. e = [[atom a']]lst. e' \ subst_term_type e \ a = subst_term_type e' \ a'" - by (metis Abs1_eq_iff(3) flip_commute subst_term_type_var_name) + by (metis Abs1_eq_iff(3) flip_commute subst_term_type_var_name(1)) lemmas subst_same = subst_term_same subst_type_same subst_term_type_same (* atom x \ \ \ \isin (B x _) \ *) @@ -93,13 +175,23 @@ lemma fresh_not_isin_var: "atom x \ \ \ \isin by (metis (mono_tags, lifting) binder.fresh(1) binder.strong_exhaust fresh_Cons fresh_at_base(2) isin.simps(2) isin.simps(3)) (* atom x \ t \ subst t' x t = t *) -lemma fresh_subst_term_same: "atom x \ e \ subst_term e e' x = e" -proof (induction e e' x rule: subst_term.induct) - case (5 y e x \ e2) +lemma fresh_subst_term_same: + shows "atom x \ e \ subst_term e e' x = e" + and "atom x \ alts \ subst_alt_list alts e' x = alts" + and "atom x \ alt \ subst_alt alt e' x = alt" +proof (induction e e' x and alts e' x and alt e' x rule: subst_term_subst_alt_list_subst_alt.induct) + case (6 y e x \ e2) then show ?case using fresh_PairD(2) fresh_at_base(2) by fastforce next - case (7 y e x \ e1 e2) + case (8 y e x \ e1 e2) then show ?case using fresh_PairD(2) fresh_at_base(2) by fastforce +next + case (11 y e x t) + then show ?case using fresh_PairD(2) fresh_at_base(2) by fastforce +next + case (12 tys vals e x D t) + then have "atom x \ t" by (meson fresh_PairD(2) fresh_at_base(2) fresh_star_def term_alt_list_alt.fresh(11)) + then show ?case using 12 by simp qed auto lemma fresh_subst_type_same: "atom a \ \ \ subst_type \ \ a = \" @@ -109,33 +201,60 @@ proof (induction \ \ a rule: subst_type.induct) using fresh_Pair fresh_at_base(2) fresh_def list.set(1) list.set(2) subst_type.simps(4) by fastforce qed auto -lemma fresh_subst_term_type_same: "atom a \ e \ subst_term_type e \ a = e" -proof (induction e \ a rule: subst_term_type.induct) - case (6 b \ a k e2) - then show ?case by (simp add: "6.hyps" fresh_Pair fresh_at_base(2)) +lemma fresh_subst_term_type_same: + shows "atom a \ e \ subst_term_type e \ a = e" + and "atom a \ alts \ subst_alt_list_type alts \ a = alts" + and "atom a \ alt \ subst_alt_type alt \ a = alt" +proof (induction e \ a and alts \ a and alt \ a rule: subst_term_type_subst_alt_list_type_subst_alt_type.induct) + case (7 b \ a k e2) + then show ?case by (simp add: "7.hyps" fresh_Pair fresh_at_base(2)) +next + case (12 tys vals \ a D e) + then have "atom a \ e" by (meson fresh_PairD(2) fresh_at_base(2) fresh_star_def term_alt_list_alt.fresh(11)) + then show ?case using 12 by auto qed (auto simp: fresh_subst_type_same) lemma fresh_subst_context_same: "atom a \ \ \ subst_context \ \ a = \" by (induction \ \ a rule: subst_context.induct) (auto simp: fresh_Cons fresh_subst_type_same) -lemmas fresh_subst_same = fresh_subst_term_same fresh_subst_type_same fresh_subst_term_type_same fresh_subst_context_same +lemmas fresh_subst_same = fresh_subst_term_same(1) fresh_subst_type_same fresh_subst_term_type_same(1) fresh_subst_context_same fresh_subst_term_same(2,3) fresh_subst_term_type_same(2,3) (* \ x \ y ; atom x \ t1 \ \ subst (subst e t2 x) t1 y = subst (subst e t1 y) (subst t2 t1 y) x *) -lemma subst_subst_term: "\ x \ y ; atom x \ t1 \ \ subst_term (subst_term e t2 x) t1 y = subst_term (subst_term e t1 y) (subst_term t2 t1 y) x" - by (nominal_induct e avoiding: x y t1 t2 rule: term.strong_induct) (auto simp: fresh_subst_same fresh_subst) +lemma subst_subst_term: + shows "\ x \ y ; atom x \ t1 \ \ subst_term (subst_term e t2 x) t1 y = subst_term (subst_term e t1 y) (subst_term t2 t1 y) x" + and "\ x \ y ; atom x \ t1 \ \ subst_alt_list (subst_alt_list alts t2 x) t1 y = subst_alt_list (subst_alt_list alts t1 y) (subst_term t2 t1 y) x" + and "\ x \ y ; atom x \ t1 \ \ subst_alt (subst_alt alt t2 x) t1 y = subst_alt (subst_alt alt t1 y) (subst_term t2 t1 y) x" +proof (nominal_induct e and alts and alt avoiding: x y t1 t2 rule: term_alt_list_alt.strong_induct) + case (MatchCtor D tys vals e) + have 1: "set (map atom tys) \* t2[t1/y]" unfolding fresh_star_def using fresh_subst(2) by (metis MatchCtor(3,4) ex_map_conv fresh_star_def) + have 2: "set (map atom vals) \* t2[t1/y]" unfolding fresh_star_def using fresh_subst(1) by (metis MatchCtor(7,8) ex_map_conv fresh_star_def) + have "(MatchCtor D tys vals e)[t2/x][t1/y] = MatchCtor D tys vals e[t2/x][t1/y]" using fresh_match_Pair[OF MatchCtor(4,8,1,5)] fresh_match_Pair[OF MatchCtor(3,7,2,6)] by simp + also have "... = MatchCtor D tys vals e[t1/y][t2[t1/y]/x]" using MatchCtor by simp + finally show ?case using fresh_match_Pair[OF MatchCtor(3,7,2,6)] fresh_match_Pair[OF 1 2 MatchCtor(1,5)] by simp +qed (auto simp: fresh_subst_same fresh_subst) lemma subst_subst_type: "\ a \ b ; atom a \ \1 \ \ subst_type (subst_type \ \2 a) \1 b = subst_type (subst_type \ \1 b) (subst_type \2 \1 b) a" by (nominal_induct \ avoiding: a b \1 \2 rule: \.strong_induct) (auto simp: fresh_subst_same fresh_subst) -lemma subst_subst_term_type: "\ a \ b ; atom a \ \1 \ \ subst_term_type (subst_term_type e \2 a) \1 b = subst_term_type (subst_term_type e \1 b) (subst_type \2 \1 b) a" - by (nominal_induct e avoiding: a b \1 \2 rule: term.strong_induct) (auto simp: fresh_subst_same fresh_subst subst_subst_type) +lemma subst_subst_term_type: + shows "\ a \ b ; atom a \ \1 \ \ subst_term_type (subst_term_type e \2 a) \1 b = subst_term_type (subst_term_type e \1 b) (subst_type \2 \1 b) a" + and "\ a \ b ; atom a \ \1 \ \ subst_alt_list_type (subst_alt_list_type alts \2 a) \1 b = subst_alt_list_type (subst_alt_list_type alts \1 b) (subst_type \2 \1 b) a" + and "\ a \ b ; atom a \ \1 \ \ subst_alt_type (subst_alt_type alt \2 a) \1 b = subst_alt_type (subst_alt_type alt \1 b) (subst_type \2 \1 b) a" +proof (nominal_induct e and alts and alt avoiding: a b \1 \2 rule: term_alt_list_alt.strong_induct) + case (MatchCtor D tys vals e) + have 1: "set (map atom tys) \* \2[\1/b]" unfolding fresh_star_def using fresh_subst(3) by (metis MatchCtor(3,4) ex_map_conv fresh_star_def) + have 2: "set (map atom vals) \* \2[\1/b]" unfolding fresh_star_def by simp + have "(MatchCtor D tys vals e)[\2/a][\1/b] = MatchCtor D tys vals e[\2/a][\1/b]" using fresh_match_Pair[OF MatchCtor(4,8,1,5)] fresh_match_Pair[OF MatchCtor(3,7,2,6)] by simp + also have "... = MatchCtor D tys vals e[\1/b][\2[\1/b]/a]" using MatchCtor by simp + finally show ?case using fresh_match_Pair[OF MatchCtor(3,7,2,6)] fresh_match_Pair[OF 1 2 MatchCtor(1,5)] by simp +qed (auto simp: fresh_subst_same fresh_subst subst_subst_type) lemma subst_subst_context: "\ a \ b; atom a \ \1 \ \ subst_context (subst_context \ \2 a) \1 b = subst_context (subst_context \ \1 b) (subst_type \2 \1 b) a" by (induction \ \2 a rule: subst_context.induct) (auto simp: subst_subst_type) -lemmas subst_subst = subst_subst_term subst_subst_type subst_subst_term_type subst_subst_context +lemmas subst_subst = subst_subst_term(1) subst_subst_type subst_subst_term_type(1) subst_subst_context subst_subst_term(2,3) subst_subst_term_type(2,3) (* misc *) lemma fv_supp_subset: "fv_\ \ \ supp \" by (induction \ rule: \.induct) (auto simp: \.supp \.fv_defs) lemma head_ctor_is_value: "head_ctor e \ is_value e" - by (induction e rule: term.induct) auto + by (induction e rule: term_alt_list_alt.inducts(1)) auto end From 25dad8ef166f7e7063d1536ca96e25e913353646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20van=20Br=C3=BCgge?= Date: Wed, 3 Mar 2021 17:26:52 +0100 Subject: [PATCH 4/8] Add general requirements for `case` to typing rule --- Defs.thy | 37 +++++++++++++++++++++++++++++++++++++ Typing.thy | 4 ++++ 2 files changed, 41 insertions(+) diff --git a/Defs.thy b/Defs.thy index 0e27a8b..80541fc 100644 --- a/Defs.thy +++ b/Defs.thy @@ -42,6 +42,35 @@ proof goal_cases qed (auto simp: eqvt_def head_ctor_graph_aux_def) nominal_termination (eqvt) by lexicographic_order +nominal_function head_data :: "\ \ data_name option" where + "head_data (TyVar _) = None" +| "head_data (TyData T) = Some T" +| "head_data TyArrow = None" +| "head_data (TyApp (TyData T) _) = Some T" +| "head_data (TyApp (TyVar _) _) = None" +| "head_data (TyApp TyArrow _) = None" +| "head_data (TyApp (TyApp _ _) _) = None" +| "head_data (TyApp (TyForall _ _ _) _) = None" +| "head_data (TyForall _ _ _) = None" +proof goal_cases + case (3 P x) + then show ?case + proof (cases x rule: \.exhaust) + case (TyApp \1 \2) + then show ?thesis using 3 by (cases \1 rule: \.exhaust) auto + qed +qed (auto simp: eqvt_def head_data_graph_aux_def) +nominal_termination (eqvt) by lexicographic_order + +nominal_function set_alt_list :: "alt_list \ alt set" where + "set_alt_list ANil = {}" +| "set_alt_list (ACons alt alts) = insert alt (set_alt_list alts)" +proof goal_cases + case (3 P x) + then show ?case by (cases x rule: term_alt_list_alt.exhaust(2)) +qed (auto simp: eqvt_def set_alt_list_graph_aux_def) +nominal_termination (eqvt) by lexicographic_order + nominal_function ctor_data_app :: "\ \ (data_name * tyvar list) option" where "ctor_data_app (TyVar _) = None" | "ctor_data_app (TyData T) = Some (T, [])" @@ -163,6 +192,14 @@ next qed auto nominal_termination (eqvt) by lexicographic_order +abbreviation exhaustive :: "alt_list \ \ \ data_name \ bool" where + "exhaustive alts \ T \ + (\x e. MatchVar x e \ set_alt_list alts) \ + (\D \. + (AxCtor D \ \ set \ \ ctor_type \ = Some T) \ + (\tys vals e. MatchCtor D tys vals e \ set_alt_list alts) + )" + nominal_function is_value :: "term => bool" where "is_value (Var x) = False" | "is_value (\ x : \ . e) = True" diff --git a/Typing.thy b/Typing.thy index cfddac9..2bc9869 100644 --- a/Typing.thy +++ b/Typing.thy @@ -51,6 +51,10 @@ inductive Tm :: "\ \ \ \ term \ \ , \ \ e1 : \1 ; BVar x \1 # \ , \ \ e2 : \2 \ \ \ , \ \ Let x \1 e1 e2 : \2" +| Tm_Case: "\ \ , \ \ e : \1 ; head_data \1 = Some T ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; + \m\set_alt_list alts. True + \ \ \ , \ \ Case e alts : \" + equivariance Tm lemmas Ax_intros = Ax_Ctx_Ty.intros(1-3) From f2ecf8e45cee28e9bbe793940312bf8d5e902012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20van=20Br=C3=BCgge?= Date: Mon, 12 Apr 2021 13:58:02 +0200 Subject: [PATCH 5/8] WIP --- Defs.thy | 98 +++++++++++++++++++++++++++------------------ Nominal2_Lemmas.thy | 3 ++ Semantics.thy | 2 + Syntax.thy | 9 ++++- Typing.thy | 20 +++++++-- 5 files changed, 89 insertions(+), 43 deletions(-) diff --git a/Defs.thy b/Defs.thy index 80541fc..f831e08 100644 --- a/Defs.thy +++ b/Defs.thy @@ -42,15 +42,13 @@ proof goal_cases qed (auto simp: eqvt_def head_ctor_graph_aux_def) nominal_termination (eqvt) by lexicographic_order -nominal_function head_data :: "\ \ data_name option" where +nominal_function head_data :: "\ \ (data_name * \ list) option" where "head_data (TyVar _) = None" -| "head_data (TyData T) = Some T" +| "head_data (TyData T) = Some (T, [])" | "head_data TyArrow = None" -| "head_data (TyApp (TyData T) _) = Some T" -| "head_data (TyApp (TyVar _) _) = None" -| "head_data (TyApp TyArrow _) = None" -| "head_data (TyApp (TyApp _ _) _) = None" -| "head_data (TyApp (TyForall _ _ _) _) = None" +| "head_data (TyApp \1 \2) = (case head_data \1 of + Some (T, xs) \ Some (T, xs @ [\2]) + | None \ None)" | "head_data (TyForall _ _ _) = None" proof goal_cases case (3 P x) @@ -59,7 +57,7 @@ proof goal_cases case (TyApp \1 \2) then show ?thesis using 3 by (cases \1 rule: \.exhaust) auto qed -qed (auto simp: eqvt_def head_data_graph_aux_def) +qed (auto simp: eqvt_def head_data_graph_aux_def split!: option.splits) nominal_termination (eqvt) by lexicographic_order nominal_function set_alt_list :: "alt_list \ alt set" where @@ -76,7 +74,7 @@ nominal_function ctor_data_app :: "\ \ (data_name * tyvar list) | "ctor_data_app (TyData T) = Some (T, [])" | "ctor_data_app TyArrow = None" | "ctor_data_app (TyApp \1 (TyVar a)) = (case ctor_data_app \1 of - Some (T, s) \ Some (T, a#s) + Some (T, tys) \ Some (T, a#tys) | None \ None)" | "ctor_data_app (TyApp _ (TyData _)) = None" | "ctor_data_app (TyApp _ TyArrow) = None" @@ -84,7 +82,7 @@ nominal_function ctor_data_app :: "\ \ (data_name * tyvar list) | "ctor_data_app (TyApp _ (TyForall _ _ _)) = None" | "ctor_data_app (TyForall _ _ _) = None" proof goal_cases - case 1 +case 1 then show ?case by (auto simp: eqvt_def ctor_data_app_graph_aux_def split!: option.splits) next case (3 P x) @@ -92,7 +90,7 @@ next proof (cases x rule: \.exhaust) case (TyApp \1 \2) then show ?thesis using 3 by (cases \2 rule: \.exhaust) auto - qed (auto simp: 3) + qed auto qed auto nominal_termination (eqvt) by lexicographic_order @@ -112,38 +110,38 @@ nominal_function ctor_type_app :: "\ \ (data_name * tyvar list) | "ctor_type_app (TyForall _ _ _) = None" proof goal_cases case (3 P x) - show ?case using 3(1-3,13) + then show ?case proof (cases x rule: \.exhaust) case outer: (TyApp \1 \2) - then show ?thesis using 3(9-12) + then show ?thesis using 3 proof (cases \1 rule: \.exhaust) - case inner: (TyApp \1' \2') - then show ?thesis using outer 3(4-8) by (cases \1' rule: \.exhaust) blast+ - qed blast+ - qed blast+ + case (TyApp \1 \2) + then show ?thesis using outer 3 by (cases \1 rule: \.exhaust) auto + qed auto + qed auto next case (74 a k e \1 \2 a k e \1 \2) - then show ?case by (simp add: 74) + then show ?case by presburger next case (92 a k e \2 a k e \2) - then show ?case by (simp add: 92) + then show ?case by presburger qed (auto simp: eqvt_def ctor_type_app_graph_aux_def) nominal_termination (eqvt) by lexicographic_order -nominal_function ctor_type_forall :: "\ \ (data_name * tyvar list) option" where +nominal_function ctor_type_forall :: "\ \ (data_name * tyvar list * \ list) option" where "ctor_type_forall (TyVar _) = None" -| "ctor_type_forall (TyData T) = Some (T, [])" +| "ctor_type_forall (TyData T) = Some (T, [], [])" | "ctor_type_forall TyArrow = None" -| "ctor_type_forall (TyApp \1 \2) = ctor_type_app (TyApp \1 \2)" -| "ctor_type_forall (TyForall a _ e) = (case ctor_type_forall e of - Some (T, s) \ (if a \ set s then Some (T, filter (\x. x \ a) s) else None) - | None \ None)" +| "ctor_type_forall (TyApp \1 \2) = (case ctor_type_app (TyApp \1 \2) of Some (T, tys) \ Some (T, tys, []) | None \ None)" +| "ctor_type_forall (TyForall a k e) = (case ctor_type_forall e of + Some (T, xs, ks) \ (if a \ set xs then Some (T, filter (\x. x \ a) xs, k#ks) else None) + | _ \ None)" proof goal_cases case 1 then show ?case by (auto simp: eqvt_def ctor_type_forall_graph_aux_def split!: option.splits list.splits) next case (3 P x) - then show ?case by (cases x rule: \.exhaust) + then show ?case by (cases x rule: \.exhaust) auto next case (18 a k e a' k' e') obtain c::tyvar where P: "atom c \ (a, e, a', e', ctor_type_forall_sumC e, ctor_type_forall_sumC e')" by (rule obtain_fresh) @@ -154,9 +152,10 @@ next then show ?case proof (cases "ctor_type_forall_sumC e") case (Some t) - then obtain T s where P1: "t = (T, s)" by fastforce - from Some obtain T' s' where P2: "ctor_type_forall_sumC e' = Some (T', s')" using 3 by auto - have "T = T'" using "2" P1 P2 Some Some_eqvt option.inject perm_data_name_tyvar by auto + then obtain T s ks where P1: "t = (T, s, ks)" by (metis prod.exhaust) + from Some obtain T' s' ks' where P2: "ctor_type_forall_sumC e' = Some (T', s', ks')" using 3 by auto + then have pairs: "(a \ c) \ (T, s, ks) = (a' \ c) \ (T', s', ks')" using 2 P1 Some Some_eqvt option.inject by simp + from pairs have "T = T'" "ks = ks'" by auto have same: "(a \ c) \ s = (a' \ c) \ s'" using "2" P1 P2 Some by auto have x: "a \ set s \ a' \ set s'" by (metis flip_at_simps(2) mem_permute_iff permute_flip_cancel same set_eqvt) have 4: "atom c \ s" using c(5) Some P1 fresh_Some fresh_Pair by metis @@ -167,19 +166,26 @@ next also have "... = filter (\x. x \ c) ((a' \ c) \ s')" using same by argo also have "... = (a' \ c) \ filter (\x. x \ a') s'" by simp also have "... = filter (\x. x \ a') s'" using 6 flip_fresh_fresh by blast - finally have 9: "Some (T, filter (\x. x \ a) s) = Some (T', filter (\x. x \ a') s')" using \T = T'\ by blast - then show ?thesis using Some P1 P2 x by simp + finally have 9: "Some (T, filter (\x. x \ a) s, ks) = Some (T', filter (\x. x \ a') s', ks')" using \T = T'\ \ks = ks'\ by blast + then show ?thesis + proof (cases "a \ set s") + case True + then show ?thesis using Some P1 P2 x 18(5) 9 by simp + next + case False + then show ?thesis using P1 P2 Some x by force + qed qed simp qed auto nominal_termination (eqvt) by lexicographic_order (* This function checks if a type has the form \[a:k]. [\] \ T [a] *) -nominal_function ctor_type :: "\ \ data_name option" where +nominal_function ctor_type :: "\ \ (data_name * \ list) option" where "ctor_type (TyVar a) = None" -| "ctor_type (TyData T) = Some T" +| "ctor_type (TyData T) = Some (T, [])" | "ctor_type TyArrow = None" -| "ctor_type (TyApp \1 \2) = (case ctor_type_app (TyApp \1 \2) of Some (T, []) \ Some T | _ \ None)" -| "ctor_type (TyForall a k e) = (case ctor_type_forall (TyForall a k e) of Some (T, []) \ Some T | _ \ None)" +| "ctor_type (TyApp \1 \2) = (case ctor_type_app (TyApp \1 \2) of Some (T, []) \ Some (T, []) | _ \ None)" +| "ctor_type (TyForall a k e) = (case ctor_type_forall (TyForall a k e) of Some (T, [], ks) \ Some (T, k#ks) | _ \ None)" proof goal_cases case 1 then show ?case by (auto simp: eqvt_def ctor_type_graph_aux_def split!: option.splits list.splits) @@ -188,18 +194,34 @@ next then show ?case by (cases x rule: \.exhaust) next case (18 a k e a' k' e') - then show ?case by (simp add: 18) + have "(case ctor_type_forall (\ a' : k' . e') of None \ None | Some (d, [], ks) \ Some (d, k # ks) | Some (d, t # x, ks) \ Map.empty x) = (case ctor_type_forall (\ a' : k' . e') of None \ None | Some (d, [], ks) \ Some (d, k' # ks) | Some (d, t # x, ks) \ Map.empty x)" + using "18" by fastforce + then show ?case + by (simp add: "18") qed auto nominal_termination (eqvt) by lexicographic_order abbreviation exhaustive :: "alt_list \ \ \ data_name \ bool" where "exhaustive alts \ T \ (\x e. MatchVar x e \ set_alt_list alts) \ - (\D \. - (AxCtor D \ \ set \ \ ctor_type \ = Some T) \ + (\D \ ks. + (AxCtor D \ \ set \ \ ctor_type \ = Some (T, ks)) \ (\tys vals e. MatchCtor D tys vals e \ set_alt_list alts) )" +nominal_function zip_with :: "('a::pt \ 'b::pt \ 'c::pt) \ 'a list \ 'b list \ 'c list" where + "zip_with _ [] _ = []" +| "zip_with _ _ [] = []" +| "zip_with f (a#as) (b#bs) = f a b # zip_with f as bs" +proof goal_cases + case (3 P x) + then show ?case sorry +qed (auto simp: eqvt_def zip_with_graph_aux_def) +nominal_termination (eqvt) by lexicographic_order + +lemma zip_with_length[simp]: "length (zip_with f as bs) = min (length as) (length bs)" + by (induction f as bs rule: zip_with.induct) auto + nominal_function is_value :: "term => bool" where "is_value (Var x) = False" | "is_value (\ x : \ . e) = True" diff --git a/Nominal2_Lemmas.thy b/Nominal2_Lemmas.thy index 90f0e8f..f586d5f 100644 --- a/Nominal2_Lemmas.thy +++ b/Nominal2_Lemmas.thy @@ -99,4 +99,7 @@ lemma fresh_filter: "a = b \ atom a \ xs \ atom a \y. f = Inl y \ p \ projl f = projl (p \ f)" by auto lemma Projr_permute: "\y. f = Inr y \ p \ projr f = projr (p \ f)" by auto +lemma pair3_eqvt[simp]: "(a \ b) \ (x, y, z) = ((a \ b) \ x, (a \ b) \ y, (a \ b) \ z)" + by (simp split: prod.splits) + end diff --git a/Semantics.thy b/Semantics.thy index 234a189..871dce4 100644 --- a/Semantics.thy +++ b/Semantics.thy @@ -18,6 +18,8 @@ inductive Step :: "term \ term \ bool" ("_ \ e1 e2 \ e2[e1/x]" +| ST_Case_Cong: "e \ e' \ Case e alts \ Case e' alts" + equivariance Step nominal_inductive Step . diff --git a/Syntax.thy b/Syntax.thy index 9be28e7..7477221 100644 --- a/Syntax.thy +++ b/Syntax.thy @@ -91,6 +91,13 @@ lemma perm_ctor_name_var[simp]: "((a::var) \ b) \ (D :: using flip_fresh_fresh pure_fresh by blast lemma perm_ctor_name_tyvar[simp]: "((a::tyvar) \ b) \ (D :: ctor_name) = D" using flip_fresh_fresh pure_fresh by blast - +lemma perm_kind_var[simp]: "((a::var) \ b) \ (k::\) = k" + using supp_empty_kinds flip_fresh_fresh fresh_def by blast +lemma perm_kind_tyvar[simp]: "((a::tyvar) \ b) \ (k::\) = k" + using supp_empty_kinds flip_fresh_fresh fresh_def by blast +lemma perm_kind_list_var[simp]: "((a::var) \ b) \ (ks::\ list) = ks" + by (induction ks) auto +lemma perm_kind_list_tyvar[simp]: "((a::tyvar) \ b) \ (ks::\ list) = ks" + by (induction ks) auto end diff --git a/Typing.thy b/Typing.thy index 2bc9869..4b127f0 100644 --- a/Typing.thy +++ b/Typing.thy @@ -12,7 +12,11 @@ inductive Ax :: "\ \ bool" ("\ _") | Ax_Data: "\ \ \ ; \k. AxData T k \ set \ \ \ \ AxData T \ # \" +<<<<<<< HEAD | Ax_Ctor: "\ [] , \ \\<^sub>t\<^sub>y \ : \ ; ctor_type \ = Some T ; \t. AxCtor D t \ set \ \ \ \ AxCtor D \ # \" +======= +| Ax_Ctor: "\ [] , \ \\<^sub>t\<^sub>y \ : \ ; ctor_type \ = Some (T, ks, tys) ; atom D \ \ \ \ \ AxCtor D \ # \" +>>>>>>> 9b53bd3 (WIP) (* ------------------------------ *) @@ -36,7 +40,8 @@ inductive Ax :: "\ \ bool" ("\ _") equivariance Ax -inductive Tm :: "\ \ \ \ term \ \ \ bool" ("_ , _ \ _ : _" 50) where +inductive Tm :: "\ \ \ \ term \ \ \ bool" ("_ , _ \ _ : _" 50) and + Alts :: "\ \ \ \ data_name \ \ list \ \ \ alt_list \ \ \ bool" where Tm_Var: "\ \ \ \ ; BVar x \ \ \ \ \ \ , \ \ (Var x) : \" | Tm_Abs: "BVar x \1 # \ , \ \ e : \2 \ \ , \ \ (\ x : \1 . e) : (\1 \ \2)" @@ -51,9 +56,16 @@ inductive Tm :: "\ \ \ \ term \ \ , \ \ e1 : \1 ; BVar x \1 # \ , \ \ e2 : \2 \ \ \ , \ \ Let x \1 e1 e2 : \2" -| Tm_Case: "\ \ , \ \ e : \1 ; head_data \1 = Some T ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; - \m\set_alt_list alts. True - \ \ \ , \ \ Case e alts : \" +| Tm_Case: "\ \ , \ \ e : \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; + exhaustive alts \ T ; Alts \ \ T \s \1 alts \ \ \ \ , \ \ Case e alts : \" + +| Alts_Nil: "Alts _ _ _ _ _ ANil _" + +| Alts_Var: "\ BVar x \1#\, \ \ e : \ ; Alts \ \ T \s \1 alts \ \ \ Alts \ \ T \s \1 (ACons (MatchVar x e) alts) \" + +| Alts_Ctor: "\ AxCtor K cty \ set \ ; ctor_type cty = Some (T, ks, args) ; length ks = length tys ; + length args = length vals ; (zip_with BVar vals args) @ (zip_with BTyVar tys ks) @ \, \ \ e : \ ; Alts \ \ T \s \1 alts \ + \ \ Alts \ \ T \s \1 (ACons (MatchCtor K tys vals e) alts) \" equivariance Tm From 5c234aaf4579f50a6d81ae410d03a3892d5018d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20van=20Br=C3=BCgge?= Date: Wed, 14 Apr 2021 13:28:31 +0200 Subject: [PATCH 6/8] WIP --- Defs.thy | 73 +++++++++++------------- Defs2.thy | 79 ++++++++++++++++++++++++++ Lemmas.thy | 11 ++-- Nominal2_Lemmas.thy | 5 ++ Syntax.thy | 1 - Typing.thy | 133 +++++++++++++++++++++++++++++++------------- 6 files changed, 216 insertions(+), 86 deletions(-) create mode 100644 Defs2.thy diff --git a/Defs.thy b/Defs.thy index f831e08..3fa6847 100644 --- a/Defs.thy +++ b/Defs.thy @@ -27,6 +27,13 @@ proof goal_cases qed (auto simp: eqvt_def isin_graph_aux_def) nominal_termination (eqvt) by lexicographic_order +nominal_function set_alts :: "alt_list \ alt fset" where + "set_alts ANil = {||}" +| "set_alts (ACons alt alts) = finsert alt (set_alts alts)" + apply (auto simp: eqvt_def set_alts_graph_aux_def) + by (cases rule: term_alt_list_alt.exhaust(2)) auto +nominal_termination (eqvt) by lexicographic_order + nominal_function head_ctor :: "term \ bool" where "head_ctor (Var _) = False" | "head_ctor (Lam _ _ _) = False" @@ -202,12 +209,7 @@ qed auto nominal_termination (eqvt) by lexicographic_order abbreviation exhaustive :: "alt_list \ \ \ data_name \ bool" where - "exhaustive alts \ T \ - (\x e. MatchVar x e \ set_alt_list alts) \ - (\D \ ks. - (AxCtor D \ \ set \ \ ctor_type \ = Some (T, ks)) \ - (\tys vals e. MatchCtor D tys vals e \ set_alt_list alts) - )" + "exhaustive alts \ T \ \D \ ks. (AxCtor D \ \ set \ \ ctor_type \ = Some (T, ks)) \ (\tys vals e. MatchCtor D tys vals e |\| set_alts alts)" nominal_function zip_with :: "('a::pt \ 'b::pt \ 'c::pt) \ 'a list \ 'b list \ 'c list" where "zip_with _ [] _ = []" @@ -215,7 +217,12 @@ nominal_function zip_with :: "('a::pt \ 'b::pt \ 'c::pt) | "zip_with f (a#as) (b#bs) = f a b # zip_with f as bs" proof goal_cases case (3 P x) - then show ?case sorry + then obtain f xs ys where P: "x = (f, xs, ys)" by (metis prod.exhaust) + then show ?case using 3 + proof (cases xs) + case (Cons a list) + then show ?thesis using 3 P by (cases ys) auto + qed simp qed (auto simp: eqvt_def zip_with_graph_aux_def) nominal_termination (eqvt) by lexicographic_order @@ -261,7 +268,6 @@ nominal_function (default "case_sum (\x. Inl undefined) (case_sum (\ (e, x) \ subst_alt (MatchVar y t) e x = MatchVar y (subst_term t e x)" | "set (map atom tys @ map atom vals) \* (e, x) \ subst_alt (MatchCtor D tys vals t) e x = MatchCtor D tys vals (subst_term t e x)" proof (goal_cases) @@ -308,31 +314,26 @@ proof (goal_cases) next case (Inr c) then obtain m e y where "c = (m, e, y)" by (metis prod.exhaust) - then show ?thesis using 3(11,12) Inr outer fresh_star_insert + then show ?thesis using 3 Inr outer fresh_star_insert apply (cases m rule: term_alt_list_alt.strong_exhaust(3)[of "(e, y)"]) - apply auto - by blast + by auto qed qed next - case (54 y e x \ e2 y' e' x' \' e2') - have "(\ y : \ . subst_term e2 e x) = (\ y' : \' . subst_term e2' e' x')" using Abs_sumC[OF 54(5,6) eqvt_at_term[OF 54(1)] eqvt_at_term[OF 54(2)]] 54(7) by fastforce - then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_def, symmetric, unfolded fun_eq_iff]) -next - case (61 y e x k e2 y' e' x' k' e2') - have "(\ y : k . subst_term e2 e x) = (\ y' : k' . subst_term e2' e' x')" using Abs_sumC[OF 61(5,6) eqvt_at_term[OF 61(1)] eqvt_at_term[OF 61(2)]] 61(7) by fastforce + case (49 y e x \ e2 y' e' x' \' e2') + have "(\ y : \ . subst_term e2 e x) = (\ y' : \' . subst_term e2' e' x')" using Abs_sumC[OF 49(5,6) eqvt_at_term[OF 49(1)] eqvt_at_term[OF 49(2)]] 49(7) by fastforce then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_def, symmetric, unfolded fun_eq_iff]) next - case (67 y e x \ e1 e2 y' e' x' \' e1' e2') - have "Let y \ (subst_term e1 e x) (subst_term e2 e x) = Let y' \' (subst_term e1' e' x') (subst_term e2' e' x')" using Abs_sumC[OF 67(9,10) eqvt_at_term[OF 67(2)] eqvt_at_term[OF 67(4)]] 67(11) by fastforce + case (55 y e x k e2 y' e' x' k' e2') + have "(\ y : k . subst_term e2 e x) = (\ y' : k' . subst_term e2' e' x')" using Abs_sumC[OF 55(5,6) eqvt_at_term[OF 55(1)] eqvt_at_term[OF 55(2)]] 55(7) by fastforce then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_def, symmetric, unfolded fun_eq_iff]) next - case (79 y e x t y' e' x' t') - have "MatchVar y (subst_term t e x) = MatchVar y' (subst_term t' e' x')" using Abs_sumC[OF 79(5,6) eqvt_at_term[OF 79(1)] eqvt_at_term[OF 79(2)]] 79(7) by fastforce + case (60 y e x \ e1 e2 y' e' x' \' e1' e2') + have "Let y \ (subst_term e1 e x) (subst_term e2 e x) = Let y' \' (subst_term e1' e' x') (subst_term e2' e' x')" using Abs_sumC[OF 60(9,10) eqvt_at_term[OF 60(2)] eqvt_at_term[OF 60(4)]] 60(11) by fastforce then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_def, symmetric, unfolded fun_eq_iff]) next - case (81 tys vals e x D t tys' vals' e' x' D' t') - have "MatchCtor D tys vals (subst_term t e x) = MatchCtor D' tys' vals' (subst_term t' e' x')" using Abs_sumC_star[OF 81(5,6) eqvt_at_term[OF 81(1)] eqvt_at_term[OF 81(2)]] 81(7) by fastforce + case (69 tys vals e x D t tys' vals' e' x' D' t') + have "MatchCtor D tys vals (subst_term t e x) = MatchCtor D' tys' vals' (subst_term t' e' x')" using Abs_sumC_star[OF 69(5,6) eqvt_at_term[OF 69(1)] eqvt_at_term[OF 69(2)]] 69(7) by fastforce then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_def, symmetric, unfolded fun_eq_iff]) } qed (auto simp: eqvt_def subst_term_subst_alt_list_subst_alt_graph_aux_def) nominal_termination (eqvt) by lexicographic_order @@ -373,7 +374,6 @@ nominal_function (default "case_sum (\x. Inl undefined) (case_sum (\ a = ACons (subst_alt_type alt \ a) (subst_alt_list_type alts \ a)" -| "atom y \ (\, a) \ subst_alt_type (MatchVar y e) \ a = MatchVar y (subst_term_type e \ a)" | "set (map atom tys @ map atom vals) \* (\, a) \ subst_alt_type (MatchCtor D tys vals e) \ a = MatchCtor D tys vals (subst_term_type e \ a)" proof goal_cases @@ -420,31 +420,26 @@ proof goal_cases next case (Inr c) then obtain m e y where P: "c = (m, e, y)" by (metis prod.exhaust) - then show ?thesis using Inr outer 3(11,12) - apply (cases m rule: term_alt_list_alt.strong_exhaust(3)[of "(e, y)"]) apply simp - using fresh_star_insert by blast + then show ?thesis using Inr outer 3 + apply (cases m rule: term_alt_list_alt.strong_exhaust(3)[of "(e, y)"]) by simp qed qed next - case (54 y \ a \2 e2 y' \' a' \2' e2') - have "(\ y : subst_type \2 \ a . subst_term_type e2 \ a) = (\ y' : subst_type \2' \' a' . subst_term_type e2' \' a')" using Abs_sumC[OF 54(5,6) eqvt_at_term[OF 54(1)] eqvt_at_term[OF 54(2)]] 54(7) by fastforce + case (49 y \ a \2 e2 y' \' a' \2' e2') + have "(\ y : subst_type \2 \ a . subst_term_type e2 \ a) = (\ y' : subst_type \2' \' a' . subst_term_type e2' \' a')" using Abs_sumC[OF 49(5,6) eqvt_at_term[OF 49(1)] eqvt_at_term[OF 49(2)]] 49(7) by fastforce then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_type_def, symmetric, unfolded fun_eq_iff]) next - case (61 b \ a k e2 b' \' a' k' e2') - have "(\ b : k . subst_term_type e2 \ a) = (\ b' : k' . subst_term_type e2' \' a')" using Abs_sumC[OF 61(5,6) eqvt_at_term[OF 61(1)] eqvt_at_term[OF 61(2)]] 61(7) by fastforce + case (55 b \ a k e2 b' \' a' k' e2') + have "(\ b : k . subst_term_type e2 \ a) = (\ b' : k' . subst_term_type e2' \' a')" using Abs_sumC[OF 55(5,6) eqvt_at_term[OF 55(1)] eqvt_at_term[OF 55(2)]] 55(7) by fastforce then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_type_def, symmetric, unfolded fun_eq_iff]) next - case (67 y \ a \2 e1 e2 y' \' a' \2' e1' e2') + case (60 y \ a \2 e1 e2 y' \' a' \2' e1' e2') have "Let y (subst_type \2 \ a) (subst_term_type e1 \ a) (subst_term_type e2 \ a) = Let y' (subst_type \2' \' a') (subst_term_type e1' \' a') (subst_term_type e2' \' a')" - using Abs_sumC[OF 67(9,10) eqvt_at_term[OF 67(2)] eqvt_at_term[OF 67(4)]] 67(11) by fastforce - then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_type_def, symmetric, unfolded fun_eq_iff]) -next - case (79 y \ a e y' \' a' e') - have "MatchVar y (subst_term_type e \ a) = MatchVar y' (subst_term_type e' \' a')" using Abs_sumC[OF 79(5,6) eqvt_at_term[OF 79(1)] eqvt_at_term[OF 79(2)]] 79(7) by fastforce + using Abs_sumC[OF 60(9,10) eqvt_at_term[OF 60(2)] eqvt_at_term[OF 60(4)]] 60(11) by fastforce then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_type_def, symmetric, unfolded fun_eq_iff]) next - case (81 tys vals \ a D e tys' vals' \' a' D' e') - have "MatchCtor D tys vals (subst_term_type e \ a) = MatchCtor D' tys' vals' (subst_term_type e' \' a')" using Abs_sumC_star[OF 81(5,6) eqvt_at_term[OF 81(1)] eqvt_at_term[OF 81(2)]] 81(7) by fastforce + case (69 tys vals \ a D e tys' vals' \' a' D' e') + have "MatchCtor D tys vals (subst_term_type e \ a) = MatchCtor D' tys' vals' (subst_term_type e' \' a')" using Abs_sumC_star[OF 69(5,6) eqvt_at_term[OF 69(1)] eqvt_at_term[OF 69(2)]] 69(7) by fastforce then show ?case by (auto simp: Abs_fresh_iff meta_eq_to_obj_eq[OF subst_term_type_def, symmetric, unfolded fun_eq_iff]) } qed (auto simp: eqvt_def subst_term_type_subst_alt_list_type_subst_alt_type_graph_aux_def) nominal_termination (eqvt) by lexicographic_order diff --git a/Defs2.thy b/Defs2.thy new file mode 100644 index 0000000..c620065 --- /dev/null +++ b/Defs2.thy @@ -0,0 +1,79 @@ +theory Defs2 + imports Lemmas +begin + +nominal_function ctor_data_app_subst :: "\ \ bool" where + "ctor_data_app_subst (TyVar _) = False" +| "ctor_data_app_subst (TyData _) = True" +| "ctor_data_app_subst TyArrow = False" +| "ctor_data_app_subst (TyApp \1 _) = ctor_data_app_subst \1" +| "ctor_data_app_subst (TyForall _ _ _) = False" +proof goal_cases + case (3 P x) + then show ?case by (cases x rule: \.exhaust) auto +qed (auto simp: eqvt_def ctor_data_app_subst_graph_aux_def) +nominal_termination (eqvt) by lexicographic_order + +nominal_function ctor_args :: "\ \ \ list option" where + "ctor_args (TyVar _) = None" +| "ctor_args (TyData T) = Some []" +| "ctor_args TyArrow = None" +| "ctor_args (TyApp (TyApp TyArrow \1) \2) = (case ctor_args \2 of + Some tys \ Some (\1#tys) + | None \ None)" +| "ctor_args (TyApp (TyApp (TyVar a) \1) \2) = (if ctor_data_app_subst (TyApp (TyApp (TyVar a) \1) \2) then Some [] else None)" +| "ctor_args (TyApp (TyApp (TyData T) \1) \2) = (if ctor_data_app_subst (TyApp (TyApp (TyData T) \1) \2) then Some [] else None)" +| "ctor_args (TyApp (TyApp (TyApp \1' \2') \1) \2) = (if ctor_data_app_subst (TyApp (TyApp (TyApp \1' \2') \1) \2) then Some [] else None)" +| "ctor_args (TyApp (TyApp (TyForall a k e) \1) \2) = (if ctor_data_app_subst (TyApp (TyApp (TyForall a k e) \1) \2) then Some [] else None)" +| "ctor_args (TyApp (TyVar a) \2) = (if ctor_data_app_subst (TyApp (TyVar a) \2) then Some [] else None)" +| "ctor_args (TyApp (TyData T) \2) = (if ctor_data_app_subst (TyApp (TyData T) \2) then Some [] else None)" +| "ctor_args (TyApp TyArrow \2) = (if ctor_data_app_subst (TyApp TyArrow \2) then Some [] else None)" +| "ctor_args (TyApp (TyForall a k e) \2) = (if ctor_data_app_subst (TyApp (TyForall a k e) \2) then Some [] else None)" +| "ctor_args (TyForall _ _ _) = None" +proof goal_cases + case 1 + then show ?case by (auto simp: eqvt_def ctor_args_graph_aux_def split!: option.splits) +next + case (3 P x) + then show ?case + proof (cases x rule: \.exhaust) + case outer: (TyApp \1 \2) + then show ?thesis using 3 + proof (cases \1 rule: \.exhaust) + case (TyApp \1 \2) + then show ?thesis using outer 3 by (cases \1 rule: \.exhaust) auto + qed auto + qed auto +qed auto +nominal_termination (eqvt) by lexicographic_order + +nominal_function subst_ctor :: "\ \ \ list \ \ list option" where + "subst_ctor (TyVar _) _ = None" +| "subst_ctor TyArrow _ = None" +| "subst_ctor (TyData _) [] = Some []" +| "subst_ctor (TyData _) (_#_) = None" +| "subst_ctor (TyApp \1 \2) [] = ctor_args (TyApp \1 \2)" +| "subst_ctor (TyApp _ _) (_#_) = None" +| "subst_ctor (TyForall _ _ _) [] = None" +| "subst_ctor (TyForall a _ e) (\#\s) = subst_ctor e[\/a] \s" +proof goal_cases + case (3 P x) + then obtain t xs where P: "x = (t, xs)" by fastforce + then show ?case using 3 + proof (cases t rule: \.exhaust) + case TyData + then show ?thesis using P 3 by (cases xs) auto + next + case TyApp + then show ?thesis using P 3 by (cases xs) auto + next + case TyForall + then show ?thesis using P 3 by (cases xs) auto + qed auto +next + case (39 a k e \ \s a' k' e' \' \s') + then show ?case by (metis Pair_inject \.eq_iff(5) list.inject subst_same(2)) +qed (auto simp: eqvt_def subst_ctor_graph_aux_def) +nominal_termination (eqvt) by lexicographic_order + +end \ No newline at end of file diff --git a/Lemmas.thy b/Lemmas.thy index 0b8d7b0..10f7ae9 100644 --- a/Lemmas.thy +++ b/Lemmas.thy @@ -186,12 +186,9 @@ next case (8 y e x \ e1 e2) then show ?case using fresh_PairD(2) fresh_at_base(2) by fastforce next - case (11 y e x t) - then show ?case using fresh_PairD(2) fresh_at_base(2) by fastforce -next - case (12 tys vals e x D t) + case (11 tys vals e x D t) then have "atom x \ t" by (meson fresh_PairD(2) fresh_at_base(2) fresh_star_def term_alt_list_alt.fresh(11)) - then show ?case using 12 by simp + then show ?case using 11 by simp qed auto lemma fresh_subst_type_same: "atom a \ \ \ subst_type \ \ a = \" @@ -209,9 +206,9 @@ proof (induction e \ a and alts \ a and alt \ a rule: subst_term_ case (7 b \ a k e2) then show ?case by (simp add: "7.hyps" fresh_Pair fresh_at_base(2)) next - case (12 tys vals \ a D e) + case (11 tys vals \ a D e) then have "atom a \ e" by (meson fresh_PairD(2) fresh_at_base(2) fresh_star_def term_alt_list_alt.fresh(11)) - then show ?case using 12 by auto + then show ?case using 11 by auto qed (auto simp: fresh_subst_type_same) lemma fresh_subst_context_same: "atom a \ \ \ subst_context \ \ a = \" diff --git a/Nominal2_Lemmas.thy b/Nominal2_Lemmas.thy index f586d5f..0c6a200 100644 --- a/Nominal2_Lemmas.thy +++ b/Nominal2_Lemmas.thy @@ -102,4 +102,9 @@ lemma Projr_permute: "\y. f = Inr y \ p \ projr lemma pair3_eqvt[simp]: "(a \ b) \ (x, y, z) = ((a \ b) \ x, (a \ b) \ y, (a \ b) \ z)" by (simp split: prod.splits) +lemma eqvt_fBall[eqvt]: "p \ fBall s f = fBall (p \ s) (p \ f)" + apply auto + apply (metis eqvt_bound eqvt_lambda fBallE in_fset_eqvt permute_pure) + by (metis eqvt_apply fBallE fBallI in_fset_eqvt permute_pure) + end diff --git a/Syntax.thy b/Syntax.thy index 7477221..d5450c7 100644 --- a/Syntax.thy +++ b/Syntax.thy @@ -47,7 +47,6 @@ and "alt_list" = | ACons "alt" "alt_list" and "alt" = MatchCtor "ctor_name" tys::"tyvar list" vals::"var list" e::"term" binds tys vals in e -| MatchVar x::"var" e::"term" binds x in e nominal_datatype "binder" = BVar "var" "\" diff --git a/Typing.thy b/Typing.thy index 4b127f0..dc635e4 100644 --- a/Typing.thy +++ b/Typing.thy @@ -1,5 +1,5 @@ theory Typing - imports Syntax Defs Lemmas + imports Syntax Defs Defs2 Lemmas begin no_notation Set.member ("(_/ : _)" [51, 51] 50) @@ -12,11 +12,7 @@ inductive Ax :: "\ \ bool" ("\ _") | Ax_Data: "\ \ \ ; \k. AxData T k \ set \ \ \ \ AxData T \ # \" -<<<<<<< HEAD -| Ax_Ctor: "\ [] , \ \\<^sub>t\<^sub>y \ : \ ; ctor_type \ = Some T ; \t. AxCtor D t \ set \ \ \ \ AxCtor D \ # \" -======= -| Ax_Ctor: "\ [] , \ \\<^sub>t\<^sub>y \ : \ ; ctor_type \ = Some (T, ks, tys) ; atom D \ \ \ \ \ AxCtor D \ # \" ->>>>>>> 9b53bd3 (WIP) +| Ax_Ctor: "\ [] , \ \\<^sub>t\<^sub>y \ : \ ; ctor_type \ = Some (T, ks) ; \t. AxCtor D t \ set \ \ \ \ AxCtor D \ # \" (* ------------------------------ *) @@ -40,8 +36,12 @@ inductive Ax :: "\ \ bool" ("\ _") equivariance Ax -inductive Tm :: "\ \ \ \ term \ \ \ bool" ("_ , _ \ _ : _" 50) and - Alts :: "\ \ \ \ data_name \ \ list \ \ \ alt_list \ \ \ bool" where +syntax + "_fBall" :: "pttrn \ 'a fset \ bool \ bool" ("(3\(_/|\|_)./ _)" [0, 0, 10] 10) +translations + "\x|\|A. P" \ "CONST fBall A (\x. P)" + +inductive Tm :: "\ \ \ \ term \ \ \ bool" ("_ , _ \ _ : _" 50) where Tm_Var: "\ \ \ \ ; BVar x \ \ \ \ \ \ , \ \ (Var x) : \" | Tm_Abs: "BVar x \1 # \ , \ \ e : \2 \ \ , \ \ (\ x : \1 . e) : (\1 \ \2)" @@ -56,16 +56,12 @@ inductive Tm :: "\ \ \ \ term \ \ , \ \ e1 : \1 ; BVar x \1 # \ , \ \ e2 : \2 \ \ \ , \ \ Let x \1 e1 e2 : \2" -| Tm_Case: "\ \ , \ \ e : \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; - exhaustive alts \ T ; Alts \ \ T \s \1 alts \ \ \ \ , \ \ Case e alts : \" - -| Alts_Nil: "Alts _ _ _ _ _ ANil _" - -| Alts_Var: "\ BVar x \1#\, \ \ e : \ ; Alts \ \ T \s \1 alts \ \ \ Alts \ \ T \s \1 (ACons (MatchVar x e) alts) \" - -| Alts_Ctor: "\ AxCtor K cty \ set \ ; ctor_type cty = Some (T, ks, args) ; length ks = length tys ; - length args = length vals ; (zip_with BVar vals args) @ (zip_with BTyVar tys ks) @ \, \ \ e : \ ; Alts \ \ T \s \1 alts \ - \ \ Alts \ \ T \s \1 (ACons (MatchCtor K tys vals e) alts) \" +| Tm_Case: "\ \ , \ \ e : \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; + \e |\| set_alts alts. (\K tys vals e' cty ks. + e = MatchCtor K tys vals e' \ + AxCtor K cty \ set \ \ ctor_type cty = Some (T, ks) \ + \ , \ \ e' : \ + ) \ \ \ , \ \ Case e alts : \" equivariance Tm @@ -105,6 +101,20 @@ lemma Ty_induct[consumes 1, case_names Var App Data Arrow Forall]: shows "P \ \ \ \" using Ax_Ctx_Ty.inducts(3)[OF assms(1), of "\a. True" P "\a b. True"] assms(2-6) by simp +lemma Tm_induct[consumes 1, case_names Var Abs App TAbs TApp Ctor Let Case]: + fixes P::"\ \ \ \ term \ \ \ bool" + assumes "\ , \ \ e : \" + and "\\ \ x \. \ \ \ \ ; BVar x \ \ \ \ \ P \ \ (Var x) \" + and "\x \1 \ \ e \2. \ BVar x \1 # \ , \ \ e : \2 ; P (BVar x \1 # \) \ e \2 \ \ P \ \ (\ x : \1 . e) (\1 \ \2)" + and "\\ \ e1 \1 \2 e2. \ \ , \ \ e1 : \1 \ \2 ; P \ \ e1 (\1 \ \2) ; \ , \ \ e2 : \1 ; P \ \ e2 \1 \ \ P \ \ (App e1 e2) \2" + and "\a k \ \ e \. \ BTyVar a k # \ , \ \ e : \ ; P (BTyVar a k # \) \ e \ \ \ P \ \ (\ a : k . e) (\ a : k . \)" + and "\\ \ e a k \ \. \ \ , \ \ e : \ a : k . \ ; P \ \ e (\ a : k . \) ; \ , \ \\<^sub>t\<^sub>y \ : k \ \ P \ \ (TApp e \) \[\/a]" + and "\\ \ D \. \ \ \ \ ; AxCtor D \ \ set \ \ \ P \ \ (Ctor D) \" + and "\\ \ e1 \1 x e2 \2. \ \ , \ \ e1 : \1 ; P \ \ e1 \1 ; BVar x \1 # \ , \ \ e2 : \2 ; P (BVar x \1 # \) \ e2 \2 \ \ P \ \ (Let x \1 e1 e2) \2" + and "\\ \ e \1 T \s \ alts. \ \ , \ \ e : \1 ; P \ \ e \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; Alts \ \ T \s \1 alts \ \ \ P \ \ (Case e alts) \" +shows "P \ \ e \" + using Tm_Alts.inducts(1)[OF assms(1), of _ "\_ _ _ _ _ _ _. True"] assms(2-9) by auto + (* axiom validity *) lemma axioms_valid_aux: shows "\ \ \ \ \ \" @@ -119,7 +129,7 @@ lemma axioms_valid_context: "\ \ \ \ \< lemma axioms_valid_ty: "\ , \ \\<^sub>t\<^sub>y \ : k \ \ \" using axioms_valid_aux by simp lemma axioms_valid_tm: "\ , \ \ e : \ \ \ \" - by (induction \ \ e \ rule: Tm.induct) (auto simp: axioms_valid_context axioms_valid_ty) + by (induction \ \ e \ rule: Tm_induct) (auto simp: axioms_valid_context axioms_valid_ty) lemmas axioms_valid = axioms_valid_context axioms_valid_ty axioms_valid_tm lemma Ctx_Ty_induct_split[case_names Ctx_Empty Ctx_TyVar Ctx_Var Ty_Var Ty_App Ty_Data Ty_Arrow Ty_Forall]: @@ -188,9 +198,11 @@ qed lemma context_valid_ty: "\ , \ \\<^sub>t\<^sub>y \ : \ \ \ \ \" by (induction \ \ \ \ rule: Ty_induct) auto lemma context_valid_tm: "\ , \ \ e : \ \ \ \ \" - by (induction \ \ e \ rule: Tm.induct) (auto simp: context_valid_ty) + by (induction \ \ e \ rule: Tm_induct) (auto simp: context_valid_ty) lemmas context_valid = context_valid_ty context_valid_tm + + (* \ \ \ e : t ; atom x \ \ \ \ atom x \ e *) lemma fresh_in_context_ty: "\ \ , \ \\<^sub>t\<^sub>y \ : k ; atom (a::tyvar) \ \ \ \ atom a \ \" proof (induction \ \ \ k rule: Ty_induct) @@ -198,24 +210,6 @@ proof (induction \ \ \ k rule: Ty_induct) then show ?case using fresh_at_base(2) fresh_not_isin_tyvar by fastforce qed (auto simp: fresh_Cons) -lemma fresh_in_context_term_var: "\ \ , \ \ e : \ ; atom (x::var) \ \ \ \ atom x \ e" -proof (induction \ \ e \ rule: Tm.induct) -case (Tm_Var \ \ x \) - then show ?case using fresh_ineq_at_base fresh_not_isin_var by force -qed (auto simp: fresh_Cons) - -lemma fresh_in_context_term_tyvar: "\ \ , \ \ e : \ ; atom (a::tyvar) \ \ \ \ atom a \ e" -proof (induction \ \ e \ rule: Tm.induct) - case (Tm_Abs x \1 \ \ e \2) - then have "atom a \ \1" by (meson CtxE(2) context_valid_tm fresh_in_context_ty) - then show ?case by (simp add: Tm_Abs fresh_Cons) -next - case (Tm_Let \ e1 e2 \1 \2 x) - then show ?case - by (metis (mono_tags, lifting) CtxE(2) binder.fresh(1) context_valid_tm fresh_Cons fresh_in_context_ty fresh_ineq_at_base list.set_intros(1) term.fresh(7)) -qed (auto simp: fresh_Cons fresh_in_context_ty) -lemmas fresh_in_context = fresh_in_context_ty fresh_in_context_term_var fresh_in_context_term_tyvar - lemma fresh_in_axioms: "\ \ \ atom (a::tyvar) \ \" proof - fix \ \ k @@ -226,7 +220,7 @@ proof - have "(\ \ \ atom a \ \) \ (\ \ \ \ ?W \ \) \ (\ , \ \\<^sub>t\<^sub>y \ : k \ ?Q \ \ \ k)" proof (induction rule: Ax_Ctx_Ty.induct[of "\x. atom a \ x" ?Q ?W]) case (Ax_Ctor \ \ D) - then show ?case using fresh_in_context(1)[OF Ax_Ctor(1) fresh_Nil] fresh_Cons fresh_Nil by fastforce + then show ?case using fresh_in_context_ty[OF Ax_Ctor(1) fresh_Nil] fresh_Cons fresh_Nil by fastforce qed (auto simp: fresh_Nil fresh_Cons) then show ?thesis using a by simp @@ -247,6 +241,67 @@ proof goal_cases then show ?case using 2 fresh_star_def by fastforce qed auto + + + + + +lemma fresh_in_context_term_var: + assumes "atom (x::var) \ \" + shows "\ , \ \ e : \ \ atom x \ e" + and "Alts \ \ T \s \1 alts \ \ atom x \ alts" + and "Alt \ \ T \ \1 alt \ \ atom x \ alt" +proof (induction \ \ e \ and \ \ T \s \1 alts \ and rule: Tm_Alts.induct) + + + + + + + + + + + + + + + + + + + +thm Tm_Alts.induct[of "\_ _ e _. atom x \ e" "\_ _ _ _ _ alts _. atom x \ alts" \ \ e \ \ \ T \ \1 alts \] + + + +lemma fresh_in_context_term_var: "\ \ , \ \ e : \ ; atom (x::var) \ \ \ \ atom x \ e" +proof (induction \ \ e \ rule: Tm_induct) + case (Var \ \ x \) + then show ?case using fresh_ineq_at_base fresh_not_isin_var by force +next + case (Case \ \ e \1 T \s \ alts) + then show ?case sorry +qed (auto simp: fresh_Cons) + +lemma fresh_in_context_term_tyvar: "\ \ , \ \ e : \ ; atom (a::tyvar) \ \ \ \ atom a \ e" +proof (induction \ \ e \ rule: Tm.induct) + case (Tm_Abs x \1 \ \ e \2) + then have "atom a \ \1" by (meson CtxE(2) context_valid_tm fresh_in_context_ty) + then show ?case by (simp add: Tm_Abs fresh_Cons) +next + case (Tm_Let \ e1 e2 \1 \2 x) + then show ?case + by (metis (mono_tags, lifting) CtxE(2) binder.fresh(1) context_valid_tm fresh_Cons fresh_in_context_ty fresh_ineq_at_base list.set_intros(1) term.fresh(7)) +qed (auto simp: fresh_Cons fresh_in_context_ty) +lemmas fresh_in_context = fresh_in_context_ty fresh_in_context_term_var fresh_in_context_term_tyvar + + + + + + + nominal_inductive Tm avoids Tm_Abs: x | Tm_TAbs: a From 75e910576fd4ff30c3a4c9f03c27d87e94dc557c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20van=20Br=C3=BCgge?= Date: Tue, 22 Jun 2021 17:28:29 +0200 Subject: [PATCH 7/8] Prove the strong induction of the typing judgement --- Defs.thy | 65 +++-- Defs2.thy | 43 ++-- Lemmas.thy | 78 ++++++ Nominal2_Lemmas.thy | 11 + Semantics.thy | 2 +- Syntax.thy | 6 + Typing.thy | 601 ++++++++++++++++++++++++++++++++++++++------ 7 files changed, 692 insertions(+), 114 deletions(-) diff --git a/Defs.thy b/Defs.thy index 3fa6847..eaadfae 100644 --- a/Defs.thy +++ b/Defs.thy @@ -83,10 +83,7 @@ nominal_function ctor_data_app :: "\ \ (data_name * tyvar list) | "ctor_data_app (TyApp \1 (TyVar a)) = (case ctor_data_app \1 of Some (T, tys) \ Some (T, a#tys) | None \ None)" -| "ctor_data_app (TyApp _ (TyData _)) = None" -| "ctor_data_app (TyApp _ TyArrow) = None" -| "ctor_data_app (TyApp _ (TyApp _ _)) = None" -| "ctor_data_app (TyApp _ (TyForall _ _ _)) = None" +| "\a. \2 = TyVar a \ ctor_data_app (TyApp _ \2) = None" | "ctor_data_app (TyForall _ _ _) = None" proof goal_cases case 1 @@ -96,7 +93,7 @@ next then show ?case proof (cases x rule: \.exhaust) case (TyApp \1 \2) - then show ?thesis using 3 by (cases \2 rule: \.exhaust) auto + then show ?thesis using 3 by (cases "\a. \2 = TyVar a") auto qed auto qed auto nominal_termination (eqvt) by lexicographic_order @@ -106,32 +103,15 @@ nominal_function ctor_type_app :: "\ \ (data_name * tyvar list) | "ctor_type_app (TyData T) = Some (T, [])" | "ctor_type_app TyArrow = None" | "ctor_type_app (TyApp (TyApp TyArrow \1) \2) = ctor_type_app \2" -| "ctor_type_app (TyApp (TyApp (TyVar a) \1) \2) = ctor_data_app (TyApp (TyApp (TyVar a) \1) \2)" -| "ctor_type_app (TyApp (TyApp (TyData T) \1) \2) = ctor_data_app (TyApp (TyApp (TyData T) \1) \2)" -| "ctor_type_app (TyApp (TyApp (TyApp \1' \2') \1) \2) = ctor_data_app (TyApp (TyApp (TyApp \1' \2') \1) \2)" -| "ctor_type_app (TyApp (TyApp (TyForall a k e) \1) \2) = ctor_data_app (TyApp (TyApp (TyForall a k e) \1) \2)" -| "ctor_type_app (TyApp (TyVar a) \2) = ctor_data_app (TyApp (TyVar a) \2)" -| "ctor_type_app (TyApp (TyData T) \2) = ctor_data_app (TyApp (TyData T) \2)" -| "ctor_type_app (TyApp TyArrow \2) = ctor_data_app (TyApp TyArrow \2)" -| "ctor_type_app (TyApp (TyForall a k e) \2) = ctor_data_app (TyApp (TyForall a k e) \2)" +| "\\1'. \1 = TyApp TyArrow \1' \ ctor_type_app (TyApp \1 \2) = ctor_data_app (TyApp \1 \2)" | "ctor_type_app (TyForall _ _ _) = None" proof goal_cases case (3 P x) then show ?case proof (cases x rule: \.exhaust) - case outer: (TyApp \1 \2) - then show ?thesis using 3 - proof (cases \1 rule: \.exhaust) - case (TyApp \1 \2) - then show ?thesis using outer 3 by (cases \1 rule: \.exhaust) auto - qed auto - qed auto -next - case (74 a k e \1 \2 a k e \1 \2) - then show ?case by presburger -next - case (92 a k e \2 a k e \2) - then show ?case by presburger + case (TyApp e1 e2) + then show ?thesis using 3(4,5) by (cases "\\1'. e1 = TyApp TyArrow \1'") auto + qed (auto simp: 3) qed (auto simp: eqvt_def ctor_type_app_graph_aux_def) nominal_termination (eqvt) by lexicographic_order @@ -192,7 +172,7 @@ nominal_function ctor_type :: "\ \ (data_name * \ list) | "ctor_type (TyData T) = Some (T, [])" | "ctor_type TyArrow = None" | "ctor_type (TyApp \1 \2) = (case ctor_type_app (TyApp \1 \2) of Some (T, []) \ Some (T, []) | _ \ None)" -| "ctor_type (TyForall a k e) = (case ctor_type_forall (TyForall a k e) of Some (T, [], ks) \ Some (T, k#ks) | _ \ None)" +| "ctor_type (TyForall a k e) = (case ctor_type_forall (TyForall a k e) of Some (T, [], ks) \ Some (T, ks) | _ \ None)" proof goal_cases case 1 then show ?case by (auto simp: eqvt_def ctor_type_graph_aux_def split!: option.splits list.splits) @@ -465,4 +445,35 @@ consts subst :: "'a \ 'b \ 'c \ 'a" ("_[_'/_ adhoc_overloading subst subst_term subst_alt_list subst_alt subst_type subst_term_type subst_alt_list_type subst_alt_type subst_context +fun get_tyvars :: "atom list \ tyvar list" where + "get_tyvars [] = []" +| "get_tyvars (a#as) = (if sort_of a = sort_of (atom (undefined :: tyvar)) + then Abs_tyvar a # get_tyvars as + else get_tyvars as)" + +fun get_vars :: "atom list \ var list" where + "get_vars [] = []" +| "get_vars (a#as) = (if sort_of a = sort_of (atom (undefined :: var)) + then Abs_var a # get_vars as + else get_vars as)" + +lemma get_tyvars_append: "get_tyvars (map atom (tys::tyvar list) @ map atom (vars::var list)) = tys" +proof (induction tys arbitrary: vars) +case Nil + then show ?case by (induction vars) auto +next + case (Cons a tys) + then show ?case apply auto by (simp add: Rep_tyvar_inverse atom_tyvar_def) +qed + +lemma get_vars_append: "get_vars (map atom (tys::tyvar list) @ map atom (vars::var list)) = vars" +proof (induction tys arbitrary: vars) + case outer: Nil + then show ?case + proof (induction vars) + case (Cons a vars) + then show ?case apply auto by (simp add: Rep_var_inverse atom_var_def) + qed simp +qed simp + end diff --git a/Defs2.thy b/Defs2.thy index c620065..ebb2ef8 100644 --- a/Defs2.thy +++ b/Defs2.thy @@ -21,14 +21,7 @@ nominal_function ctor_args :: "\ \ \ list option" where | "ctor_args (TyApp (TyApp TyArrow \1) \2) = (case ctor_args \2 of Some tys \ Some (\1#tys) | None \ None)" -| "ctor_args (TyApp (TyApp (TyVar a) \1) \2) = (if ctor_data_app_subst (TyApp (TyApp (TyVar a) \1) \2) then Some [] else None)" -| "ctor_args (TyApp (TyApp (TyData T) \1) \2) = (if ctor_data_app_subst (TyApp (TyApp (TyData T) \1) \2) then Some [] else None)" -| "ctor_args (TyApp (TyApp (TyApp \1' \2') \1) \2) = (if ctor_data_app_subst (TyApp (TyApp (TyApp \1' \2') \1) \2) then Some [] else None)" -| "ctor_args (TyApp (TyApp (TyForall a k e) \1) \2) = (if ctor_data_app_subst (TyApp (TyApp (TyForall a k e) \1) \2) then Some [] else None)" -| "ctor_args (TyApp (TyVar a) \2) = (if ctor_data_app_subst (TyApp (TyVar a) \2) then Some [] else None)" -| "ctor_args (TyApp (TyData T) \2) = (if ctor_data_app_subst (TyApp (TyData T) \2) then Some [] else None)" -| "ctor_args (TyApp TyArrow \2) = (if ctor_data_app_subst (TyApp TyArrow \2) then Some [] else None)" -| "ctor_args (TyApp (TyForall a k e) \2) = (if ctor_data_app_subst (TyApp (TyForall a k e) \2) then Some [] else None)" +| "\\1'. \1 = TyApp TyArrow \1' \ ctor_args (TyApp \1 \2) = (if ctor_data_app_subst (TyApp \1 \2) then Some [] else None)" | "ctor_args (TyForall _ _ _) = None" proof goal_cases case 1 @@ -37,12 +30,8 @@ next case (3 P x) then show ?case proof (cases x rule: \.exhaust) - case outer: (TyApp \1 \2) - then show ?thesis using 3 - proof (cases \1 rule: \.exhaust) - case (TyApp \1 \2) - then show ?thesis using outer 3 by (cases \1 rule: \.exhaust) auto - qed auto + case (TyApp \1 \2) + then show ?thesis using 3 by (cases "\\1'. \1 = TyApp TyArrow \1'") auto qed auto qed auto nominal_termination (eqvt) by lexicographic_order @@ -76,4 +65,30 @@ next qed (auto simp: eqvt_def subst_ctor_graph_aux_def) nominal_termination (eqvt) by lexicographic_order +lemma supp_ctor_args: "ctor_args \ = Some args \ supp args \ supp \" +proof (induction \ arbitrary: args rule: ctor_args.induct) + case (2 T) + then show ?case unfolding \.supp(2) pure_supp using supp_Nil by simp +next + case (4 \1 \2) + then show ?case apply (auto split!: option.splits) unfolding \.supp supp_Cons by auto +next + case (5 \1 \2 a) + then show ?case using supp_Nil by (auto split!: if_splits) +qed auto + +lemma supp_subst_ctor: "subst_ctor \ \s = Some args \ supp args \ supp \ \ supp \s" +proof (induction \ \s arbitrary: args rule: subst_ctor.induct) + case (3 T) + then show ?case unfolding \.supp(2) pure_supp by simp +next + case (5 \1 \2) + then have "ctor_args (TyApp \1 \2) = Some args" by simp + then show ?case using supp_Nil supp_ctor_args by auto +next + case (8 a k e \ \s) + then have "supp args \ supp e[\/a] \ supp \s" by simp + then show ?case unfolding \.supp(5) pure_supp supp_Cons using supp_subst_type by fastforce +qed auto + end \ No newline at end of file diff --git a/Lemmas.thy b/Lemmas.thy index 10f7ae9..7622018 100644 --- a/Lemmas.thy +++ b/Lemmas.thy @@ -173,6 +173,7 @@ lemma fresh_not_isin_tyvar: "atom a \ \ \ \is lemma fresh_not_isin_var: "atom x \ \ \ \isin (BVar x \) \" apply (induction \) apply simp by (metis (mono_tags, lifting) binder.fresh(1) binder.strong_exhaust fresh_Cons fresh_at_base(2) isin.simps(2) isin.simps(3)) +lemmas fresh_not_isin = fresh_not_isin_tyvar fresh_not_isin_var (* atom x \ t \ subst t' x t = t *) lemma fresh_subst_term_same: @@ -254,4 +255,81 @@ lemma fv_supp_subset: "fv_\ \ \ supp \" lemma head_ctor_is_value: "head_ctor e \ is_value e" by (induction e rule: term_alt_list_alt.inducts(1)) auto +lemma strengthen_isin_tyvar: "isin (BTyVar a k) (\' @ BVar x \ # \) \ isin (BTyVar a k) (\' @ \)" +proof (induction \') + case (Cons a \') + then show ?case by (cases a rule: binder.exhaust) auto +qed auto + +lemma isin_split: "isin bndr \ \ \\1 \2. \ = \1 @ bndr # \2" +proof (induction \) + case (Cons a \) + then show ?case + proof (cases "a = bndr") + case True + then show ?thesis by blast + next + case False + then have "isin bndr \" using Cons(2) + by (cases a rule: binder.exhaust; cases bndr rule: binder.exhaust) auto + then show ?thesis using Cons(1) by (metis Cons_eq_appendI) + qed +qed simp + +lemma supp_subst_type: "supp (subst_type \ \ a) \ (supp \ - {atom a}) \ supp \" +proof (induction \ \ a rule: subst_type.induct) + case (2 b \ a) + then show ?case by (cases "b = a") (auto simp: supp_at_base \.supp(1)) +qed (auto simp: \.supp pure_supp) + +lemma supp_head_data: "head_data \ = Some (T, \s) \ supp \s \ supp \" +proof (induction \ arbitrary: \s rule: head_data.induct) + case (2 T) + then show ?case using \.supp(2) pure_supp supp_Nil by auto +next + case (4 \1 \2) + then obtain xs where P: "head_data \1 = Some (T, xs)" by (auto split!: option.splits) + then have 1: "supp xs \ supp \1" by (rule 4(1)) + from 4(2) P have "\s = xs @ [\2]" by auto + then show ?case using 1 supp_append supp_Nil supp_Cons unfolding \.supp(4) by blast +qed auto + +lemma supp_zip_with_var: "supp (zip_with BVar vals args) \ supp vals \ supp args" +proof (induction vals arbitrary: args) + case Nil + then show ?case using supp_Nil by auto +next + case (Cons a vals) + then show ?case by (cases args) (auto simp: supp_Nil supp_Cons binder.supp) +qed + +lemma supp_zip_with_tyvar: "supp (zip_with BTyVar tys ks) \ supp tys \ supp ks" +proof (induction tys arbitrary: ks) + case Nil + then show ?case using supp_Nil by auto +next + case (Cons a vals) + then show ?case by (cases ks) (auto simp: supp_Nil supp_Cons binder.supp) +qed +lemmas supp_zip_with = supp_zip_with_var supp_zip_with_tyvar + +lemma supp_vars: "supp (vars::var list) = set (map atom vars)" + by (induction vars) (auto simp: supp_Nil supp_Cons supp_at_base) +lemma supp_tyvars: "supp (tyvars::tyvar list) = set (map atom tyvars)" + by (induction tyvars) (auto simp: supp_Nil supp_Cons supp_at_base) + +lemma permute_atoms_split: + fixes tys tys2::"tyvar list" and vars vars2::"var list" + assumes "p \ (map atom tys2 @ map atom vars2) = map atom tys @ map atom vars" + shows "p \ tys2 = tys" "p \ vars2 = vars" +proof - + have 1: "map atom (p \ tys2) @ map atom (p \ vars2) = map atom tys @ map atom vars" (is "?L = ?R") + using assms by simp + then have "get_tyvars ?L = get_tyvars ?R" by simp + then show "p \ tys2 = tys" using get_tyvars_append by auto + + from 1 have "get_vars ?L = get_vars ?R" by simp + then show "p \ vars2 = vars" using get_vars_append by auto +qed + end diff --git a/Nominal2_Lemmas.thy b/Nominal2_Lemmas.thy index 0c6a200..57cb3d2 100644 --- a/Nominal2_Lemmas.thy +++ b/Nominal2_Lemmas.thy @@ -92,6 +92,11 @@ lemma Abs_rename_body: shows "(a \ b) \ e1 = e2" by (metis Abs1_eq_iff'(3) Nominal2_Base.swap_self assms flip_commute flip_def fresh_star_zero supp_perm_eq_test) +lemma Abs_rename_body_star: + fixes as bs::"atom list" and e1 e2::"'b::fs" + assumes "[as]lst. e1 = [bs]lst. e2" + obtains p where "p \ e1 = e2" "p \ as = bs" "supp p \ set as \ set bs" + by (metis (full_types) Abs_eq_iff2(3) alpha_lst.simps assms) lemma fresh_filter: "a = b \ atom a \ xs \ atom a \ filter (\x. x \ b) xs" by (induction xs) (auto simp: fresh_Cons fresh_Nil) @@ -107,4 +112,10 @@ lemma eqvt_fBall[eqvt]: "p \ fBall s f = fBall (p \ s) (p \ xs = ys" + shows "length xs = length ys" +using assms by (induction xs arbitrary: ys) auto + end diff --git a/Semantics.thy b/Semantics.thy index 871dce4..ba0f749 100644 --- a/Semantics.thy +++ b/Semantics.thy @@ -47,7 +47,7 @@ next show ?case proof (rule ccontr) assume "\beta_nf (TApp e \)" - then obtain e' where "TApp e \ \ e'" using beta_nf_def by blast + then obtain e' where "TApp e \ \ e'" using beta_nf_def (* by blast*) then show "False" using TApp head_ctor_is_value beta_nf_def by cases auto qed next diff --git a/Syntax.thy b/Syntax.thy index d5450c7..8304ad5 100644 --- a/Syntax.thy +++ b/Syntax.thy @@ -23,6 +23,12 @@ nominal_datatype "\" = Star ("\") | KArrow "\" "\" (infixr "\" 50) +instance \ :: pure +proof (standard, goal_cases) + case (1 p x) + then show ?case by (induction x rule: \.induct) auto +qed + nominal_datatype "\" = TyVar "tyvar" | TyData "data_name" diff --git a/Typing.thy b/Typing.thy index dc635e4..703792d 100644 --- a/Typing.thy +++ b/Typing.thy @@ -41,7 +41,9 @@ syntax translations "\x|\|A. P" \ "CONST fBall A (\x. P)" -inductive Tm :: "\ \ \ \ term \ \ \ bool" ("_ , _ \ _ : _" 50) where +inductive Tm :: "\ \ \ \ term \ \ \ bool" ("_ , _ \ _ : _" 50) and + Alts :: "\ \ \ \ term \ alt_list \ \ \ bool" and + Alt :: "\ \ \ \ term \ alt \ \ \ bool" where Tm_Var: "\ \ \ \ ; BVar x \ \ \ \ \ \ , \ \ (Var x) : \" | Tm_Abs: "BVar x \1 # \ , \ \ e : \2 \ \ , \ \ (\ x : \1 . e) : (\1 \ \2)" @@ -56,12 +58,16 @@ inductive Tm :: "\ \ \ \ term \ \ , \ \ e1 : \1 ; BVar x \1 # \ , \ \ e2 : \2 \ \ \ , \ \ Let x \1 e1 e2 : \2" -| Tm_Case: "\ \ , \ \ e : \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; - \e |\| set_alts alts. (\K tys vals e' cty ks. - e = MatchCtor K tys vals e' \ - AxCtor K cty \ set \ \ ctor_type cty = Some (T, ks) \ - \ , \ \ e' : \ - ) \ \ \ , \ \ Case e alts : \" +| Tm_Case: "\ \ , \ \ e : \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; Alts \ \ e alts \ \ \ \ , \ \ Case e alts : \" + +| Alts_Nil: "Alts \ \ e ANil \" + +| Alts_Cons: "\ Alt \ \ e alt \ ; Alts \ \ e alts \ \ \ Alts \ \ e (ACons alt alts) \" + +| Alt_Ctor: "\ \ , \ \ e : \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; + AxCtor K cty \ set \ ; ctor_type cty = Some (T, ks) ; subst_ctor cty \s = Some args ; + length vals = length args ; length tys = length ks ; + zip_with BVar vals args @ zip_with BTyVar tys ks @ \ , \ \ e' : \ \ \ Alt \ \ e (MatchCtor K tys vals e') \" equivariance Tm @@ -88,6 +94,10 @@ inductive_cases TmE[elim!]: "\ , \ \ App e1 e2 : \2" "\ , \ \ TApp e \ : \2" "\ , \ \ Ctor D : \" + "\ , \ \ Case e alts : \" + +inductive_cases AltsE[elim!]: + "Alts \ \ e (ACons alt alts) \" (* Split induction principles *) lemma Ty_induct[consumes 1, case_names Var App Data Arrow Forall]: @@ -111,9 +121,9 @@ lemma Tm_induct[consumes 1, case_names Var Abs App TAbs TApp Ctor Let Case]: and "\\ \ e a k \ \. \ \ , \ \ e : \ a : k . \ ; P \ \ e (\ a : k . \) ; \ , \ \\<^sub>t\<^sub>y \ : k \ \ P \ \ (TApp e \) \[\/a]" and "\\ \ D \. \ \ \ \ ; AxCtor D \ \ set \ \ \ P \ \ (Ctor D) \" and "\\ \ e1 \1 x e2 \2. \ \ , \ \ e1 : \1 ; P \ \ e1 \1 ; BVar x \1 # \ , \ \ e2 : \2 ; P (BVar x \1 # \) \ e2 \2 \ \ P \ \ (Let x \1 e1 e2) \2" - and "\\ \ e \1 T \s \ alts. \ \ , \ \ e : \1 ; P \ \ e \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; Alts \ \ T \s \1 alts \ \ \ P \ \ (Case e alts) \" + and "\\ \ e \1 T \s \ alts. \ \ , \ \ e : \1 ; P \ \ e \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; Alts \ \ e alts \ \ \ P \ \ (Case e alts) \" shows "P \ \ e \" - using Tm_Alts.inducts(1)[OF assms(1), of _ "\_ _ _ _ _ _ _. True"] assms(2-9) by auto + using Tm_Alts_Alt.inducts(1)[OF assms(1), of _ "\_ _ _ _ _. True" "\_ _ _ _ _. True"] assms(2-9) by auto (* axiom validity *) lemma axioms_valid_aux: @@ -201,33 +211,41 @@ lemma context_valid_tm: "\ , \ \ e : \ \ \ e \ rule: Tm_induct) (auto simp: context_valid_ty) lemmas context_valid = context_valid_ty context_valid_tm - - -(* \ \ \ e : t ; atom x \ \ \ \ atom x \ e *) -lemma fresh_in_context_ty: "\ \ , \ \\<^sub>t\<^sub>y \ : k ; atom (a::tyvar) \ \ \ \ atom a \ \" +lemma supp_in_context_ty: "\ , \ \\<^sub>t\<^sub>y \ : k \ supp \ \ supp \" proof (induction \ \ \ k rule: Ty_induct) case (Var \ \ a k) - then show ?case using fresh_at_base(2) fresh_not_isin_tyvar by fastforce -qed (auto simp: fresh_Cons) + then show ?case by (metis \.supp(1) fresh_def fresh_not_isin_tyvar singletonD subsetCI supp_at_base) +next + case (Forall \ \ a k \) + from Forall(2) show ?case unfolding supp_Cons binder.supp(2) \.supp(5) pure_supp supp_at_base by auto +qed (auto simp: \.supp pure_supp) -lemma fresh_in_axioms: "\ \ \ atom (a::tyvar) \ \" -proof - - fix \ \ k - assume a: "\ \" - let ?Q = "\b c d e. atom a \ c" - let ?W = "\b c. atom a \ b" - - have "(\ \ \ atom a \ \) \ (\ \ \ \ ?W \ \) \ (\ , \ \\<^sub>t\<^sub>y \ : k \ ?Q \ \ \ k)" - proof (induction rule: Ax_Ctx_Ty.induct[of "\x. atom a \ x" ?Q ?W]) - case (Ax_Ctor \ \ D) - then show ?case using fresh_in_context_ty[OF Ax_Ctor(1) fresh_Nil] fresh_Cons fresh_Nil by fastforce - qed (auto simp: fresh_Nil fresh_Cons) - - then show ?thesis using a by simp -qed +corollary fresh_in_context_ty: "\ \ , \ \\<^sub>t\<^sub>y \ : k ; atom (a::tyvar) \ \ \ \ atom a \ \" + unfolding fresh_def using supp_in_context_ty by blast -lemma perm_axioms_tyvars[simp]: "\ \ \ ((a::tyvar) \ b) \ \ = \" - using flip_fresh_fresh fresh_in_axioms by blast +lemma axioms_cons_valid[elim]: "\ ax # \ \ (\ \ \ P) \ P" + by (cases rule: Ax.cases) (auto simp: axioms_valid(2)) + +lemma axioms_empty_supp: "\ \ \ supp \ = {}" +proof (induction \) + case (Cons a \) + then show ?case + proof (cases a rule: axiom.exhaust) + case (AxData D k) + then show ?thesis by (metis AxE(1) Cons.IH Cons.prems axiom.supp(1) pure_supp supp_Cons) + next + case (AxCtor K \) + then have "[] , \ \\<^sub>t\<^sub>y \ : \" using Cons by blast + then have 1: "supp \ = {}" using supp_in_context_ty supp_Nil by blast + have 2: "supp \ = {}" using Cons by auto + then show ?thesis using 1 AxCtor axiom.supp(2) pure_supp unfolding supp_Cons by blast + qed +qed (simp add: supp_Nil) + +corollary fresh_in_axioms: "\ \ \ atom (a::tyvar) \ \" + unfolding fresh_def using axioms_empty_supp by simp +corollary permute_axioms[simp]: "\ \ \ p \ \ = \" + using axioms_empty_supp by (simp add: fresh_star_def supp_perm_eq) nominal_inductive Ax avoids Ty_Forall: a @@ -241,71 +259,500 @@ proof goal_cases then show ?case using 2 fresh_star_def by fastforce qed auto +lemma var_strengthen_aux: + shows "\ \ \' @ BVar x \ # \ \ \ \ \' @ \" + and "\' @ BVar x \ # \ , \ \\<^sub>t\<^sub>y \ : k \ \' @ \ , \ \\<^sub>t\<^sub>y \ : k" +proof (induction rule: Ctx_Ty_induct_split) + case Ctx_Empty + then show ?case using context_valid(1) by auto +next + case (Ctx_TyVar \' b k2) + then show ?case by (metis Ctx.simps append_Cons fresh_Cons fresh_append) +next + case (Ctx_Var \' \ x) + then have "atom x \ \' @ \" using fresh_append fresh_Cons by blast + then show ?case using Ctx_intros(3)[OF Ctx_Var(2)] by simp +next + case (Ty_Var \' b k2) + then have "BTyVar b k2 \ (\' @ \)" using strengthen_isin_tyvar by simp + then show ?case by (rule Ty_intros(1)[OF Ty_Var(2)]) +qed (auto intro: Ty_intros) +lemma var_strengthen_context: "\ \ \' @ BVar x \ # \ \ \ \ \' @ \" + using var_strengthen_aux by simp +lemma var_strengthen_ty: "\' @ BVar x \ # \ , \ \\<^sub>t\<^sub>y \ : k \ \' @ \ , \ \\<^sub>t\<^sub>y \ : k" + using var_strengthen_aux by simp +lemmas strengthen = var_strengthen_context var_strengthen_ty + +lemma context_cons_valid[elim]: "(\::\) \ bndr # \ \ (\ \ \ \ P) \ P" + by (cases rule: Ctx.cases) (auto simp: context_valid(1)) + +lemma isin_subset: + fixes \::"\" + assumes "\ \ \' @ \" + shows "bndr \ \ \ bndr \ (\' @ \)" +proof + assume "bndr \ \" + then show "bndr \ (\' @ \)" + using assms proof (induction \' arbitrary: \) + case (Cons b \2) + have 1: "\ \ \2 @ \" using Cons(3) by auto + have 2: "bndr \ (\2 @ \)" by (rule Cons(1)[OF Cons(2) 1]) + show ?case + proof (cases b rule: binder.exhaust) + case (BVar x \) + then have "atom x \ (\2 @ \)" using Cons by auto + then show ?thesis using 2 BVar fresh_not_isin_var by (cases bndr rule: binder.exhaust) auto + next + case (BTyVar a k) + then have "atom a \ (\2 @ \)" using Cons by auto + then show ?thesis using 2 BTyVar fresh_not_isin_tyvar by (cases bndr rule: binder.exhaust) auto + qed + qed auto +qed +lemma Ty_Forall_Inv: + assumes a: "\ , \ \\<^sub>t\<^sub>y (\a:k. \) : \" and b: "atom a \ \" + shows "BTyVar a k # \ , \ \\<^sub>t\<^sub>y \ : \ \ \ = \" +proof (cases rule: Ty.cases[OF a]) + case (5 a' k' \' \' \') + then have 1: "(BTyVar a' k # \) , \ \\<^sub>t\<^sub>y \' : \" by simp + have valid: "\ \" by (rule axioms_valid(2)[OF 1]) + have "(a' \ a) \ \' = \" using Abs_rename_body[of a' \' a \] 5(3) by auto + then have 2: "((a' \ a) \ (BTyVar a' k # \)) , \ \\<^sub>t\<^sub>y \ : \" using Ty.eqvt[OF 1, of "(a' \ a)"] valid by auto + have 3: "((a' \ a) \ (BTyVar a' k # \)) = BTyVar a k # ((a' \ a) \ \)" using Cons_eqvt flip_fresh_fresh by force + have 4: "(a' \ a) \ \ = \" by (metis 5(1,5) CtxE(1) b context_valid_ty flip_def swap_fresh_fresh) + show ?thesis using 2 3 4 5(4) by argo +qed simp_all + +lemma weaken_isin: "\ bndr \ (\ @ \') ; \ \ \ @ xs @ \' \ \ bndr \ (\ @ xs @ \')" +proof (induction \ arbitrary: bndr \' xs) + case Nil + then show ?case by (cases bndr rule: binder.exhaust) (auto simp: isin_subset) +next + case (Cons b \) + have 1: "\ \ \ @ xs @ \'" using Cons(3) Ctx.cases by auto + then show ?case + proof (cases b rule: binder.exhaust) + case (BVar x \) + then show ?thesis using 1 Cons by (cases bndr rule: binder.exhaust) auto + next + case (BTyVar a k) + then show ?thesis using 1 Cons by (cases bndr rule: binder.exhaust) auto + qed +qed +lemma weaken_ty: "\ \ @ \' , \ \\<^sub>t\<^sub>y \ : k ; \ \ \ @ xs @ \' \ \ \ @ xs @ \' , \ \\<^sub>t\<^sub>y \ : k" +proof (nominal_induct \ avoiding: \ \' xs k rule: \.strong_induct) + case (TyVar x) + have 1: "BTyVar x k \ (\ @ \')" by (cases rule: Ty.cases[OF TyVar(1)]) auto + show ?case by (rule Ty_Var[OF TyVar(2) weaken_isin[OF 1 TyVar(2)]]) +next + case (TyData T) + then have "AxData T k \ set \" by blast + then show ?case by (rule Ty_Data[OF TyData(2)]) +next + case TyArrow + then have "k = (\ \ \ \ \)" by blast + then show ?case using Ty_Arrow[OF TyArrow(2)] by argo +next + case (TyApp \1 \2) + then obtain k1 where P: "\ @ \' , \ \\<^sub>t\<^sub>y \1 : k1 \ k" "\ @ \' , \ \\<^sub>t\<^sub>y \2 : k1" by blast + have 2: "\ @ xs @ \' , \ \\<^sub>t\<^sub>y \1 : k1 \ k" by (rule TyApp(1)[OF P(1) TyApp(4)]) + have 3: "\ @ xs @ \' , \ \\<^sub>t\<^sub>y \2 : k1" by (rule TyApp(2)[OF P(2) TyApp(4)]) + show ?case by (rule Ty_App[OF 2 3]) +next + case (TyForall a k1 \) + have P: "(BTyVar a k1 # \) @ \' , \ \\<^sub>t\<^sub>y \ : \" "k = \" using Ty_Forall_Inv[OF TyForall(6)] TyForall(1,2) fresh_append by auto + have 1: "atom a \ \ @ xs @ \'" using TyForall(1-3) fresh_append by blast + have 2: "\ \ (BTyVar a k1 # \) @ xs @ \'" using Ctx_TyVar[OF TyForall(7) 1] by simp + have 3: "BTyVar a k1 # \ @ xs @ \' , \ \\<^sub>t\<^sub>y \ : \" using TyForall(5)[OF P(1) 2] by simp + show ?case using Ty_Forall[OF 3] P(2) by simp +qed +lemma weaken_axioms_ty: "\ \ , \' @ \ \\<^sub>t\<^sub>y \ : k ; \' @ xs @ \ \ \ \ \ \ , \' @ xs @ \ \\<^sub>t\<^sub>y \ : k" +proof (nominal_induct \ avoiding: \ \' k xs \ rule: \.strong_induct) + case (TyApp \1 \2) + then show ?case using Ty_App by blast +next + case (TyForall a k1 \) + have P: "BTyVar a k1 # \ , \' @ \ \\<^sub>t\<^sub>y \ : \" "k = \" using Ty_Forall_Inv[OF TyForall(7,5)] by auto + have 1: "BTyVar a k1 # \ , \' @ xs @ \ \\<^sub>t\<^sub>y \ : \" by (rule TyForall(6)[OF P(1) Ctx_TyVar[OF TyForall(8,5)]]) + show ?case using Ty_Forall[OF 1] P(2) by argo +qed (auto intro: Ty_intros) +lemmas weaken = weaken_isin weaken_ty weaken_axioms_ty + +(* inversion rules for abstractions *) +lemma T_Abs_Inv: + assumes a: "\ , \ \ (\x : \1 . e) : \" and b: "atom x \ \" + obtains \2 where "BVar x \1 # \ , \ \ e : \2" "\ = arrow_app \1 \2" +proof (cases rule: Tm.cases[OF a]) + case (2 x' \1' \' \' e' \2) + then have swap: "(x' \ x) \ e' = e" using Abs_rename_body[of x' e' x e] by auto + have valid: "\ \" using axioms_valid(3)[OF 2(5)] 2(2) by simp + show ?thesis + proof (cases "atom x' = atom x") + case True + then show ?thesis using 2 swap that by auto + next + case False + then have 1: "atom x \ BVar x' \1' # \'" using b by (simp add: 2 fresh_Cons) + have 3: "((x' \ x) \ (BVar x' \1 # \)) , \ \ (x' \ x) \ e' : \2" using 2 Tm.eqvt[OF 2(5), of "(x' \ x)"] by fastforce + have "((x' \ x) \ (BVar x' \1) # ((x' \ x) \ \)) = BVar x \1 # \" + by (metis "1" "2"(1) "2"(5) CtxE(2) binder.perm_simps(1) context_valid_tm flip_at_simps(1) flip_fresh_fresh fresh_Cons perm_\_vars) + then show ?thesis using 1 2 3 swap that by auto + qed +qed simp_all + +lemma T_Let_Inv: + assumes a: "\ , \ \ Let x \1 e1 e2 : \" and b: "atom x \ \" + shows "\ , \ \ e1 : \1 \ BVar x \1 # \ , \ \ e2 : \" +proof (cases rule: Tm.cases[OF a]) + case (7 \' \' e1' \1' x' e2' \2') + have swap: "(x' \ x) \ e2' = e2" using Abs_rename_body[of x' e2' x e2] 7(3) by simp + show ?thesis + proof (cases "atom x' = atom x") + case True + then show ?thesis using 7 swap by auto + next + case False + then have 1: "atom x \ BVar x' \1 # \'" using b by (simp add: 7 fresh_Cons) + have 2: "((x' \ x) \ (BVar x' \1#\)) , \ \ (x' \ x) \ e2' : \" using Tm.eqvt[OF 7(6), of "(x' \ x)"] 7 by auto + have 3: "((x' \ x) \ (BVar x' \1) # ((x' \ x) \ \)) = BVar x \1#\" + by (metis "1" 7(1,6) CtxE(2) binder.perm_simps(1) context_valid_tm flip_at_simps(1) flip_def fresh_Cons perm_\_vars swap_fresh_fresh) + from 2 3 7 swap show ?thesis by auto + qed +qed simp_all + +lemma T_AbsT_Inv: + assumes a: "\ , \ \ (\ a : k . e) : \" and b: "atom a \ \" "atom a \ \" + obtains \ where "BTyVar a k # \ , \ \ e : \" "\ = (\ a:k. \)" +proof (cases rule: Tm.cases[OF a]) + case (4 a' k' \' \' e' \') + then have fresh: "atom a' \ \" by (cases rule: Ctx.cases[OF context_valid(2)[OF 4(5)]]) auto + have swap: "(a' \ a) \ e' = e" using Abs_rename_body[of a' e' a e] 4(3) by simp + have valid: "\ \" using axioms_valid(3)[OF 4(5)] 4(2) by simp + show ?thesis + proof (cases "atom a = atom a'") + case True + then show ?thesis by (metis 4 Abs1_eq_iff(3) atom_eq_iff term_alt_list_alt.eq_iff(6) that) + next + case False + then have 1: "atom a \ BTyVar a' k # \" using b by (simp add: 4 fresh_Cons) + have 2: "((a' \ a) \ (BTyVar a' k # \)), \ \ (a' \ a) \ e' : (a' \ a) \ \'" using Tm.eqvt[OF 4(5), of "(a' \ a)"] valid 4 by auto + have "((a' \ a) \ (BTyVar a' k # \)) = ((a' \ a) \ BTyVar a' k) # \" using 1 fresh flip_fresh_fresh b(1) by simp + then have "((a' \ a) \ (BTyVar a' k # \)) = BTyVar a k # \" by (simp add: flip_fresh_fresh) + then have "BTyVar a k # \ , \ \ e : (a' \ a) \ \'" using 2 swap by argo + then show ?thesis by (metis "4"(3,4) Abs1_eq_iff(3) False \.eq_iff(5) \.fresh(5) b(2) empty_iff flip_commute insert_iff list.set(1,2) term_alt_list_alt.eq_iff(6) that) + qed +qed simp_all + +lemma zip_with_context_fresh_vars: "\ \ \ zip_with BVar vars xs @ \ ; length vars \ length xs \ \ set (map atom vars) \* \" +proof (induction vars arbitrary: xs) + case Nil + then show ?case using fresh_star_def by auto +next + case (Cons a vars) + then obtain x xs' where P: "xs = x # xs'" by (cases xs) auto + then have 1: "length vars \ length xs'" using Cons by simp + let ?\ = "zip_with BVar vars xs' @ \" + from P have "\ \ BVar a x # ?\" using Cons(2) by simp + then have "?\ , \ \\<^sub>t\<^sub>y x : \" and 2:"atom a \ ?\" by auto + then have 3: "\ \ ?\" using context_valid(1) by simp + show ?case using Cons(1)[OF 3 1] 2 fresh_append + by (metis (no_types, lifting) fresh_star_def list.simps(9) set_ConsD) +qed +lemma zip_with_context_fresh_tyvars: "\ \ \ zip_with BTyVar tys xs @ \ ; length tys \ length xs \ \ set (map atom tys) \* \" +proof (induction tys arbitrary: xs) + case Nil + then show ?case using fresh_star_def by auto +next + case (Cons a vars) + then obtain x xs' where P: "xs = x # xs'" by (cases xs) auto + then have 1: "length vars \ length xs'" using Cons by simp + let ?\ = "zip_with BTyVar vars xs' @ \" + from P have "\ \ BTyVar a x # ?\" using Cons(2) by simp + then have 3: "\ \ ?\" "atom a \ ?\" by auto + show ?case using Cons(1)[OF 3(1) 1] 3(2) fresh_append + by (metis (no_types, lifting) fresh_star_def list.simps(9) set_ConsD) +qed -lemma fresh_in_context_term_var: - assumes "atom (x::var) \ \" - shows "\ , \ \ e : \ \ atom x \ e" - and "Alts \ \ T \s \1 alts \ \ atom x \ alts" - and "Alt \ \ T \ \1 alt \ \ atom x \ alt" -proof (induction \ \ e \ and \ \ T \s \1 alts \ and rule: Tm_Alts.induct) - - - - - - - - - - - - - - - - +lemma context_valid_append: "\::\ \ \' @ \ \ \ \ \" +proof (induction \') + case (Cons a \') + then show ?case using context_valid(1) by (cases a rule: binder.exhaust) auto +qed auto +lemma axioms_split_valid: "\ \' @ \ \ \ \" +proof (induction \') + case (Cons a \') + then show ?case using axioms_valid(2) by (cases a rule: axiom.exhaust) auto +qed simp +lemma axioms_regularity: "\ \' @ AxCtor D \ # \ \ [] , \ \\<^sub>t\<^sub>y \ : \" + using Ax_Ctor axioms_split_valid by (induction \) blast+ -thm Tm_Alts.induct[of "\_ _ e _. atom x \ e" "\_ _ _ _ _ alts _. atom x \ alts" \ \ e \ \ \ T \ \1 alts \] +lemma context_regularity: "\ \ \' @ BVar x \ # \ \ \ , \ \\<^sub>t\<^sub>y \ : \" + using Ctx_Var context_valid_append by (induction \) blast+ +lemma isin_same_kind: "\ BTyVar a k1 \ (\' @ BTyVar a k2 # \) ; \ \ \' @ BTyVar a k2 # \ \ \ k1 = k2" +proof (induction \') + case (Cons bndr \') + then show ?case by (cases rule: Ctx.cases[OF Cons(3)]) (auto split: if_splits simp: fresh_Cons fresh_append fresh_at_base(2)) +qed auto +lemma isin_same_type: "\ BVar x \ \ (\' @ BVar x \2 # \) ; \ \ \' @ BVar x \2 # \ \ \ \ = \2" +proof (induction \') + case (Cons a \') + then show ?case by (cases rule: Ctx.cases[OF Cons(3)]) (auto split: if_splits simp: fresh_Cons fresh_append fresh_at_base) +qed auto +lemmas isin_same = isin_same_kind isin_same_type -lemma fresh_in_context_term_var: "\ \ , \ \ e : \ ; atom (x::var) \ \ \ \ atom x \ e" +lemma isin_subst_tyvar: "\ BTyVar a k \ (\' @ BTyVar b k2 # \) ; \ \ \' @ BTyVar b k2 # \ ; a \ b \ \ BTyVar a k \ (\'[\/b] @ \)" +proof (induction \') + case (Cons bndr \') + then show ?case + proof (cases rule: Ctx.cases[OF Cons(3)]) + case (2 \2 c k3) + then have "BTyVar a k = bndr \ BTyVar a k \ (\' @ BTyVar b k2 # \)" by (metis Cons.prems(1) Cons_eq_append_conv isin.simps(5) list.inject) + then show ?thesis + proof + assume a: "BTyVar a k = bndr" + then show ?thesis using 2 Cons by auto + next + assume "BTyVar a k \ (\' @ BTyVar b k2 # \)" + then show ?thesis using 2 Cons fresh_not_isin_tyvar by auto + qed + next + case (3 \ \ x) + then show ?thesis using Cons by auto + qed simp +qed simp + +lemma axiom_isin_split: "\ b \ set \ ; \ \ \ \ \\1 \2. \ = \1 @ b # \2" +proof (induction \) + case (Cons a \) + then show ?case + proof (cases "a = b") + case True + then show ?thesis by blast + next + case False + then show ?thesis by (meson Cons.prems(1) split_list) + qed +qed simp + +lemma type_substitution_aux: + assumes "\ , \ \\<^sub>t\<^sub>y \ : k" + shows "(\ \ (\' @ BTyVar a k # \) \ \ \ (subst_context \' \ a @ \))" + and "(\' @ BTyVar a k # \ , \ \\<^sub>t\<^sub>y \ : k2 \ subst_context \' \ a @ \ , \ \\<^sub>t\<^sub>y subst_type \ \ a : k2)" +proof (induction rule: Ctx_Ty_induct_split) + case Ctx_Empty + then show ?case using context_valid(1)[OF assms] by simp +next + case (Ctx_TyVar \' b k2) + then have "atom b \ \" using assms fresh_Cons fresh_append fresh_in_context_ty by blast + then have 1: "atom b \ \'[\/a] @ \" by (meson Ctx_TyVar(3) fresh_Cons fresh_append fresh_subst_context_tyvar) + show ?case using Ax_Ctx_Ty.Ctx_TyVar[OF Ctx_TyVar(2) 1] assms by auto +next + case (Ctx_Var \' \ x) + have 1: "atom x \ \'[\/a] @ \" by (meson Ctx_Var(3) fresh_Cons fresh_append fresh_subst_context_var) + show ?case using Ax_Ctx_Ty.Ctx_Var[OF Ctx_Var(2) 1] by simp +next + case (Ty_Var \' b k2) + then show ?case + proof (cases "b = a") + case True + then have "k = k2" using isin_same(1) Ty_Var by blast + then have "\ , \ \\<^sub>t\<^sub>y (TyVar b)[\/a] : k2" using True assms(1) by simp + then show ?thesis using weaken_ty[of "[]"] Ty_Var(2) by auto + next + case False + have 1: "BTyVar b k2 \ (\'[\/a] @ \)" by (rule isin_subst_tyvar[OF Ty_Var(3,1) False]) + show ?thesis using Ax_Ctx_Ty.Ty_Var[OF Ty_Var(2) 1] False by simp + qed +next + case (Ty_Forall \' b k2 \') + have 1: "a \ b" by (metis CtxE(1) Ty_Forall(1) binder.fresh(2) context_valid_ty fresh_Cons fresh_append fresh_at_base(2)) + then have 2: "BTyVar b k2 # \'[\/a] @ \ , \ \\<^sub>t\<^sub>y \'[\/a] : \" using Ty_Forall(2) by simp + show "\'[\/a] @ \ , \ \\<^sub>t\<^sub>y (\ b : k2 . \')[\/a] : \" using Ax_Ctx_Ty.Ty_Forall[OF 2] + by (metis "1" "2" CtxE(1) assms atom_eq_iff context_valid_ty fresh_Pair fresh_append fresh_at_base(2) fresh_in_context_ty subst_type.simps(5)) +qed (auto intro: Ty_intros) +corollary type_substitution_context: "\ \ \ \' @ BTyVar a k # \ ; \ , \ \\<^sub>t\<^sub>y \ : k \ \ \ \ \'[\/a] @ \" + using type_substitution_aux by blast +corollary type_substitution_ty: "\ \' @ BTyVar a k # \ , \ \\<^sub>t\<^sub>y \ : k2 ; \ , \ \\<^sub>t\<^sub>y \ : k \ \ \'[\/a] @ \ , \ \\<^sub>t\<^sub>y \[\/a] : k2" + using type_substitution_aux by blast + +lemma typing_regularity: "\ , \ \ e : \ \ \ , \ \\<^sub>t\<^sub>y \ : \" proof (induction \ \ e \ rule: Tm_induct) case (Var \ \ x \) - then show ?case using fresh_ineq_at_base fresh_not_isin_var by force + then obtain \1 \2 where 1: "\ = \1 @ BVar x \ # \2" using isin_split by blast + then have "\2 , \ \\<^sub>t\<^sub>y \ : \" using context_regularity Var(1) by blast + then show ?case using weaken_ty[of "[]" \2 \ \ \ "\1 @ [BVar x \]"] Var(1) 1 by simp next - case (Case \ \ e \1 T \s \ alts) - then show ?case sorry -qed (auto simp: fresh_Cons) - -lemma fresh_in_context_term_tyvar: "\ \ , \ \ e : \ ; atom (a::tyvar) \ \ \ \ atom a \ e" -proof (induction \ \ e \ rule: Tm.induct) - case (Tm_Abs x \1 \ \ e \2) - then have "atom a \ \1" by (meson CtxE(2) context_valid_tm fresh_in_context_ty) - then show ?case by (simp add: Tm_Abs fresh_Cons) + case (Abs x \1 \ \ e \2) + have 1: "\ , \ \\<^sub>t\<^sub>y \1 : \" using context_regularity context_valid(1)[OF Abs(2)] by blast + have 2: "\ , \ \\<^sub>t\<^sub>y \2 : \" using strengthen(2)[of "[]"] Abs(2) by force + have 3: "\ \ \" by (rule context_valid(1)[OF 1]) + show ?case by (rule Ty_App[OF Ty_App[OF Ty_Arrow[OF 3] 1] 2]) next - case (Tm_Let \ e1 e2 \1 \2 x) - then show ?case - by (metis (mono_tags, lifting) CtxE(2) binder.fresh(1) context_valid_tm fresh_Cons fresh_in_context_ty fresh_ineq_at_base list.set_intros(1) term.fresh(7)) -qed (auto simp: fresh_Cons fresh_in_context_ty) -lemmas fresh_in_context = fresh_in_context_ty fresh_in_context_term_var fresh_in_context_term_tyvar - + case (TApp \ \ e a k \ \) + obtain a' \' where P: "(\ a:k. \) = (\ a':k. \')" "BTyVar a' k # \ , \ \\<^sub>t\<^sub>y \' : \" by (cases rule: Ty.cases[OF TApp(3)]) auto + have "\ , \ \\<^sub>t\<^sub>y \'[\/a'] : \" using type_substitution_ty[of "[]", OF _ TApp(2)] P by auto + then show ?case using P(1) subst_type_same by auto +next + case (Ctor \ \ D \) + from Ctor(1) have 1: "\ \" by (rule axioms_valid(1)) + then obtain \1 \2 where 2: "\ = \1 @ AxCtor D \ # \2" using axiom_isin_split[OF Ctor(2) 1] by blast + then have "[] , \2 \\<^sub>t\<^sub>y \ : \" using axioms_regularity 1 by blast + then have "[] , \ \\<^sub>t\<^sub>y \ : \" using weaken(3)[of "[]" "[]" \2 \ \ "\1 @ [AxCtor D \]"] 1 2 Ctx_Empty by simp + then show ?case using weaken(2)[of "[]" "[]"] Ctor(1) by simp +next + case (Let \ e1 \1 x e2 \2) + then show ?case using strengthen(2)[of "[]"] by force +qed (auto intro: Ty_intros) +corollary supp_cty: "\ \ \ ; AxCtor K cty \ set \ \ \ supp cty = {}" + using axioms_empty_supp by (metis axiom.supp(2) axioms_split_valid split_list sup_bot.neutr_eq_iff supp_Cons) +lemma supp_args: + assumes "\ , \ \ e : \1" "head_data \1 = Some (T, \s)" "AxCtor K cty \ set \" "subst_ctor cty \s = Some args" + shows "supp args \ supp \" +proof - + have 1: "supp cty = {}" by (rule supp_cty[OF axioms_valid(3)[OF assms(1)] assms(3)]) + have "\ , \ \\<^sub>t\<^sub>y \1 : \" by (rule typing_regularity[OF assms(1)]) + then have "supp \1 \ supp \" by (rule supp_in_context_ty) + then have "supp \s \ supp \" using supp_head_data[OF assms(2)] by simp + then show "supp args \ supp \" using supp_subst_ctor[OF assms(4)] 1 by simp +qed +lemma Alt_Ctor_Inv: + assumes a: "Alt \ \ e (MatchCtor K tys vals e') \" + and fresh: "set (map atom tys) \* \" "set (map atom vals) \* \" "set (map atom tys) \* \" +obtains \1 T \s cty ks args where "\ , \ \ e : \1" "head_data \1 = Some (T, \s)" "\ , \ \\<^sub>t\<^sub>y \ : \" "AxCtor K cty \ set \" "ctor_type cty = Some (T, ks)" + "length args = length vals" "length ks = length tys" + "subst_ctor cty \s = Some args" "zip_with BVar vals args @ zip_with BTyVar tys ks @ \ , \ \ e' : \" +proof (cases rule: Alt.cases[OF a]) + case (1 \2 \2 e2 \1 T \s \2 K2 cty ks args vals2 tys2 e'2) + let ?tys = "map atom tys" and ?vals = "map atom vals" + let ?tys2 = "map atom tys2" and ?vals2 = "map atom vals2" + from 1 have 2: "[?tys2 @ ?vals2]lst. e'2 = [?tys @ ?vals]lst. e'" by simp + from 1 have valid: "\ \ zip_with BVar vals2 args @ zip_with BTyVar tys2 ks @ \" using context_valid(2) by simp + then have valid_axioms: "\ \" by (rule axioms_valid(1)) + + have g1: "set ?vals2 \* \" using zip_with_context_fresh_vars[OF valid] 1(12) fresh_append by (simp add: fresh_star_list(1)) + have g2: "set ?tys2 \* \" using zip_with_context_fresh_tyvars valid context_valid_append 1(13) by (metis order_refl) + then have g: "set (?tys2 @ ?vals2) \* \" using g1 using fresh_star_Un by auto + + obtain p where P: "p \ e'2 = e'" "p \ (?tys2 @ ?vals2) = ?tys @ ?vals" "supp p \ set (?tys2 @ ?vals2) \ set (?tys @ ?vals)" by (rule Abs_rename_body_star[OF 2]) + have G: "supp \ \ supp p = {}" using g fresh(1-2) P(3) unfolding fresh_star_def fresh_def using UnE disjoint_iff set_append subsetD by auto + then have 3: "p \ \ = \" by (meson disjoint_iff fresh_def fresh_star_def supp_perm_eq_test) + + from 1(1,2,5) g have t1: "set (?tys2 @ ?vals2) \* \" using fresh_in_context_ty[OF 1(8)] unfolding fresh_star_def by auto + have t2: "set (?tys @ ?vals) \* \" using fresh(3) unfolding fresh_star_def by auto + then have "supp \ \ supp p = {}" using t1 P(3) unfolding fresh_star_def fresh_def by blast + then have 4: "p \ \ = \" by (meson disjoint_iff fresh_def fresh_star_def supp_perm_eq_test) + + have "supp cty = {}" using supp_cty[OF valid_axioms] 1(2,9) by simp + then have 5: "supp args \ supp \s" using supp_subst_ctor 1(11) by blast + + have "supp args \ supp \" using supp_args[OF 1(6,7,9,11)] 1(1) by argo + then have "supp args \ supp p = {}" using G by blast + then have 6: "p \ args = args" by (meson disjoint_iff fresh_def fresh_star_def supp_perm_eq) + have 7: "p \ vals2 = vals" "p \ tys2 = tys" using permute_atoms_split[OF P(2)] by auto + + have "p \ (zip_with BVar vals2 args @ zip_with BTyVar tys2 ks @ \) , p \ \ \ e' : p \ \" using 1(1,2,5,14) P(1) Tm.eqvt by blast + then have "zip_with BVar (p \ vals2) args @ zip_with BTyVar (p \ tys2) ks @ \ , \ \ e' : \" using 3 4 permute_axioms[OF valid_axioms] 6 by simp + then have "zip_with BVar vals args @ zip_with BTyVar tys ks @ \ , \ \ e' : \" using 7 by simp + then show ?thesis using 1 that permute_length[OF 7(1)] permute_length[OF 7(2)] by auto +qed +corollary supp_in_context_term_type: "\ , \ \ e : \ \ supp \ \ supp \" + using typing_regularity supp_in_context_ty by blast +lemma supp_in_context_term_aux: + shows "\ , \ \ e : \ \ supp e \ supp \" + and "\e. Alts \ \ e alts \ \ supp alts \ supp \" + and "\e. Alt \ \ e alt \ \ supp alt \ supp \" +proof (nominal_induct e and alts and alt avoiding: \ \ \ rule: term_alt_list_alt.strong_induct) + case (Var x) + then show ?case by (metis TmE(1) fresh_def fresh_not_isin_var singletonD subsetCI supp_at_base term_alt_list_alt.supp(1)) +next + case (App e1 e2) + then show ?case by (metis TmE(2) Un_least term_alt_list_alt.supp(2)) +next + case (TApp e \) + then show ?case by (metis TmE(3) Un_least supp_in_context_ty term_alt_list_alt.supp(3)) +next + case (Ctor T) + then show ?case using term_alt_list_alt.supp(4) pure_supp by auto +next + case (Lam x \1 e) + show ?case + proof standard + assume a: "\ , \ \ \ x : \1 . e : \" + then have "\ , \ \\<^sub>t\<^sub>y \1 : \" by (meson CtxE(2) Lam.hyps(1) T_Abs_Inv context_valid_tm) + then have 1: "supp \1 \ supp \" by (rule supp_in_context_ty) + have "supp e \ supp (BVar x \1 # \)" using Lam(4) T_Abs_Inv[OF a Lam(1)] by metis + then show "supp (\ x : \1 . e) \ supp \" unfolding term_alt_list_alt.supp supp_Cons binder.supp supp_at_base using 1 by auto + qed +next + case (TyLam a k e) + show ?case + proof standard + assume a: "\ , \ \ \ a : k . e : \" + have "supp e \ supp (BTyVar a k # \)" using TyLam(4) T_AbsT_Inv[OF a TyLam(1,3)] by metis + then show "supp (\ a : k . e) \ supp \" unfolding term_alt_list_alt.supp pure_supp supp_Cons binder.supp supp_at_base by auto + qed +next + case (Let x \1 e1 e2) + show ?case + proof standard + assume a: "\ , \ \ Let x \1 e1 e2 : \" + then have "\ , \ \\<^sub>t\<^sub>y \1 : \" using Let(1) T_Let_Inv typing_regularity by blast + then have 1: "supp \1 \ supp \" by (rule supp_in_context_ty) + have "supp e1 \ supp \" "supp e2 \ supp (BVar x \1 # \)" using Let(4,5) T_Let_Inv[OF a Let(1)] by blast+ + then show "supp (Let x \1 e1 e2) \ supp \" unfolding term_alt_list_alt.supp supp_Cons binder.supp supp_at_base using 1 by auto + qed +next + case (Case e alts) + then show ?case unfolding term_alt_list_alt.supp by blast +next + case ANil + then show ?case using term_alt_list_alt.supp by simp +next + case (ACons alt alts) + then show ?case unfolding term_alt_list_alt.supp by blast +next + case (MatchCtor K tys vals e') + show ?case + proof (standard, standard) + fix e + assume a: "Alt \ \ e (MatchCtor K tys vals e') \" + obtain \1 T \s cty ks args where P: "\ , \ \ e : \1" "head_data \1 = Some (T, \s)" "\ , \ \\<^sub>t\<^sub>y \ : \" "AxCtor K cty \ set \" "ctor_type cty = Some (T, ks)" + "length args = length vals" "length ks = length tys" "subst_ctor cty \s = Some args" "zip_with BVar vals args @ zip_with BTyVar tys ks @ \ , \ \ e' : \" + by (rule Alt_Ctor_Inv[OF a MatchCtor(1,4,3)]) + then have "supp e' \ supp (zip_with BVar vals args @ zip_with BTyVar tys ks @ \)" using MatchCtor(7) by simp + then have "supp e' \ supp vals \ supp args \ supp tys \ supp \" unfolding supp_append using supp_zip_with pure_supp by blast + then have "supp e' \ supp vals \ supp tys \ supp \" using supp_args[OF P(1,2,4,8)] by blast + then show "supp (MatchCtor K tys vals e') \ supp \" unfolding term_alt_list_alt.supp pure_supp supp_vars supp_tyvars by auto + qed +qed +corollary supp_in_context_term: "\ , \ \ e : \ \ supp e \ supp \ \ supp \" + using supp_in_context_ty[OF typing_regularity] supp_in_context_term_aux(1) by simp +lemmas supp_in_context = supp_in_context_ty supp_in_context_term + +corollary fresh_in_context_term_var: "\ \ , \ \ e : \ ; atom (y::var) \ \ \ \ atom y \ e" + using supp_in_context_term unfolding fresh_def by blast +corollary fresh_in_context_term_tyvar: "\ \ , \ \ e : \ ; atom (a::tyvar) \ \ \ \ atom a \ e \ atom a \ \" + using supp_in_context_term unfolding fresh_def by blast +lemmas fresh_in_context = fresh_in_context_ty fresh_in_context_term_var fresh_in_context_term_tyvar nominal_inductive Tm avoids Tm_Abs: x | Tm_TAbs: a | Tm_Let: x + | Alt_Ctor: tys and vals proof goal_cases case (1 x \1 \ \ e \2) then have "\ \ BVar x \1 # \" by (rule context_valid) @@ -330,6 +777,16 @@ next then obtain y e2' where 2: "Let x \1 e1 e2 = Let y \1 e1 e2' \ atom x \ Let y \1 e1 e2'" using Abs_fresh_var by auto then have "atom x \ (\, \, Let y \1 e1 e2', \2)" using 1 fresh_Pair by simp then show ?case using 2 fresh_star_def by fastforce +next + case (7 \ \ e \1 T \s \ K cty ks args vals tys e') + have 1: "\ \ zip_with BVar vals args @ zip_with BTyVar tys ks @ \" by (rule context_valid(2)[OF 7(9)]) + have g1: "set (map atom vals) \* \" using zip_with_context_fresh_vars[OF 1] 7(7) unfolding fresh_star_def fresh_append by simp + have "set (map atom tys) \* \" using zip_with_context_fresh_tyvars[OF context_valid_append[OF 1]] 7(8) by simp + then have 2: "(set (map atom vals) \ set (map atom tys)) \* \" (is "?x \* \") using g1 unfolding fresh_star_def by blast + have 3: "?x \* e" using fresh_in_context(2,3)[OF 7(1)] 2 unfolding fresh_star_def by auto + have 4: "?x \* \" using fresh_in_context(1)[OF 7(3)] 2 unfolding fresh_star_def by auto + have "?x \* \" using fresh_in_axioms[OF axioms_valid(3)[OF 7(1)]] unfolding fresh_star_def by auto + then show ?case using 2 3 4 unfolding fresh_star_def fresh_Pair by auto qed auto end From 37a9aa9be022ff59a6938187d8468d5781973749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20van=20Br=C3=BCgge?= Date: Thu, 24 Jun 2021 18:27:38 +0200 Subject: [PATCH 8/8] Use forall instead of mutually recursive typing judgement --- Syntax.thy | 5 ++ Typing.thy | 258 +++++++++++++++++++---------------------------------- 2 files changed, 96 insertions(+), 167 deletions(-) diff --git a/Syntax.thy b/Syntax.thy index 8304ad5..d0525f4 100644 --- a/Syntax.thy +++ b/Syntax.thy @@ -53,6 +53,9 @@ and "alt_list" = | ACons "alt" "alt_list" and "alt" = MatchCtor "ctor_name" tys::"tyvar list" vals::"var list" e::"term" binds tys vals in e +lemmas term_supp = term_alt_list_alt.supp(1-8) +lemmas alt_list_supp = term_alt_list_alt.supp(9,10) +lemmas alt_supp = term_alt_list_alt.supp(11) nominal_datatype "binder" = BVar "var" "\" @@ -87,6 +90,8 @@ lemma no_tyvars_in_kinds[simp]: "atom (a :: tyvar) \ (k :: \)" lemma supp_empty_kinds[simp]: "supp (k :: \) = {}" by (induction k rule: \.induct) (auto simp: \.supp) +lemma supp_empty_kind_list[simp]: "supp (ks :: \ list) = {}" + by (induction ks) (auto simp: supp_Nil supp_Cons) lemma perm_data_name_var[simp]: "((a::var) \ b) \ (T :: data_name) = T" using flip_fresh_fresh pure_fresh by blast diff --git a/Typing.thy b/Typing.thy index 703792d..08b7c4a 100644 --- a/Typing.thy +++ b/Typing.thy @@ -41,9 +41,7 @@ syntax translations "\x|\|A. P" \ "CONST fBall A (\x. P)" -inductive Tm :: "\ \ \ \ term \ \ \ bool" ("_ , _ \ _ : _" 50) and - Alts :: "\ \ \ \ term \ alt_list \ \ \ bool" and - Alt :: "\ \ \ \ term \ alt \ \ \ bool" where +inductive Tm :: "\ \ \ \ term \ \ \ bool" ("_ , _ \ _ : _" 50) where Tm_Var: "\ \ \ \ ; BVar x \ \ \ \ \ \ , \ \ (Var x) : \" | Tm_Abs: "BVar x \1 # \ , \ \ e : \2 \ \ , \ \ (\ x : \1 . e) : (\1 \ \2)" @@ -58,16 +56,14 @@ inductive Tm :: "\ \ \ \ term \ \ , \ \ e1 : \1 ; BVar x \1 # \ , \ \ e2 : \2 \ \ \ , \ \ Let x \1 e1 e2 : \2" -| Tm_Case: "\ \ , \ \ e : \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; Alts \ \ e alts \ \ \ \ , \ \ Case e alts : \" - -| Alts_Nil: "Alts \ \ e ANil \" - -| Alts_Cons: "\ Alt \ \ e alt \ ; Alts \ \ e alts \ \ \ Alts \ \ e (ACons alt alts) \" - -| Alt_Ctor: "\ \ , \ \ e : \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; - AxCtor K cty \ set \ ; ctor_type cty = Some (T, ks) ; subst_ctor cty \s = Some args ; - length vals = length args ; length tys = length ks ; - zip_with BVar vals args @ zip_with BTyVar tys ks @ \ , \ \ e' : \ \ \ Alt \ \ e (MatchCtor K tys vals e') \" +| Tm_Case: "\ \ , \ \ e : \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; + \alt |\| set_alts alts. (\K tys vals e' cty ks args \'. + alt = MatchCtor K tys vals e' \ + AxCtor K cty \ set \ \ ctor_type cty = Some (T, ks) \ + subst_ctor cty \s = Some args \ + \' = zip_with BVar vals args @ zip_with BTyVar tys ks @ \ \ + \' , \ \ e' : \ + ) \ \ \ , \ \ Case e alts : \" equivariance Tm @@ -96,9 +92,6 @@ inductive_cases TmE[elim!]: "\ , \ \ Ctor D : \" "\ , \ \ Case e alts : \" -inductive_cases AltsE[elim!]: - "Alts \ \ e (ACons alt alts) \" - (* Split induction principles *) lemma Ty_induct[consumes 1, case_names Var App Data Arrow Forall]: fixes P::"\ \ \ \ \ \ \ \ bool" @@ -111,20 +104,6 @@ lemma Ty_induct[consumes 1, case_names Var App Data Arrow Forall]: shows "P \ \ \ \" using Ax_Ctx_Ty.inducts(3)[OF assms(1), of "\a. True" P "\a b. True"] assms(2-6) by simp -lemma Tm_induct[consumes 1, case_names Var Abs App TAbs TApp Ctor Let Case]: - fixes P::"\ \ \ \ term \ \ \ bool" - assumes "\ , \ \ e : \" - and "\\ \ x \. \ \ \ \ ; BVar x \ \ \ \ \ P \ \ (Var x) \" - and "\x \1 \ \ e \2. \ BVar x \1 # \ , \ \ e : \2 ; P (BVar x \1 # \) \ e \2 \ \ P \ \ (\ x : \1 . e) (\1 \ \2)" - and "\\ \ e1 \1 \2 e2. \ \ , \ \ e1 : \1 \ \2 ; P \ \ e1 (\1 \ \2) ; \ , \ \ e2 : \1 ; P \ \ e2 \1 \ \ P \ \ (App e1 e2) \2" - and "\a k \ \ e \. \ BTyVar a k # \ , \ \ e : \ ; P (BTyVar a k # \) \ e \ \ \ P \ \ (\ a : k . e) (\ a : k . \)" - and "\\ \ e a k \ \. \ \ , \ \ e : \ a : k . \ ; P \ \ e (\ a : k . \) ; \ , \ \\<^sub>t\<^sub>y \ : k \ \ P \ \ (TApp e \) \[\/a]" - and "\\ \ D \. \ \ \ \ ; AxCtor D \ \ set \ \ \ P \ \ (Ctor D) \" - and "\\ \ e1 \1 x e2 \2. \ \ , \ \ e1 : \1 ; P \ \ e1 \1 ; BVar x \1 # \ , \ \ e2 : \2 ; P (BVar x \1 # \) \ e2 \2 \ \ P \ \ (Let x \1 e1 e2) \2" - and "\\ \ e \1 T \s \ alts. \ \ , \ \ e : \1 ; P \ \ e \1 ; head_data \1 = Some (T, \s) ; \ , \ \\<^sub>t\<^sub>y \ : \ ; exhaustive alts \ T ; Alts \ \ e alts \ \ \ P \ \ (Case e alts) \" -shows "P \ \ e \" - using Tm_Alts_Alt.inducts(1)[OF assms(1), of _ "\_ _ _ _ _. True" "\_ _ _ _ _. True"] assms(2-9) by auto - (* axiom validity *) lemma axioms_valid_aux: shows "\ \ \ \ \ \" @@ -139,7 +118,7 @@ lemma axioms_valid_context: "\ \ \ \ \< lemma axioms_valid_ty: "\ , \ \\<^sub>t\<^sub>y \ : k \ \ \" using axioms_valid_aux by simp lemma axioms_valid_tm: "\ , \ \ e : \ \ \ \" - by (induction \ \ e \ rule: Tm_induct) (auto simp: axioms_valid_context axioms_valid_ty) + by (induction \ \ e \ rule: Tm.induct) (auto simp: axioms_valid_context axioms_valid_ty) lemmas axioms_valid = axioms_valid_context axioms_valid_ty axioms_valid_tm lemma Ctx_Ty_induct_split[case_names Ctx_Empty Ctx_TyVar Ctx_Var Ty_Var Ty_App Ty_Data Ty_Arrow Ty_Forall]: @@ -204,11 +183,38 @@ proof - then show "\ \ \' @ \ \ P \ \'" and "\' @ \ , \ \\<^sub>t\<^sub>y \ : k2 \ Q \' \ \ k2" by simp_all qed +lemma alts_induct[consumes 1, case_names MatchCtor]: + assumes "\alt |\| set_alts alts. (\K tys vals e' cty ks args \'. + alt = MatchCtor K tys vals e' \ + AxCtor K cty \ set \ \ ctor_type cty = Some (T, ks) \ + subst_ctor cty \s = Some args \ + \' = zip_with BVar vals args @ zip_with BTyVar tys ks @ \ \ + \' , \ \ e' : \ \ P \' e' + )" + and "\K tys vals e' cty ks args. \ AxCtor K cty \ set \ ; ctor_type cty = Some (T, ks) ; subst_ctor cty \s = Some args ; + zip_with BVar vals args @ zip_with BTyVar tys ks @ \ , \ \ e' : \ ; P (zip_with BVar vals args @ zip_with BTyVar tys ks @ \) e' \ \ Q \ (MatchCtor K tys vals e')" +shows "\alt |\| set_alts alts. Q \ alt" +proof - + let ?W = "\alt. (\K tys vals e' cty ks args \'. + alt = MatchCtor K tys vals e' \ + AxCtor K cty \ set \ \ ctor_type cty = Some (T, ks) \ + subst_ctor cty \s = Some args \ + \' = zip_with BVar vals args @ zip_with BTyVar tys ks @ \ \ + \' , \ \ e' : \ \ P \' e')" + show ?thesis + using assms(1) proof (induction alts rule: term_alt_list_alt.inducts(2)[of "\_. True" _ "\alt. ?W alt \ Q \ alt"]) + next + case (MatchCtor K tys vals e') + then show ?case using assms(2) apply auto + by (metis term_alt_list_alt.eq_iff(11)) + qed simp_all +qed + (* context validity *) lemma context_valid_ty: "\ , \ \\<^sub>t\<^sub>y \ : \ \ \ \ \" by (induction \ \ \ \ rule: Ty_induct) auto lemma context_valid_tm: "\ , \ \ e : \ \ \ \ \" - by (induction \ \ e \ rule: Tm_induct) (auto simp: context_valid_ty) + by (induction \ \ e \ rule: Tm.induct) (auto simp: context_valid_ty) lemmas context_valid = context_valid_ty context_valid_tm lemma supp_in_context_ty: "\ , \ \\<^sub>t\<^sub>y \ : k \ supp \ \ supp \" @@ -584,31 +590,31 @@ corollary type_substitution_ty: "\ \' @ BTyVar a k # \ , \ using type_substitution_aux by blast lemma typing_regularity: "\ , \ \ e : \ \ \ , \ \\<^sub>t\<^sub>y \ : \" -proof (induction \ \ e \ rule: Tm_induct) - case (Var \ \ x \) +proof (induction \ \ e \ rule: Tm.induct) + case (Tm_Var \ \ x \) then obtain \1 \2 where 1: "\ = \1 @ BVar x \ # \2" using isin_split by blast - then have "\2 , \ \\<^sub>t\<^sub>y \ : \" using context_regularity Var(1) by blast - then show ?case using weaken_ty[of "[]" \2 \ \ \ "\1 @ [BVar x \]"] Var(1) 1 by simp + then have "\2 , \ \\<^sub>t\<^sub>y \ : \" using context_regularity Tm_Var(1) by blast + then show ?case using weaken_ty[of "[]" \2 \ \ \ "\1 @ [BVar x \]"] Tm_Var(1) 1 by simp next - case (Abs x \1 \ \ e \2) - have 1: "\ , \ \\<^sub>t\<^sub>y \1 : \" using context_regularity context_valid(1)[OF Abs(2)] by blast - have 2: "\ , \ \\<^sub>t\<^sub>y \2 : \" using strengthen(2)[of "[]"] Abs(2) by force + case (Tm_Abs x \1 \ \ e \2) + have 1: "\ , \ \\<^sub>t\<^sub>y \1 : \" using context_regularity context_valid(1)[OF Tm_Abs(2)] by blast + have 2: "\ , \ \\<^sub>t\<^sub>y \2 : \" using strengthen(2)[of "[]"] Tm_Abs(2) by force have 3: "\ \ \" by (rule context_valid(1)[OF 1]) show ?case by (rule Ty_App[OF Ty_App[OF Ty_Arrow[OF 3] 1] 2]) next - case (TApp \ \ e a k \ \) - obtain a' \' where P: "(\ a:k. \) = (\ a':k. \')" "BTyVar a' k # \ , \ \\<^sub>t\<^sub>y \' : \" by (cases rule: Ty.cases[OF TApp(3)]) auto - have "\ , \ \\<^sub>t\<^sub>y \'[\/a'] : \" using type_substitution_ty[of "[]", OF _ TApp(2)] P by auto + case (Tm_TApp \ \ e a k \ \) + obtain a' \' where P: "(\ a:k. \) = (\ a':k. \')" "BTyVar a' k # \ , \ \\<^sub>t\<^sub>y \' : \" by (cases rule: Ty.cases[OF Tm_TApp(3)]) auto + have "\ , \ \\<^sub>t\<^sub>y \'[\/a'] : \" using type_substitution_ty[of "[]", OF _ Tm_TApp(2)] P by auto then show ?case using P(1) subst_type_same by auto next - case (Ctor \ \ D \) - from Ctor(1) have 1: "\ \" by (rule axioms_valid(1)) - then obtain \1 \2 where 2: "\ = \1 @ AxCtor D \ # \2" using axiom_isin_split[OF Ctor(2) 1] by blast + case (Tm_Ctor \ \ D \) + from Tm_Ctor(1) have 1: "\ \" by (rule axioms_valid(1)) + then obtain \1 \2 where 2: "\ = \1 @ AxCtor D \ # \2" using axiom_isin_split[OF Tm_Ctor(2) 1] by blast then have "[] , \2 \\<^sub>t\<^sub>y \ : \" using axioms_regularity 1 by blast then have "[] , \ \\<^sub>t\<^sub>y \ : \" using weaken(3)[of "[]" "[]" \2 \ \ "\1 @ [AxCtor D \]"] 1 2 Ctx_Empty by simp - then show ?case using weaken(2)[of "[]" "[]"] Ctor(1) by simp + then show ?case using weaken(2)[of "[]" "[]"] Tm_Ctor(1) by simp next - case (Let \ e1 \1 x e2 \2) + case (Tm_Let \ \ e1 \1 x e2 \2) then show ?case using strengthen(2)[of "[]"] by force qed (auto intro: Ty_intros) @@ -626,133 +632,61 @@ proof - then show "supp args \ supp \" using supp_subst_ctor[OF assms(4)] 1 by simp qed -lemma Alt_Ctor_Inv: - assumes a: "Alt \ \ e (MatchCtor K tys vals e') \" - and fresh: "set (map atom tys) \* \" "set (map atom vals) \* \" "set (map atom tys) \* \" -obtains \1 T \s cty ks args where "\ , \ \ e : \1" "head_data \1 = Some (T, \s)" "\ , \ \\<^sub>t\<^sub>y \ : \" "AxCtor K cty \ set \" "ctor_type cty = Some (T, ks)" - "length args = length vals" "length ks = length tys" - "subst_ctor cty \s = Some args" "zip_with BVar vals args @ zip_with BTyVar tys ks @ \ , \ \ e' : \" -proof (cases rule: Alt.cases[OF a]) - case (1 \2 \2 e2 \1 T \s \2 K2 cty ks args vals2 tys2 e'2) - let ?tys = "map atom tys" and ?vals = "map atom vals" - let ?tys2 = "map atom tys2" and ?vals2 = "map atom vals2" - from 1 have 2: "[?tys2 @ ?vals2]lst. e'2 = [?tys @ ?vals]lst. e'" by simp - from 1 have valid: "\ \ zip_with BVar vals2 args @ zip_with BTyVar tys2 ks @ \" using context_valid(2) by simp - then have valid_axioms: "\ \" by (rule axioms_valid(1)) - - have g1: "set ?vals2 \* \" using zip_with_context_fresh_vars[OF valid] 1(12) fresh_append by (simp add: fresh_star_list(1)) - have g2: "set ?tys2 \* \" using zip_with_context_fresh_tyvars valid context_valid_append 1(13) by (metis order_refl) - then have g: "set (?tys2 @ ?vals2) \* \" using g1 using fresh_star_Un by auto - - obtain p where P: "p \ e'2 = e'" "p \ (?tys2 @ ?vals2) = ?tys @ ?vals" "supp p \ set (?tys2 @ ?vals2) \ set (?tys @ ?vals)" by (rule Abs_rename_body_star[OF 2]) - have G: "supp \ \ supp p = {}" using g fresh(1-2) P(3) unfolding fresh_star_def fresh_def using UnE disjoint_iff set_append subsetD by auto - then have 3: "p \ \ = \" by (meson disjoint_iff fresh_def fresh_star_def supp_perm_eq_test) - - from 1(1,2,5) g have t1: "set (?tys2 @ ?vals2) \* \" using fresh_in_context_ty[OF 1(8)] unfolding fresh_star_def by auto - have t2: "set (?tys @ ?vals) \* \" using fresh(3) unfolding fresh_star_def by auto - then have "supp \ \ supp p = {}" using t1 P(3) unfolding fresh_star_def fresh_def by blast - then have 4: "p \ \ = \" by (meson disjoint_iff fresh_def fresh_star_def supp_perm_eq_test) - - have "supp cty = {}" using supp_cty[OF valid_axioms] 1(2,9) by simp - then have 5: "supp args \ supp \s" using supp_subst_ctor 1(11) by blast - - have "supp args \ supp \" using supp_args[OF 1(6,7,9,11)] 1(1) by argo - then have "supp args \ supp p = {}" using G by blast - then have 6: "p \ args = args" by (meson disjoint_iff fresh_def fresh_star_def supp_perm_eq) - have 7: "p \ vals2 = vals" "p \ tys2 = tys" using permute_atoms_split[OF P(2)] by auto - - have "p \ (zip_with BVar vals2 args @ zip_with BTyVar tys2 ks @ \) , p \ \ \ e' : p \ \" using 1(1,2,5,14) P(1) Tm.eqvt by blast - then have "zip_with BVar (p \ vals2) args @ zip_with BTyVar (p \ tys2) ks @ \ , \ \ e' : \" using 3 4 permute_axioms[OF valid_axioms] 6 by simp - then have "zip_with BVar vals args @ zip_with BTyVar tys ks @ \ , \ \ e' : \" using 7 by simp - then show ?thesis using 1 that permute_length[OF 7(1)] permute_length[OF 7(2)] by auto -qed - corollary supp_in_context_term_type: "\ , \ \ e : \ \ supp \ \ supp \" - using typing_regularity supp_in_context_ty by blast - -lemma supp_in_context_term_aux: - shows "\ , \ \ e : \ \ supp e \ supp \" - and "\e. Alts \ \ e alts \ \ supp alts \ supp \" - and "\e. Alt \ \ e alt \ \ supp alt \ supp \" -proof (nominal_induct e and alts and alt avoiding: \ \ \ rule: term_alt_list_alt.strong_induct) - case (Var x) - then show ?case by (metis TmE(1) fresh_def fresh_not_isin_var singletonD subsetCI supp_at_base term_alt_list_alt.supp(1)) -next - case (App e1 e2) - then show ?case by (metis TmE(2) Un_least term_alt_list_alt.supp(2)) -next - case (TApp e \) - then show ?case by (metis TmE(3) Un_least supp_in_context_ty term_alt_list_alt.supp(3)) -next - case (Ctor T) - then show ?case using term_alt_list_alt.supp(4) pure_supp by auto + using supp_in_context_ty[OF typing_regularity] by simp + +lemma supp_in_context_term: "\ , \ \ e : \ \ supp e \ supp \" +proof (induction \ \ e \ rule: Tm.induct) + case (Tm_Var \ \ x \) + then show ?case by (metis fresh_def fresh_not_isin_var singletonD subsetCI supp_at_base term_alt_list_alt.supp(1)) next - case (Lam x \1 e) - show ?case - proof standard - assume a: "\ , \ \ \ x : \1 . e : \" - then have "\ , \ \\<^sub>t\<^sub>y \1 : \" by (meson CtxE(2) Lam.hyps(1) T_Abs_Inv context_valid_tm) - then have 1: "supp \1 \ supp \" by (rule supp_in_context_ty) - have "supp e \ supp (BVar x \1 # \)" using Lam(4) T_Abs_Inv[OF a Lam(1)] by metis - then show "supp (\ x : \1 . e) \ supp \" unfolding term_alt_list_alt.supp supp_Cons binder.supp supp_at_base using 1 by auto - qed + case (Tm_Abs x \1 \ \ e \2) + then have "supp \1 \ supp \" by (meson CtxE(2) context_valid_tm supp_in_context_ty) + then show ?case using Tm_Abs(2) unfolding supp_Cons binder.supp supp_at_base term_supp by auto next - case (TyLam a k e) - show ?case - proof standard - assume a: "\ , \ \ \ a : k . e : \" - have "supp e \ supp (BTyVar a k # \)" using TyLam(4) T_AbsT_Inv[OF a TyLam(1,3)] by metis - then show "supp (\ a : k . e) \ supp \" unfolding term_alt_list_alt.supp pure_supp supp_Cons binder.supp supp_at_base by auto - qed + case (Tm_App \ \ e1 \1 \2 e2) + then show ?case unfolding term_supp by simp next - case (Let x \1 e1 e2) - show ?case - proof standard - assume a: "\ , \ \ Let x \1 e1 e2 : \" - then have "\ , \ \\<^sub>t\<^sub>y \1 : \" using Let(1) T_Let_Inv typing_regularity by blast - then have 1: "supp \1 \ supp \" by (rule supp_in_context_ty) - have "supp e1 \ supp \" "supp e2 \ supp (BVar x \1 # \)" using Let(4,5) T_Let_Inv[OF a Let(1)] by blast+ - then show "supp (Let x \1 e1 e2) \ supp \" unfolding term_alt_list_alt.supp supp_Cons binder.supp supp_at_base using 1 by auto - qed + case (Tm_TAbs a k \ \ e \) + then show ?case unfolding supp_Cons binder.supp pure_supp term_supp supp_at_base by auto next - case (Case e alts) - then show ?case unfolding term_alt_list_alt.supp by blast + case (Tm_TApp \ \ e a k \ \) + then have "supp \ \ supp \" using supp_in_context_ty by simp + then show ?case using Tm_TApp(3) unfolding term_supp by auto next - case ANil - then show ?case using term_alt_list_alt.supp by simp + case (Tm_Ctor \ \ D \) + then show ?case unfolding term_supp pure_supp by simp next - case (ACons alt alts) - then show ?case unfolding term_alt_list_alt.supp by blast + case (Tm_Let \ \ e1 \1 x e2 \2) + then have "supp \1 \ supp \" using supp_in_context_term_type by auto + then show ?case using Tm_Let(3,4) unfolding term_supp supp_Cons binder.supp supp_at_base by auto next - case (MatchCtor K tys vals e') - show ?case - proof (standard, standard) - fix e - assume a: "Alt \ \ e (MatchCtor K tys vals e') \" - obtain \1 T \s cty ks args where P: "\ , \ \ e : \1" "head_data \1 = Some (T, \s)" "\ , \ \\<^sub>t\<^sub>y \ : \" "AxCtor K cty \ set \" "ctor_type cty = Some (T, ks)" - "length args = length vals" "length ks = length tys" "subst_ctor cty \s = Some args" "zip_with BVar vals args @ zip_with BTyVar tys ks @ \ , \ \ e' : \" - by (rule Alt_Ctor_Inv[OF a MatchCtor(1,4,3)]) - then have "supp e' \ supp (zip_with BVar vals args @ zip_with BTyVar tys ks @ \)" using MatchCtor(7) by simp - then have "supp e' \ supp vals \ supp args \ supp tys \ supp \" unfolding supp_append using supp_zip_with pure_supp by blast - then have "supp e' \ supp vals \ supp tys \ supp \" using supp_args[OF P(1,2,4,8)] by blast - then show "supp (MatchCtor K tys vals e') \ supp \" unfolding term_alt_list_alt.supp pure_supp supp_vars supp_tyvars by auto + case (Tm_Case \ \ e \1 T \s \ alts) + have "\alt |\| set_alts alts. supp alt \ supp \" using Tm_Case(6) + proof (induction rule: alts_induct) + case (MatchCtor K tys vals e' cty ks args) + have "supp args \ supp \" by (rule supp_args[OF Tm_Case(1,2) MatchCtor(1,3)]) + then have "supp e' \ supp tys \ supp vals \ supp \" using supp_zip_with MatchCtor(5) unfolding supp_append by fastforce + then show ?case unfolding alt_supp pure_supp using supp_vars supp_tyvars by auto qed + then have "supp alts \ supp \" + by (induction alts rule: term_alt_list_alt.inducts(2)) (auto simp: alt_list_supp) + then show ?case using Tm_Case term_supp by auto qed -corollary supp_in_context_term: "\ , \ \ e : \ \ supp e \ supp \ \ supp \" - using supp_in_context_ty[OF typing_regularity] supp_in_context_term_aux(1) by simp -lemmas supp_in_context = supp_in_context_ty supp_in_context_term +lemmas supp_in_context = supp_in_context_ty supp_in_context_term supp_in_context_term_type corollary fresh_in_context_term_var: "\ \ , \ \ e : \ ; atom (y::var) \ \ \ \ atom y \ e" using supp_in_context_term unfolding fresh_def by blast -corollary fresh_in_context_term_tyvar: "\ \ , \ \ e : \ ; atom (a::tyvar) \ \ \ \ atom a \ e \ atom a \ \" +corollary fresh_in_context_term_tyvar: "\ \ , \ \ e : \ ; atom (a::tyvar) \ \ \ \ atom a \ e" using supp_in_context_term unfolding fresh_def by blast -lemmas fresh_in_context = fresh_in_context_ty fresh_in_context_term_var fresh_in_context_term_tyvar +corollary fresh_in_context_term_type_tyvar: "\ \ , \ \ e : \ ; atom (a::tyvar) \ \ \ \ atom a \ \" + using supp_in_context_term_type unfolding fresh_def by blast +lemmas fresh_in_context = fresh_in_context_ty fresh_in_context_term_var fresh_in_context_term_tyvar fresh_in_context_term_type_tyvar -nominal_inductive Tm avoids +(*nominal_inductive Tm avoids Tm_Abs: x | Tm_TAbs: a | Tm_Let: x - | Alt_Ctor: tys and vals proof goal_cases case (1 x \1 \ \ e \2) then have "\ \ BVar x \1 # \" by (rule context_valid) @@ -777,16 +711,6 @@ next then obtain y e2' where 2: "Let x \1 e1 e2 = Let y \1 e1 e2' \ atom x \ Let y \1 e1 e2'" using Abs_fresh_var by auto then have "atom x \ (\, \, Let y \1 e1 e2', \2)" using 1 fresh_Pair by simp then show ?case using 2 fresh_star_def by fastforce -next - case (7 \ \ e \1 T \s \ K cty ks args vals tys e') - have 1: "\ \ zip_with BVar vals args @ zip_with BTyVar tys ks @ \" by (rule context_valid(2)[OF 7(9)]) - have g1: "set (map atom vals) \* \" using zip_with_context_fresh_vars[OF 1] 7(7) unfolding fresh_star_def fresh_append by simp - have "set (map atom tys) \* \" using zip_with_context_fresh_tyvars[OF context_valid_append[OF 1]] 7(8) by simp - then have 2: "(set (map atom vals) \ set (map atom tys)) \* \" (is "?x \* \") using g1 unfolding fresh_star_def by blast - have 3: "?x \* e" using fresh_in_context(2,3)[OF 7(1)] 2 unfolding fresh_star_def by auto - have 4: "?x \* \" using fresh_in_context(1)[OF 7(3)] 2 unfolding fresh_star_def by auto - have "?x \* \" using fresh_in_axioms[OF axioms_valid(3)[OF 7(1)]] unfolding fresh_star_def by auto - then show ?case using 2 3 4 unfolding fresh_star_def fresh_Pair by auto -qed auto +qed auto*) end