diff --git a/Defs.thy b/Defs.thy index 64e5533..eaadfae 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" @@ -35,34 +42,59 @@ 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 +nominal_function head_data :: "\ \ (data_name * \ list) option" where + "head_data (TyVar _) = None" +| "head_data (TyData T) = Some (T, [])" +| "head_data TyArrow = 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) + 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 split!: option.splits) +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, [])" | "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" -| "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 +case 1 then show ?case by (auto simp: eqvt_def ctor_data_app_graph_aux_def split!: option.splits) next case (3 P x) then show ?case proof (cases x rule: \.exhaust) case (TyApp \1 \2) - then show ?thesis using 3 by (cases \2 rule: \.exhaust) auto - qed (auto simp: 3) + then show ?thesis using 3 by (cases "\a. \2 = TyVar a") auto + qed auto qed auto nominal_termination (eqvt) by lexicographic_order @@ -71,49 +103,32 @@ 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) - 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) - 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+ -next - case (74 a k e \1 \2 a k e \1 \2) - then show ?case by (simp add: 74) -next - case (92 a k e \2 a k e \2) - then show ?case by (simp add: 92) + 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 -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) @@ -124,9 +139,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 @@ -137,19 +153,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, 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) @@ -158,10 +181,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 \ \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 _ [] _ = []" +| "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 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 + +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" @@ -170,44 +217,105 @@ 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)" + +| "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 Inr outer fresh_star_insert + apply (cases m rule: term_alt_list_alt.strong_exhaust(3)[of "(e, y)"]) + by auto + qed + qed +next + 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 (26 y e x \ e2 y' e' x' \' e2') - then show ?case using Abs_sumC[OF 26(5,6,1,2)] 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 (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 (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 (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 (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 nominal_function subst_type :: "\ \ \ \ tyvar \ \" where @@ -219,41 +327,101 @@ 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)" + +| "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 + apply (cases m rule: term_alt_list_alt.strong_exhaust(3)[of "(e, y)"]) by simp + qed + qed 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 (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 (29 b \ a k e2 b' \' a' k' e2') - then show ?case using Abs_sumC[OF 29(5,6,1,2)] 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 (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 (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 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 (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 nominal_function subst_context :: "\ \ \ \ tyvar \ \" where @@ -275,6 +443,37 @@ 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 + +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 new file mode 100644 index 0000000..ebb2ef8 --- /dev/null +++ b/Defs2.thy @@ -0,0 +1,94 @@ +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)" +| "\\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 + 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 (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 + +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 + +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 b520a3a..7622018 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 _) \ *) @@ -91,15 +173,23 @@ 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: "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 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 11 by simp qed auto lemma fresh_subst_type_same: "atom a \ \ \ subst_type \ \ a = \" @@ -109,33 +199,137 @@ 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 (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 11 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 + +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 421adae..57cb3d2 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,30 @@ 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) +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 + +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) + +lemma permute_length: + fixes xs ys::"'a::at list" + assumes "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 234a189..ba0f749 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 . @@ -45,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 837495b..d0525f4 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" @@ -41,6 +47,15 @@ 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 +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" "\" @@ -75,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 @@ -84,6 +101,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 cfddac9..08b7c4a 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,7 +12,7 @@ inductive Ax :: "\ \ bool" ("\ _") | Ax_Data: "\ \ \ ; \k. AxData T k \ set \ \ \ \ AxData T \ # \" -| 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) ; \t. AxCtor D t \ set \ \ \ \ AxCtor D \ # \" (* ------------------------------ *) @@ -36,6 +36,11 @@ inductive Ax :: "\ \ bool" ("\ _") equivariance Ax +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) : \" @@ -51,6 +56,15 @@ 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 ; + \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 lemmas Ax_intros = Ax_Ctx_Ty.intros(1-3) @@ -76,6 +90,7 @@ inductive_cases TmE[elim!]: "\ , \ \ App e1 e2 : \2" "\ , \ \ TApp e \ : \2" "\ , \ \ Ctor D : \" + "\ , \ \ Case e alts : \" (* Split induction principles *) lemma Ty_induct[consumes 1, case_names Var App Data Arrow Forall]: @@ -168,6 +183,33 @@ 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 @@ -175,49 +217,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) - -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) + then show ?case by (metis \.supp(1) fresh_def fresh_not_isin_tyvar singletonD subsetCI supp_at_base) 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 (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(1)[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 axioms_cons_valid[elim]: "\ ax # \ \ (\ \ \ P) \ P" + by (cases rule: Ax.cases) (auto simp: axioms_valid(2)) -lemma perm_axioms_tyvars[simp]: "\ \ \ ((a::tyvar) \ b) \ \ = \" - using flip_fresh_fresh fresh_in_axioms by blast +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 @@ -231,7 +265,425 @@ proof goal_cases then show ?case using 2 fresh_star_def by fastforce qed auto -nominal_inductive Tm avoids +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 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+ + +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 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 (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 Tm_Var(1) by blast + then show ?case using weaken_ty[of "[]" \2 \ \ \ "\1 @ [BVar x \]"] Tm_Var(1) 1 by simp +next + 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 (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 (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 "[]" "[]"] Tm_Ctor(1) by simp +next + case (Tm_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 + +corollary supp_in_context_term_type: "\ , \ \ e : \ \ supp \ \ supp \" + 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 (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 (Tm_App \ \ e1 \1 \2 e2) + then show ?case unfolding term_supp by simp +next + 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 (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 (Tm_Ctor \ \ D \) + then show ?case unfolding term_supp pure_supp by simp +next + 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 (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 +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" + using supp_in_context_term unfolding fresh_def by blast +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 Tm_Abs: x | Tm_TAbs: a | Tm_Let: x @@ -259,6 +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 -qed auto +qed auto*) end