# HG changeset patch # User Christian Urban # Date 1295643531 -3600 # Node ID ddc05a611005f036f038b2f1c19484a9c7170d0c # Parent 87b735f860606edadcc4172a9ce1a8511e6da7c9 added unbind example diff -r 87b735f86060 -r ddc05a611005 Tutorial/Tutorial1.thy --- a/Tutorial/Tutorial1.thy Fri Jan 21 00:55:28 2011 +0100 +++ b/Tutorial/Tutorial1.thy Fri Jan 21 21:58:51 2011 +0100 @@ -5,26 +5,26 @@ ==================================== Nominal Isabelle is a definitional extension of Isabelle/HOL, which - means it does not add any new axioms to higher-order logic. It merely + means it does not add any new axioms to higher-order logic. It just adds new definitions and an infrastructure for 'nominal resoning'. The jEdit Interface ------------------- - The Isabelle theorem prover comes with an interface for the jEdit. + The Isabelle theorem prover comes with an interface for jEdit. Unlike many other theorem prover interfaces (e.g. ProofGeneral) where you - try to advance a 'checked' region in a proof script, this interface immediately - checks the whole buffer. The text you type is also immediately checked - as you type. Malformed text or unfinished proofs are highlighted in red - with a little red 'stop' signal on the left-hand side. If you drag the - 'red-box' cursor over a line, the Output window gives further feedback. + advance a 'checked' region in a proof script, this interface immediately + checks the whole buffer. The text you type is also immediately checked. + Malformed text or unfinished proofs are highlighted in red with a little + red 'stop' signal on the left-hand side. If you drag the 'red-box' cursor + over a line, the Output window gives further feedback. Note: If a section is not parsed correctly, the work-around is to cut it out and paste it back into the text (cut-out: Ctrl + X; paste in: Ctrl + V; Cmd is Ctrl on the Mac) - Nominal Isabelle and the interface can be started on the command line with + Nominal Isabelle and jEdit can be started by typing on the command line isabelle jedit -l HOL-Nominal2 isabelle jedit -l HOL-Nominal2 A.thy B.thy ... @@ -55,10 +55,10 @@ : \ ~: \ - For nominal two important symbols are + For nominal the following two symbols have a special meaning - \ sharp (freshness) - \ bullet (permutations) + \ sharp (freshness) + \ bullet (permutation application) *} theory Tutorial1 @@ -70,11 +70,10 @@ text {* All formal developments in Isabelle are part of a theory. A theory needs to have a name and must import some pre-existing theory. The - imported theory will normally be the theory Nominal2 (which contains - many useful concepts like set-theory, lists, nominal theory etc). - For the purpose of the tutorial we import the theory Lambda.thy which - contains already some useful definitions for (alpha-equated) lambda - terms. + imported theory will normally be Nominal2 (which provides many useful + concepts like set-theory, lists, nominal things etc). For the purpose + of this tutorial we import the theory Lambda.thy, which contains + already some useful definitions for (alpha-equated) lambda terms. *} @@ -135,16 +134,22 @@ term "atom (x::name)" -- {* atom is an overloded function *} text {* - Lam [x].Var is the syntax we made up for lambda abstractions. You can have - your own syntax, if you prefer (but \ is already taken up for Isabelle's - functions). We also came up with "name". If you prefer, you can call - it "ident" or have more than one type for (object language) variables. + Lam [x].Var is the syntax we made up for lambda abstractions. If you + prefer, you can have your own syntax (but \ is already taken up for + Isabelle's functions). We also came up with the type "name" for variables. + You can introduce your own types of object variables using the + command atom_decl: +*} +atom_decl ident +atom_decl ty_var + +text {* Isabelle provides some useful colour feedback about its constants (black), free variables (blue) and bound variables (green). *} -term "True" -- {* a constant that is defined in HOL...written in black *} +term "True" -- {* a constant defined somewhere...written in black *} term "true" -- {* not recognised as a constant, therefore it is interpreted as a free variable, written in blue *} term "\x. P x" -- {* x is bound (green), P is free (blue) *} @@ -262,15 +267,16 @@ Examples are *} + + lemma alpha_equ: shows "Lam [x].Var x = Lam [y].Var y" by (simp add: lam.eq_iff Abs1_eq_iff lam.fresh fresh_at_base) lemma Lam_freshness: - assumes a: "x \ y" - and b: "atom y \ Lam [x].t" - shows "atom y \ t" - using a b by (simp add: lam.fresh Abs_fresh_iff) + assumes a: "atom y \ Lam [x].t" + shows "(y = x) \ (y \ x \ atom y \ t)" + using a by (auto simp add: lam.fresh Abs_fresh_iff) lemma neutral_element: fixes x::"nat" @@ -500,20 +506,20 @@ assumes a: "t1 \b* t2" shows "t1 \b** t2" using a -by (induct) (auto intro: beta_star2.intros) + by (induct) (auto intro: beta_star2.intros) lemma assumes a: "t1 \b* t2" and b: "t2 \b* t3" shows "t1 \b* t3" -using a b -by (induct) (auto intro: beta_star1.intros) + using a b + by (induct) (auto intro: beta_star1.intros) lemma assumes a: "t1 \b** t2" shows "t1 \b* t2" -using a -by (induct) (auto intro: bs1_trans2 beta_star1.intros) + using a + by (induct) (auto intro: bs1_trans2 beta_star1.intros) inductive eval :: "lam \ lam \ bool" ("_ \ _" [60, 60] 60) @@ -556,13 +562,10 @@ term "CAppL" term "CAppL \ (Var x)" -text {* +subsection {* MINI EXERCISE *} - 1.) MINI EXERCISE - ----------------- - +text {* Try and see what happens if you apply a Hole to a Hole? - *} type_synonym ctxs = "ctx list" @@ -593,14 +596,13 @@ proof(induct) case (ms1 e1 Es1) have c: " \* " by fact - show " \* " sorry + then show " \* " by simp next case (ms2 e1 Es1 e2 Es2 e2' Es2') have ih: " \* \ \* " by fact have d1: " \* " by fact have d2: " \ " by fact - - show " \* " sorry + show " \* " using d1 d2 ih by blast qed text {* @@ -658,7 +660,6 @@ shows "val t'" using a by (induct) (auto) - theorem assumes a: "t \ t'" shows " \* " @@ -666,7 +667,7 @@ proof (induct) case (e_Lam x t) -- {* no assumptions *} - show " \* " sorry + show " \* " by auto next case (e_App t1 x t t2 v' v) -- {* all assumptions in this case *} @@ -697,230 +698,6 @@ shows " \* " using a eval_implies_machines_ctx by simp -section {* Types *} - -nominal_datatype ty = - tVar "string" -| tArr "ty" "ty" ("_ \ _" [100, 100] 100) - - -text {* - Having defined them as nominal datatypes gives us additional - definitions and theorems that come with types (see below). - - We next define the type of typing contexts, a predicate that - defines valid contexts (i.e. lists that contain only unique - variables) and the typing judgement. - -*} - -type_synonym ty_ctx = "(name \ ty) list" - - -inductive - valid :: "ty_ctx \ bool" -where - v1[intro]: "valid []" -| v2[intro]: "\valid \; atom x \ \\\ valid ((x, T) # \)" - - -inductive - typing :: "ty_ctx \ lam \ ty \ bool" ("_ \ _ : _" [60, 60, 60] 60) -where - t_Var[intro]: "\valid \; (x, T) \ set \\ \ \ \ Var x : T" -| t_App[intro]: "\\ \ t1 : T1 \ T2; \ \ t2 : T1\ \ \ \ App t1 t2 : T2" -| t_Lam[intro]: "\atom x \ \; (x, T1) # \ \ t : T2\ \ \ \ Lam [x].t : T1 \ T2" - - -text {* - The predicate atom x \ \, read as x fresh for \, is defined by - Nominal Isabelle. Freshness is defined for lambda-terms, products, - lists etc. For example we have: - *} - -lemma - fixes x::"name" - shows "atom x \ Lam [x].t" - and "atom x \ (t1, t2) \ atom x \ App t1 t2" - and "atom x \ Var y \ atom x \ y" - and "\atom x \ t1; atom x \ t2\ \ atom x \ (t1, t2)" - and "\atom x \ l1; atom x \ l2\ \ atom x \ (l1 @ l2)" - and "atom x \ y \ x \ y" - by (simp_all add: lam.fresh fresh_append fresh_at_base) - -text {* - We can also prove that every variable is fresh for a type. -*} - -lemma ty_fresh: - fixes x::"name" - and T::"ty" - shows "atom x \ T" -by (induct T rule: ty.induct) - (simp_all add: ty.fresh pure_fresh) - -text {* - In order to state the weakening lemma in a convenient form, we - using the following abbreviation. Abbreviations behave like - definitions, except that they are always automatically folded - and unfolded. -*} - -abbreviation - "sub_ty_ctx" :: "ty_ctx \ ty_ctx \ bool" ("_ \ _" [60, 60] 60) -where - "\1 \ \2 \ \x. x \ set \1 \ x \ set \2" - - -subsection {* EXERCISE 4 *} - -text {* - Fill in the details and give a proof of the weakening lemma. -*} - -lemma - assumes a: "\1 \ t : T" - and b: "valid \2" - and c: "\1 \ \2" - shows "\2 \ t : T" -using a b c -proof (induct arbitrary: \2) - case (t_Var \1 x T) - have a1: "valid \1" by fact - have a2: "(x, T) \ set \1" by fact - have a3: "valid \2" by fact - have a4: "\1 \ \2" by fact - - show "\2 \ Var x : T" sorry -next - case (t_Lam x \1 T1 t T2) - have ih: "\\3. \valid \3; (x, T1) # \1 \ \3\ \ \3 \ t : T2" by fact - have a0: "atom x \ \1" by fact - have a1: "valid \2" by fact - have a2: "\1 \ \2" by fact - - show "\2 \ Lam [x].t : T1 \ T2" sorry -qed (auto) -- {* the application case *} - - -text {* - Despite the frequent claim that the weakening lemma is trivial, - routine or obvious, the proof in the lambda-case does not go - through smoothly. Painful variable renamings seem to be necessary. - But the proof using renamings is horribly complicated (see below). -*} - -equivariance valid -equivariance typing - -lemma weakening_NOT_TO_BE_TRIED_AT_HOME: - assumes a: "\1 \ t : T" - and b: "valid \2" - and c: "\1 \ \2" - shows "\2 \ t : T" -using a b c -proof (induct arbitrary: \2) - -- {* lambda case *} - case (t_Lam x \1 T1 t T2) - have fc0: "atom x \ \1" by fact - have ih: "\\3. \valid \3; (x, T1) # \1 \ \3\ \ \3 \ t : T2" by fact - -- {* we choose a fresh variable *} - obtain c::"name" where fc1: "atom c \ (x, t, \1, \2)" by (rule obtain_fresh) - -- {* we alpha-rename the abstraction *} - have "Lam [c].((c \ x) \ t) = Lam [x].t" using fc1 - by (auto simp add: lam.eq_iff Abs1_eq_iff flip_def) - moreover - -- {* we can then alpha rename the goal *} - have "\2 \ Lam [c].((c \ x) \ t) : T1 \ T2" - proof - - -- {* we need to establish - * (x, T1) # \1 \ (x, T1) # ((c \ x) \ \2) and - ** valid ((x, T1) # ((c \ x) \ \2)) *} - have *: "(x, T1) # \1 \ (x, T1) # ((c \ x) \ \2)" - proof - - have "\1 \ \2" by fact - then have "(c \ x) \ ((x, T1) # \1 \ (x, T1) # ((c \ x) \ \2))" using fc0 fc1 - by (perm_simp) (simp add: flip_fresh_fresh) - then show "(x, T1) # \1 \ (x, T1) # ((c \ x) \ \2)" by (rule permute_boolE) - qed - moreover - have **: "valid ((x, T1) # ((c \ x) \ \2))" - proof - - have "valid \2" by fact - then show "valid ((x, T1) # ((c \ x) \ \2))" using fc1 - by (auto simp add: fresh_permute_left atom_eqvt valid.eqvt) - qed - -- {* these two facts give us by induction hypothesis the following *} - ultimately have "(x, T1) # ((c \ x) \ \2) \ t : T2" using ih by simp - -- {* we now apply renamings to get to our goal *} - then have "(c \ x) \ ((x, T1) # ((c \ x) \ \2) \ t : T2)" by (rule permute_boolI) - then have "(c, T1) # \2 \ ((c \ x) \ t) : T2" using fc1 - by (perm_simp) (simp add: flip_fresh_fresh ty_fresh) - then show "\2 \ Lam [c].((c \ x) \ t) : T1 \ T2" using fc1 by auto - qed - ultimately show "\2 \ Lam [x].t : T1 \ T2" by simp -qed (auto) -- {* var and app cases, luckily, are automatic *} - - -text {* - The remedy is to use a stronger induction principle that - has the usual "variable convention" already build in. The - following command derives this induction principle for us. - (We shall explain what happens here later.) -*} - -nominal_inductive typing - avoids t_Lam: "x" - unfolding fresh_star_def - by (simp_all add: fresh_Pair lam.fresh ty_fresh) - -text {* Compare the two induction principles *} - -thm typing.induct -thm typing.strong_induct -- {* has the additional assumption {atom x} \ c *} - -text {* - We can use the stronger induction principle by replacing - the line - - proof (induct arbitrary: \2) - - with - - proof (nominal_induct avoiding: \2 rule: typing.strong_induct) - - Try now the proof. -*} - - -lemma weakening: - assumes a: "\1 \ t : T" - and b: "valid \2" - and c: "\1 \ \2" - shows "\2 \ t : T" -using a b c -proof (nominal_induct avoiding: \2 rule: typing.strong_induct) - case (t_Var \1 x T) -- {* variable case is as before *} - have "\1 \ \2" by fact - moreover - have "valid \2" by fact - moreover - have "(x, T)\ set \1" by fact - ultimately show "\2 \ Var x : T" by auto -next - case (t_Lam x \1 T1 t T2) - have vc: "atom x \ \2" by fact -- {* additional fact afforded by the stron induction *} - have ih: "\\3. \valid \3; (x, T1) # \1 \ \3\ \ \3 \ t : T2" by fact - have a0: "atom x \ \1" by fact - have a1: "valid \2" by fact - have a2: "\1 \ \2" by fact - have "valid ((x, T1) # \2)" using a1 vc by auto - moreover - have "(x, T1) # \1 \ (x, T1) # \2" using a2 by auto - ultimately - have "(x, T1) # \2 \ t : T2" using ih by simp - then show "\2 \ Lam [x].t : T1 \ T2" using vc by auto -qed (auto) -- {* app case *} section {* Function Definitions: Filling a Lambda-Term into a Context *} @@ -1003,8 +780,7 @@ shows "E \ \ = E" by (induct E) (simp_all) -lemma odot_assoc: - fixes E1 E2 E3::"ctx" +lemma odot_assoc: (* fixme call compose *) shows "(E1 \ E2) \ E3 = E1 \ (E2 \ E3)" by (induct E1) (simp_all) @@ -1114,7 +890,6 @@ (auto simp add: lam.fresh fresh_at_base) lemma fresh_fact: - fixes z::"name" assumes a: "atom z \ s" and b: "z = y \ atom z \ t" shows "atom z \ t[y ::= s]" diff -r 87b735f86060 -r ddc05a611005 Tutorial/Tutorial2.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Tutorial/Tutorial2.thy Fri Jan 21 21:58:51 2011 +0100 @@ -0,0 +1,277 @@ +theory Tutorial2 +imports Tutorial1 +begin + +(* fixme: put height example here *) + + +section {* Types *} + +nominal_datatype ty = + tVar "string" +| tArr "ty" "ty" ("_ \ _" [100, 100] 100) + + +text {* + Having defined them as nominal datatypes gives us additional + definitions and theorems that come with types (see below). + + We next define the type of typing contexts, a predicate that + defines valid contexts (i.e. lists that contain only unique + variables) and the typing judgement. + +*} + +type_synonym ty_ctx = "(name \ ty) list" + + +inductive + valid :: "ty_ctx \ bool" +where + v1[intro]: "valid []" +| v2[intro]: "\valid \; atom x \ \\\ valid ((x, T) # \)" + + +inductive + typing :: "ty_ctx \ lam \ ty \ bool" ("_ \ _ : _" [60, 60, 60] 60) +where + t_Var[intro]: "\valid \; (x, T) \ set \\ \ \ \ Var x : T" +| t_App[intro]: "\\ \ t1 : T1 \ T2; \ \ t2 : T1\ \ \ \ App t1 t2 : T2" +| t_Lam[intro]: "\atom x \ \; (x, T1) # \ \ t : T2\ \ \ \ Lam [x].t : T1 \ T2" + + +text {* + The predicate atom x \ \, read as x fresh for \, is defined by + Nominal Isabelle. It is defined for lambda-terms, products, lists etc. + For example we have: +*} + +lemma + fixes x::"name" + shows "atom x \ Lam [x].t" + and "atom x \ (t1, t2) \ atom x \ App t1 t2" + and "atom x \ Var y \ atom x \ y" + and "\atom x \ t1; atom x \ t2\ \ atom x \ (t1, t2)" + and "\atom x \ l1; atom x \ l2\ \ atom x \ (l1 @ l2)" + and "atom x \ y \ x \ y" + by (simp_all add: lam.fresh fresh_append fresh_at_base) + +text {* + We can also prove that every variable is fresh for a type. +*} + +lemma ty_fresh: + fixes x::"name" + and T::"ty" + shows "atom x \ T" +by (induct T rule: ty.induct) + (simp_all add: ty.fresh pure_fresh) + +text {* + In order to state the weakening lemma in a convenient form, we + using the following abbreviation. Abbreviations behave like + definitions, except that they are always automatically folded + and unfolded. +*} + +abbreviation + "sub_ty_ctx" :: "ty_ctx \ ty_ctx \ bool" ("_ \ _" [60, 60] 60) +where + "\1 \ \2 \ \x. x \ set \1 \ x \ set \2" + + +subsection {* EXERCISE 4 *} + +text {* + Fill in the details and give a proof of the weakening lemma. +*} + +lemma + assumes a: "\1 \ t : T" + and b: "valid \2" + and c: "\1 \ \2" + shows "\2 \ t : T" +using a b c +proof (induct arbitrary: \2) + case (t_Var \1 x T) + have a1: "valid \1" by fact + have a2: "(x, T) \ set \1" by fact + have a3: "valid \2" by fact + have a4: "\1 \ \2" by fact + + show "\2 \ Var x : T" sorry +next + case (t_Lam x \1 T1 t T2) + have ih: "\\3. \valid \3; (x, T1) # \1 \ \3\ \ \3 \ t : T2" by fact + have a0: "atom x \ \1" by fact + have a1: "valid \2" by fact + have a2: "\1 \ \2" by fact + + show "\2 \ Lam [x].t : T1 \ T2" sorry +qed (auto) -- {* the application case *} + + +text {* + Despite the frequent claim that the weakening lemma is trivial, + routine or obvious, the proof in the lambda-case does not go + through smoothly. Painful variable renamings seem to be necessary. + But the proof using renamings is horribly complicated (see below). +*} + +equivariance valid +equivariance typing + +lemma weakening_NOT_TO_BE_TRIED_AT_HOME: + assumes a: "\1 \ t : T" + and b: "valid \2" + and c: "\1 \ \2" + shows "\2 \ t : T" +using a b c +proof (induct arbitrary: \2) + -- {* lambda case *} + case (t_Lam x \1 T1 t T2) + have fc0: "atom x \ \1" by fact + have ih: "\\3. \valid \3; (x, T1) # \1 \ \3\ \ \3 \ t : T2" by fact + -- {* we choose a fresh variable *} + obtain c::"name" where fc1: "atom c \ (x, t, \1, \2)" by (rule obtain_fresh) + -- {* we alpha-rename the abstraction *} + have "Lam [c].((c \ x) \ t) = Lam [x].t" using fc1 + by (auto simp add: lam.eq_iff Abs1_eq_iff flip_def) + moreover + -- {* we can then alpha rename the goal *} + have "\2 \ Lam [c].((c \ x) \ t) : T1 \ T2" + proof - + -- {* we need to establish *} + -- {* (1) (x, T1) # \1 \ (x, T1) # ((c \ x) \ \2) *} + -- {* (2) valid ((x, T1) # ((c \ x) \ \2)) *} + have "(1)": "(x, T1) # \1 \ (x, T1) # ((c \ x) \ \2)" + proof - + have "\1 \ \2" by fact + then have "(c \ x) \ ((x, T1) # \1 \ (x, T1) # ((c \ x) \ \2))" using fc0 fc1 + by (perm_simp) (simp add: flip_fresh_fresh) + then show "(x, T1) # \1 \ (x, T1) # ((c \ x) \ \2)" by (rule permute_boolE) + qed + moreover + have "(2)": "valid ((x, T1) # ((c \ x) \ \2))" + proof - + have "valid \2" by fact + then show "valid ((x, T1) # ((c \ x) \ \2))" using fc1 + by (auto simp add: fresh_permute_left atom_eqvt valid.eqvt) + qed + -- {* these two facts give us by induction hypothesis the following *} + ultimately have "(x, T1) # ((c \ x) \ \2) \ t : T2" using ih by simp + -- {* we now apply renamings to get to our goal *} + then have "(c \ x) \ ((x, T1) # ((c \ x) \ \2) \ t : T2)" by (rule permute_boolI) + then have "(c, T1) # \2 \ ((c \ x) \ t) : T2" using fc1 + by (perm_simp) (simp add: flip_fresh_fresh ty_fresh) + then show "\2 \ Lam [c].((c \ x) \ t) : T1 \ T2" using fc1 by auto + qed + ultimately show "\2 \ Lam [x].t : T1 \ T2" by simp +qed (auto) -- {* var and app cases, luckily, are automatic *} + + +text {* + The remedy is to use a stronger induction principle that + has the usual "variable convention" already build in. The + following command derives this induction principle for us. + (We shall explain what happens here later.) +*} + +nominal_inductive typing + avoids t_Lam: "x" + unfolding fresh_star_def + by (simp_all add: fresh_Pair lam.fresh ty_fresh) + +text {* Compare the two induction principles *} + +thm typing.induct +thm typing.strong_induct -- {* has the additional assumption {atom x} \ c *} + +text {* + We can use the stronger induction principle by replacing + the line + + proof (induct arbitrary: \2) + + with + + proof (nominal_induct avoiding: \2 rule: typing.strong_induct) + + Try now the proof. +*} + + +lemma weakening: + assumes a: "\1 \ t : T" + and b: "valid \2" + and c: "\1 \ \2" + shows "\2 \ t : T" +using a b c +proof (nominal_induct avoiding: \2 rule: typing.strong_induct) + case (t_Var \1 x T) -- {* variable case is as before *} + have "\1 \ \2" by fact + moreover + have "valid \2" by fact + moreover + have "(x, T)\ set \1" by fact + ultimately show "\2 \ Var x : T" by auto +next + case (t_Lam x \1 T1 t T2) + have vc: "atom x \ \2" by fact -- {* additional fact afforded by the strong induction *} + have ih: "\\3. \valid \3; (x, T1) # \1 \ \3\ \ \3 \ t : T2" by fact + have a0: "atom x \ \1" by fact + have a1: "valid \2" by fact + have a2: "\1 \ \2" by fact + have "valid ((x, T1) # \2)" using a1 vc by auto + moreover + have "(x, T1) # \1 \ (x, T1) # \2" using a2 by auto + ultimately + have "(x, T1) # \2 \ t : T2" using ih by simp + then show "\2 \ Lam [x].t : T1 \ T2" using vc by auto +qed (auto) -- {* app case *} + + +text {* unbind / inconsistency example *} + +inductive + unbind :: "lam \ lam \ bool" ("_ \ _" [60, 60] 60) +where + u_Var[intro]: "Var x \ Var x" +| u_App[intro]: "App t1 t2 \ App t1 t2" +| u_Lam[intro]: "t \ t' \ Lam [x].t \ t'" + +lemma unbind_simple: + shows "Lam [x].Var x \ Var x" + by auto + +equivariance unbind + +nominal_inductive unbind + avoids u_Lam: "x" + sorry + +lemma unbind_fake: + fixes y::"name" + assumes a: "t \ t'" + and b: "atom y \ t" + shows "atom y \ t'" +using a b +proof (nominal_induct avoiding: y rule: unbind.strong_induct) + case (u_Lam t t' x y) + have ih: "atom y \ t \ atom y \ t'" by fact + have asm: "atom y \ Lam [x]. t" by fact + have fc: "atom x \ y" by fact + then have in_eq: "x \ y" by (simp add: fresh_at_base) + then have "atom y \ t" using asm by (simp add: lam.fresh) + then show "atom y \ t'" using ih by simp +qed + +lemma + shows "False" +proof - + have "atom x \ Lam [x]. Var x" by (simp add: lam.fresh) + then have "atom x \ Var x" using unbind_fake unbind_simple by auto + then show "False" by (simp add: lam.fresh fresh_at_base) +qed + +end diff -r 87b735f86060 -r ddc05a611005 Tutorial/Tutorial4.thy --- a/Tutorial/Tutorial4.thy Fri Jan 21 00:55:28 2011 +0100 +++ b/Tutorial/Tutorial4.thy Fri Jan 21 21:58:51 2011 +0100 @@ -1,6 +1,5 @@ - theory Tutorial4 -imports Tutorial1 +imports Tutorial1 Tutorial2 begin section {* The CBV Reduction Relation (Small-Step Semantics) *} @@ -136,22 +135,28 @@ lemma machines_implies_cbvs_ctx: assumes a: " \* " shows "(Es\)\e\ \cbv* (Es'\)\e'\" -using a -by (induct) (auto dest: machine_implies_cbvs_ctx) +using a machine_implies_cbvs_ctx +by (induct) (blast)+ text {* So whenever we let the CL machine start in an initial state and it arrives at a final state, then there exists - a corresponding cbv-reduction sequence. *} + a corresponding cbv-reduction sequence. +*} corollary machines_implies_cbvs: assumes a: " \* " shows "e \cbv* e'" -using a by (auto dest: machines_implies_cbvs_ctx) +proof - + have "[]\\e\ \cbv* []\\e'\" + using a machines_implies_cbvs_ctx by blast + then show "e \cbv* e'" by simp +qed text {* We now want to relate the cbv-reduction to the evaluation - relation. For this we need two auxiliary lemmas. *} + relation. For this we need two auxiliary lemmas. +*} lemma eval_val: assumes a: "val t" @@ -160,16 +165,15 @@ lemma e_App_elim: assumes a: "App t1 t2 \ v" - shows "\x t v'. t1 \ Lam [x].t \ t2 \ v' \ t[x::=v'] \ v" + obtains x t v' where "t1 \ Lam [x].t" "t2 \ v'" "t[x::=v'] \ v" using a by (cases) (auto simp add: lam.eq_iff lam.distinct) -text {****************************************************************** - - 10.) Exercise - ------------- + +subsection {* EXERCISE *} - Complete the first case in the proof below. - +text {* + Complete the first and second case in the + proof below. *} lemma cbv_eval: @@ -180,8 +184,9 @@ case (cbv1 v x t t3) have a1: "val v" by fact have a2: "t[x ::= v] \ t3" by fact - - show "App (Lam [x].t) v \ t3" sorry + have a3: "Lam [x].t \ Lam [x].t" by auto + have a4: "v \ v" using a1 eval_val by auto + show "App (Lam [x].t) v \ t3" using a3 a4 a2 by auto next case (cbv2 t t' t2 t3) have ih: "\t3. t' \ t3 \ t \ t3" by fact @@ -189,10 +194,10 @@ then obtain x t'' v' where a1: "t' \ Lam [x].t''" and a2: "t2 \ v'" - and a3: "t''[x ::= v'] \ t3" using e_App_elim by blast + and a3: "t''[x ::= v'] \ t3" by (rule e_App_elim) have "t \ Lam [x].t''" using ih a1 by auto then show "App t t2 \ t3" using a2 a3 by auto -qed (auto dest!: e_App_elim) +qed (auto elim!: e_App_elim) text {* @@ -206,7 +211,8 @@ text {* Finally, we can show that if from a term t we reach a value - by a cbv-reduction sequence, then t evaluates to this value. *} + by a cbv-reduction sequence, then t evaluates to this value. +*} lemma cbvs_implies_eval: assumes a: "t \cbv* v" "val v" @@ -216,15 +222,16 @@ text {* All facts tied together give us the desired property about - K machines. *} + machines. +*} theorem machines_implies_eval: assumes a: " \* " and b: "val t2" shows "t1 \ t2" proof - - have "t1 \cbv* t2" using a by (simp add: machines_implies_cbvs) - then show "t1 \ t2" using b by (simp add: cbvs_implies_eval) + have "t1 \cbv* t2" using a machines_implies_cbvs by simp + then show "t1 \ t2" using b cbvs_implies_eval by simp qed lemma valid_elim: @@ -252,9 +259,9 @@ by (induct) (auto simp add: fresh_list fresh_Pair fresh_at_base) lemma type_substitution_aux: - assumes a: "(\ @ [(x, T')] @ \) \ e : T" + assumes a: "\ @ [(x, T')] @ \ \ e : T" and b: "\ \ e' : T'" - shows "(\ @ \) \ e[x ::= e'] : T" + shows "\ @ \ \ e[x ::= e'] : T" using a b proof (nominal_induct \'\"\ @ [(x, T')] @ \" e T avoiding: x e' \ rule: typing.strong_induct) case (t_Var y T x e' \) @@ -264,40 +271,42 @@ from a1 have a4: "valid (\ @ \)" by (rule valid_insert) { assume eq: "x = y" from a1 a2 have "T = T'" using eq by (auto intro: context_unique) - with a3 have "\ @ \ \ Var y[x::=e'] : T" using eq a4 by (auto intro: weakening) + with a3 have "\ @ \ \ Var y[x ::= e'] : T" using eq a4 by (auto intro: weakening) } moreover { assume ineq: "x \ y" from a2 have "(y, T) \ set (\ @ \)" using ineq by simp - then have "\ @ \ \ Var y[x::=e'] : T" using ineq a4 by auto + then have "\ @ \ \ Var y[x ::= e'] : T" using ineq a4 by auto } ultimately show "\ @ \ \ Var y[x::=e'] : T" by blast qed (force simp add: fresh_append fresh_Cons)+ corollary type_substitution: - assumes a: "(x,T') # \ \ e : T" + assumes a: "(x, T') # \ \ e : T" and b: "\ \ e' : T'" - shows "\ \ e[x::=e'] : T" + shows "\ \ e[x ::= e'] : T" using a b type_substitution_aux[where \="[]"] -by (auto) +by auto lemma t_App_elim: assumes a: "\ \ App t1 t2 : T" - shows "\T'. \ \ t1 : T' \ T \ \ \ t2 : T'" + obtains T' where "\ \ t1 : T' \ T" "\ \ t2 : T'" using a by (cases) (auto simp add: lam.eq_iff lam.distinct) +text {* we have not yet generated strong elimination rules *} lemma t_Lam_elim: assumes ty: "\ \ Lam [x].t : T" and fc: "atom x \ \" - shows "\T1 T2. T = T1 \ T2 \ (x, T1) # \ \ t : T2" + obtains T1 T2 where "T = T1 \ T2" "(x, T1) # \ \ t : T2" using ty fc apply(cases) apply(auto simp add: lam.eq_iff lam.distinct ty.eq_iff) apply(auto simp add: Abs1_eq_iff) -apply(rule_tac p="(x \ xa)" in permute_boolE) +apply(rotate_tac 3) +apply(drule_tac p="(x \ xa)" in permute_boolI) apply(perm_simp) -apply(simp add: flip_def swap_fresh_fresh ty_fresh) +apply(auto simp add: flip_def swap_fresh_fresh ty_fresh) done theorem cbv_type_preservation: @@ -306,7 +315,7 @@ shows "\ \ t' : T" using a b by (nominal_induct avoiding: \ T rule: cbv.strong_induct) - (auto dest!: t_Lam_elim t_App_elim simp add: type_substitution ty.eq_iff) + (auto elim!: t_Lam_elim t_App_elim simp add: type_substitution ty.eq_iff) corollary cbvs_type_preservation: assumes a: "t \cbv* t'" @@ -316,15 +325,17 @@ by (induct) (auto intro: cbv_type_preservation) text {* - The Type-Preservation Property for the Machine and Evaluation Relation. *} + The type-preservation property for the machine and + evaluation relation. +*} theorem machine_type_preservation: assumes a: " \* " and b: "\ \ t : T" shows "\ \ t' : T" proof - - from a have "t \cbv* t'" by (simp add: machines_implies_cbvs) - then show "\ \ t' : T" using b by (simp add: cbvs_type_preservation) + have "t \cbv* t'" using a machines_implies_cbvs by simp + then show "\ \ t' : T" using b cbvs_type_preservation by simp qed theorem eval_type_preservation: @@ -332,8 +343,8 @@ and b: "\ \ t : T" shows "\ \ t' : T" proof - - from a have " \* " by (simp add: eval_implies_machines) - then show "\ \ t' : T" using b by (simp add: machine_type_preservation) + have " \* " using a eval_implies_machines by simp + then show "\ \ t' : T" using b machine_type_preservation by simp qed text {* The Progress Property *} @@ -341,7 +352,7 @@ lemma canonical_tArr: assumes a: "[] \ t : T1 \ T2" and b: "val t" - shows "\x t'. t = Lam [x].t'" + obtains x t' where "t = Lam [x].t'" using b a by (induct) (auto) theorem progress: @@ -349,6 +360,11 @@ shows "(\t'. t \cbv t') \ (val t)" using a by (induct \\"[]::ty_ctx" t T) - (auto intro: cbv.intros dest!: canonical_tArr) + (auto elim: canonical_tArr) +text {* + Done! +*} +end +