17 The type of boolean values is a predefined datatype |
17 The type of boolean values is a predefined datatype |
18 @{datatype[display] bool} |
18 @{datatype[display] bool} |
19 with the two values \indexed{@{const True}}{True} and \indexed{@{const False}}{False} and |
19 with the two values \indexed{@{const True}}{True} and \indexed{@{const False}}{False} and |
20 with many predefined functions: @{text "\<not>"}, @{text "\<and>"}, @{text "\<or>"}, @{text |
20 with many predefined functions: @{text "\<not>"}, @{text "\<and>"}, @{text "\<or>"}, @{text |
21 "\<longrightarrow>"}, etc. Here is how conjunction could be defined by pattern matching: |
21 "\<longrightarrow>"}, etc. Here is how conjunction could be defined by pattern matching: |
22 *} |
22 \<close> |
23 |
23 |
24 fun conj :: "bool \<Rightarrow> bool \<Rightarrow> bool" where |
24 fun conj :: "bool \<Rightarrow> bool \<Rightarrow> bool" where |
25 "conj True True = True" | |
25 "conj True True = True" | |
26 "conj _ _ = False" |
26 "conj _ _ = False" |
27 |
27 |
28 text{* Both the datatype and function definitions roughly follow the syntax |
28 text\<open>Both the datatype and function definitions roughly follow the syntax |
29 of functional programming languages. |
29 of functional programming languages. |
30 |
30 |
31 \subsection{Type \indexed{@{typ nat}}{nat}} |
31 \subsection{Type \indexed{@{typ nat}}{nat}} |
32 |
32 |
33 Natural numbers are another predefined datatype: |
33 Natural numbers are another predefined datatype: |
35 All values of type @{typ nat} are generated by the constructors |
35 All values of type @{typ nat} are generated by the constructors |
36 @{text 0} and @{const Suc}. Thus the values of type @{typ nat} are |
36 @{text 0} and @{const Suc}. Thus the values of type @{typ nat} are |
37 @{text 0}, @{term"Suc 0"}, @{term"Suc(Suc 0)"}, etc. |
37 @{text 0}, @{term"Suc 0"}, @{term"Suc(Suc 0)"}, etc. |
38 There are many predefined functions: @{text "+"}, @{text "*"}, @{text |
38 There are many predefined functions: @{text "+"}, @{text "*"}, @{text |
39 "\<le>"}, etc. Here is how you could define your own addition: |
39 "\<le>"}, etc. Here is how you could define your own addition: |
40 *} |
40 \<close> |
41 |
41 |
42 fun add :: "nat \<Rightarrow> nat \<Rightarrow> nat" where |
42 fun add :: "nat \<Rightarrow> nat \<Rightarrow> nat" where |
43 "add 0 n = n" | |
43 "add 0 n = n" | |
44 "add (Suc m) n = Suc(add m n)" |
44 "add (Suc m) n = Suc(add m n)" |
45 |
45 |
46 text{* And here is a proof of the fact that @{prop"add m 0 = m"}: *} |
46 text\<open>And here is a proof of the fact that @{prop"add m 0 = m"}:\<close> |
47 |
47 |
48 lemma add_02: "add m 0 = m" |
48 lemma add_02: "add m 0 = m" |
49 apply(induction m) |
49 apply(induction m) |
50 apply(auto) |
50 apply(auto) |
51 done |
51 done |
52 (*<*) |
52 (*<*) |
53 lemma "add m 0 = m" |
53 lemma "add m 0 = m" |
54 apply(induction m) |
54 apply(induction m) |
55 (*>*) |
55 (*>*) |
56 txt{* The \isacom{lemma} command starts the proof and gives the lemma |
56 txt\<open>The \isacom{lemma} command starts the proof and gives the lemma |
57 a name, @{text add_02}. Properties of recursively defined functions |
57 a name, @{text add_02}. Properties of recursively defined functions |
58 need to be established by induction in most cases. |
58 need to be established by induction in most cases. |
59 Command \isacom{apply}@{text"(induction m)"} instructs Isabelle to |
59 Command \isacom{apply}@{text"(induction m)"} instructs Isabelle to |
60 start a proof by induction on @{text m}. In response, it will show the |
60 start a proof by induction on @{text m}. In response, it will show the |
61 following proof state\ifsem\footnote{See page \pageref{proof-state} for how to |
61 following proof state\ifsem\footnote{See page \pageref{proof-state} for how to |
73 using first the definition of @{const add} and then the induction hypothesis. |
73 using first the definition of @{const add} and then the induction hypothesis. |
74 In summary, both subproofs rely on simplification with function definitions and |
74 In summary, both subproofs rely on simplification with function definitions and |
75 the induction hypothesis. |
75 the induction hypothesis. |
76 As a result of that final \isacom{done}, Isabelle associates the lemma |
76 As a result of that final \isacom{done}, Isabelle associates the lemma |
77 just proved with its name. You can now inspect the lemma with the command |
77 just proved with its name. You can now inspect the lemma with the command |
78 *} |
78 \<close> |
79 |
79 |
80 thm add_02 |
80 thm add_02 |
81 |
81 |
82 txt{* which displays @{thm[show_question_marks,display] add_02} The free |
82 txt\<open>which displays @{thm[show_question_marks,display] add_02} The free |
83 variable @{text m} has been replaced by the \concept{unknown} |
83 variable @{text m} has been replaced by the \concept{unknown} |
84 @{text"?m"}. There is no logical difference between the two but there is an |
84 @{text"?m"}. There is no logical difference between the two but there is an |
85 operational one: unknowns can be instantiated, which is what you want after |
85 operational one: unknowns can be instantiated, which is what you want after |
86 some lemma has been proved. |
86 some lemma has been proved. |
87 |
87 |
151 |
151 |
152 \subsection{Type \indexed{@{text list}}{list}} |
152 \subsection{Type \indexed{@{text list}}{list}} |
153 |
153 |
154 Although lists are already predefined, we define our own copy for |
154 Although lists are already predefined, we define our own copy for |
155 demonstration purposes: |
155 demonstration purposes: |
156 *} |
156 \<close> |
157 (*<*) |
157 (*<*) |
158 apply(auto) |
158 apply(auto) |
159 done |
159 done |
160 declare [[names_short]] |
160 declare [[names_short]] |
161 (*>*) |
161 (*>*) |
162 datatype 'a list = Nil | Cons 'a "'a list" |
162 datatype 'a list = Nil | Cons 'a "'a list" |
163 (*<*) |
163 (*<*) |
164 for map: map |
164 for map: map |
165 (*>*) |
165 (*>*) |
166 |
166 |
167 text{* |
167 text\<open> |
168 \begin{itemize} |
168 \begin{itemize} |
169 \item Type @{typ "'a list"} is the type of lists over elements of type @{typ 'a}. Because @{typ 'a} is a type variable, lists are in fact \concept{polymorphic}: the elements of a list can be of arbitrary type (but must all be of the same type). |
169 \item Type @{typ "'a list"} is the type of lists over elements of type @{typ 'a}. Because @{typ 'a} is a type variable, lists are in fact \concept{polymorphic}: the elements of a list can be of arbitrary type (but must all be of the same type). |
170 \item Lists have two constructors: @{const Nil}, the empty list, and @{const Cons}, which puts an element (of type @{typ 'a}) in front of a list (of type @{typ "'a list"}). |
170 \item Lists have two constructors: @{const Nil}, the empty list, and @{const Cons}, which puts an element (of type @{typ 'a}) in front of a list (of type @{typ "'a list"}). |
171 Hence all lists are of the form @{const Nil}, or @{term"Cons x Nil"}, |
171 Hence all lists are of the form @{const Nil}, or @{term"Cons x Nil"}, |
172 or @{term"Cons x (Cons y Nil)"}, etc. |
172 or @{term"Cons x (Cons y Nil)"}, etc. |
173 \item \isacom{datatype} requires no quotation marks on the |
173 \item \isacom{datatype} requires no quotation marks on the |
174 left-hand side, but on the right-hand side each of the argument |
174 left-hand side, but on the right-hand side each of the argument |
175 types of a constructor needs to be enclosed in quotation marks, unless |
175 types of a constructor needs to be enclosed in quotation marks, unless |
176 it is just an identifier (e.g., @{typ nat} or @{typ 'a}). |
176 it is just an identifier (e.g., @{typ nat} or @{typ 'a}). |
177 \end{itemize} |
177 \end{itemize} |
178 We also define two standard functions, append and reverse: *} |
178 We also define two standard functions, append and reverse:\<close> |
179 |
179 |
180 fun app :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
180 fun app :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
181 "app Nil ys = ys" | |
181 "app Nil ys = ys" | |
182 "app (Cons x xs) ys = Cons x (app xs ys)" |
182 "app (Cons x xs) ys = Cons x (app xs ys)" |
183 |
183 |
184 fun rev :: "'a list \<Rightarrow> 'a list" where |
184 fun rev :: "'a list \<Rightarrow> 'a list" where |
185 "rev Nil = Nil" | |
185 "rev Nil = Nil" | |
186 "rev (Cons x xs) = app (rev xs) (Cons x Nil)" |
186 "rev (Cons x xs) = app (rev xs) (Cons x Nil)" |
187 |
187 |
188 text{* By default, variables @{text xs}, @{text ys} and @{text zs} are of |
188 text\<open>By default, variables @{text xs}, @{text ys} and @{text zs} are of |
189 @{text list} type. |
189 @{text list} type. |
190 |
190 |
191 Command \indexed{\isacommand{value}}{value} evaluates a term. For example, *} |
191 Command \indexed{\isacommand{value}}{value} evaluates a term. For example,\<close> |
192 |
192 |
193 value "rev(Cons True (Cons False Nil))" |
193 value "rev(Cons True (Cons False Nil))" |
194 |
194 |
195 text{* yields the result @{value "rev(Cons True (Cons False Nil))"}. This works symbolically, too: *} |
195 text\<open>yields the result @{value "rev(Cons True (Cons False Nil))"}. This works symbolically, too:\<close> |
196 |
196 |
197 value "rev(Cons a (Cons b Nil))" |
197 value "rev(Cons a (Cons b Nil))" |
198 |
198 |
199 text{* yields @{value "rev(Cons a (Cons b Nil))"}. |
199 text\<open>yields @{value "rev(Cons a (Cons b Nil))"}. |
200 \medskip |
200 \medskip |
201 |
201 |
202 Figure~\ref{fig:MyList} shows the theory created so far. |
202 Figure~\ref{fig:MyList} shows the theory created so far. |
203 Because @{text list}, @{const Nil}, @{const Cons}, etc.\ are already predefined, |
203 Because @{text list}, @{const Nil}, @{const Cons}, etc.\ are already predefined, |
204 Isabelle prints qualified (long) names when executing this theory, for example, @{text MyList.Nil} |
204 Isabelle prints qualified (long) names when executing this theory, for example, @{text MyList.Nil} |
236 \subsection{The Proof Process} |
236 \subsection{The Proof Process} |
237 |
237 |
238 We will now demonstrate the typical proof process, which involves |
238 We will now demonstrate the typical proof process, which involves |
239 the formulation and proof of auxiliary lemmas. |
239 the formulation and proof of auxiliary lemmas. |
240 Our goal is to show that reversing a list twice produces the original |
240 Our goal is to show that reversing a list twice produces the original |
241 list. *} |
241 list.\<close> |
242 |
242 |
243 theorem rev_rev [simp]: "rev(rev xs) = xs" |
243 theorem rev_rev [simp]: "rev(rev xs) = xs" |
244 |
244 |
245 txt{* Commands \isacom{theorem} and \isacom{lemma} are |
245 txt\<open>Commands \isacom{theorem} and \isacom{lemma} are |
246 interchangeable and merely indicate the importance we attach to a |
246 interchangeable and merely indicate the importance we attach to a |
247 proposition. Via the bracketed attribute @{text simp} we also tell Isabelle |
247 proposition. Via the bracketed attribute @{text simp} we also tell Isabelle |
248 to make the eventual theorem a \conceptnoidx{simplification rule}: future proofs |
248 to make the eventual theorem a \conceptnoidx{simplification rule}: future proofs |
249 involving simplification will replace occurrences of @{term"rev(rev xs)"} by |
249 involving simplification will replace occurrences of @{term"rev(rev xs)"} by |
250 @{term"xs"}. The proof is by induction: *} |
250 @{term"xs"}. The proof is by induction:\<close> |
251 |
251 |
252 apply(induction xs) |
252 apply(induction xs) |
253 |
253 |
254 txt{* |
254 txt\<open> |
255 As explained above, we obtain two subgoals, namely the base case (@{const Nil}) and the induction step (@{const Cons}): |
255 As explained above, we obtain two subgoals, namely the base case (@{const Nil}) and the induction step (@{const Cons}): |
256 @{subgoals[display,indent=0,margin=65]} |
256 @{subgoals[display,indent=0,margin=65]} |
257 Let us try to solve both goals automatically: |
257 Let us try to solve both goals automatically: |
258 *} |
258 \<close> |
259 |
259 |
260 apply(auto) |
260 apply(auto) |
261 |
261 |
262 txt{*Subgoal~1 is proved, and disappears; the simplified version |
262 txt\<open>Subgoal~1 is proved, and disappears; the simplified version |
263 of subgoal~2 becomes the new subgoal~1: |
263 of subgoal~2 becomes the new subgoal~1: |
264 @{subgoals[display,indent=0,margin=70]} |
264 @{subgoals[display,indent=0,margin=70]} |
265 In order to simplify this subgoal further, a lemma suggests itself. |
265 In order to simplify this subgoal further, a lemma suggests itself. |
266 |
266 |
267 \subsubsection{A First Lemma} |
267 \subsubsection{A First Lemma} |
268 |
268 |
269 We insert the following lemma in front of the main theorem: |
269 We insert the following lemma in front of the main theorem: |
270 *} |
270 \<close> |
271 (*<*) |
271 (*<*) |
272 oops |
272 oops |
273 (*>*) |
273 (*>*) |
274 lemma rev_app [simp]: "rev(app xs ys) = app (rev ys) (rev xs)" |
274 lemma rev_app [simp]: "rev(app xs ys) = app (rev ys) (rev xs)" |
275 |
275 |
276 txt{* There are two variables that we could induct on: @{text xs} and |
276 txt\<open>There are two variables that we could induct on: @{text xs} and |
277 @{text ys}. Because @{const app} is defined by recursion on |
277 @{text ys}. Because @{const app} is defined by recursion on |
278 the first argument, @{text xs} is the correct one: |
278 the first argument, @{text xs} is the correct one: |
279 *} |
279 \<close> |
280 |
280 |
281 apply(induction xs) |
281 apply(induction xs) |
282 |
282 |
283 txt{* This time not even the base case is solved automatically: *} |
283 txt\<open>This time not even the base case is solved automatically:\<close> |
284 apply(auto) |
284 apply(auto) |
285 txt{* |
285 txt\<open> |
286 \vspace{-5ex} |
286 \vspace{-5ex} |
287 @{subgoals[display,goals_limit=1]} |
287 @{subgoals[display,goals_limit=1]} |
288 Again, we need to abandon this proof attempt and prove another simple lemma |
288 Again, we need to abandon this proof attempt and prove another simple lemma |
289 first. |
289 first. |
290 |
290 |
291 \subsubsection{A Second Lemma} |
291 \subsubsection{A Second Lemma} |
292 |
292 |
293 We again try the canonical proof procedure: |
293 We again try the canonical proof procedure: |
294 *} |
294 \<close> |
295 (*<*) |
295 (*<*) |
296 oops |
296 oops |
297 (*>*) |
297 (*>*) |
298 lemma app_Nil2 [simp]: "app xs Nil = xs" |
298 lemma app_Nil2 [simp]: "app xs Nil = xs" |
299 apply(induction xs) |
299 apply(induction xs) |
300 apply(auto) |
300 apply(auto) |
301 done |
301 done |
302 |
302 |
303 text{* |
303 text\<open> |
304 Thankfully, this worked. |
304 Thankfully, this worked. |
305 Now we can continue with our stuck proof attempt of the first lemma: |
305 Now we can continue with our stuck proof attempt of the first lemma: |
306 *} |
306 \<close> |
307 |
307 |
308 lemma rev_app [simp]: "rev(app xs ys) = app (rev ys) (rev xs)" |
308 lemma rev_app [simp]: "rev(app xs ys) = app (rev ys) (rev xs)" |
309 apply(induction xs) |
309 apply(induction xs) |
310 apply(auto) |
310 apply(auto) |
311 |
311 |
312 txt{* |
312 txt\<open> |
313 We find that this time @{text"auto"} solves the base case, but the |
313 We find that this time @{text"auto"} solves the base case, but the |
314 induction step merely simplifies to |
314 induction step merely simplifies to |
315 @{subgoals[display,indent=0,goals_limit=1]} |
315 @{subgoals[display,indent=0,goals_limit=1]} |
316 The missing lemma is associativity of @{const app}, |
316 The missing lemma is associativity of @{const app}, |
317 which we insert in front of the failed lemma @{text rev_app}. |
317 which we insert in front of the failed lemma @{text rev_app}. |
318 |
318 |
319 \subsubsection{Associativity of @{const app}} |
319 \subsubsection{Associativity of @{const app}} |
320 |
320 |
321 The canonical proof procedure succeeds without further ado: |
321 The canonical proof procedure succeeds without further ado: |
322 *} |
322 \<close> |
323 (*<*)oops(*>*) |
323 (*<*)oops(*>*) |
324 lemma app_assoc [simp]: "app (app xs ys) zs = app xs (app ys zs)" |
324 lemma app_assoc [simp]: "app (app xs ys) zs = app xs (app ys zs)" |
325 apply(induction xs) |
325 apply(induction xs) |
326 apply(auto) |
326 apply(auto) |
327 done |
327 done |