# HG changeset patch # User urbanc # Date 1175038183 -7200 # Node ID c55f5631a4ecedbe9dfbc7c338bdbe4b0a6158f0 # Parent 35debf264656fa0e6f08512895668bc71b3a8a5d adapted to nominal_inductive infrastructure diff -r 35debf264656 -r c55f5631a4ec src/HOL/Nominal/Examples/Fsub.thy --- a/src/HOL/Nominal/Examples/Fsub.thy Wed Mar 28 01:09:23 2007 +0200 +++ b/src/HOL/Nominal/Examples/Fsub.thy Wed Mar 28 01:29:43 2007 +0200 @@ -87,9 +87,11 @@ "domain [] = {}" "domain (X#\) = {fst X}\(domain \)" -lemma domain_eqvt: +lemma domain_eqvt[eqvt]: fixes pi::"tyvrs prm" - shows "pi\(domain \) = domain (pi\\)" + and pi'::"vrs prm" + shows "pi\(domain \) = domain (pi\\)" + and "pi'\(domain \) = domain (pi'\\)" by (induct \) (simp_all add: eqvt) lemma finite_domain: @@ -140,7 +142,7 @@ "closed_in" :: "ty \ ty_context \ bool" ("_ closed'_in _" [100,100] 100) "S closed_in \ \ (supp S)\(domain \)" -lemma closed_in_eqvt: +lemma closed_in_eqvt[eqvt]: fixes pi::"tyvrs prm" assumes a: "S closed_in \" shows "(pi\S) closed_in (pi\\)" @@ -153,32 +155,35 @@ by (simp add: domain_eqvt pt_perm_supp[OF pt_tyvrs_inst, OF at_tyvrs_inst]) qed +lemma ty_vrs_prm_simp: + fixes pi::"vrs prm" + and S::"ty" + shows "pi\S = S" +by (induct S rule: ty.induct_weak) (auto simp add: calc_atm) + +lemma ty_context_vrs_prm_simp: + fixes pi::"vrs prm" + and \::"ty_context" + shows "pi\\ = \" +by (induct \) + (auto simp add: calc_atm ty_vrs_prm_simp) + +lemma closed_in_eqvt'[eqvt]: + fixes pi::"vrs prm" + assumes a: "S closed_in \" + shows "(pi\S) closed_in (pi\\)" +using a +by (simp add: ty_vrs_prm_simp ty_context_vrs_prm_simp) + text {* Now validity of a context is a straightforward inductive definition. *} -inductive2 valid_rel :: "ty_context \ bool" ("\ _ ok" [100] 100) +inductive2 + valid_rel :: "ty_context \ bool" ("\ _ ok" [100] 100) where valid_nil[simp]: "\ [] ok" | valid_cons[simp]: "\\ \ ok; X\(domain \); T closed_in \\ \ \ ((X,T)#\) ok" -lemma valid_eqvt: - fixes pi::"tyvrs prm" - assumes a: "\ \ ok" - shows "\ (pi\\) ok" - using a -proof (induct) - case valid_nil - show "\ (pi\[]) ok" by simp -next - case (valid_cons \ X T) - have "\ (pi\\) ok" by fact - moreover - have "X\(domain \)" by fact - hence "(pi\X)\(domain (pi\\))" by (simp add: fresh_bij domain_eqvt[symmetric]) - moreover - have "T closed_in \" by fact - hence "(pi\T) closed_in (pi\\)" by (simp add: closed_in_eqvt) - ultimately show "\ (pi\((X,T)#\)) ok" by simp -qed +equivariance valid_rel lemma validE: assumes a: "\ ((X,T)#\) ok" @@ -259,7 +264,8 @@ apply (fresh_guess)+ done -consts subst_tyc :: "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)" @@ -273,14 +279,20 @@ does \emph{not} make the subtyping-relation ``partial"\ldots because we work over $\alpha$-equivalence classes.) *} -inductive2 subtype_of :: "ty_context \ ty \ ty \ bool" ("_\_<:_" [100,100,100] 100) +inductive2 + subtype_of :: "ty_context \ ty \ ty \ bool" ("_\_<:_" [100,100,100] 100) where 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" +| 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_ok: + fixes X::"tyvrs" + assumes a: "\ \ S <: T" + shows "\ \ ok" +using a by (induct) (auto) lemma subtype_implies_closed: assumes a: "\ \ S <: T" @@ -303,12 +315,6 @@ ultimately show "(Tvar X) closed_in \ \ T closed_in \" by simp qed (auto simp add: closed_in_def ty.supp supp_atm abs_supp) -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" @@ -324,125 +330,10 @@ ultimately show "X\S \ X\T" by (force simp add: supp_prod fresh_def) qed -lemma subtype_eqvt: - fixes pi::"tyvrs prm" - shows "\ \ S <: T \ (pi\\) \ (pi\S) <: (pi\T)" -apply(erule subtype_of.induct) -apply(force intro: valid_eqvt closed_in_eqvt eqvt) -apply(force intro!: S_Var - intro: closed_in_eqvt valid_eqvt - dest: pt_set_bij2[OF pt_tyvrs_inst, OF at_tyvrs_inst] - simp add: set_eqvt) -apply(force intro: valid_eqvt - dest: pt_set_bij2[OF pt_tyvrs_inst, OF at_tyvrs_inst] - simp add: domain_eqvt) -apply(force) -apply(force intro!: S_Forall simp add: fresh_prod fresh_bij) -done - -text {* The most painful part of the subtyping definition is the strengthening of the - induction principle. The induction principle that comes for free with the definition of - @{term "subtype_of"} requires to prove the @{text "S_Forall"}-case for \emph{all} binders - @{text "X"}. This will often cause some renaming-manoeuvres in the reasoning. To avoid this, - we strengthening the induction-principle so that we only have to establish - the @{text "S_Forall"}-case for \emph{fresh} binders @{text "X"}. The property that allows - us to strengthen the induction-principle is that the equivariance of @{text "subtype_of"}. *} +nominal_inductive subtype_of + by (simp_all add: abs_fresh subtype_implies_fresh) -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. \(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)" - proof (induct) - case (S_Top \ S) - thus "P x (pi\\) (pi\S) (pi\Top)" by (force intro: valid_eqvt closed_in_eqvt a1) - next - case (S_Var X S \ T) - 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: set_eqvt) - moreover - have "\ \ S <: T" by fact - hence "(pi\\) \ (pi\S) <: (pi\T)" by (rule subtype_eqvt) - moreover - have "\(pi::tyvrs prm) x. P x (pi\\) (pi\S) (pi\T)" by fact - hence "\x. P x (pi\\) (pi\S) (pi\T)" by simp - ultimately - show "P x (pi\\) (pi\(Tvar X)) (pi\T)" by (simp add: a2) - next - case (S_Refl \ X) - have "\ \ ok" by fact - hence "\ (pi\\) ok" by (rule valid_eqvt) - moreover - have "X \ domain \" by fact - hence "(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 set_eqvt) - ultimately show "P x (pi\\) (pi\(Tvar X)) (pi\(Tvar X))" by (simp add: a3) - next - case S_Arrow thus ?case by (auto intro: a4 subtype_eqvt) - next - case (S_Forall \ T1 S1 X S2 T2) - 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 - have b5: "\(pi::tyvrs prm) x. P x (pi\((X,T1)#\)) (pi\S2) (pi\T2)" by fact - have b3: "X\\" by fact - have b3': "X\T1" "X\S1" using b1 b3 by (simp_all add: subtype_implies_fresh) - have "\C::tyvrs. C\(pi\X,pi\S2,pi\T2,pi\S1,pi\T1,pi\\,x)" - by (rule exists_fresh', 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 x (?pi'\\) (?pi'\T1) (?pi'\S1)" by simp - from b5 have "\x. P x (?pi'\((X,T1)#\)) (?pi'\S2) (?pi'\T2)" by simp - hence "\x. P x ((?pi'\X,?pi'\T1)#(?pi'\\)) (?pi'\S2) (?pi'\T2)" by simp - hence c2: "\x. P x ((C,?pi'\T1)#(?pi'\\)) (?pi'\S2) (?pi'\T2)" 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 x (?pi'\\) (\[C<:(?pi'\S1)].(?pi'\S2)) (\[C<:(?pi'\T1)].(?pi'\T2))" - 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 x (pi\\) (pi\(\[X<:S1].S2)) (pi\(\[X<:T1].T2))" - using alpha1 alpha2 f6a main by simp - qed - hence "P x (([]::tyvrs prm)\\) (([]::tyvrs prm)\S) (([]::tyvrs prm)\T)" by blast - thus ?thesis by simp -qed +thm subtype_of.strong_induct section {* Reflexivity of Subtyping *} @@ -522,7 +413,7 @@ and c: "\ extends \" shows "\ \ S <: T" using a b c -proof (nominal_induct \ S T avoiding: \ rule: subtype_of_induct) +proof (nominal_induct \ S T avoiding: \ rule: subtype_of.strong_induct) case (S_Top \ S) have lh_drv_prem: "S closed_in \" by fact have "\ \ ok" by fact @@ -531,7 +422,7 @@ hence "S closed_in \" using lh_drv_prem by (simp only: extends_closed) ultimately show "\ \ S <: Top" by force next - case (S_Var \ X S T) + case (S_Var X S \ T) have lh_drv_prem: "(X,S) \ set \" by fact have ih: "\\. \ \ ok \ \ extends \ \ \ \ S <: T" by fact have ok: "\ \ ok" by fact @@ -549,9 +440,9 @@ hence "X \ domain \" using lh_drv_prem by (force dest: extends_domain) ultimately show "\ \ Tvar X <: Tvar X" by force 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 + case (S_Arrow \ T\<^isub>1 S\<^isub>1 S\<^isub>2 T\<^isub>2) thus "\ \ S\<^isub>1 \ S\<^isub>2 <: T\<^isub>1 \ T\<^isub>2" by blast next - case (S_Forall \ X S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2) + case (S_Forall \ T\<^isub>1 S\<^isub>1 X S\<^isub>2 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 @@ -578,8 +469,8 @@ and c: "\ extends \" shows "\ \ S <: T" using a b c -proof (nominal_induct \ S T avoiding: \ rule: subtype_of_induct) - case (S_Forall \ X S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2) +proof (nominal_induct \ S T avoiding: \ rule: subtype_of.strong_induct) + case (S_Forall \ T\<^isub>1 S\<^isub>1 X S\<^isub>2 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 @@ -639,7 +530,7 @@ 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(drule_tac pi="[(X,Xa)]" in subtype_of_eqvt(2)) apply(simp add: calc_atm) apply(simp add: pt_fresh_fresh[OF pt_tyvrs_inst, OF at_tyvrs_inst]) done @@ -696,7 +587,7 @@ assume "\' \ S' <: Q" --{* left-hand derivation *} and "\' \ Q <: T" --{* right-hand derivation *} thus "\' \ S' <: T" - proof (nominal_induct \' S' Q\Q rule: subtype_of_induct) + proof (nominal_induct \' S' Q\Q rule: subtype_of.strong_induct) case (S_Top \ S) --{* \begin{minipage}[t]{0.9\textwidth} In this case the left-hand derivation is @{term "\ \ S <: Top"}, giving @@ -710,7 +601,7 @@ hence "\ \ S <: Top" by (simp add: subtype_of.S_Top) thus "\ \ S <: T" using T_inst by simp next - case (S_Var \ Y U) + 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)"} @@ -727,7 +618,7 @@ derivation.\end{minipage}*} thus "\ \ Tvar X <: T" by simp next - case (S_Arrow \ S\<^isub>1 S\<^isub>2 Q\<^isub>1 Q\<^isub>2) + case (S_Arrow \ Q\<^isub>1 S\<^isub>1 S\<^isub>2 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 @@ -770,7 +661,7 @@ } ultimately show "\ \ S\<^isub>1 \ S\<^isub>2 <: T" by blast next - case (S_Forall \ X S\<^isub>1 S\<^isub>2 Q\<^isub>1 Q\<^isub>2) + case (S_Forall \ Q\<^isub>1 S\<^isub>1 X S\<^isub>2 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 @@ -794,7 +685,8 @@ 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 + have "X\\" by fact + then have fresh_cond: "X\\" "X\Q\<^isub>1" using lh_drv_prm\<^isub>1 by (simp_all add: subtype_implies_fresh) 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 " using fresh_cond by auto from rh_drv @@ -838,7 +730,7 @@ 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) + proof (nominal_induct \\"\@[(X,Q)]@\" M N avoiding: \ \ X rule: subtype_of.strong_induct) case (S_Top _ S \ \ X) --{* \begin{minipage}[t]{0.9\textwidth} In this case the left-hand derivation is @{term "(\@[(X,Q)]@\) \ S <: Top"}. We show @@ -854,7 +746,7 @@ 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) + case (S_Var Y S _ N \ \ X) --{* \begin{minipage}[t]{0.9\textwidth} In this case the left-hand derivation is @{term "(\@[(X,Q)]@\) \ Tvar Y <: N"} and by inner induction hypothesis we have @{term "(\@[(X,P)]@\) \ S <: N"}. We therefore @@ -908,13 +800,13 @@ 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 _ Q\<^isub>1 Q\<^isub>2 S\<^isub>1 S\<^isub>2 \ \ X) + case (S_Arrow _ S\<^isub>1 Q\<^isub>1 Q\<^isub>2 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_Forall _ Y S\<^isub>1 S\<^isub>2 T\<^isub>1 T\<^isub>2 \ \ X) + case (S_Forall _ T\<^isub>1 S\<^isub>1 Y S\<^isub>2 T\<^isub>2 \ \ X) --{* \begin{minipage}[t]{0.9\textwidth} In this case the 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