# HG changeset patch # User urbanc # Date 1136761510 -3600 # Node ID 4a3806b41d29361b72c331205f3307b038ab90ab # Parent fc8b5f275359b82c38d0d13f647d6e8e53345ca5 commented the transitivity and narrowing proof diff -r fc8b5f275359 -r 4a3806b41d29 src/HOL/Nominal/Examples/Fsub.thy --- a/src/HOL/Nominal/Examples/Fsub.thy Sat Jan 07 23:28:01 2006 +0100 +++ b/src/HOL/Nominal/Examples/Fsub.thy Mon Jan 09 00:05:10 2006 +0100 @@ -14,11 +14,11 @@ with great help from Stefan Berghofer and Markus Wenzel. *} -section {* Atom Types, Types and Terms *} +section {* Types for Names, Nominal Datatype Declaration for Types and Terms *} text {* The main point of this solution is to use names everywhere (be they bound, - binding or free). There are two kinds of names corresponding to type-variables and - to term-variables in System \FSUB. These two kinds of names are represented in + binding or free). In System \FSUB{} there are two kinds of names corresponding to + type-variables and to term-variables. These two kinds of names are represented in the nominal datatype package as atom-types @{text "tyvrs"} and @{text "vrs"}: *} atom_decl tyvrs vrs @@ -44,9 +44,9 @@ | Tapp "trm" "ty" text {* To be polite to the eye, some more familiar notation is introduced. - Because of the change in the order of the argument, one needs to use + Because of the change in the order of arguments, one needs to use translation rules, instead of syntax annotations at the term-constructors - like for @{term "Arrow"}. *} + as given for @{term "Arrow"}. *} syntax Forall_syn :: "tyvrs \ ty \ ty \ ty" ("\[_<:_]._" [100,100,100] 100) @@ -58,9 +58,11 @@ "Lam [x:T].t" \ "trm.Lam x t T" "Tabs [X<:T].t" \ "trm.Tabs X t T" -text {* Note that the nominal-datatype declarations for @{typ "ty"} and @{typ "trm"} - do \emph{not} define "classical" constructor-based datatypes, but rather define - $\alpha$-equivalence classes. Indeed we can show that $\alpha$-equivalent @{typ "ty"}s +text {* Again there are numerous facts that are proved automatically for @{typ "ty"} + and @{typ "trm"}: for example that the set of free variables, i.e.~@{text "support"}, + is only finite. However note that nominal-datatype declarations do \emph{not} define + "classical" constructor-based datatypes, but rather define $\alpha$-equivalence + classes---we can for example show that $\alpha$-equivalent @{typ "ty"}s and @{typ "trm"}s are equal: *} lemma alpha_illustration: @@ -68,15 +70,16 @@ and "Lam [x:T].(Var x) = Lam [y:T].(Var y)" by (simp_all add: ty.inject trm.inject alpha calc_atm fresh_atm) -section {* Typing Contexts *} +section {* SubTyping Contexts *} types ty_context = "(tyvrs\ty) list" -text {* Typing contexts are represented as lists "growing" on the left, - in contrast to the POPLmark-paper. *} +text {* Typing contexts are represented as lists "growing" on the left; we + thereby deviating from the convention in the POPLmark-paper. The lists contain + pairs of type-variables and types. *} -text {* In order to state valitity-conditions for typing-context, the notion of - a domain of a typing-context is handy. *} +text {* In order to state valitity-conditions for typing-contexts, the notion of + a @{text "domain"} of a typing-context is handy. *} consts "domain" :: "ty_context \ tyvrs set" @@ -93,6 +96,10 @@ shows "finite (domain \)" by (induct \, auto) +lemma domain_supp: + shows "(supp (domain \)) = (domain \)" + by (simp only: at_fin_set_supp at_tyvrs_inst finite_domain) + lemma domain_inclusion: assumes a: "(X,T)\set \" shows "X\(domain \)" @@ -107,19 +114,32 @@ shows "domain (\@\) = ((domain \) \ (domain \))" by (induct \, auto) +lemma fresh_domain_cons: + fixes X::"tyvrs" + shows "X\(domain (Y#\)) = (X\(fst Y) \ X\(domain \))" + by (simp add: fresh_fin_insert pt_tyvrs_inst at_tyvrs_inst fs_tyvrs_inst finite_domain) + +lemma fresh_domain: + fixes X::"tyvrs" + assumes a: "X\\" + shows "X\(domain \)" +using a +apply(induct \) +apply(simp add: fresh_set_empty) +apply(simp only: fresh_domain_cons) +apply(auto simp add: fresh_prod fresh_list_cons) +done + text {* Not all lists of type @{typ "ty_context"} are well-formed. One condition requires that in @{term "(X,S)#\"} all free variables of @{term "S"} must be - in @{term "domain \"}, that is @{term "S"} must be closed in @{term "\"}. *} + in the @{term "domain"} of @{term "\"}, that is @{term "S"} must be @{text "closed"} + in @{term "\"}. The set of free variables of @{term "S"} is defined as the + @{text "support"} of @{term "S"}. *} 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 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 \" @@ -133,6 +153,8 @@ by (simp add: domain_eqvt pt_perm_supp[OF pt_tyvrs_inst, OF at_tyvrs_inst]) qed +text {* Now validity of a context is a straightforward inductive definition. *} + consts valid_rel :: "ty_context set" valid_sym :: "ty_context \ bool" ("\ _ ok" [100] 100) @@ -140,9 +162,8 @@ "\ \ ok" \ "\ \ valid_rel" inductive valid_rel intros -v_nil[intro]: "\ [] ok" -v_cons[intro]: "\\ \ ok; X\\; T closed_in \\ \ \ ((X,T)#\) ok" - +valid_nil[simp]: "\ [] ok" +valid_cons[simp]: "\\ \ ok; X\(domain \); T closed_in \\ \ \ ((X,T)#\) ok" lemma valid_eqvt: fixes pi::"tyvrs prm" @@ -150,23 +171,23 @@ shows "\ (pi\\) ok" using a proof (induct) - case v_nil - show "\ (pi\[]) ok" by (simp add: valid_rel.v_nil) + case valid_nil + show "\ (pi\[]) ok" by simp next - case (v_cons T X \) - have "\ (pi \ \) ok" by fact + case (valid_cons T X \) + have "\ (pi\\) ok" by fact moreover - have "X\\" by fact - hence "(pi\X)\(pi\\)" by (simp add: fresh_eqvt) + have "X\(domain \)" by fact + hence "(pi\X)\(domain (pi\\))" by (simp add: fresh_eqvt domain_eqvt[symmetric]) moreover have "T closed_in \" by fact - hence "(pi\T) closed_in (pi\\)" by (rule closed_in_eqvt) - ultimately show "\ (pi\((X,T)#\)) ok" by (simp add: valid_rel.v_cons) + hence "(pi\T) closed_in (pi\\)" by (simp add: closed_in_eqvt) + ultimately show "\ (pi\((X,T)#\)) ok" by simp qed lemma validE: assumes a: "\ ((X,T)#\) ok" - shows "\ \ ok \ X\\ \ T closed_in \" + shows "\ \ ok \ X\(domain \) \ T closed_in \" using a by (cases, auto) lemma validE_append: @@ -174,74 +195,61 @@ shows "\ \ ok" using a by (induct \, auto dest: validE) -lemma domain_fresh: - fixes X::"tyvrs" - assumes a: "\ \ ok" - shows "X\(domain \) = X\\" -using a -apply(induct \) -apply(auto simp add: fresh_list_nil fresh_list_cons fresh_set_empty fresh_prod fresh_atm - fresh_fin_insert[OF pt_tyvrs_inst, OF at_tyvrs_inst, OF fs_tyvrs_inst, OF finite_domain]) -apply(force simp add: closed_in_def2 fresh_def) -done - lemma closed_in_fresh: fixes X::"tyvrs" - assumes a1: "S closed_in \" - and a2: "X\\" - and a3: "\ \ ok" + assumes a: "S closed_in \" + and b: "X\(domain \)" + and c: "\ \ 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 +using a b c by (force simp add: fresh_def domain_supp closed_in_def) lemma replace_type: assumes a: "\ (\@(X,T)#\) ok" and b: "S closed_in \" shows "\ (\@(X,S)#\) ok" -using a b +using a b apply(induct \) -apply(auto dest!: validE intro!: v_cons 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) +apply(auto dest!: validE intro!: valid_cons simp add: domain_append closed_in_def) done -lemma fresh_implies_not_member: - fixes \::"ty_context" - assumes a: "X\\" - shows "\(\T.(X,T)\(set \))" - using a by (induct \, auto dest: validE simp add: fresh_list_cons fresh_prod fresh_atm) - lemma uniqueness_of_ctxt: fixes \::"ty_context" assumes a: "\ \ ok" and b: "(X,T)\set \" and c: "(X,S)\set \" shows "T=S" - using a b c by (induct \, auto dest: validE fresh_implies_not_member) - -subsection {* Size Functions and Capture-Avoiding Substitutiuon for Types *} +using a b c +proof (induct) + case valid_nil thus "T=S" by simp +next + case (valid_cons U Y \) + moreover + { fix \::"ty_context" + assume a: "X\(domain \)" + have "\(\T.(X,T)\(set \))" using a + proof (induct \) + case (Cons Y \) + thus "\ (\T.(X,T)\set(Y#\))" + by (simp only: fresh_domain_cons, auto simp add: fresh_atm) + qed (simp) + } + ultimately show "T=S" by auto +qed -text {* In the current version of the nominal datatype - package even simple functions (such as size of types and capture-avoiding - substitution) can only be defined manually via some sophisticated proof - constructions. Therefore we sill just assume them here. *} +section {* Size and Capture-Avoiding Substitutiuon for Types *} + +text {* In the current version of the nominal datatype-package even simple + functions (such as size of types and capture-avoiding substitution) can + only be defined manually via some labourious proof constructions. Therefore + we sill just assume them here. *} consts size_ty :: "ty \ nat" lemma size_ty[simp]: shows "size_ty (Tvar X) = 1" and "size_ty (Top) = 1" - and "\size_ty t\<^isub>1 = m ; size_ty t\<^isub>2 = n\ \ size_ty (t\<^isub>1 \ t\<^isub>2) = m + n + 1" - and "\size_ty t\<^isub>1 = m ; size_ty t\<^isub>2 = n\ \ size_ty (\[a<:t\<^isub>1].t\<^isub>2) = m + n + 1" + and "\size_ty T\<^isub>1 = m; size_ty T\<^isub>2 = n\ \ size_ty (T\<^isub>1 \ T\<^isub>2) = m + n + 1" + and "\size_ty T\<^isub>1 = m; size_ty T\<^isub>2 = n\ \ size_ty (\[X<:T\<^isub>1].T\<^isub>2) = m + n + 1" sorry consts subst_ty :: "ty \ tyvrs \ ty \ ty" ("_[_:=_]\<^isub>t\<^isub>y" [100,100,100] 100) @@ -254,7 +262,7 @@ and "\X\Y; X\T\ \ (\[X<:T\<^isub>1].T\<^isub>2)[Y:=T]\<^isub>t\<^isub>y = (\[X<:(T\<^isub>1[Y:=T]\<^isub>t\<^isub>y)].(T\<^isub>2[Y:=T]\<^isub>t\<^isub>y))" sorry -consts subst_ctxt :: "ty_context \ tyvrs \ ty \ ty_context" ("_[_:=_]\<^isub>t\<^isub>y\<^isub>c" [100,100,100] 100) +consts subst_tyc :: "ty_context \ tyvrs \ ty \ ty_context" ("_[_:=_]\<^isub>t\<^isub>y\<^isub>c" [100,100,100] 100) primrec "([])[Y:=T]\<^isub>t\<^isub>y\<^isub>c= []" "(XT#\)[Y:=T]\<^isub>t\<^isub>y\<^isub>c = (fst XT,(snd XT)[Y:=T]\<^isub>t\<^isub>y)#(\[Y:=T]\<^isub>t\<^isub>y\<^isub>c)" @@ -264,18 +272,18 @@ consts subtype_of :: "(ty_context \ ty \ ty) set" syntax - subtype_of_syn :: "ty_context \ ty \ ty \ bool" ("_ \ _ <: _" [100,100,100] 100) + subtype_of_syn :: "ty_context \ ty \ ty \ bool" ("_\_<:_" [100,100,100] 100) translations "\ \ S <: T" \ "(\,S,T) \ subtype_of" inductive subtype_of intros -S_Top[intro]: "\\ \ ok; S closed_in \\ \ \ \ S <: Top" -S_Var[intro]: "\\ \ ok; (X,S) \ set \; \ \ S <: T\ \ \ \ (Tvar X) <: T" -S_Refl[intro]: "\\ \ ok; X \ domain \\\ \ \ Tvar X <: Tvar X" -S_Arrow[intro]: "\\ \ T\<^isub>1 <: S\<^isub>1; \ \ S\<^isub>2 <: T\<^isub>2\ \ \ \ (S\<^isub>1 \ S\<^isub>2) <: (T\<^isub>1 \ T\<^isub>2)" -S_All[intro]: "\\ \ T\<^isub>1 <: S\<^isub>1; X\\; ((X,T\<^isub>1)#\) \ S\<^isub>2 <: T\<^isub>2\ - \ \ \ \[X<:S\<^isub>1].S\<^isub>2 <: \[X<:T\<^isub>1].T\<^isub>2" +S_Top[intro]: "\\ \ ok; S closed_in \\ \ \ \ S <: Top" +S_Var[intro]: "\(X,S) \ set \; \ \ S <: T\ \ \ \ (Tvar X) <: T" +S_Refl[intro]: "\\ \ ok; X \ domain \\\ \ \ Tvar X <: Tvar X" +S_Arrow[intro]: "\\ \ T\<^isub>1 <: S\<^isub>1; \ \ S\<^isub>2 <: T\<^isub>2\ \ \ \ (S\<^isub>1 \ S\<^isub>2) <: (T\<^isub>1 \ T\<^isub>2)" +S_Forall[intro]: "\\ \ T\<^isub>1 <: S\<^isub>1; X\\; ((X,T\<^isub>1)#\) \ S\<^isub>2 <: T\<^isub>2\ + \ \ \ \[X<:S\<^isub>1].S\<^isub>2 <: \[X<:T\<^isub>1].T\<^isub>2" lemma subtype_implies_closed: assumes a: "\ \ S <: T" @@ -311,11 +319,11 @@ shows "X\S \ X\T" proof - from a1 have "\ \ ok" by (rule subtype_implies_ok) - with a2 have "X\domain(\)" by (simp add: domain_fresh) + with a2 have "X\domain(\)" by (simp add: fresh_domain) moreover from a1 have "S closed_in \ \ T closed_in \" by (rule subtype_implies_closed) hence "supp S \ ((supp (domain \))::tyvrs set)" - and "supp T \ ((supp (domain \))::tyvrs set)" by (simp_all add: closed_in_def2) + and "supp T \ ((supp (domain \))::tyvrs set)" by (simp_all add: domain_supp closed_in_def) ultimately show "X\S \ X\T" by (force simp add: supp_prod fresh_def) qed @@ -344,20 +352,20 @@ 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 fresh_eqvt) +apply(force intro!: S_Forall simp add: fresh_prod fresh_eqvt) done -lemma subtype_of_induct[consumes 1, case_names S_Top S_Var S_Refl S_Arrow S_All]: +lemma subtype_of_induct[consumes 1, case_names S_Top S_Var S_Refl S_Arrow S_Forall]: fixes P :: "'a::fs_tyvrs\ty_context \ ty \ ty \bool" assumes a: "\ \ S <: T" - and a1: "\\ S x. \ \ ok \ S closed_in \ \ P x \ S Top" - and a2: "\\ X S T x. \ \ ok \ (X,S)\set \ \ \ \ S <: T \ (\z. P z \ S T) - \ P x \ (Tvar X) T" - and a3: "\\ X x. \ \ ok \ X\domain \ \ P x \ (Tvar X) (Tvar X)" - and a4: "\\ S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2 x. \ \ T\<^isub>1 <: S\<^isub>1 \ (\z. P z \ T\<^isub>1 S\<^isub>1) \ \ \ S\<^isub>2 <: T\<^isub>2 \ - (\z. P z \ S\<^isub>2 T\<^isub>2) \ P x \ (S\<^isub>1 \ S\<^isub>2) (T\<^isub>1 \ T\<^isub>2)" - and a5: "\\ X S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2 x. X\x \ X\(\,S\<^isub>1,T\<^isub>1) \ \ \ T\<^isub>1 <: S\<^isub>1 \ (\z. P z \ T\<^isub>1 S\<^isub>1) - \ ((X,T\<^isub>1)#\) \ S\<^isub>2 <: T\<^isub>2 \ (\z. P z ((X,T\<^isub>1)#\) S\<^isub>2 T\<^isub>2) \ P x \ (\[X<:S\<^isub>1].S\<^isub>2) (\[X<:T\<^isub>1].T\<^isub>2)" + and a1: "\\ S x. \\ \ ok; S closed_in \\ \ P x \ S Top" + and a2: "\\ X S T x. \(X,S)\set \; \ \ S <: T; \z. P z \ S T\ \ P x \ (Tvar X) T" + and a3: "\\ X x. \\ \ ok; X\domain \\ \ P x \ (Tvar X) (Tvar X)" + and a4: "\\ S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2 x. \\ \ T\<^isub>1 <: S\<^isub>1; \z. P z \ T\<^isub>1 S\<^isub>1; \ \ S\<^isub>2 <: T\<^isub>2; \z. P z \ S\<^isub>2 T\<^isub>2\ + \ P x \ (S\<^isub>1 \ S\<^isub>2) (T\<^isub>1 \ T\<^isub>2)" + and a5: "\\ X S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2 x. + \X\x; X\(\,S\<^isub>1,T\<^isub>1); \ \ T\<^isub>1 <: S\<^isub>1; \z. P z \ T\<^isub>1 S\<^isub>1; ((X,T\<^isub>1)#\) \ S\<^isub>2 <: T\<^isub>2; \z. P z ((X,T\<^isub>1)#\) S\<^isub>2 T\<^isub>2\ + \ P x \ (\[X<:S\<^isub>1].S\<^isub>2) (\[X<:T\<^isub>1].T\<^isub>2)" shows "P x \ S T" proof - from a have "\(pi::tyvrs prm) (x::'a::fs_tyvrs). P x (pi\\) (pi\S) (pi\T)" @@ -366,9 +374,6 @@ thus "P x (pi\\) (pi\S) (pi\Top)" by (force intro: valid_eqvt closed_in_eqvt a1) next case (S_Var S T X \) - have "\ \ ok" by fact - hence "\ (pi\\) ok" by (rule valid_eqvt) - moreover have "(X,S) \ set \" by fact hence "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]) @@ -392,7 +397,7 @@ next case S_Arrow thus ?case by (auto intro: a4 subtype_eqvt) next - case (S_All S1 S2 T1 T2 X \) + case (S_Forall S1 S2 T1 T2 X \) have b1: "\ \ T1 <: S1" by fact have b2: "\(pi::tyvrs prm) x. P x (pi\\) (pi\T1) (pi\S1)" by fact have b4: "((X,T1)#\) \ S2 <: T2" by fact @@ -444,7 +449,7 @@ thus ?thesis by simp qed -subsection {* Reflexivity of Subtyping *} +section {* Reflexivity of Subtyping *} lemma subtype_reflexivity: assumes a: "\ \ ok" @@ -456,19 +461,20 @@ have ih_T\<^isub>1: "\\. \ \ ok \ T\<^isub>1 closed_in \ \ \ \ T\<^isub>1 <: T\<^isub>1" by fact have ih_T\<^isub>2: "\\. \ \ ok \ T\<^isub>2 closed_in \ \ \ \ T\<^isub>2 <: T\<^isub>2" by fact have fresh_cond: "X\\" by fact + hence fresh_domain: "X\(domain \)" by (simp add: fresh_domain) have "(\[X<:T\<^isub>2].T\<^isub>1) closed_in \" by fact hence closed\<^isub>T\<^isub>2: "T\<^isub>2 closed_in \" and closed\<^isub>T\<^isub>1: "T\<^isub>1 closed_in ((X,T\<^isub>2)#\)" by (auto simp add: closed_in_def ty.supp abs_supp) have ok: "\ \ ok" by fact - hence ok': "\ ((X,T\<^isub>2)#\) ok" using closed\<^isub>T\<^isub>2 fresh_cond by force + hence ok': "\ ((X,T\<^isub>2)#\) ok" using closed\<^isub>T\<^isub>2 fresh_domain by simp have "\ \ T\<^isub>2 <: T\<^isub>2" using ih_T\<^isub>2 closed\<^isub>T\<^isub>2 ok by simp moreover have "((X,T\<^isub>2)#\) \ T\<^isub>1 <: T\<^isub>1" using ih_T\<^isub>1 closed\<^isub>T\<^isub>1 ok' by simp ultimately show "\ \ \[X<:T\<^isub>2].T\<^isub>1 <: \[X<:T\<^isub>2].T\<^isub>1" using fresh_cond - by (simp add: subtype_of.S_All) + by (simp add: subtype_of.S_Forall) qed (auto simp add: closed_in_def ty.supp supp_atm) -lemma subtype_reflexivity: +lemma subtype_reflexivity_semiautomated: assumes a: "\ \ ok" and b: "T closed_in \" shows "\ \ T <: T" @@ -476,10 +482,10 @@ apply(nominal_induct T avoiding: \ rule: ty.induct_unsafe) apply(auto simp add: ty.supp abs_supp closed_in_def supp_atm) --{* Too bad that this instantiation cannot be found automatically by - auto; blast cannot be used since the simplification rule - @{text "closed_in_def"} needs to be applied. *} + \isakeyword{auto}; \isakeyword{blast} would find it if we had not used + the definition @{text "closed_in_def"}. *} apply(drule_tac x="(tyvrs, ty2)#\" in meta_spec) -apply(force simp add: closed_in_def) +apply(force simp add: closed_in_def fresh_domain) done text {* Inversion lemmas *} @@ -493,7 +499,7 @@ 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: +lemma S_ForallE_left: shows "\\ \ \[X<:S1].S2 <: T; X\\; X\S1\ \ T = Top \ (\T1 T2. T = \[X<:T1].T2 \ \ \ T1 <: S1 \ ((X,T1)#\) \ S2 <: T2)" apply(frule subtype_implies_ok) @@ -512,7 +518,7 @@ apply(simp add: pt_fresh_left[OF pt_tyvrs_inst, OF at_tyvrs_inst] calc_atm) apply(drule_tac \="((Xa,T\<^isub>1)#\)" in subtype_implies_closed)+ apply(simp add: closed_in_def) - apply(simp add: domain_fresh[of "\" "X", symmetric]) + apply(drule fresh_domain)+ apply(simp add: fresh_def) apply(subgoal_tac "X \ (insert Xa (domain \))")(*A*) apply(force) @@ -534,7 +540,7 @@ lemma subst_ty_fresh: fixes X :: "tyvrs" assumes a: "X\(T,P)" - shows "X\(subst_ty T Y P)" + shows "X\T[Y:=P]\<^isub>t\<^isub>y" using a apply (nominal_induct T avoiding : T Y P rule: ty.induct_unsafe) apply (auto simp add: fresh_prod abs_fresh) @@ -543,7 +549,7 @@ lemma subst_ctxt_fresh: fixes X::"tyvrs" assumes a: "X\(\,P)" - shows "X\(subst_ctxt \ Y P)" + shows "X\\[Y:=P]\<^isub>t\<^isub>y\<^isub>c" using a apply (induct \) apply (auto intro: subst_ty_fresh simp add: fresh_prod fresh_list_cons) @@ -663,8 +669,9 @@ next case (S_Arrow \ S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2) thus "\ \ S\<^isub>1 \ S\<^isub>2 <: T\<^isub>1 \ T\<^isub>2" by blast next - case (S_All \ X S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2) + case (S_Forall \ X S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2) have fresh_cond: "X\\" by fact + hence fresh_domain: "X\(domain \)" by (simp add: fresh_domain) have ih\<^isub>1: "\\. \ \ ok \ \ extends \ \ \ \ T\<^isub>1 <: S\<^isub>1" by fact have ih\<^isub>2: "\\. \ \ ok \ \ extends ((X,T\<^isub>1)#\) \ \ \ S\<^isub>2 <: T\<^isub>2" by fact have lh_drv_prem: "\ \ T\<^isub>1 <: S\<^isub>1" by fact @@ -672,26 +679,27 @@ have ok: "\ \ ok" by fact have ext: "\ extends \" by fact have "T\<^isub>1 closed_in \" using ext closed\<^isub>T\<^isub>1 by (simp only: extends_closed) - hence "\ ((X,T\<^isub>1)#\) ok" using fresh_cond ok by force + hence "\ ((X,T\<^isub>1)#\) ok" using fresh_domain ok by force moreover have "((X,T\<^isub>1)#\) extends ((X,T\<^isub>1)#\)" using ext by (force simp add: extends_def) ultimately have "((X,T\<^isub>1)#\) \ S\<^isub>2 <: T\<^isub>2" using ih\<^isub>2 by simp moreover have "\ \ T\<^isub>1 <: S\<^isub>1" using ok ext ih\<^isub>1 by simp - ultimately show "\ \ \[X<:S\<^isub>1].S\<^isub>2 <: \[X<:T\<^isub>1].T\<^isub>2" using ok by (force intro: S_All) + ultimately show "\ \ \[X<:S\<^isub>1].S\<^isub>2 <: \[X<:T\<^isub>1].T\<^isub>2" using ok by (force intro: S_Forall) qed text {* In fact all "non-binding" cases can be solved automatically: *} -lemma weakening: +lemma weakening_semiautomated: assumes a: "\ \ S <: T" and b: "\ \ ok" and c: "\ extends \" shows "\ \ S <: T" using a b c proof (nominal_induct \ S T avoiding: \ rule: subtype_of_induct) - case (S_All \ X S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2) + case (S_Forall \ X S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2) have fresh_cond: "X\\" by fact + hence fresh_domain: "X\(domain \)" by (simp add: fresh_domain) have ih\<^isub>1: "\\. \ \ ok \ \ extends \ \ \ \ T\<^isub>1 <: S\<^isub>1" by fact have ih\<^isub>2: "\\. \ \ ok \ \ extends ((X,T\<^isub>1)#\) \ \ \ S\<^isub>2 <: T\<^isub>2" by fact have lh_drv_prem: "\ \ T\<^isub>1 <: S\<^isub>1" by fact @@ -699,230 +707,303 @@ have ok: "\ \ ok" by fact have ext: "\ extends \" by fact have "T\<^isub>1 closed_in \" using ext closed\<^isub>T\<^isub>1 by (simp only: extends_closed) - hence "\ ((X,T\<^isub>1)#\) ok" using fresh_cond ok by force + hence "\ ((X,T\<^isub>1)#\) ok" using fresh_domain ok by force moreover have "((X,T\<^isub>1)#\) extends ((X,T\<^isub>1)#\)" using ext by (force simp add: extends_def) ultimately have "((X,T\<^isub>1)#\) \ S\<^isub>2 <: T\<^isub>2" using ih\<^isub>2 by simp moreover have "\ \ T\<^isub>1 <: S\<^isub>1" using ok ext ih\<^isub>1 by simp - ultimately show "\ \ \[X<:S\<^isub>1].S\<^isub>2 <: \[X<:T\<^isub>1].T\<^isub>2" using ok by (force intro: S_All) + ultimately show "\ \ \[X<:S\<^isub>1].S\<^isub>2 <: \[X<:T\<^isub>1].T\<^isub>2" using ok by (force intro: S_Forall) qed (blast intro: extends_closed extends_memb dest: extends_domain)+ -text {* our contexts grow from right to left *} +text {* Next we prove the transitivity and narrowing for the subtyping relation. +The POPLmark-paper says the following: + +\begin{lemma}[Transitivity and Narrowing] \ +\begin{enumerate} +\item If @{term "\ \ S<:Q"} and @{term "\ \ Q<:T"}, then @{term "\ \ S<:T"}. +\item If @{text "\,X<:Q,\ \ M<:N"} and @{term "\ \ P<:Q"} then @{text "\,X<:P,\ \ M<:N"}. +\end{enumerate} +\end{lemma} + +The two parts are proved simultaneously, by induction on the size +of @{term "Q"}. The argument for part (2) assumes that part (1) has +been established already for the @{term "Q"} in question; part (1) uses +part (2) only for strictly smaller @{term "Q"}. + +For the induction on the size of @{term "Q"}, we use the induction-rule +@{text "measure_induct_rule"}: + +\begin{center} +@{thm measure_induct_rule[of "size_ty",no_vars]} +\end{center} -lemma transitivity_and_narrowing: - shows "\ \ S <: Q \ \ \ Q <: T \ \ \ S <: T" - and "(\@[(X,Q)]@\) \ M <: N \ \ \ P <: Q \ (\@[(X,P)]@\) \ M <: N" -proof (induct Q fixing: \ S T and \ \ X P M N taking: "size_ty" rule: measure_induct_rule) - case (less Q) - note IH_trans = prems[THEN conjunct1, rule_format] - note IH_narrow = prems[THEN conjunct2, THEN spec, of _ "[]", simplified, rule_format] +It says in English: in order to show a property @{term "P a"} for all @{term "a"}, +it requires to prove that for all @{term x} @{term "P x"} holds using the +assumption that for all @{term y} whose size is strictly smaller than +that of @{term x} the property @{term "P y"} holds. *} - --{* The inner induction for transitivity over @{term "\ \ S <: Q"} *} - have transitivity: - "\\ S T. \ \ S <: Q \ \ \ Q <: T \ \ \ S <: T" +lemma + shows trans: "\\S<:Q \ \\Q<:T \ \\S<:T" + and narrow: "(\@[(X,Q)]@\)\M<:N \ \\P<:Q \ (\@[(X,P)]@\)\M<:N" +proof (induct Q fixing: \ S T \ X P M N taking: "size_ty" rule: measure_induct_rule) + case (less Q) + --{* \begin{minipage}[t]{0.9\textwidth} + First we mention the induction hypotheses of the outer induction for later + reference:\end{minipage}*} + have IH_trans: + "\Q' \ S T. \size_ty Q' < size_ty Q; \\S<:Q'; \\Q'<:T\ \ \\S<:T" by fact + have IH_narrow: + "\Q' \ \ X M N P. \size_ty Q' < size_ty Q; (\@[(X,Q')]@\)\M<:N; \\P<:Q'\ + \ (\@[(X,P)]@\)\M<:N" by fact + --{* \begin{minipage}[t]{0.9\textwidth} + We proceed with the transitivity proof as an auxiliary lemma, because it needs + to be referenced in the narrowing proof.\end{minipage}*} + have transitivity_aux: + "\\ S T. \\ \ S <: 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 :-). To do so we establish a little - lemma that is invoked where needed in the induction for transitivity. *} - 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_prm1: "S closed_in \" - and S_Top_prm2: "\ \ ok" - and alternative: "P \ \ \ S <: T'" - and "T'=Top \ P" - moreover - { assume "T'=Top" - hence "\ \ S <: T'" using S_Top_prm1 S_Top_prm2 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 the inner induction on the left-hand derivation *} fix \' S' T - assume a: "\' \ S' <: Q" --{* lh derivation *} - assume b: "\' \ Q <: T" --{* rh derivation *} - from a b show "\' \ S' <: T" - proof(nominal_induct \' S' Q\Q avoiding: \' S' T rule: subtype_of_induct) + assume "\' \ S' <: Q" --{* left-hand derivation *} + and "\' \ Q <: T" --{* right-hand derivation *} + thus "\' \ S' <: T" + proof (nominal_induct \' S' Q\Q avoiding: \' S' rule: subtype_of_induct) case (S_Top \ S) - --{* in this case lh drv is @{term "\ \ S <: Top"} *} + --{* \begin{minipage}[t]{0.9\textwidth} + In this case the left-hand derivation is @{term "\ \ S <: Top"}, giving + us @{term "\ \ ok"} and @{term "S closed_in \"}. This case is straightforward, + because the right-hand derivation must be of the form @{term "\ \ Top <: Top"} + giving us the equation @{term "T = Top"}.\end{minipage}*} hence rh_drv: "\ \ Top <: T" by simp hence T_inst: "T = Top" by (simp add: S_TopE) - have lh_drv_prm1: "\ \ ok" by fact - have lh_drv_prm2: "S closed_in \" by fact - from lh_drv_prm1 lh_drv_prm2 have "\ \ S <: Top" by (simp add: subtype_of.S_Top) + have "\ \ ok" + and "S closed_in \" by fact + hence "\ \ S <: Top" by (simp add: subtype_of.S_Top) thus "\ \ S <: T" using T_inst by simp next - case (S_Var \ Y U Q) - --{* in this case lh drv is @{term "\ \ Tvar(Y) <: Q"} *} + case (S_Var \ Y U) + -- {* \begin{minipage}[t]{0.9\textwidth} + In this case the left-hand derivation is @{term "\ \ Tvar Y <: Q"} + with @{term "S = Tvar Y"}. We have therefore @{term "(Y,U)"} + is in @{term "\"} and by inner induction hypothesis @{term "\ \ U <: T"}. + By @{text "S_Var"} follows @{term "\ \ Tvar Y <: T"}.\end{minipage}*} hence IH_inner: "\ \ U <: T" by simp - have lh_drv_prm1: "\ \ ok" by fact - have lh_drv_prm2: "(Y,U)\set \" by fact - from IH_inner show "\ \ Tvar Y <: T" using lh_drv_prm1 lh_drv_prm2 - by (simp add: subtype_of.S_Var) + have "(Y,U) \ set \" by fact + with IH_inner show "\ \ Tvar Y <: T" by (simp add: subtype_of.S_Var) next case (S_Refl \ X) - --{* in this case lh drv is @{term "\ \ Tvar X <: Tvar X"} *} + --{* \begin{minipage}[t]{0.9\textwidth} + In this case the left-hand derivation is @{term "\\(Tvar X) <: (Tvar X)"} with + @{term "Q=Tvar X"}. The goal then follows immediately from the right-hand + derivation.\end{minipage}*} thus "\ \ Tvar X <: T" by simp next - case (S_Arrow \ S1 S2 Q1 Q2) - --{* in this case lh drv is @{term "\ \ S1 \ S2 <: Q1 \ Q2"} *} - hence rh_drv: "\ \ Q1 \ Q2 <: T" by simp - have Q_inst: "Q1 \ Q2 = Q" by fact - hence Q1_less: "size_ty Q1 < size_ty Q" - and Q2_less: "size_ty Q2 < size_ty Q" by auto - have lh_drv_prm1: "\ \ Q1 <: S1" by fact - have lh_drv_prm2: "\ \ S2 <: Q2" by fact - have "S1 closed_in \" and "S2 closed_in \" - using lh_drv_prm1 lh_drv_prm2 by (simp_all add: subtype_implies_closed) - hence "(S1 \ S2) closed_in \" by (simp add: closed_in_def ty.supp) + case (S_Arrow \ S\<^isub>1 S\<^isub>2 Q\<^isub>1 Q\<^isub>2) + --{* \begin{minipage}[t]{0.9\textwidth} + In this case the left-hand derivation is @{term "\ \ S\<^isub>1 \ S\<^isub>2 <: Q\<^isub>1 \ Q\<^isub>2"} with + @{term "S\<^isub>1\S\<^isub>2=S"} and @{term "Q\<^isub>1\Q\<^isub>2=Q"}. We know that the @{text "size_ty"} of + @{term Q\<^isub>1} and @{term Q\<^isub>2} is smaller than that of @{term Q}; + so we can apply the outer induction hypotheses for @{term Q\<^isub>1} and @{term Q\<^isub>2}. + We also have the sub-derivations @{term "\\Q\<^isub>1<:S\<^isub>1"} and @{term "\\S\<^isub>2<:Q\<^isub>2"}. + The right-hand derivation is @{term "\ \ Q\<^isub>1 \ Q\<^isub>2 <: T"}. There exists types + @{text "T\<^isub>1,T\<^isub>2"} such that @{term "T=Top \ T=T\<^isub>1\T\<^isub>2"}. The @{term "Top"}-case is + straightforward once we know @{term "(S\<^isub>1 \ S\<^isub>2) closed_in \"} and @{term "\ \ ok"}. + In the other case we have the sub-derivations @{term "\\T\<^isub>1<:Q\<^isub>1"} and @{term "\\Q\<^isub>2<:T\<^isub>2"}. + Using the outer induction hypothesis for transitivity we can derive @{term "\\T\<^isub>1<:S\<^isub>1"} + and @{term "\\S\<^isub>2<:T\<^isub>2"}. By rule @{text "S_Arrow"} follows @{term "\ \ S\<^isub>1 \ S\<^isub>2 <: T\<^isub>1 \ T\<^isub>2"}, + which is @{term "\ \ S\<^isub>1 \ S\<^isub>2 <: T\<^isub>"}.\end{minipage}*} + hence rh_drv: "\ \ Q\<^isub>1 \ Q\<^isub>2 <: T" by simp + from `Q\<^isub>1 \ Q\<^isub>2 = Q` + have Q\<^isub>1\<^isub>2_less: "size_ty Q\<^isub>1 < size_ty Q" "size_ty Q\<^isub>2 < size_ty Q" by auto + have lh_drv_prm\<^isub>1: "\ \ Q\<^isub>1 <: S\<^isub>1" by fact + have lh_drv_prm\<^isub>2: "\ \ S\<^isub>2 <: Q\<^isub>2" by fact + from rh_drv have "T=Top \ (\T\<^isub>1 T\<^isub>2. T=T\<^isub>1\T\<^isub>2 \ \\T\<^isub>1<:Q\<^isub>1 \ \\Q\<^isub>2<:T\<^isub>2)" + by (simp add: S_ArrowE_left) + moreover + have "S\<^isub>1 closed_in \" and "S\<^isub>2 closed_in \" + using lh_drv_prm\<^isub>1 lh_drv_prm\<^isub>2 by (simp_all add: subtype_implies_closed) + hence "(S\<^isub>1 \ S\<^isub>2) closed_in \" by (simp add: closed_in_def ty.supp) moreover have "\ \ ok" using rh_drv by (rule subtype_implies_ok) moreover - from rh_drv have "T = Top \ (\T1 T2. T = T1 \ T2 \ \ \ T1 <: Q1 \ \ \ Q2 <: T2)" - by (simp add: S_ArrowE_left) - moreover - { assume "\T1 T2. T = T1 \ T2 \ \ \ T1 <: Q1 \ \ \ Q2 <: T2" - then obtain T1 T2 - where T_inst: "T = T1 \ T2" - and rh_drv_prm1: "\ \ T1 <: Q1" - and rh_drv_prm2: "\ \ Q2 <: T2" by force - from IH_trans[of "Q1"] have "\ \ T1 <: S1" using Q1_less rh_drv_prm1 lh_drv_prm1 by simp + { assume "\T\<^isub>1 T\<^isub>2. T=T\<^isub>1\T\<^isub>2 \ \\T\<^isub>1<:Q\<^isub>1 \ \\Q\<^isub>2<:T\<^isub>2" + then obtain T\<^isub>1 T\<^isub>2 + where T_inst: "T = T\<^isub>1 \ T\<^isub>2" + and rh_drv_prm\<^isub>1: "\ \ T\<^isub>1 <: Q\<^isub>1" + and rh_drv_prm\<^isub>2: "\ \ Q\<^isub>2 <: T\<^isub>2" by force + from IH_trans[of "Q\<^isub>1"] + have "\ \ T\<^isub>1 <: S\<^isub>1" using Q\<^isub>1\<^isub>2_less rh_drv_prm\<^isub>1 lh_drv_prm\<^isub>1 by simp moreover - from IH_trans[of "Q2"] have "\ \ S2 <: T2" using Q2_less rh_drv_prm2 lh_drv_prm2 by simp - ultimately have "\ \ S1 \ S2 <: T1 \ T2" by (simp add: subtype_of.S_Arrow) - hence "\ \ S1 \ S2 <: T" using T_inst by simp + from IH_trans[of "Q\<^isub>2"] + have "\ \ S\<^isub>2 <: T\<^isub>2" using Q\<^isub>1\<^isub>2_less rh_drv_prm\<^isub>2 lh_drv_prm\<^isub>2 by simp + ultimately have "\ \ S\<^isub>1 \ S\<^isub>2 <: T\<^isub>1 \ T\<^isub>2" by (simp add: subtype_of.S_Arrow) + hence "\ \ S\<^isub>1 \ S\<^isub>2 <: T" using T_inst by simp } - ultimately show "\ \ S1 \ S2 <: T" using top_case by blast + ultimately show "\ \ S\<^isub>1 \ S\<^isub>2 <: T" by blast next - case (S_All \ X S1 S2 Q1 Q2) - --{* in this case lh drv is @{term "\\\[X<:S1].S2 <: \[X<:Q1].Q2"} *} - hence rh_drv: "\ \ \[X<:Q1].Q2 <: T" by simp - have lh_drv_prm1: "\ \ Q1 <: S1" by fact - have lh_drv_prm2: "((X,Q1)#\) \ S2 <: Q2" by fact - have fresh_cond: "X\\" "X\Q1" by fact - have Q_inst: "\[X<:Q1].Q2 = Q" by fact - hence Q1_less: "size_ty Q1 < size_ty Q" - and Q2_less: "size_ty Q2 < size_ty Q " by auto - have "S1 closed_in \" and "S2 closed_in ((X,Q1)#\)" - using lh_drv_prm1 lh_drv_prm2 by (simp_all add: subtype_implies_closed) - hence "(\[X<:S1].S2) closed_in \" by (force simp add: closed_in_def ty.supp abs_supp) + case (S_Forall \ X S\<^isub>1 S\<^isub>2 Q\<^isub>1 Q\<^isub>2) + --{* \begin{minipage}[t]{0.9\textwidth} + In this case the left-hand derivation is @{text "\\\[X<:S\<^isub>1].S\<^isub>2 <: \[X<:Q\<^isub>1].Q\<^isub>2"} with + @{text "\[X<:S\<^isub>1].S\<^isub>2=S"} and @{text "\[X<:Q\<^isub>1].Q\<^isub>2=Q"}. We therefore have the sub-derivations + @{term "\\Q\<^isub>1<:S\<^isub>1"} and @{term "((X,Q\<^isub>1)#\)\S\<^isub>2<:Q\<^isub>2"}. Since @{term "X"} is a binder, we + assume that it is sufficiently fresh; in particular we have the freshness conditions + @{term "X\\"} and @{term "X\Q\<^isub>1"} (these assumptions are provided by the strong induction + rule @{text "subtype_of_induct"}). We know that the @{text "size_ty"} of + @{term Q\<^isub>1} and @{term Q\<^isub>2} is smaller than that of @{term Q}; + so we can apply the outer induction hypotheses for @{term Q\<^isub>1} and @{term Q\<^isub>2}. + The right-hand derivation is @{text "\ \ \[X<:Q\<^isub>1].Q\<^isub>2 <: T"}. Since @{term "X\\"} + and @{term "X\Q\<^isub>1"} there exists types @{text "T\<^isub>1,T\<^isub>2"} such that + @{text "T=Top \ T=\[X<:T\<^isub>1].T\<^isub>2"}. The @{term "Top"}-case is straightforward once we know + @{text "(\[X<:S\<^isub>1].S\<^isub>2) closed_in \"} and @{term "\ \ ok"}. In the other case we have + the sub-derivations @{term "\\T\<^isub>1<:Q\<^isub>1"}. @{term "((X,T\<^isub>1)#\)\Q\<^isub>2<:T\<^isub>2"}. Using the outer + induction hypothesis for transitivity we can derive @{term "\\T\<^isub>1<:S\<^isub>1"}. From the outer + induction for narrowing we get @{term "((X,T\<^isub>1)#\) \ S\<^isub>2 <: Q\<^isub>2"} and then using induction + again @{term "((X,T\<^isub>1)#\) \ S\<^isub>2 <: T\<^isub>2"}. By rule @{text "S_Forall"} and the freshness + condition @{term "X\\"} follows @{text "\ \ \[X<:S\<^isub>1].S\<^isub>2 <: \[X<:T\<^isub>1].T\<^isub>2"}.which is + @{text "\ \ \[X<:S\<^isub>1].S\<^isub>2 <: T\<^isub>"}.\end{minipage}*} + hence rh_drv: "\ \ \[X<:Q\<^isub>1].Q\<^isub>2 <: T" by simp + have lh_drv_prm\<^isub>1: "\ \ Q\<^isub>1 <: S\<^isub>1" by fact + have lh_drv_prm\<^isub>2: "((X,Q\<^isub>1)#\) \ S\<^isub>2 <: Q\<^isub>2" by fact + have fresh_cond: "X\\" "X\Q\<^isub>1" by fact + from `\[X<:Q\<^isub>1].Q\<^isub>2 = Q` + have Q\<^isub>1\<^isub>2_less: "size_ty Q\<^isub>1 < size_ty Q" "size_ty Q\<^isub>2 < size_ty Q " by auto + from rh_drv + have "T=Top \ (\T\<^isub>1 T\<^isub>2. T=\[X<:T\<^isub>1].T\<^isub>2 \ \\T\<^isub>1<:Q\<^isub>1 \ ((X,T\<^isub>1)#\)\Q\<^isub>2<:T\<^isub>2)" + using fresh_cond by (simp add: S_ForallE_left) + moreover + have "S\<^isub>1 closed_in \" and "S\<^isub>2 closed_in ((X,Q\<^isub>1)#\)" + using lh_drv_prm\<^isub>1 lh_drv_prm\<^isub>2 by (simp_all add: subtype_implies_closed) + hence "(\[X<:S\<^isub>1].S\<^isub>2) closed_in \" by (force simp add: closed_in_def ty.supp abs_supp) moreover have "\ \ ok" using rh_drv by (rule subtype_implies_ok) moreover - from rh_drv have "T = Top \ (\T1 T2. T = \[X<:T1].T2 \ \ \ T1 <: Q1 \ ((X,T1)#\) \ Q2 <: T2)" - using fresh_cond by (simp add: S_AllE_left) - moreover - { assume "\T1 T2. T = \[X<:T1].T2 \ \ \ T1 <: Q1 \ ((X,T1)#\) \ Q2 <: T2" - then obtain T1 T2 - where T_inst: "T = \[X<:T1].T2" - and rh_drv_prm1: "\ \ T1 <: Q1" - and rh_drv_prm2:"((X,T1)#\) \ Q2 <: T2" by force - from IH_trans[of "Q1"] have "\ \ T1 <: S1" - using lh_drv_prm1 rh_drv_prm1 Q1_less by blast - moreover - from IH_narrow[of "Q1"] have "((X,T1)#\) \ S2 <: Q2" - using Q1_less lh_drv_prm2 rh_drv_prm1 by blast - with IH_trans[of "Q2"] have "((X,T1)#\) \ S2 <: T2" - using Q2_less rh_drv_prm2 by blast - moreover - ultimately have "\ \ \[X<:S1].S2 <: \[X<:T1].T2" - using fresh_cond by (simp add: subtype_of.S_All) - hence "\ \ \[X<:S1].S2 <: T" using T_inst by simp + { assume "\T\<^isub>1 T\<^isub>2. T=\[X<:T\<^isub>1].T\<^isub>2 \ \\T\<^isub>1<:Q\<^isub>1 \ ((X,T\<^isub>1)#\)\Q\<^isub>2<:T\<^isub>2" + then obtain T\<^isub>1 T\<^isub>2 + where T_inst: "T = \[X<:T\<^isub>1].T\<^isub>2" + and rh_drv_prm\<^isub>1: "\ \ T\<^isub>1 <: Q\<^isub>1" + and rh_drv_prm\<^isub>2:"((X,T\<^isub>1)#\) \ Q\<^isub>2 <: T\<^isub>2" by force + from IH_trans[of "Q\<^isub>1"] + have "\ \ T\<^isub>1 <: S\<^isub>1" using lh_drv_prm\<^isub>1 rh_drv_prm\<^isub>1 Q\<^isub>1\<^isub>2_less by blast + moreover + from IH_narrow[of "Q\<^isub>1" "[]"] + have "((X,T\<^isub>1)#\) \ S\<^isub>2 <: Q\<^isub>2" using Q\<^isub>1\<^isub>2_less lh_drv_prm\<^isub>2 rh_drv_prm\<^isub>1 by simp + with IH_trans[of "Q\<^isub>2"] + have "((X,T\<^isub>1)#\) \ S\<^isub>2 <: T\<^isub>2" using Q\<^isub>1\<^isub>2_less rh_drv_prm\<^isub>2 by simp + ultimately have "\ \ \[X<:S\<^isub>1].S\<^isub>2 <: \[X<:T\<^isub>1].T\<^isub>2" + using fresh_cond by (simp add: subtype_of.S_Forall) + hence "\ \ \[X<:S\<^isub>1].S\<^isub>2 <: T" using T_inst by simp } - ultimately show "\ \ \[X<:S1].S2 <: T" using top_case by blast + ultimately show "\ \ \[X<:S\<^isub>1].S\<^isub>2 <: T" by blast qed qed - --{* The inner induction for narrowing over @{term "(\@[(X,Q)]@\) \ M <: N"} *} - have narrowing: - "\\ \ X M N P. (\@[(X,Q)]@\) \ M <: N \ \ \ P<:Q \ (\@[(X,P)]@\) \ M <: N" - proof - - fix \' \' X M N P - assume a: "(\'@[(X,Q)]@\') \ M <: N" - assume b: "\' \ P<:Q" - from a b show "(\'@[(X,P)]@\') \ M <: N" - proof (nominal_induct \\"\'@[(X,Q)]@\'" M N avoiding: \' \' X rule: subtype_of_induct) + { --{* The transitivity proof is now by the auxiliary lemma. *} + case 1 + have "\ \ S <: Q" + and "\ \ Q <: T" by fact + thus "\ \ S <: T" by (rule transitivity_aux) + next + --{* The narrowing proof proceeds by an induction over @{term "(\@[(X,Q)]@\) \ M <: N"}. *} + case 2 + have "(\@[(X,Q)]@\) \ M <: N" --{* left-hand derivation *} + and "\ \ P<:Q" by fact --{* right-hand derivation *} + thus "(\@[(X,P)]@\) \ M <: N" + proof (nominal_induct \\"\@[(X,Q)]@\" M N avoiding: \ \ X rule: subtype_of_induct) case (S_Top _ S \ \ X) - --{* in this case lh drv is @{term "(\@[(X,Q)]@\) \ S <: Top"} *} - hence lh_drv_prm1: "\ (\@[(X,Q)]@\) ok" - and lh_drv_prm2: "S closed_in (\@[(X,Q)]@\)" by simp_all + --{* \begin{minipage}[t]{0.9\textwidth} + In this case the left-hand derivation is @{term "(\@[(X,Q)]@\) \ S <: Top"}. We show + that the context @{term "\@[(X,P)]@\"} is ok and that @{term S} is closed in + @{term "\@[(X,P)]@\"}. Then we can apply the @{text "S_Top"}-rule.\end{minipage}*} + hence lh_drv_prm\<^isub>1: "\ (\@[(X,Q)]@\) ok" + and lh_drv_prm\<^isub>2: "S closed_in (\@[(X,Q)]@\)" by simp_all have rh_drv: "\ \ P <: Q" by fact hence "P closed_in \" by (simp add: subtype_implies_closed) - with lh_drv_prm1 have "\ (\@[(X,P)]@\) ok" by (simp add: replace_type) + with lh_drv_prm\<^isub>1 have "\ (\@[(X,P)]@\) ok" by (simp add: replace_type) moreover - from lh_drv_prm2 have "S closed_in (\@[(X,P)]@\)" by (simp add: closed_in_def domain_append) + from lh_drv_prm\<^isub>2 have "S closed_in (\@[(X,P)]@\)" + by (simp add: closed_in_def domain_append) ultimately show "(\@[(X,P)]@\) \ S <: Top" by (simp add: subtype_of.S_Top) next case (S_Var _ Y S N \ \ X) - --{* in this case lh drv is @{term "(\@[(X,Q)]@\) \ Tvar Y <: N"} *} - hence IH_inner: "(\@[(X,P)]@\) \ S <: N" - and lh_drv_prm1: "\ (\@[(X,Q)]@\) ok" - and lh_drv_prm2: "(Y,S)\set (\@[(X,Q)]@\)" by simp_all - have rh_drv: "\ \ P <: Q" by fact - hence "P closed_in \" by (simp add: subtype_implies_closed) - hence cntxt_ok: "\ (\@[(X,P)]@\) ok" using lh_drv_prm1 by (simp add: replace_type) - -- {* we distinguishing the cases @{term "X\Y"} and @{term "X=Y"} (the latter - being the interesting one) *} - { assume "X\Y" - hence "(Y,S)\set (\@[(X,P)]@\)" using lh_drv_prm2 by simp - with IH_inner have "(\@[(X,P)]@\) \ Tvar Y <: N" - using cntxt_ok by (simp add: subtype_of.S_Var) - } - moreover - { have memb_XQ: "(X,Q)\set (\@[(X,Q)]@\)" by simp - have memb_XP: "(X,P)\set (\@[(X,P)]@\)" by simp - assume "X=Y" - hence "S=Q" using lh_drv_prm1 lh_drv_prm2 memb_XQ by (simp only: uniqueness_of_ctxt) + --{* \begin{minipage}[t]{0.9\textwidth} + In this case the left-hand derivation is @{term "(\@[(X,Q)]@\) \ Tvar Y <: N"}. We therefore + know that the contexts @{term "\@[(X,Q)]@\"} and @{term "\@[(X,P)]@\"} are ok, and that + @{term "(Y,S)"} is in @{term "\@[(X,Q)]@\"}. By inner induction hypothesis we have + @{term "(\@[(X,P)]@\) \ S <: N"}. We need to show that @{term "(\@[(X,P)]@\) \ Tvar Y <: N"} + holds. In case @{term "X\Y"} we know that @{term "(Y,S)"} is in @{term "\@[(X,P)]@\"} and + can use the inner induction hypothesis and rule @{text "S_Var"} to conclude. In case + @{term "X=Y"} we can infer that @{term "S=Q"}; moreover we have that + @{term "(\@[(X,P)]@\) extends \"} and therefore by @{text "weakening"} that + @{term "(\@[(X,P)]@\) \ P <: Q"} holds. By transitivity we obtain then + @{term "(\@[(X,P)]@\) \ P <: N"} and can conclude by applying rule @{text "S_Var"}. + \end{minipage}*} + hence IH_inner: "(\@[(X,P)]@\) \ S <: N" + and lh_drv_prm: "(Y,S) \ set (\@[(X,Q)]@\)" + and rh_drv: "\ \ P<:Q" + and ok\<^isub>Q: "\ (\@[(X,Q)]@\) ok" by (simp_all add: subtype_implies_ok) + hence ok\<^isub>P: "\ (\@[(X,P)]@\) ok" by (simp add: subtype_implies_ok) + show "(\@[(X,P)]@\) \ Tvar Y <: N" + proof (cases "X=Y") + case False + have "X\Y" by fact + hence "(Y,S)\set (\@[(X,P)]@\)" using lh_drv_prm by simp + with IH_inner show "(\@[(X,P)]@\) \ Tvar Y <: N" by (simp add: subtype_of.S_Var) + next + case True + have memb\<^isub>X\<^isub>Q: "(X,Q)\set (\@[(X,Q)]@\)" by simp + have memb\<^isub>X\<^isub>P: "(X,P)\set (\@[(X,P)]@\)" by simp + have eq: "X=Y" by fact + hence "S=Q" using ok\<^isub>Q lh_drv_prm memb\<^isub>X\<^isub>Q by (simp only: uniqueness_of_ctxt) hence "(\@[(X,P)]@\) \ Q <: N" using IH_inner by simp moreover have "(\@[(X,P)]@\) extends \" by (simp add: extends_def) - hence "(\@[(X,P)]@\) \ P <: Q" using rh_drv cntxt_ok by (simp only: weakening) - ultimately have "(\@[(X,P)]@\) \ P <: N" using transitivity by simp - hence "(\@[(X,P)]@\) \ Tvar X <: N" using memb_XP cntxt_ok - by (simp only: subtype_of.S_Var) - } - ultimately show "(\@[(X,P)]@\) \ Tvar Y <: N" by blast + hence "(\@[(X,P)]@\) \ P <: Q" using rh_drv ok\<^isub>P by (simp only: weakening) + ultimately have "(\@[(X,P)]@\) \ P <: N" by (simp add: transitivity_aux) + thus "(\@[(X,P)]@\) \ Tvar Y <: N" using memb\<^isub>X\<^isub>P eq by (simp only: subtype_of.S_Var) + qed next case (S_Refl _ Y \ \ X) - --{* in this case lh drv is @{term "(\@[(X,Q)]@\) \ Tvar Y <: Tvar Y"} *} - hence lh_drv_prm1: "\ (\@[(X,Q)]@\) ok" - and lh_drv_prm2: "Y \ domain (\@[(X,Q)]@\)" by simp_all + --{* \begin{minipage}[t]{0.9\textwidth} + In this case the left-hand derivation is @{term "(\@[(X,Q)]@\) \ Tvar Y <: Tvar Y"} and we + therefore know that @{term "\@[(X,Q)]@\"} is ok and thad @{term "Y"} is in + the domain of @{term "\@[(X,Q)]@\"}. We therefore know that @{term "\@[(X,P)]@\"} is ok + and that @{term Y} is in the domain of @{term "\@[(X,P)]@\"}. We can conclude by applying + rule @{text "S_Refl"}.\end{minipage}*} + hence lh_drv_prm\<^isub>1: "\ (\@[(X,Q)]@\) ok" + and lh_drv_prm\<^isub>2: "Y \ domain (\@[(X,Q)]@\)" by simp_all have "\ \ P <: Q" by fact hence "P closed_in \" by (simp add: subtype_implies_closed) - with lh_drv_prm1 have "\ (\@[(X,P)]@\) ok" by (simp add: replace_type) + with lh_drv_prm\<^isub>1 have "\ (\@[(X,P)]@\) ok" by (simp add: replace_type) moreover - from lh_drv_prm2 have "Y \ domain (\@[(X,P)]@\)" by (simp add: domain_append) + from lh_drv_prm\<^isub>2 have "Y \ domain (\@[(X,P)]@\)" by (simp add: domain_append) ultimately show "(\@[(X,P)]@\) \ Tvar Y <: Tvar Y" by (simp add: subtype_of.S_Refl) next - case (S_Arrow _ Q1 Q2 S1 S2 \ \ X) - --{* in this case lh drv is @{term "(\@[(X,Q)]@\) \ Q1 \ Q2 <: S1 \ S2"} *} - thus "(\@[(X,P)]@\) \ Q1 \ Q2 <: S1 \ S2" by blast + case (S_Arrow _ Q\<^isub>1 Q\<^isub>2 S\<^isub>1 S\<^isub>2 \ \ X) + --{* \begin{minipage}[t]{0.9\textwidth} + In this case the left-hand derivation is @{term "(\@[(X,Q)]@\) \ Q\<^isub>1 \ Q\<^isub>2 <: S\<^isub>1 \ S\<^isub>2"} + and the proof is trivial.\end{minipage}*} + thus "(\@[(X,P)]@\) \ Q\<^isub>1 \ Q\<^isub>2 <: S\<^isub>1 \ S\<^isub>2" by blast next - case (S_All _ Y S1 S2 T1 T2 \ \ X) - --{* in this case lh drv is @{term "(\@[(X,Q)]@\) \ \[Y<:S1].S2 <: \[Y<:T1].T2"} *} - hence IH_inner1: "(\@[(X,P)]@\) \ T1 <: S1" - and IH_inner2: "((Y,T1)#\@[(X,P)]@\) \ S2 <: T2" - and lh_drv_prm2: "Y\(\@[(X,Q)]@\)" by force+ + case (S_Forall _ Y S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2 \ \ X) + --{* \begin{minipage}[t]{0.9\textwidth} + In this case teh left-hand derivation is @{text "(\@[(X,Q)]@\) \ \[Y<:S\<^isub>1].S\<^isub>2 <: \[Y<:T\<^isub>1].T\<^isub>2"} + and therfore we know that the binder @{term Y} is fresh for @{term "\@[(X,Q)]@\"}. By + the inner induction hypothesis we have that @{term "(\@[(X,P)]@\) \ T\<^isub>1 <: S\<^isub>1"} and + @{term "((Y,T\<^isub>1)#\@[(X,P)]@\) \ S\<^isub>2 <: T\<^isub>2"}. Since @{term P} is a subtype of @{term Q} + we can infer that @{term Y} is fresh for @{term P} and thus also fresh for + @{term "\@[(X,P)]@\"}. We can then conclude by applying rule @{text "S_Forall"}. + \end{minipage}*} + hence IH_inner\<^isub>1: "(\@[(X,P)]@\) \ T\<^isub>1 <: S\<^isub>1" + and IH_inner\<^isub>2: "((Y,T\<^isub>1)#\@[(X,P)]@\) \ S\<^isub>2 <: T\<^isub>2" + and lh_drv_prm: "Y\(\@[(X,Q)]@\)" by force+ have rh_drv: "\ \ P <: Q" by fact - hence "Y\P" using lh_drv_prm2 by (simp only: fresh_list_append subtype_implies_fresh) - hence "Y\(\@[(X,P)]@\)" using lh_drv_prm2 + hence "Y\P" using lh_drv_prm by (simp only: fresh_list_append subtype_implies_fresh) + hence "Y\(\@[(X,P)]@\)" using lh_drv_prm by (simp add: fresh_list_append fresh_list_cons fresh_prod) - with IH_inner1 IH_inner2 - show "(\@[(X,P)]@\) \ \[Y<:S1].S2 <: \[Y<:T1].T2" by (simp add: subtype_of.S_All) + with IH_inner\<^isub>1 IH_inner\<^isub>2 + show "(\@[(X,P)]@\) \ \[Y<:S\<^isub>1].S\<^isub>2 <: \[Y<:T\<^isub>1].T\<^isub>2" by (simp add: subtype_of.S_Forall) qed - qed - from transitivity narrowing show ?case by blast + } qed - - end \ No newline at end of file