diff -r 67451725fb41 -r 8ae1c2e6369e Tutorial/Tutorial1.thy --- a/Tutorial/Tutorial1.thy Tue Jan 25 02:46:05 2011 +0900 +++ b/Tutorial/Tutorial1.thy Tue Jan 25 02:51:44 2011 +0900 @@ -1,4 +1,3 @@ - header {* Nominal Isabelle Tutorial at POPL'11 @@ -183,7 +182,7 @@ text {* In this section we want to define inductively the evaluation - relation for lambda terms. + relation and for cbv-reduction relation. Inductive definitions in Isabelle start with the keyword "inductive" and a predicate name. One can optionally provide a type for the predicate. @@ -208,15 +207,13 @@ *} inductive - eval :: "lam \ lam \ bool" ("_ \ _" [60, 60] 60) + eval :: "lam \ lam \ bool" (infixr "\" 60) where e_Lam[intro]: "Lam [x].t \ Lam [x].t" | e_App[intro]: "\t1 \ Lam [x].t; t2 \ v'; t[x::=v'] \ v\ \ App t1 t2 \ v" - text {* - Values are also defined using inductive. In our case values - are just lambda-abstractions. + Values and cbv are also defined using inductive. *} inductive @@ -224,7 +221,6 @@ where v_Lam[intro]: "val (Lam [x].t)" - section {* Theorems *} text {* @@ -362,6 +358,7 @@ Two very simple example proofs are as follows. *} +subsection {* EXERCISE 1 *} lemma eval_val: assumes a: "val t" @@ -372,7 +369,11 @@ show "Lam [x]. t \ Lam [x]. t" sorry qed -lemma eavl_to_val: +subsection {* EXERCISE 2 *} + +text {* Fill the gaps in the proof below. *} + +lemma eval_to_val: assumes a: "t \ t'" shows "val t'" using a @@ -381,16 +382,96 @@ show "val (Lam [x].t)" sorry next case (e_App t1 x t t2 v v') + -- {* all assumptions in this case *} have "t1 \ Lam [x].t" by fact have ih1: "val (Lam [x]. t)" by fact have "t2 \ v" by fact have ih2: "val v" by fact have "t [x ::= v] \ v'" by fact have ih3: "val v'" by fact + show "val v'" sorry qed + + +section {* Datatypes: Evaluation Contexts*} + +text {* + Datatypes can be defined in Isabelle as follows: we have to provide the name + of the datatype and a list its type-constructors. Each type-constructor needs + to have the information about the types of its arguments, and optionally + can also contain some information about pretty syntax. For example, we like + to write "\" for holes. +*} - +datatype ctx = + Hole ("\") + | CAppL "ctx" "lam" + | CAppR "lam" "ctx" + +text {* Now Isabelle knows about: *} + +typ ctx +term "\" +term "CAppL" +term "CAppL \ (Var x)" + +subsection {* MINI EXERCISE *} + +text {* + Try and see what happens if you apply a Hole to a Hole? +*} + + +section {* Machines for Evaluation *} + +type_synonym ctxs = "ctx list" + +inductive + machine :: "lam \ ctxs \lam \ ctxs \ bool" ("<_,_> \ <_,_>" [60, 60, 60, 60] 60) +where + m1: " \ t2) # Es>" +| m2: "val v \ t2) # Es> \ ) # Es>" +| m3: "val v \ ) # Es> \ " + +text {* + Since the machine defined above only performs a single reduction, + we need to define the transitive closure of this machine. *} + +inductive + machines :: "lam \ ctxs \ lam \ ctxs \ bool" ("<_,_> \* <_,_>" [60, 60, 60, 60] 60) +where + ms1: " \* " +| ms2: "\ \ ; \* \ \ \* " + +declare machine.intros[intro] machines.intros[intro] + +section {* EXERCISE 3 *} + +text {* + We need to show that the machines-relation is transitive. + Fill in the gaps below. +*} + +lemma ms3[intro]: + assumes a: " \* " + and b: " \* " + shows " \* " +using a b +proof(induct) + case (ms1 e1 Es1) + have c: " \* " by fact + + show " \* " sorry +next + case (ms2 e1 Es1 e2 Es2 e2' Es2') + have ih: " \* \ \* " by fact + have d1: " \* " by fact + have d2: " \ " by fact + + show " \* " sorry +qed + text {* Just like gotos in the Basic programming language, labels often reduce the readability of proofs. Therefore one can use in Isar the notation @@ -398,7 +479,22 @@ the next have-statement. This is used in the second case below. *} - +lemma + assumes a: " \* " + and b: " \* " + shows " \* " +using a b +proof(induct) + case (ms1 e1 Es1) + show " \* " by fact +next + case (ms2 e1 Es1 e2 Es2 e2' Es2') + have ih: " \* \ \* " by fact + have " \* " by fact + then have d3: " \* " using ih by simp + have d2: " \ " by fact + show " \* " using d2 d3 by auto +qed text {* The label ih2 cannot be got rid of in this way, because it is used @@ -418,108 +514,6 @@ "statement". With this we can simplify our proof further to: *} - -text {* - While automatic proof procedures in Isabelle are not able to prove statements - like "P = NP" assuming usual definitions for P and NP, they can automatically - discharge the lemmas we just proved. For this we only have to set up the induction - and auto will take care of the rest. This means we can write: -*} - - - - -section {* Datatypes: Evaluation Contexts *} - -text {* - - Datatypes can be defined in Isabelle as follows: we have to provide the name - of the datatype and list its type-constructors. Each type-constructor needs - to have the information about the types of its arguments, and optionally - can also contain some information about pretty syntax. For example, we like - to write "\" for holes. -*} - -datatype ctx = - Hole ("\") - | CAppL "ctx" "lam" - | CAppR "lam" "ctx" - -text {* Now Isabelle knows about: *} - -typ ctx -term "\" -term "CAppL" -term "CAppL \ (Var x)" - -subsection {* MINI EXERCISE *} - -text {* - Try and see what happens if you apply a Hole to a Hole? -*} - -type_synonym ctxs = "ctx list" - -inductive - machine :: "lam \ ctxs \lam \ ctxs \ bool" ("<_,_> \ <_,_>" [60, 60, 60, 60] 60) -where - m1[intro]: " \ t2) # Es>" -| m2[intro]: "val v \ t2) # Es> \ ) # Es>" -| m3[intro]: "val v \ ) # Es> \ " - - -text {* - Since the machine defined above only performs a single reduction, - we need to define the transitive closure of this machine. *} - -inductive - machines :: "lam \ ctxs \ lam \ ctxs \ bool" ("<_,_> \* <_,_>" [60, 60, 60, 60] 60) -where - ms1[intro]: " \* " -| ms2[intro]: "\ \ ; \* \ \ \* " - -lemma - assumes a: " \* " - and b: " \* " - shows " \* " -using a b -proof(induct) - case (ms1 e1 Es1) - have c: " \* " by fact - 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 " \* " using d1 d2 ih by blast -qed - -text {* - Just like gotos in the Basic programming language, labels can reduce - the readability of proofs. Therefore one can use in Isar the notation - "then have" in order to feed a have-statement to the proof of - the next have-statement. In the proof below this has been used - in order to get rid of the labels c and d1. -*} - -lemma - assumes a: " \* " - and b: " \* " - shows " \* " -using a b -proof(induct) - case (ms1 e1 Es1) - show " \* " by fact -next - case (ms2 e1 Es1 e2 Es2 e2' Es2') - have ih: " \* \ \* " by fact - have " \* " by fact - then have d3: " \* " using ih by simp - have d2: " \ " by fact - show " \* " using d2 d3 by auto -qed - lemma assumes a: " \* " and b: " \* " @@ -539,16 +533,36 @@ qed -lemma ms3[intro]: +text {* + While automatic proof procedures in Isabelle are not able to prove statements + like "P = NP" assuming usual definitions for P and NP, they can automatically + discharge the lemmas we just proved. For this we only have to set up the induction + and auto will take care of the rest. This means we can write: +*} + +lemma + assumes a: "val t" + shows "t \ t" +using a by (induct) (auto) + +lemma + assumes a: "t \ t'" + shows "val t'" +using a by (induct) (auto) + +lemma assumes a: " \* " and b: " \* " shows " \* " using a b by (induct) (auto) -lemma eval_to_val: (* fixme: done above *) - assumes a: "t \ t'" - shows "val t'" -using a by (induct) (auto) + +section {* EXERCISE 4 *} + +text {* + The point of the machine is that it simulates the evaluation + relation. Therefore we like to prove the following: +*} theorem assumes a: "t \ t'" @@ -567,10 +581,12 @@ have ih2: " \* " by fact have a3: "t[x::=v'] \ v" by fact have ih3: " \* " by fact + -- {* your reasoning *} show " \* " sorry qed + text {* Again the automatic tools in Isabelle can discharge automatically of the routine work in these proofs. We can write: @@ -589,7 +605,6 @@ using a eval_implies_machines_ctx by simp - section {* Function Definitions: Filling a Lambda-Term into a Context *} text {* @@ -607,6 +622,7 @@ | "(CAppL E t')\t\ = App (E\t\) t'" | "(CAppR t' E)\t\ = App t' (E\t\)" + text {* After this definition Isabelle will be able to simplify statements like: @@ -617,7 +633,7 @@ by simp fun - ctx_compose :: "ctx \ ctx \ ctx" ("_ \ _" [99,98] 99) + ctx_compose :: "ctx \ ctx \ ctx" (infixr "\" 99) where "\ \ E' = E'" | "(CAppL E t') \ E' = CAppL (E \ E') t'" @@ -666,11 +682,19 @@ show "((CAppR t' E1) \ E2)\t\ = (CAppR t' E1)\E2\t\\" sorry qed + +subsection {* EXERCISE 6 *} + +text {* + Remove the sorries in the ctx_append proof below. You can make + use of the following two properties. +*} + lemma neut_hole: shows "E \ \ = E" by (induct E) (simp_all) -lemma odot_assoc: (* fixme call compose *) +lemma compose_assoc: shows "(E1 \ E2) \ E3 = E1 \ (E2 \ E3)" by (induct E1) (simp_all) @@ -686,7 +710,6 @@ show "((E # Es1) @ Es2)\ = Es2\ \ (E # Es1)\" sorry qed - text {* The last proof involves several steps of equational reasoning. Isar provides some convenient means to express such equational @@ -694,7 +717,6 @@ construction. *} - lemma shows "(Es1 @ Es2)\ = (Es2\) \ (Es1\)" proof (induct Es1) @@ -703,14 +725,14 @@ next case (Cons E Es1) have ih: "(Es1 @ Es2)\ = Es2\ \ Es1\" by fact - have "((E # Es1) @ Es2)\ = (Es1 @ Es2)\ \ E" by simp + have "((E # Es1) @ Es2)\ = (E # (Es1 @ Es2))\" by simp + also have "\ = (Es1 @ Es2)\ \ E" by simp also have "\ = (Es2\ \ Es1\) \ E" using ih by simp - also have "\ = Es2\ \ (Es1\ \ E)" using odot_assoc by simp + also have "\ = Es2\ \ (Es1\ \ E)" using compose_assoc by simp also have "\ = Es2\ \ (E # Es1)\" by simp finally show "((E # Es1) @ Es2)\ = Es2\ \ (E # Es1)\" by simp qed - end