# HG changeset patch # User urbanc # Date 1132926699 -3600 # Node ID 676d2e625d9872ab41e1dc4df5cd220b2fb3b35a # Parent 65e60434b3c241684ab13a2ebbb4ddc294bc3af0 added fsub.thy (poplmark challenge) to the examples directory. diff -r 65e60434b3c2 -r 676d2e625d98 src/HOL/Nominal/Examples/Fsub.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Nominal/Examples/Fsub.thy Fri Nov 25 14:51:39 2005 +0100 @@ -0,0 +1,1009 @@ +theory fsub +imports nominal +begin + +atom_decl tyvrs vrs + +section {* Types *} + +nominal_datatype ty = TyVar "tyvrs" + | Top + | Arrow "ty" "ty" ("_ \ _" [900,900] 900) + | TAll "\tyvrs\ty" "ty" + +syntax + TAll_syn :: "tyvrs \ ty \ ty \ ty" ("\ [_<:_]._" [900,900,900] 900) +translations + "(\[a<:ty1].ty2)" \ "TAll a ty2 ty1" + +section {* typing contexts and their domains *} + +types ty_context = "(tyvrs\ty) list" + +text {* domain of a context --- (the name "dom" is already used elsewhere) *} +consts + "domain" :: "ty_context \ tyvrs set" +primrec + "domain [] = {}" + "domain (X#\) = {fst X}\(domain \)" + +lemma domain_eqvt: + fixes pi::"tyvrs prm" + shows "pi\(domain \) = domain (pi\\)" + by (induct \, auto simp add: perm_set_def) + +lemma finite_domain: + fixes \::"ty_context" + shows "finite (domain \)" + by (induct \, auto) + +lemma domain_inclusion[rule_format]: + shows "(X,T)\set \ \ X\(domain \)" + by (induct \, auto) + +lemma domain_existence[rule_format]: + shows "X\(domain \) \ (\T.(X,T)\set \)" + by (induct \, auto) + +lemma domain_append: + shows "domain (\@\) = ((domain \) \ (domain \))" + by (induct \, auto) + +section {* Two functions over types *} + +text {* they cannot yet be defined conveniently unless we have a recursion combinator *} + +consts size_ty :: "ty \ nat" + +lemma size_ty[simp]: + shows "size_ty (TyVar X) = 1" + and "size_ty (Top) = 1" + and "\size_ty t1 = m ; size_ty t2 = n\ \ size_ty (t1 \ t2) = m + n + 1" + and "\size_ty t1 = m ; size_ty t2 = n\ \ size_ty (\ [a<:t1].t2) = m + n + 1" +sorry + +consts subst_ty :: "ty \ tyvrs \ ty \ ty" + +lemma subst_ty[simp]: + shows "subst_ty (TyVar X) Y T = (if X=Y then T else (TyVar X))" + and "subst_ty Top Y T = Top" + and "subst_ty (T1 \ T2) Y T = (subst_ty T1 Y T) \ (subst_ty T2 Y T)" + and "X\(Y,T) \ subst_ty (\[X<:T1].T2) Y T = (\[X<:(subst_ty T1 Y T)].(subst_ty T2 Y T))" + and "\X\Y; X\T\ \ subst_ty (\[X<:T1].T2) Y T = (\[X<:(subst_ty T1 Y T)].(subst_ty T2 Y T))" +sorry + + +consts subst_ctxt :: "ty_context \ tyvrs \ ty \ ty_context" +primrec +"subst_ctxt [] Y T = []" +"subst_ctxt (XT#Xs) Y T = (fst XT, subst_ty (snd XT) Y T)#(subst_ctxt Xs Y T)" + + +text {* valid contexts *} + +constdefs + "closed_in" :: "ty \ ty_context \ bool" ("_ closed'_in _" [100,100] 100) + "S closed_in \ \ (supp S)\(domain \)" + +lemma closed_in_def2: + shows "(S closed_in \) = ((supp S)\((supp (domain \)):: tyvrs set))" +apply(simp add: closed_in_def) +apply(simp add: at_fin_set_supp[OF at_tyvrs_inst, OF finite_domain]) +done + +lemma closed_in_eqvt: + fixes pi::"tyvrs prm" + assumes a: "S closed_in \" + shows "(pi\S) closed_in (pi\\)" + using a +proof (unfold "closed_in_def") + assume "supp S \ (domain \)" + hence "pi\(supp S) \ pi\(domain \)" + by (simp add: pt_subseteq_eqvt[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + thus "(supp (pi\S)) \ (domain (pi\\))" + by (simp add: domain_eqvt pt_perm_supp[OF pt_tyvrs_inst, OF at_tyvrs_inst]) +qed + +consts + valid_rel :: "ty_context set" + valid_sym :: "ty_context \ bool" ("\ _ ok" [100] 100) +translations + "\ \ ok" \ "\ \ valid_rel" +inductive valid_rel +intros +v1[intro]: "\ [] ok" +v2[intro]: "\\ \ ok; X\\; T closed_in \\ \ \ ((X,T)#\) ok" + +lemma valid_eqvt: + fixes pi::"tyvrs prm" + assumes a: "\ \ ok" + shows "\ (pi\\) ok" + using a +proof (induct) + case v1 + show ?case by force +next + case (v2 T X \) + have a1: "\ (pi \ \) ok" by fact + have a2: "X\\" by fact + have a3: "T closed_in \" by fact + show ?case + proof (simp, rule valid_rel.v2) + show "\ (pi \ \) ok" using a1 by simp + next + show "(pi\X)\(pi\\)" using a2 by (simp add: pt_fresh_bij[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + next + show "(pi\T) closed_in (pi\\)" using a3 by (rule closed_in_eqvt) + qed +qed + +lemma validE: + assumes a: "\ ((X,T)#\) ok" + shows "\ \ ok \ X\\ \ T closed_in \" +using a by (cases, auto) + +lemma validE_append[rule_format]: + shows "\ (\@\) ok \ \ \ ok" + by (induct \, auto dest: validE) + +lemma domain_fresh[rule_format]: + fixes X::"tyvrs" + shows "\ \ ok \ (X\(domain \) = X\\)" +apply(induct \) +apply(simp add: fresh_list_nil fresh_set_empty) +apply(simp add: fresh_list_cons fresh_prod + fresh_fin_insert[OF pt_tyvrs_inst, OF at_tyvrs_inst, OF fs_tyvrs_inst, OF finite_domain]) +apply(rule impI) +apply(clarify) +apply(simp add: fresh_prod) +apply(drule validE) +apply(simp) +apply(simp add: closed_in_def2 fresh_def) +apply(force) +done + +lemma closed_in_fresh: + fixes X::"tyvrs" + assumes a1: "S closed_in \" + and a2: "X\\" + and a3: "\ \ ok" + shows "X\S" +using a1 a2 a3 +apply(simp add: closed_in_def2) +apply(simp add: domain_fresh[symmetric]) +apply(simp add: fresh_def) +apply(force) +done + +lemma replace_type[rule_format]: + shows "\ (\@(X,T)#\) ok \ S closed_in \ \ \ (\@(X,S)#\) ok" +apply(induct \) +apply(auto dest!: validE intro!: v2 simp add: fresh_list_append fresh_list_cons fresh_prod) +apply(drule validE_append) +apply(drule validE) +apply(drule_tac S="S" in closed_in_fresh) +apply(simp) +apply(force)+ +apply(simp add: closed_in_def2) +apply(simp add: domain_append) +done + + +lemma fresh_implies_not_member[rule_format]: + fixes \::"ty_context" + shows "X\\ \ \(\T.(X,T)\(set \))" + apply (induct \) + apply (auto dest: validE simp add: fresh_list_cons fresh_prod fresh_atm) + done + +lemma uniqueness_of_ctxt: + fixes \::"ty_context" + shows "\ \ ok \ (X,T)\(set \) \ (X,S)\(set \) \ (T = S)" + apply (induct \) + apply (auto dest!: validE fresh_implies_not_member) + done + + +section {* Subtyping *} + +consts + subtype_of_rel :: "(ty_context \ ty \ ty) set" + subtype_of_sym :: "ty_context \ ty \ ty \ bool" ("_ \ _ <: _" [100,100,100] 100) +translations + "\ \ S <: T" \ "(\,S,T) \ subtype_of_rel" +inductive subtype_of_rel +intros +S_Top[intro]: "\\ \ ok; S closed_in \\ \ \ \ S <: Top" +S_Var[intro]: "\\ \ ok; (X,S) \ (set \); \ \ S <: T\ \ \ \ (TyVar X) <: T" +S_Refl[intro]: "\\ \ ok; X \ (domain \)\\ \ \ TyVar X <: TyVar X" +S_Arrow[intro]: "\\ \ T1 <: S1; \ \ S2 <: T2\ \ \ \ (S1 \ S2) <: (T1 \ T2)" +S_All[intro]: "\\ \ T1 <: S1; X\\; ((X,T1)#\) \ S2 <: T2\ + \ \ \ \ [X<:S1].S2 <: \ [X<:T1].T2" + +lemma subtype_implies_closed: + assumes a: "\ \ S <: T" + shows "S closed_in \ \ T closed_in \" +using a +proof (induct) + case (S_Top S \) + have "Top closed_in \" + by (simp add: closed_in_def ty.supp) + moreover + have "S closed_in \" by fact + ultimately show "S closed_in \ \ Top closed_in \" by simp +next + case (S_Var S T X \) + have "(X,S)\set \" by fact + hence "X\(domain \)" by (rule domain_inclusion) + hence "(TyVar X) closed_in \" by (simp add: closed_in_def ty.supp supp_atm) + moreover + have "S closed_in \ \ T closed_in \" by fact + hence "T closed_in \" by force + ultimately show "(TyVar X) closed_in \ \ T closed_in \" by simp +next + case S_Refl thus ?case + by (simp add: closed_in_def ty.supp supp_atm) +next + case S_Arrow thus ?case by (force simp add: closed_in_def ty.supp) +next + case S_All thus ?case by (auto simp add: closed_in_def ty.supp abs_supp) +qed + +text {* completely automated proof *} +lemma subtype_implies_closed: + assumes a: "\ \ S <: T" + shows "S closed_in \ \ T closed_in \" +using a +apply (induct) +apply (auto simp add: closed_in_def ty.supp abs_supp domain_inclusion supp_atm) +done + +lemma subtype_implies_ok: + fixes X::"tyvrs" + assumes a1: "\ \ S <: T" + shows "\ \ ok" +using a1 by (induct, auto) + +lemma subtype_implies_fresh: + fixes X::"tyvrs" + assumes a1: "\ \ S <: T" + and a2: "X\\" + shows "X\(S,T)" +proof - + from a1 have "\ \ ok" by (rule subtype_implies_ok) + with a2 have b0: "X\domain(\)" by (simp add: domain_fresh) + from a1 have "S closed_in \ \ T closed_in \" by (rule subtype_implies_closed) + hence b1: "supp S \ ((supp (domain \))::tyvrs set)" + and b2: "supp T \ ((supp (domain \))::tyvrs set)" by (simp_all add: closed_in_def2) + thus "X\(S,T)" using b0 b1 b2 by (force simp add: supp_prod fresh_def) +qed + +lemma silly_eqvt1: + fixes X::"'a::pt_tyvrs" + and S::"'b::pt_tyvrs" + and pi::"tyvrs prm" + shows "(X,S) \ set \ \ (pi\X,pi\S) \ set (pi\\)" +apply(drule_tac pi="pi" in pt_set_bij2[OF pt_tyvrs_inst, OF at_tyvrs_inst]) +apply(simp add: pt_list_set_pi[OF pt_tyvrs_inst]) +done + +lemma silly_eqvt2: + fixes X::"tyvrs" + and pi::"tyvrs prm" + shows "X \ (domain \) \ (pi\X) \ (domain (pi\\))" +apply(drule_tac pi="pi" in pt_set_bij2[OF pt_tyvrs_inst, OF at_tyvrs_inst]) +apply(simp add: domain_eqvt pt_list_set_pi[OF pt_tyvrs_inst] ) +done + +lemma subtype_eqvt: + fixes pi::"tyvrs prm" + shows "\ \ S <: T \ (pi\\) \ (pi\S) <: (pi\T)" +apply(erule subtype_of_rel.induct) +apply(force intro: valid_eqvt closed_in_eqvt) +(* +apply(simp) +apply(rule S_Var) +apply(rule valid_eqvt) +apply(assumption) +*) +(* FIXME: here *) +(* apply(auto intro: closed_in_eqvt valid_eqvt dest: pt_set_bij2[OF pt_tyvrs_inst, OF at_tyvrs_inst]) *) +apply(force intro: closed_in_eqvt valid_eqvt silly_eqvt1) +apply(force intro: valid_eqvt silly_eqvt2) +apply(force) +apply(force intro!: S_All simp add: fresh_prod pt_fresh_bij1[OF pt_tyvrs_inst, OF at_tyvrs_inst]) +done + +lemma subtype_of_rel_induct_aux[rule_format]: + fixes P :: "ty_context \ ty \ ty \'a::fs_tyvrs\bool" + assumes a: "\ \ S <: T" + and a1: "\x \ S. (\ \ ok) \ (S closed_in \) \ P \ S Top x" + and a2: "\x \ X S T. (\ \ ok) \ ((X,S)\set \) \ (\ \ S <: T) \ (\z. P \ S T z) + \ P \ (TyVar X) T x" + and a3: "\x \ X. (\ \ ok) \ X\(domain \) \ P \ (TyVar X) (TyVar X) x" + and a4: "\x \ S1 S2 T1 T2. \ \ T1 <: S1 \ (\z. P \ T1 S1 z) \ \ \ S2 <: T2 \ + (\z. P \ S2 T2 z) \ P \ (S1 \ S2) (T1 \ T2) x" + and a5: "\x \ X S1 S2 T1 T2. + X\x \ X\(\,S1,T1) \ \ \ T1 <: S1 \ (\z. P \ T1 S1 z) \ ((X,T1)#\) \ S2 <: T2 + \ (\z. P ((X,T1)#\) S2 T2 z) \ P \ (\ [X<:S1].S2) (\ [X<:T1].T2) x" + shows "\(pi::tyvrs prm) (x::'a::fs_tyvrs). P (pi\\) (pi\S) (pi\T) x" +using a +proof (induct) + case (S_Top S \) + have b1: "\ \ ok" by fact + have b2: "S closed_in \" by fact + show ?case + proof (intro strip, simp) + fix pi::"tyvrs prm" and x::"'a::fs_tyvrs" + from b1 have "\ (pi\\) ok" by (rule valid_eqvt) + moreover + from b2 have "(pi\S) closed_in (pi\\)" by (rule closed_in_eqvt) + ultimately show "P (pi \ \) (pi \ S) Top x" by (rule a1) + qed +next + case (S_Var S T X \) + have b1: "\ \ ok" by fact + have b2: "(X,S) \ set \" by fact + have b3: "\ \ S <: T" by fact + have b4: "\(pi::tyvrs prm) x. P (pi\\) (pi\S) (pi\T) x" by fact + show ?case + proof (intro strip, simp) + fix pi::"tyvrs prm" and x::"'a::fs_tyvrs" + from b1 have "\ (pi\\) ok" by (rule valid_eqvt) + moreover + from b2 have "pi\(X,S)\pi\(set \)" by (rule pt_set_bij2[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + hence "(pi\X,pi\S)\set (pi\\)" by (simp add: pt_list_set_pi[OF pt_tyvrs_inst]) + moreover + from b3 have "(pi\\) \ (pi\S) <: (pi\T)" by (rule subtype_eqvt) + moreover + from b4 have "\x. P (pi\\) (pi\S) (pi\T) x" by simp + ultimately + show "P (pi\\) (TyVar (pi\X)) (pi\T) x" by (rule a2) + qed +next + case (S_Refl X \) + have b1: "\ \ ok" by fact + have b2: "X \ domain \" by fact + show ?case + proof (intro strip, simp) + fix pi::"tyvrs prm" and x::"'a::fs_tyvrs" + from b1 have "\ (pi\\) ok" by (rule valid_eqvt) + moreover + from b2 have "(pi\X)\pi\domain \" by (rule pt_set_bij2[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + hence "(pi\X)\domain (pi\\)" by (simp add: domain_eqvt pt_list_set_pi[OF pt_tyvrs_inst]) + ultimately show "P (pi\\) (TyVar (pi\X)) (TyVar (pi\X)) x" by (rule a3) + qed +next + case S_Arrow thus ?case by (simp, auto intro!: a4 subtype_eqvt) +next + case (S_All S1 S2 T1 T2 X \) + have b1: "\ \ T1 <: S1" by fact + have b2: "\(pi::tyvrs prm) x. P (pi\\) (pi\T1) (pi\S1) x" by fact + have b4: "((X,T1)#\) \ S2 <: T2" by fact + have b5: "\(pi::tyvrs prm) x. P (pi\((X,T1)#\)) (pi\S2) (pi\T2) x" by fact + have b3': "X\\" by fact + have b3'': "X\(T1,S1)" using b1 b3' by (rule subtype_implies_fresh) + have b3: "X\(\,S1,T1)" using b3' b3'' by (simp add: fresh_prod) + show ?case + proof (intro strip) + fix pi::"tyvrs prm" and x::"'a::fs_tyvrs" + have "\C::tyvrs. C\(pi\X,pi\S2,pi\T2,pi\S1,pi\T1,pi\\,x)" + by (rule at_exists_fresh[OF at_tyvrs_inst], simp add: fs_tyvrs1) + then obtain C::"tyvrs" where f1: "C\(pi\X)" and f2: "C\(pi\S1)" and f3: "C\(pi\T1)" + and f4: "C\(pi\S2)" and f5: "C\(pi\T2)" and f6: "C\(pi\\)" and f7: "C\x" + by (auto simp add: fresh_prod fresh_atm) + let ?pi' = "[(C,pi\X)]@pi" + from b2 have c1: "\x. P (?pi'\\) (?pi'\T1) (?pi'\S1) x" by simp + from b5 have "\x. P (?pi'\((X,T1)#\)) (?pi'\S2) (?pi'\T2) x" by simp + hence "\x. P ((?pi'\X,?pi'\T1)#(?pi'\\)) (?pi'\S2) (?pi'\T2) x" by simp + hence c2: "\x. P ((C,?pi'\T1)#(?pi'\\)) (?pi'\S2) (?pi'\T2) x" using f1 + by (simp only: pt_tyvrs2 calc_atm, simp) + from b3 have "(pi\X)\(pi\\)" + by (simp add: fresh_prod pt_fresh_bij[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + with f6 have f6a: "?pi'\\=pi\\" + by (simp only: pt_tyvrs2 pt_fresh_fresh[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + hence f6': "C\(?pi'\\)" using f6 by simp + from b3 have "(pi\X)\(pi\S1)" + by (simp add: fresh_prod pt_fresh_bij[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + with f2 have f2a: "?pi'\S1=pi\S1" + by (simp only: pt_tyvrs2 pt_fresh_fresh[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + hence f2': "C\(?pi'\S1)" using f2 by simp + from b3 have "(pi\X)\(pi\T1)" + by (simp add: fresh_prod pt_fresh_bij[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + with f3 have f3a: "?pi'\T1=pi\T1" + by (simp only: pt_tyvrs2 pt_fresh_fresh[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + hence f3': "C\(?pi'\T1)" using f3 by simp + from b1 have e1: "(?pi'\\) \ (?pi'\T1) <: (?pi'\S1)" by (rule subtype_eqvt) + from b4 have "(?pi'\((X,T1)#\)) \ (?pi'\S2) <: (?pi'\T2)" by (rule subtype_eqvt) + hence "((?pi'\X,?pi'\T1)#(?pi'\\)) \ (?pi'\S2) <: (?pi'\T2)" by simp + hence e2: "((C,?pi'\T1)#(?pi'\\)) \ (?pi'\S2) <: (?pi'\T2)" using f1 + by (simp only: pt_tyvrs2 calc_atm, simp) + have fnew: "C\(?pi'\\,?pi'\S1,?pi'\T1)" using f6' f2' f3' by (simp add: fresh_prod) + have main: "P (?pi'\\) (\ [C<:(?pi'\S1)].(?pi'\S2)) (\ [C<:(?pi'\T1)].(?pi'\T2)) x" + using f7 fnew e1 c1 e2 c2 by (rule a5) + have alpha1: "(\ [C<:(?pi'\S1)].(?pi'\S2)) = (pi\(\ [X<:S1].S2))" + using f1 f4 f2a[symmetric] by (simp add: ty.inject alpha pt_tyvrs2[symmetric]) + have alpha2: "(\ [C<:(?pi'\T1)].(?pi'\T2)) = (pi\(\ [X<:T1].T2))" + using f1 f5 f3a[symmetric] by (simp add: ty.inject alpha pt_tyvrs2[symmetric]) + show "P (pi\\) (pi\(\ [X<:S1].S2)) (pi\(\ [X<:T1].T2)) x" + using alpha1 alpha2 f6a main by simp + qed +qed + +lemma subtype_of_rel_induct[case_names S_Top S_Var S_Refl S_Arrow S_All]: + fixes P :: "ty_context \ ty \ ty \'a::fs_tyvrs\bool" + assumes a: "\ \ S <: T" + and a1: "\x \ S. (\ \ ok) \ (S closed_in \) \ P \ S Top x" + and a2: "\x \ X S T. (\ \ ok) \ ((X,S)\set \) \ (\ \ S <: T) \ (\z. P \ S T z) + \ P \ (TyVar X) T x" + and a3: "\x \ X. (\ \ ok) \ X\domain \ \ P \ (TyVar X) (TyVar X) x" + and a4: "\x \ S1 S2 T1 T2. \ \ T1 <: S1 \ (\z. P \ T1 S1 z) \ \ \ S2 <: T2 \ + (\z. P \ S2 T2 z) \ P \ (S1 \ S2) (T1 \ T2) x" + and a5: "\x \ X S1 S2 T1 T2. + X\x \ X\(\,S1,T1) \ \ \ T1 <: S1 \ (\z. P \ T1 S1 z) \ ((X,T1)#\) \ S2 <: T2 + \ (\z. P ((X,T1)#\) S2 T2 z) \ P \ (\ [X<:S1].S2) (\ [X<:T1].T2) x" + shows "P \ S T x" +using a a1 a2 a3 a4 a5 subtype_of_rel_induct_aux[of "\" "S" "T" "P" "[]" "x", simplified] by force + + +section {* Two proofs for reflexivity of subtyping *} + +lemma subtype_reflexivity: + shows "\ \ ok \ T closed_in \ \ \ \ T <: T" +proof(nominal_induct T rule: ty.induct_unsafe) + case (TAll \ X T1 T2) + have i1: "\\. \ \ ok \ T1 closed_in \ \ \ \ T1 <: T1" by fact + have i2: "\\. \ \ ok \ T2 closed_in \ \ \ \ T2 <: T2" by fact + have f: "X\\" by fact + show "\ \ ok \ (\[X<:T2].T1) closed_in \ \ \ \ \[X<:T2].T1 <: \[X<:T2].T1" + proof (intro strip) + assume "(\[X<:T2].T1) closed_in \" + hence b1: "T2 closed_in \" and b2: "T1 closed_in ((X,T2)#\)" + by (auto simp add: closed_in_def ty.supp abs_supp) + assume c1: "\ \ ok" + hence c2: "\ ((X,T2)#\) ok" using b1 f by force + have "\ \ T2 <: T2" using i2 b1 c1 by simp + moreover + have "((X,T2)#\) \ T1 <: T1" using i1 b2 c2 by simp + ultimately show "\ \ \[X<:T2].T1 <: \[X<:T2].T1" using f by force + qed +qed (auto simp add: closed_in_def ty.supp supp_atm) + +lemma subtype_refl: + shows "\ \ ok \ T closed_in \ \ \ \ T <: T" +apply(nominal_induct T rule: ty.induct_unsafe) +apply(auto simp add: ty.supp abs_supp closed_in_def supp_atm) +(* FIXME: the new induction method from Markus will fix this uglyness *) +apply(atomize) +apply(drule_tac x="(tyvrs, ty2)#z" in spec) +apply(force simp add: closed_in_def) +done + +text {* Inversion lemmas\ *} +lemma S_TopE: + shows "\ \ Top <: T \ T = Top" +apply(ind_cases "\ \ Top <: T", auto) +done + +lemma S_ArrowE_left: + assumes a: "\ \ S1 \ S2 <: T" + shows "T = Top \ (\T1 T2. T = T1 \ T2 \ \ \ T1 <: S1 \ \ \ S2 <: T2)" +using a by (cases, auto simp add: ty.inject) + +lemma S_AllE_left: + shows "\\ \ \[X<:S1].S2 <: T; X\(\,S1)\ + \ T = Top \ (\T1 T2. T = \[X<:T1].T2 \ \ \ T1 <: S1 \ ((X,T1)#\) \ S2 <: T2)" + apply(frule subtype_implies_ok) + apply(ind_cases "\ \ \[X<:S1].S2 <: T") + apply(auto simp add: ty.inject alpha) + apply(rule_tac x="[(X,Xa)]\T2" in exI) + (* term *) + apply(rule conjI) + apply(rule sym) + apply(rule pt_bij2[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + apply(rule pt_tyvrs3) + apply(simp) + apply(rule at_ds5[OF at_tyvrs_inst]) + (* 1st conjunct *) + apply(rule conjI) + apply(simp add: pt_fresh_left[OF pt_tyvrs_inst, OF at_tyvrs_inst] calc_atm) + apply(simp add: fresh_prod) + apply(drule_tac \="((Xa,T1)#\)" in subtype_implies_closed)+ + apply(simp add: closed_in_def) + apply(auto simp add: domain_fresh[of "\" "X", symmetric]) + apply(simp add: fresh_def) + apply(subgoal_tac "X \ (insert Xa (domain \))")(*A*) + apply(force) + (*A*) + apply(simp add: at_fin_set_supp[OF at_tyvrs_inst, OF finite_domain]) + (* 2nd conjunct *) + apply(frule_tac X="X" in subtype_implies_fresh) + apply(simp add: fresh_prod) + apply(drule_tac X="Xa" in subtype_implies_fresh) + apply(assumption) + apply(simp add: fresh_prod) + apply(drule_tac pi="[(X,Xa)]" in subtype_eqvt) + apply(simp add: calc_atm) + apply(simp add: pt_fresh_fresh[OF pt_tyvrs_inst, OF at_tyvrs_inst]) + done + +section {* Type substitution *} + +lemma subst_ty_fresh[rule_format]: + fixes P :: "ty" + and X :: "tyvrs" + shows "X\(T,P) \ X\(subst_ty T Y P)" + apply (nominal_induct T rule: ty.induct_unsafe) + apply (auto simp add: fresh_prod abs_fresh) + done + +lemma subst_ctxt_fresh[rule_format]: + fixes X::"tyvrs" + shows "X\(\,P) \ X\(subst_ctxt \ Y P)" + apply (induct \) + apply (auto intro: subst_ty_fresh simp add: fresh_prod fresh_list_cons) + done + +(* +lemma subst_ctxt_closed: + shows "subst_ty b X P closed_in (subst_ctxt \ X P @ \)" + + +lemma substitution_ok: + shows "\ (\@(X,Q)#\) ok \ \ \ P <: Q \ \ ((subst_ctxt \ X P)@\) ok" + apply (induct \) + apply (auto dest: validE) + apply (rule v2) + apply assumption + apply (drule validE) + apply (auto simp add: fresh_list_append) + apply (rule subst_ctxt_fresh) + apply (simp add: fresh_prod) + apply (drule_tac X = "a" in subtype_implies_fresh) + apply (simp add: fresh_list_cons) + apply (simp add: fresh_prod) + apply (simp add: fresh_list_cons) + apply (drule validE) + +done +*) + +(* note: What should nominal induct do if the context is compound? *) +(* +lemma type_substitution: + assumes a0: "(\@(X,Q)#\) \ S <: T" + shows "\ (\@(X,Q)#\) ok \ \ \ P <: Q + \ ((subst_ctxt \ X P)@\) \ (subst_ty S X P) <: (subst_ty T X P)" + using a0 + thm subtype_of_rel_induct + apply(rule subtype_of_rel_induct[of "\@(X,Q)#\" "S" "T" _ "P"]) + apply(auto) + apply(rule S_Top) + defer + defer + defer + apply(rule S_Var) + defer + defer + defer + defer + apply(rule S_Refl) + defer + defer + + +apply (nominal_induct \ X Q \ S T rule: subtype_of_rel_induct) +*) + +section {* Weakening *} + +constdefs + extends :: "ty_context \ ty_context \ bool" ("_ extends _" [100,100] 100) + "\ extends \ \ \X Q. (X,Q)\set \ \ (X,Q)\set \" + +lemma extends_domain: + assumes a: "\ extends \" + shows "domain \ \ domain \" + using a + apply (auto simp add: extends_def) + apply (drule domain_existence) + apply (force simp add: domain_inclusion) + done + +lemma extends_closed: + assumes a1: "T closed_in \" + and a2: "\ extends \" + shows "T closed_in \" + using a1 a2 + by (auto dest: extends_domain simp add: closed_in_def) + +lemma weakening: + assumes a1: "\ \ S <: T" + shows "\ \ ok \ \ extends \ \ \ \ S <: T" + using a1 +proof (nominal_induct \ S T rule: subtype_of_rel_induct) + case (S_Top \ \ S) + have lh_drv_prem: "S closed_in \" by fact + show "\ \ ok \ \ extends \ \ \ \ S <: Top" + proof (intro strip) + assume "\ \ ok" + moreover + assume "\ extends \" + hence "S closed_in \" using lh_drv_prem by (rule_tac extends_closed) + ultimately show "\ \ S <: Top" by force + qed +next + case (S_Var \ \ X S T) + have lh_drv_prem: "(X,S) \ set \" by fact + have ih: "\\. \ \ ok \ \ extends \ \ \ \ S <: T" by fact + show "\ \ ok \ \ extends \ \ \ \ TyVar X <: T" + proof (intro strip) + assume ok: "\ \ ok" + and extends: "\ extends \" + have "(X,S) \ set \" using lh_drv_prem extends by (simp add: extends_def) + moreover + have "\ \ S <: T" using ok extends ih by simp + ultimately show "\ \ TyVar X <: T" using ok by force + qed +next + case (S_Refl \ \ X) + have lh_drv_prem: "X \ domain \" by fact + show ?case + proof (intro strip) + assume "\ \ ok" + moreover + assume "\ extends \" + hence "X \ domain \" using lh_drv_prem by (force dest: extends_domain) + ultimately show "\ \ TyVar X <: TyVar X" by force + qed +next + case S_Arrow thus ?case by force +next + case (S_All \ \ X S1 S2 T1 T2) + have fresh: "X\\" by fact + have ih1: "\\. \ \ ok \ \ extends \ \ \ \ T1 <: S1" by fact + have ih2: "\\. \ \ ok \ \ extends ((X,T1)#\) \ \ \ S2 <: T2" by fact + have lh_drv_prem: "\ \ T1 <: S1" by fact + hence b5: "T1 closed_in \" by (simp add: subtype_implies_closed) + show "\ \ ok \ \ extends \ \ \ \ \ [X<:S1].S2 <: \ [X<:T1].T2" + proof (intro strip) + assume ok: "\ \ ok" + and extends: "\ extends \" + have "T1 closed_in \" using extends b5 by (simp only: extends_closed) + hence "\ ((X,T1)#\) ok" using fresh ok by force + moreover + have "((X,T1)#\) extends ((X,T1)#\)" using extends by (force simp add: extends_def) + ultimately have "((X,T1)#\) \ S2 <: T2" using ih2 by simp + moreover + have "\ \ T1 <: S1" using ok extends ih1 by simp + ultimately show "\ \ \ [X<:S1].S2 <: \ [X<:T1].T2" using ok by (force intro: S_All) + qed +qed + +text {* more automated proof *} + +lemma weakening: + assumes a1: "\ \ S <: T" + shows "\ \ ok \ \ extends \ \ \ \ S <: T" + using a1 +proof (nominal_induct \ S T rule: subtype_of_rel_induct) + case (S_Top \ \ S) thus ?case by (force intro: extends_closed) +next + case (S_Var \ \ X S T) thus ?case by (force simp add: extends_def) +next + case (S_Refl \ \ X) thus ?case by (force dest: extends_domain) +next + case S_Arrow thus ?case by force +next + case (S_All \ \ X S1 S2 T1 T2) + have fresh: "X\\" by fact + have ih1: "\\. \ \ ok \ \ extends \ \ \ \ T1 <: S1" by fact + have ih2: "\\. \ \ ok \ \ extends ((X,T1)#\) \ \ \ S2 <: T2" by fact + have lh_drv_prem: "\ \ T1 <: S1" by fact + hence b5: "T1 closed_in \" by (simp add: subtype_implies_closed) + show "\ \ ok \ \ extends \ \ \ \ \ [X<:S1].S2 <: \ [X<:T1].T2" + proof (intro strip) + assume ok: "\ \ ok" + and extends: "\ extends \" + have "T1 closed_in \" using extends b5 by (simp only: extends_closed) + hence "\ ((X,T1)#\) ok" using fresh ok by force + moreover + have "((X,T1)#\) extends ((X,T1)#\)" using extends by (force simp add: extends_def) + ultimately have "((X,T1)#\) \ S2 <: T2" using ih2 by simp + moreover + have "\ \ T1 <: S1" using ok extends ih1 by simp + ultimately show "\ \ \ [X<:S1].S2 <: \ [X<:T1].T2" using ok by (force intro: S_All) + qed +qed + +(* helper lemma to calculate the measure of the induction *) +lemma measure_eq [simp]: "(x, y) \ measure f = (f x < f y)" + by (simp add: measure_def inv_image_def) + +(* HERE *) + + +lemma transitivity_and_narrowing: + "(\\ S T. \ \ S <: Q \ \ \ Q <: T \ \ \ S <: T) \ + (\\ \ X P M N. (\@(X,Q)#\) \ M <: N \ \ \ P <: Q \ (\@(X,P)#\) \ M <: N)" +proof (rule wf_induct [of "measure size_ty" _ Q, rule_format]) + show "wf (measure size_ty)" by simp +next + case (goal2 Q) + note IH1_outer = goal2[THEN conjunct1] + and IH2_outer = goal2[THEN conjunct2, THEN spec, of _ "[]", simplified] + (* CHECK: Not clear whether the condition size_ty Q = size_ty Q' is needed, or whether + just doing it for Q'=Q is enough *) + have transitivity: + "\\ S Q' T. \ \ S <: Q' \ size_ty Q = size_ty Q' \ \ \ Q' <: T \ \ \ S <: T" + proof - + + (* We first handle the case where T = Top once and for all; this saves some + repeated argument below (just like on paper :-). We establish a little lemma + that is invoked where needed in each case of the induction. *) + have top_case: + "\\ S T' P. \\ \ ok; S closed_in \; P \ \ \ S <: T'; T'=Top \ P\ \ \ \ S <: T'" + proof - + fix \ S T' P + assume S_Top_prem1: "S closed_in \" + and S_Top_prem2: "\ \ ok" + and alternative: "P \ \ \ S <: T'" + and "T'=Top \ P" + moreover + { assume "T'=Top" + hence "\ \ S <: T'" using S_Top_prem1 S_Top_prem2 by (simp add: S_Top) + } + moreover + { assume P + with alternative have "\ \ S <: T'" by simp + } + ultimately show "\ \ S <: T'" by blast + qed + + (* Now proceed by induction on the left-hand derivation *) + fix \ S Q' T + assume a: "\ \ S <: Q'" + from a show "size_ty Q = size_ty Q' \ \ \ Q' <: T \ \ \ S <: T" + (* FIXME : nominal induct does not work here because Gamma S and Q are fixed variables *) + (* FIX: It would be better to use S',\',etc., instead of S1,\1, for consistency, in the cases + where these do not refer to sub-phrases of S, etc. *) + proof(rule subtype_of_rel_induct[of "\" "S" "Q'" _ "T"]) + case (goal1 T' \1 S1) --"lh drv.: \ \ S <: Q' \ \1 \ S1 <: Top" + --"automatic proof: thus ?case proof (auto intro!: S_Top dest: S_TopE)" + assume lh_drv_prem1: "\ \1 ok" + and lh_drv_prem2: "S1 closed_in \1" + show "size_ty Q = size_ty Top \ \1 \ Top <: T' \ \1 \ S1 <: T'" + proof (intro strip) + assume "\1 \ Top <: T'" --"rh drv." + hence "T' = Top" by (rule S_TopE) + thus "\1 \ S1 <: T'" using top_case[of "\1" "S1" "False" "T'"] lh_drv_prem1 lh_drv_prem2 + by simp + qed + next + case (goal2 T' \1 X1 S1 T1) --"lh drv.: \ \ S <: Q' \ \1 \ TVar(X1) <: S1" + --"automatic proof: thus ?case proof (auto intro!: S_Var)" + have lh_drv_prem1: "\ \1 ok" by fact + have lh_drv_prem2: "(X1,S1)\set \1" by fact + have IH_inner: "\T. size_ty Q = size_ty T1 \ \1 \ T1 <: T \ \1 \ S1 <: T" by fact + show "size_ty Q = size_ty T1 \ \1 \ T1 <: T' \ \1 \ TyVar X1 <: T'" + proof (intro strip) + assume "\1 \ T1 <: T'" --"right-hand drv." + and "size_ty Q = size_ty T1" + with IH_inner have "\1 \ S1 <: T'" by simp + thus "\1 \ TyVar X1 <: T'" using lh_drv_prem1 lh_drv_prem2 by (simp add: S_Var) + qed + next + case goal3 --"S_Refl case" show ?case by simp + next + case (goal4 T' \1 S1 S2 T1 T2) --"lh drv.: \ \ S <: Q' == \1 \ S1 \ S2 <: T1 \ T2" + have lh_drv_prem1: "\1 \ T1 <: S1" by fact + have lh_drv_prem2: "\1 \ S2 <: T2" by fact + show "size_ty Q = size_ty (T1 \ T2) \ \1 \ T1 \ T2 <: T' \ \1 \ S1 \ S2 <: T'" + proof (intro strip) + assume measure: "size_ty Q = size_ty (T1 \ T2)" + and rh_deriv: "\1 \ T1 \ T2 <: T'" + have "S1 closed_in \1" and "S2 closed_in \1" + using lh_drv_prem1 lh_drv_prem2 by (simp_all add: subtype_implies_closed) + hence "(S1 \ S2) closed_in \1" by (simp add: closed_in_def ty.supp) + moreover + have "\ \1 ok" using rh_deriv by (rule subtype_implies_ok) + moreover + have "T' = Top \ (\T3 T4. T'= T3 \ T4 \ \1 \ T3 <: T1 \ \1 \ T2 <: T4)" + using rh_deriv by (rule S_ArrowE_left) + moreover + { assume "\T3 T4. T'= T3 \ T4 \ \1 \ T3 <: T1 \ \1 \ T2 <: T4" + then obtain T3 T4 + where T'_inst: "T'= T3 \ T4" + and rh_drv_prem1: "\1 \ T3 <: T1" + and rh_drv_prem2: "\1 \ T2 <: T4" by force + from IH1_outer[of "T1"] have "\1 \ T3 <: S1" + using measure rh_drv_prem1 lh_drv_prem1 by (force simp add: ty.inject) + moreover + from IH1_outer[of "T2"] have "\1 \ S2 <: T4" + using measure rh_drv_prem2 lh_drv_prem2 by (force simp add: ty.inject) + ultimately have "\1 \ S1 \ S2 <: T'" using T'_inst by force + } + ultimately show "\1 \ S1 \ S2 <: T'" using top_case[of "\1" "S1\S2" _ "T'"] by blast + qed + next + case (goal5 T' \1 X S1 S2 T1 T2) --"lh drv.: \ \ S <: Q' \ \1 \ \[X:S1].S2 <: \[X:T1].T2" + have lh_drv_prem1: "\1 \ T1 <: S1" by fact + have lh_drv_prem2: "((X,T1)#\1) \ S2 <: T2" by fact + have fresh_cond: "X\(\1,S1,T1)" by fact + show "size_ty Q = size_ty (\[X<:T1].T2) \ \1 \ \[X<:T1].T2 <: T' \ \1 \ \[X<:S1].S2 <: T'" + proof (intro strip) + assume measure: "size_ty Q = size_ty (\[X<:T1].T2)" + and rh_deriv: "\1 \ \[X<:T1].T2 <: T'" + have "S1 closed_in \1" and "S2 closed_in ((X,T1)#\1)" + using lh_drv_prem1 lh_drv_prem2 by (simp_all add: subtype_implies_closed) + hence "(\[X<:S1].S2) closed_in \1" by (force simp add: closed_in_def ty.supp abs_supp) + moreover + have "\ \1 ok" using rh_deriv by (rule subtype_implies_ok) + moreover + (* FIX: Maybe T3,T4 could be T1',T2' *) + have "T' = Top \ (\T3 T4. T'=\[X<:T3].T4 \ \1 \ T3 <: T1 \ ((X,T3)#\1) \ T2 <: T4)" + using rh_deriv fresh_cond by (auto dest: S_AllE_left simp add: fresh_prod) + moreover + { assume "\T3 T4. T'=\[X<:T3].T4 \ \1 \ T3 <: T1 \ ((X,T3)#\1) \ T2 <: T4" + then obtain T3 T4 + where T'_inst: "T'= \[X<:T3].T4" + and rh_drv_prem1: "\1 \ T3 <: T1" + and rh_drv_prem2:"((X,T3)#\1) \ T2 <: T4" by force + from IH1_outer[of "T1"] have "\1 \ T3 <: S1" + using lh_drv_prem1 rh_drv_prem1 measure by (force simp add: ty.inject) + moreover + from IH2_outer[of "T1"] have "((X,T3)#\1) \ S2 <: T2" + using measure lh_drv_prem2 rh_drv_prem1 by force + with IH1_outer[of "T2"] have "((X,T3)#\1) \ S2 <: T4" + using measure rh_drv_prem2 by force + moreover + ultimately have "\1 \ \[X<:S1].S2 <: T'" + using fresh_cond T'_inst by (simp add: fresh_prod S_All) + } + ultimately show "\1 \ \[X<:S1].S2 <: T'" using top_case[of "\1" "\[X<:S1].S2" _ "T'"] by blast + qed + qed + qed + +(* test + have narrowing: + "\\ \ X M N. (\@(X,Q)#\) \ M <: N \ (\P. \ \ P<:Q \ (\@(X,P)#\) \ M <: N)" + proof - + fix \ \ X M N + assume a: "(\@(X,Q)#\) \ M <: N" + thus "\P. \ \ P <: Q \ (\@(X,P)#\) \ M <: N" + thm subtype_of_rel_induct + thm subtype_of_rel.induct + using a proof (induct) + using a proof (induct rule: subtype_of_rel_induct[of "\@(X,Q)#\" "M" "N" _ "()"]) +*) + + have narrowing: + "\\ \ \' X M N. \' \ M <: N \ \' = \@(X,Q)#\ \ (\P. \ \ P<:Q \ (\@(X,P)#\) \ M <: N)" + proof - + fix \ \ \' X M N + assume "\' \ M <: N" + thus "\' = \@(X,Q)#\ \ (\P. \ \ P <: Q \ (\@(X,P)#\) \ M <: N)" + (* FIXME : nominal induct does not work here because Gamma' M and N are fixed variables *) + (* FIX: Same comment about S1,\1 *) + proof (rule subtype_of_rel_induct[of "\'" "M" "N" "\\' M N (\,\,X). + \' = \@(X,Q)#\ \ (\P. \ \ P <: Q \ (\@(X,P)#\) \ M <: N)" "(\,\,X)", simplified], + simp_all only: split_paired_all split_conv) + case (goal1 \1 \1 X1 \2 S1) + have lh_drv_prem1: "\ \2 ok" by fact + have lh_drv_prem2: "S1 closed_in \2" by fact + show "\2 = \1@(X1,Q)#\1 \ (\P. \1 \ P <: Q \ (\1@(X1,P)#\1) \ S1 <: Top)" + proof (intro strip) + fix P + assume a1: "\2 = \1@(X1,Q)#\1" + assume a2: "\1 \ P <: Q" + from a2 have "P closed_in \1" by (simp add: subtype_implies_closed) + hence a3: "\ (\1@(X1,P)#\1) ok" using lh_drv_prem1 a1 by (rule_tac replace_type, simp_all) + show "(\1@(X1,P)#\1) \ S1 <: Top" + using a1 a3 lh_drv_prem2 by (force simp add: closed_in_def domain_append) + qed + next + case (goal2 \1 \1 X1 \2 X2 S1 T1) + have lh_drv_prem1: "\ \2 ok" by fact + have lh_drv_prem2: "(X2,S1)\set \2" by fact + have lh_drv_prem3: "\2 \ S1 <: T1" by fact + have IH_inner: + "\\1 \1 X1. \2 = \1@(X1,Q)#\1 \ (\P. \1 \ P <: Q \ (\1@(X1,P)#\1) \ S1 <: T1)" by fact + show "\2 = (\1@(X1,Q)#\1) \ (\P. \1 \ P <: Q \ (\1@(X1,P)#\1) \ TyVar X2 <: T1)" + proof (intro strip) + fix P + assume a1: "\2 = \1@(X1,Q)#\1" + and a2: "\1 \ P <: Q" + from a2 have "P closed_in \1" by (simp add: subtype_implies_closed) + hence a3: "\ (\1@(X1,P)#\1) ok" + using lh_drv_prem1 a1 by (rule_tac replace_type, simp_all) + show "(\1@(X1,P)#\1) \ TyVar X2 <: T1" + proof (cases "X1=X2") + case False + have b0: "X1\X2" by fact + from lh_drv_prem3 a1 a2 IH_inner + have b1: "(\1@(X1,P)#\1) \ S1 <: T1" by simp + from lh_drv_prem2 a1 b0 have b2: "(X2,S1)\set (\1@(X1,P)#\1)" by simp + show "(\1@(X1,P)#\1) \ TyVar X2 <: T1" using a3 b2 b1 by (rule S_Var) + next + case True + have b0: "X1=X2" by fact + have a4: "S1=Q" + proof - + have c0: "(X2,Q)\set \2" using b0 a1 by simp + with lh_drv_prem1 lh_drv_prem2 show "S1=Q" by (simp add: uniqueness_of_ctxt) + qed + have a5: "(\1@(X1,P)#\1) extends \1" by (force simp add: extends_def) + have a6: "(\1@(X2,P)#\1) \ P <: Q" using b0 a5 a2 a3 by (simp add: weakening) + have a7: "(\1@(X2,P)#\1) \ Q <: T1" using b0 IH_inner a1 lh_drv_prem3 a2 a4 by simp + have a8: "(\1@(X2,P)#\1) \ P <: T1" using a6 a7 transitivity by blast + have a9: "(X2,P)\set (\1@(X1,P)#\1)" using b0 by simp + show "(\1@(X1,P)#\1) \ TyVar X2 <: T1" using a3 b0 a8 a9 by (force simp add: S_Var) + qed + qed + next + case (goal3 \1 \1 X1 \2 X2) + have lh_drv_prem1: "\ \2 ok" by fact + have lh_drv_prem2: "X2 \ domain \2" by fact + show "\2 = (\1@(X1,Q)#\1) \ (\P. \1 \ P <: Q \ (\1@(X1,P)#\1) \ TyVar X2 <: TyVar X2)" + proof (intro strip) + fix P + assume a1: "\2 = \1@(X1,Q)#\1" + and a2: "\1 \ P <: Q" + from a2 have "P closed_in \1" by (simp add: subtype_implies_closed) + hence a3: "\ (\1@(X1,P)#\1) ok" + using lh_drv_prem1 a1 by (rule_tac replace_type, simp_all) + have b0: "X2 \ domain (\1@(X1,P)#\1)" using lh_drv_prem2 a1 by (simp add: domain_append) + show "(\1@(X1,P)#\1) \ TyVar X2 <: TyVar X2" using a3 b0 by (rule S_Refl) + qed + next + case goal4 thus ?case by blast + next + case (goal5 \1 \1 X1 \2 X2 S1 S2 T1 T2) + have IH_inner1: + "\\1 \1 X1. \2 = \1@(X1,Q)#\1 \ (\P. \1 \ P <: Q \ (\1@(X1,P)#\1) \ T1 <: S1)" by fact + have IH_inner2: + "\\1 \1 X1. (X2,T1)#\2 = \1@(X1,Q)#\1 \ (\P. \1 \ P <: Q \ (\1@(X1,P)#\1) \ S2 <: T2)" + by fact + have lh_drv_prem1: "\2 \ T1 <: S1" by fact + have lh_drv_prem2: "X2 \ (\2,S1, T1)" by fact + have lh_drv_prem3: "((X2,T1) # \2) \ S2 <: T2" by fact + have freshness: "X2\(\1, \1, X1)" by fact + show "\2 = (\1@(X1,Q)#\1) \ + (\P. \1 \ P <: Q \ (\1@(X1,P)#\1) \ \ [X2<:S1].S2 <: \ [X2<:T1].T2)" + proof (intro strip) + fix P + assume a1: "\2 = \1@(X1,Q)#\1" + and a2: "\1 \ P <: Q" + have b0: "(\1@(X1,P)#\1) \ T1 <: S1" using a1 a2 lh_drv_prem1 IH_inner1 by simp + have b1: "(((X2,T1)#\1)@(X1,P)#\1) \ S2 <: T2" using a1 a2 lh_drv_prem3 IH_inner2 + apply auto + apply (drule_tac x="(X2,T1)#\1" in spec) + apply(simp) + done + have b3: "X2\(\1@(X1,P)#\1)" using lh_drv_prem2 freshness a2 + by (auto simp add: fresh_prod fresh_list_append fresh_list_cons dest: subtype_implies_fresh) + show "(\1@(X1,P)#\1) \ \ [X2<:S1].S2 <: \ [X2<:T1].T2" using b0 b3 b1 by force + qed + qed + qed + from transitivity narrowing show ?case by blast +qed + + + +section {* Terms *} + +nominal_datatype trm = Var "vrs" + | Lam "\vrs\trm" "ty" + | TAbs "\tyvrs\trm" "ty" + | App "trm" "trm" + | TApp "trm" "ty" + +consts + Lam_syn :: "vrs \ ty \ trm \ trm" ("Lam [_:_]._" [100,100,100] 100) + TAbs_syn :: "tyvrs \ ty \ trm \ trm" ("TAbs [_<:_]._" [100,100,100] 100) +translations + "Lam [a:tys].t" \ "trm.Lam a t tys" + "TAbs [a<:tys].t" \ "trm.TAbs a t tys" + diff -r 65e60434b3c2 -r 676d2e625d98 src/HOL/Nominal/Nominal.thy --- a/src/HOL/Nominal/Nominal.thy Fri Nov 25 14:00:22 2005 +0100 +++ b/src/HOL/Nominal/Nominal.thy Fri Nov 25 14:51:39 2005 +0100 @@ -5,7 +5,7 @@ uses ("nominal_atoms.ML") ("nominal_package.ML") - ("nominal_induct.ML") +(* ("nominal_induct.ML") *) ("nominal_permeq.ML") begin @@ -2283,10 +2283,12 @@ (*****************************************) (* setup for induction principles method *) +(* use "nominal_induct.ML"; method_setup nominal_induct = {* nominal_induct_method *} {* nominal induction *} +*) (*******************************) (* permutation equality tactic *) diff -r 65e60434b3c2 -r 676d2e625d98 src/HOL/Nominal/nominal_package.ML --- a/src/HOL/Nominal/nominal_package.ML Fri Nov 25 14:00:22 2005 +0100 +++ b/src/HOL/Nominal/nominal_package.ML Fri Nov 25 14:51:39 2005 +0100 @@ -997,11 +997,15 @@ (**** prove that new datatypes have finite support ****) + val _ = warning "proving finite support for the new datatype"; + val indnames = DatatypeProp.make_tnames recTs; val abs_supp = PureThy.get_thms thy8 (Name "abs_supp"); val supp_atm = PureThy.get_thms thy8 (Name "supp_atm"); + +(* val finite_supp_thms = map (fn atom => let val atomT = Type (atom, []) in map standard (List.take @@ -1017,6 +1021,7 @@ List.concat supp_thms))))), length new_type_names)) end) atoms; +*) (**** strong induction theorem ****) @@ -1081,13 +1086,13 @@ DatatypeAux.store_thmss "inject" new_type_names inject_thms |>>> DatatypeAux.store_thmss "supp" new_type_names supp_thms |>>> DatatypeAux.store_thmss_atts "fresh" new_type_names simp_atts fresh_thms |>> - fold (fn (atom, ths) => fn thy => + (* fold (fn (atom, ths) => fn thy => let val class = Sign.intern_class thy ("fs_" ^ Sign.base_name atom) in fold (fn T => AxClass.add_inst_arity_i (fst (dest_Type T), replicate (length sorts) [class], [class]) (AxClass.intro_classes_tac [] THEN resolve_tac ths 1)) newTs thy - end) (atoms ~~ finite_supp_thms) |>> + end) (atoms ~~ finite_supp_thms) |>> *) Theory.add_path big_name |>>> PureThy.add_axioms_i [(("induct_unsafe", induct), [case_names_induct])] |>> Theory.parent_path;