25 | "fib (Suc (Suc n)) = fib n + fib (Suc n)" |
22 | "fib (Suc (Suc n)) = fib n + fib (Suc n)" |
26 |
23 |
27 text {* |
24 text {* |
28 The syntax is rather self-explanatory: We introduce a function by |
25 The syntax is rather self-explanatory: We introduce a function by |
29 giving its name, its type and a set of defining recursive |
26 giving its name, its type and a set of defining recursive |
30 equations. |
27 equations. Note that the function is not primitive recursive. |
31 *} |
28 *} |
32 |
|
33 |
|
34 |
|
35 |
|
36 |
29 |
37 text {* |
30 text {* |
38 The function always terminates, since its argument gets smaller in |
31 The function always terminates, since its argument gets smaller in |
39 every recursive call. Termination is an important requirement, since |
32 every recursive call. |
40 it prevents inconsistencies: From the "definition" @{text "f(n) = |
33 Since HOL is a logic of total functions, termination is a |
41 f(n) + 1"} we could prove @{text "0 = 1"} by subtracting @{text |
34 fundamental requirement to prevent inconsistencies\footnote{From the |
42 "f(n)"} on both sides. |
35 \qt{definition} @{text "f(n) = f(n) + 1"} we could prove |
43 |
36 @{text "0 = 1"} by subtracting @{text "f(n)"} on both sides.}. |
44 Isabelle tries to prove termination automatically when a function is |
37 |
45 defined. We will later look at cases where this fails and see what to |
38 Isabelle tries to prove termination automatically when a definition |
46 do then. |
39 is made. In \S\ref{termination}, we will look at cases where this |
|
40 fails and see what to do then. |
47 *} |
41 *} |
48 |
42 |
49 subsection {* Pattern matching *} |
43 subsection {* Pattern matching *} |
50 |
44 |
51 text {* \label{patmatch} |
45 text {* \label{patmatch} |
52 Like in functional programming, we can use pattern matching to |
46 Like in functional programming, we can use pattern matching to |
53 define functions. At the moment we will only consider \emph{constructor |
47 define functions. At the moment we will only consider \emph{constructor |
54 patterns}, which only consist of datatype constructors and |
48 patterns}, which only consist of datatype constructors and |
55 variables. |
49 (linear occurrences of) variables. |
56 |
50 |
57 If patterns overlap, the order of the equations is taken into |
51 If patterns overlap, the order of the equations is taken into |
58 account. The following function inserts a fixed element between any |
52 account. The following function inserts a fixed element between any |
59 two elements of a list: |
53 two elements of a list: |
60 *} |
54 *} |
78 text {* |
72 text {* |
79 The equations from function definitions are automatically used in |
73 The equations from function definitions are automatically used in |
80 simplification: |
74 simplification: |
81 *} |
75 *} |
82 |
76 |
83 lemma "sep (0::nat) [1, 2, 3] = [1, 0, 2, 0, 3]" |
77 lemma "sep 0 [1, 2, 3] = [1, 0, 2, 0, 3]" |
84 by simp |
78 by simp |
85 |
79 |
86 subsection {* Induction *} |
80 subsection {* Induction *} |
87 |
81 |
88 text {* |
82 text {* |
89 |
83 |
90 Isabelle provides customized induction rules for recursive functions. |
84 Isabelle provides customized induction rules for recursive functions. |
91 See \cite[\S3.5.4]{isa-tutorial}. |
85 See \cite[\S3.5.4]{isa-tutorial}. \fixme{Cases?} |
92 *} |
86 |
93 |
87 |
94 |
88 With the \cmd{fun} command, you can define about 80\% of the |
95 section {* Full form definitions *} |
89 functions that occur in practice. The rest of this tutorial explains |
|
90 the remaining 20\%. |
|
91 *} |
|
92 |
|
93 |
|
94 section {* fun vs.\ function *} |
96 |
95 |
97 text {* |
96 text {* |
98 Up to now, we were using the \cmd{fun} command, which provides a |
97 The \cmd{fun} command provides a |
99 convenient shorthand notation for simple function definitions. In |
98 convenient shorthand notation for simple function definitions. In |
100 this mode, Isabelle tries to solve all the necessary proof obligations |
99 this mode, Isabelle tries to solve all the necessary proof obligations |
101 automatically. If a proof does not go through, the definition is |
100 automatically. If a proof fails, the definition is |
102 rejected. This can either mean that the definition is indeed faulty, |
101 rejected. This can either mean that the definition is indeed faulty, |
103 or that the default proof procedures are just not smart enough (or |
102 or that the default proof procedures are just not smart enough (or |
104 rather: not designed) to handle the definition. |
103 rather: not designed) to handle the definition. |
105 |
104 |
106 By expanding the abbreviated \cmd{fun} to the full \cmd{function} |
105 By expanding the abbreviation to the more verbose \cmd{function} command, these proof obligations become visible and can be analyzed or |
107 command, the proof obligations become visible and can be analyzed or |
106 solved manually. The expansion from \cmd{fun} to \cmd{function} is as follows: |
108 solved manually. |
|
109 |
107 |
110 \end{isamarkuptext} |
108 \end{isamarkuptext} |
111 |
109 |
112 |
110 |
113 \fbox{\parbox{\textwidth}{ |
111 \[\left[\;\begin{minipage}{0.25\textwidth}\vspace{6pt} |
114 \noindent\cmd{fun} @{text "f :: \<tau>"}\\% |
112 \cmd{fun} @{text "f :: \<tau>"}\\% |
115 \cmd{where}\isanewline% |
113 \cmd{where}\\% |
116 \ \ {\it equations}\isanewline% |
114 \hspace*{2ex}{\it equations}\\% |
117 \ \ \quad\vdots |
115 \hspace*{2ex}\vdots\vspace*{6pt} |
118 }} |
116 \end{minipage}\right] |
119 |
117 \quad\equiv\quad |
120 \begin{isamarkuptext} |
118 \left[\;\begin{minipage}{0.45\textwidth}\vspace{6pt} |
121 \vspace*{1em} |
119 \cmd{function} @{text "("}\cmd{sequential}@{text ") f :: \<tau>"}\\% |
122 \noindent abbreviates |
120 \cmd{where}\\% |
123 \end{isamarkuptext} |
121 \hspace*{2ex}{\it equations}\\% |
124 |
122 \hspace*{2ex}\vdots\\% |
125 \fbox{\parbox{\textwidth}{ |
|
126 \noindent\cmd{function} @{text "("}\cmd{sequential}@{text ") f :: \<tau>"}\\% |
|
127 \cmd{where}\isanewline% |
|
128 \ \ {\it equations}\isanewline% |
|
129 \ \ \quad\vdots\\% |
|
130 \cmd{by} @{text "pat_completeness auto"}\\% |
123 \cmd{by} @{text "pat_completeness auto"}\\% |
131 \cmd{termination by} @{text "lexicographic_order"} |
124 \cmd{termination by} @{text "lexicographic_order"}\vspace{6pt} |
132 }} |
125 \end{minipage} |
|
126 \right]\] |
133 |
127 |
134 \begin{isamarkuptext} |
128 \begin{isamarkuptext} |
135 \vspace*{1em} |
129 \vspace*{1em} |
136 \noindent Some declarations and proofs have now become explicit: |
130 \noindent Some details have now become explicit: |
137 |
131 |
138 \begin{enumerate} |
132 \begin{enumerate} |
139 \item The \cmd{sequential} option enables the preprocessing of |
133 \item The \cmd{sequential} option enables the preprocessing of |
140 pattern overlaps we already saw. Without this option, the equations |
134 pattern overlaps we already saw. Without this option, the equations |
141 must already be disjoint and complete. The automatic completion only |
135 must already be disjoint and complete. The automatic completion only |
142 works with datatype patterns. |
136 works with constructor patterns. |
143 |
137 |
144 \item A function definition now produces a proof obligation which |
138 \item A function definition produces a proof obligation which |
145 expresses completeness and compatibility of patterns (We talk about |
139 expresses completeness and compatibility of patterns (we talk about |
146 this later). The combination of the methods @{text "pat_completeness"} and |
140 this later). The combination of the methods @{text "pat_completeness"} and |
147 @{text "auto"} is used to solve this proof obligation. |
141 @{text "auto"} is used to solve this proof obligation. |
148 |
142 |
149 \item A termination proof follows the definition, started by the |
143 \item A termination proof follows the definition, started by the |
150 \cmd{termination} command, which sets up the goal. The @{text |
144 \cmd{termination} command. This will be explained in \S\ref{termination}. |
151 "lexicographic_order"} method can prove termination of a certain |
|
152 class of functions by searching for a suitable lexicographic |
|
153 combination of size measures. |
|
154 \end{enumerate} |
145 \end{enumerate} |
155 Whenever a \cmd{fun} command fails, it is usually a good idea to |
146 Whenever a \cmd{fun} command fails, it is usually a good idea to |
156 expand the syntax to the more verbose \cmd{function} form, to see |
147 expand the syntax to the more verbose \cmd{function} form, to see |
157 what is actually going on. |
148 what is actually going on. |
158 *} |
149 *} |
159 |
150 |
160 |
151 |
161 section {* Proving termination *} |
152 section {* Termination *} |
162 |
153 |
163 text {* |
154 text {*\label{termination} |
|
155 The @{text "lexicographic_order"} method can prove termination of a |
|
156 certain class of functions by searching for a suitable lexicographic |
|
157 combination of size measures. Of course, not all functions have such |
|
158 a simple termination argument. |
|
159 *} |
|
160 |
|
161 subsection {* The {\tt relation} method *} |
|
162 text{* |
164 Consider the following function, which sums up natural numbers up to |
163 Consider the following function, which sums up natural numbers up to |
165 @{text "N"}, using a counter @{text "i"}: |
164 @{text "N"}, using a counter @{text "i"}: |
166 *} |
165 *} |
167 |
166 |
168 function sum :: "nat \<Rightarrow> nat \<Rightarrow> nat" |
167 function sum :: "nat \<Rightarrow> nat \<Rightarrow> nat" |
186 |
186 |
187 We can use this expression as a measure function suitable to prove termination. |
187 We can use this expression as a measure function suitable to prove termination. |
188 *} |
188 *} |
189 |
189 |
190 termination sum |
190 termination sum |
191 by (relation "measure (\<lambda>(i,N). N + 1 - i)") auto |
191 apply (relation "measure (\<lambda>(i,N). N + 1 - i)") |
192 |
192 |
193 text {* |
193 txt {* |
194 The \cmd{termination} command sets up the termination goal for the |
194 The \cmd{termination} command sets up the termination goal for the |
195 specified function @{text "sum"}. If the function name is omitted it |
195 specified function @{text "sum"}. If the function name is omitted, it |
196 implicitly refers to the last function definition. |
196 implicitly refers to the last function definition. |
197 |
197 |
198 The @{text relation} method takes a relation of |
198 The @{text relation} method takes a relation of |
199 type @{typ "('a \<times> 'a) set"}, where @{typ "'a"} is the argument type of |
199 type @{typ "('a \<times> 'a) set"}, where @{typ "'a"} is the argument type of |
200 the function. If the function has multiple curried arguments, then |
200 the function. If the function has multiple curried arguments, then |
201 these are packed together into a tuple, as it happened in the above |
201 these are packed together into a tuple, as it happened in the above |
202 example. |
202 example. |
203 |
203 |
204 The predefined function @{term_type "measure"} is a very common way of |
204 The predefined function @{term_type "measure"} constructs a |
205 specifying termination relations in terms of a mapping into the |
205 wellfounded relation from a mapping into the natural numbers (a |
206 natural numbers. |
206 \emph{measure function}). |
207 |
207 |
208 After the invocation of @{text "relation"}, we must prove that (a) |
208 After the invocation of @{text "relation"}, we must prove that (a) |
209 the relation we supplied is wellfounded, and (b) that the arguments |
209 the relation we supplied is wellfounded, and (b) that the arguments |
210 of recursive calls indeed decrease with respect to the |
210 of recursive calls indeed decrease with respect to the |
211 relation. These goals are all solved by the subsequent call to |
211 relation: |
212 @{text "auto"}. |
212 |
213 |
213 @{subgoals[display,indent=0]} |
|
214 |
|
215 These goals are all solved by @{text "auto"}: |
|
216 *} |
|
217 |
|
218 apply auto |
|
219 done |
|
220 |
|
221 text {* |
214 Let us complicate the function a little, by adding some more |
222 Let us complicate the function a little, by adding some more |
215 recursive calls: |
223 recursive calls: |
216 *} |
224 *} |
217 |
225 |
218 function foo :: "nat \<Rightarrow> nat \<Rightarrow> nat" |
226 function foo :: "nat \<Rightarrow> nat \<Rightarrow> nat" |
234 *} |
242 *} |
235 |
243 |
236 termination |
244 termination |
237 by (relation "measures [\<lambda>(i, N). N, \<lambda>(i,N). N + 1 - i]") auto |
245 by (relation "measures [\<lambda>(i, N). N, \<lambda>(i,N). N + 1 - i]") auto |
238 |
246 |
239 subsection {* Manual Termination Proofs *} |
247 subsection {* How @{text "lexicographic_order"} works *} |
240 |
248 |
241 text {* |
249 (*fun fails :: "nat \<Rightarrow> nat list \<Rightarrow> nat" |
242 The @{text relation} method is often useful, but not |
250 where |
243 necessary. Since termination proofs are just normal Isabelle proofs, |
251 "fails a [] = a" |
244 they can also be carried out manually: |
252 | "fails a (x#xs) = fails (x + a) (x # xs)" |
245 *} |
253 *) |
246 |
254 |
247 function id :: "nat \<Rightarrow> nat" |
255 text {* |
248 where |
256 To see how the automatic termination proofs work, let's look at an |
249 "id 0 = 0" |
257 example where it fails\footnote{For a detailed discussion of the |
250 | "id (Suc n) = Suc (id n)" |
258 termination prover, see \cite{bulwahnKN07}}: |
|
259 |
|
260 \end{isamarkuptext} |
|
261 \cmd{fun} @{text "fails :: \"nat \<Rightarrow> nat list \<Rightarrow> nat\""}\\% |
|
262 \cmd{where}\\% |
|
263 \hspace*{2ex}@{text "\"fails a [] = a\""}\\% |
|
264 |\hspace*{1.5ex}@{text "\"fails a (x#xs) = fails (x + a) (x#xs)\""}\\ |
|
265 \begin{isamarkuptext} |
|
266 |
|
267 \noindent Isabelle responds with the following error: |
|
268 |
|
269 \begin{isabelle} |
|
270 *** Could not find lexicographic termination order:\newline |
|
271 *** \ \ \ \ 1\ \ 2 \newline |
|
272 *** a: N <= \newline |
|
273 *** Calls:\newline |
|
274 *** a) @{text "(a, x # xs) -->> (x + a, x # xs)"}\newline |
|
275 *** Measures:\newline |
|
276 *** 1) @{text "\<lambda>x. size (fst x)"}\newline |
|
277 *** 2) @{text "\<lambda>x. size (snd x)"}\newline |
|
278 *** Unfinished subgoals:\newline |
|
279 *** @{text "\<And>a x xs."}\newline |
|
280 *** \quad @{text "(x. size (fst x)) (x + a, x # xs)"}\newline |
|
281 *** \quad @{text "\<le> (\<lambda>x. size (fst x)) (a, x # xs)"}\newline |
|
282 *** @{text "1. \<And>x. x = 0"}\newline |
|
283 *** At command "fun".\newline |
|
284 \end{isabelle} |
|
285 *} |
|
286 |
|
287 |
|
288 text {* |
|
289 |
|
290 |
|
291 The the key to this error message is the matrix at the top. The rows |
|
292 of that matrix correspond to the different recursive calls (In our |
|
293 case, there is just one). The columns are the function's arguments |
|
294 (expressed through different measure functions, which map the |
|
295 argument tuple to a natural number). |
|
296 |
|
297 The contents of the matrix summarize what is known about argument |
|
298 descents: The second argument has a weak descent (@{text "<="}) at the |
|
299 recursive call, and for the first argument nothing could be proved, |
|
300 which is expressed by @{text N}. In general, there are the values |
|
301 @{text "<"}, @{text "<="} and @{text "N"}. |
|
302 |
|
303 For the failed proof attempts, the unfinished subgoals are also |
|
304 printed. Looking at these will often point us to a missing lemma. |
|
305 |
|
306 % As a more real example, here is quicksort: |
|
307 *} |
|
308 (* |
|
309 function qs :: "nat list \<Rightarrow> nat list" |
|
310 where |
|
311 "qs [] = []" |
|
312 | "qs (x#xs) = qs [y\<in>xs. y < x] @ x # qs [y\<in>xs. y \<ge> x]" |
251 by pat_completeness auto |
313 by pat_completeness auto |
252 |
314 |
253 termination |
315 termination apply lexicographic_order |
254 proof |
316 |
255 show "wf less_than" .. |
317 text {* If we try @{text "lexicographic_order"} method, we get the |
256 next |
318 following error *} |
257 fix n show "(n, Suc n) \<in> less_than" by simp |
319 termination by (lexicographic_order simp:l2) |
258 qed |
320 |
259 |
321 lemma l: "x \<le> y \<Longrightarrow> x < Suc y" by arith |
260 text {* |
322 |
261 Of course this is just a trivial example, but manual proofs can |
323 function |
262 sometimes be the only choice if faced with very hard termination problems. |
324 |
263 *} |
325 *) |
264 |
|
265 |
326 |
266 section {* Mutual Recursion *} |
327 section {* Mutual Recursion *} |
267 |
328 |
268 text {* |
329 text {* |
269 If two or more functions call one another mutually, they have to be defined |
330 If two or more functions call one another mutually, they have to be defined |
270 in one step. The simplest example are probably @{text "even"} and @{text "odd"}: |
331 in one step. Here are @{text "even"} and @{text "odd"}: |
271 *} |
332 *} |
272 |
333 |
273 function even :: "nat \<Rightarrow> bool" |
334 function even :: "nat \<Rightarrow> bool" |
274 and odd :: "nat \<Rightarrow> bool" |
335 and odd :: "nat \<Rightarrow> bool" |
275 where |
336 where |
278 | "even (Suc n) = odd n" |
339 | "even (Suc n) = odd n" |
279 | "odd (Suc n) = even n" |
340 | "odd (Suc n) = even n" |
280 by pat_completeness auto |
341 by pat_completeness auto |
281 |
342 |
282 text {* |
343 text {* |
283 To solve the problem of mutual dependencies, Isabelle internally |
344 To eliminate the mutual dependencies, Isabelle internally |
284 creates a single function operating on the sum |
345 creates a single function operating on the sum |
285 type. Then the original functions are defined as |
346 type @{typ "nat + nat"}. Then, @{const even} and @{const odd} are |
286 projections. Consequently, termination has to be proved |
347 defined as projections. Consequently, termination has to be proved |
287 simultaneously for both functions, by specifying a measure on the |
348 simultaneously for both functions, by specifying a measure on the |
288 sum type: |
349 sum type: |
289 *} |
350 *} |
290 |
351 |
291 termination |
352 termination |
292 by (relation "measure (\<lambda>x. case x of Inl n \<Rightarrow> n | Inr n \<Rightarrow> n)") |
353 by (relation "measure (\<lambda>x. case x of Inl n \<Rightarrow> n | Inr n \<Rightarrow> n)") auto |
293 auto |
354 |
|
355 text {* |
|
356 We could also have used @{text lexicographic_order}, which |
|
357 supports mutual recursive termination proofs to a certain extent. |
|
358 *} |
294 |
359 |
295 subsection {* Induction for mutual recursion *} |
360 subsection {* Induction for mutual recursion *} |
296 |
361 |
297 text {* |
362 text {* |
298 |
363 |
299 When functions are mutually recursive, proving properties about them |
364 When functions are mutually recursive, proving properties about them |
300 generally requires simultaneous induction. The induction rules |
365 generally requires simultaneous induction. The induction rule @{text "even_odd.induct"} |
301 generated from the definitions reflect this. |
366 generated from the above definition reflects this. |
302 |
367 |
303 Let us prove something about @{const even} and @{const odd}: |
368 Let us prove something about @{const even} and @{const odd}: |
304 *} |
369 *} |
305 |
370 |
306 lemma |
371 lemma even_odd_mod2: |
307 "even n = (n mod 2 = 0)" |
372 "even n = (n mod 2 = 0)" |
308 "odd n = (n mod 2 = 1)" |
373 "odd n = (n mod 2 = 1)" |
309 |
374 |
310 txt {* |
375 txt {* |
311 We apply simultaneous induction, specifying the induction variable |
376 We apply simultaneous induction, specifying the induction variable |
325 |
390 |
326 txt {* |
391 txt {* |
327 @{subgoals[display,indent=0]} |
392 @{subgoals[display,indent=0]} |
328 |
393 |
329 \noindent These can be handeled by the descision procedure for |
394 \noindent These can be handeled by the descision procedure for |
330 presburger arithmethic. |
395 arithmethic. |
331 |
396 |
332 *} |
397 *} |
333 |
398 |
334 apply presburger |
399 apply presburger -- {* \fixme{arith} *} |
335 apply presburger |
400 apply presburger |
336 done |
401 done |
337 |
402 |
338 text {* |
403 text {* |
339 Even if we were just interested in one of the statements proved by |
404 In proofs like this, the simultaneous induction is really essential: |
340 simultaneous induction, the other ones may be necessary to |
405 Even if we are just interested in one of the results, the other |
341 strengthen the induction hypothesis. If we had left out the statement |
406 one is necessary to strengthen the induction hypothesis. If we leave |
342 about @{const odd} (by substituting it with @{term "True"}, our |
407 out the statement about @{const odd} (by substituting it with @{term |
343 proof would have failed: |
408 "True"}), the same proof fails: |
344 *} |
409 *} |
345 |
410 |
346 lemma |
411 lemma failed_attempt: |
347 "even n = (n mod 2 = 0)" |
412 "even n = (n mod 2 = 0)" |
348 "True" |
413 "True" |
349 apply (induct n rule: even_odd.induct) |
414 apply (induct n rule: even_odd.induct) |
350 |
415 |
351 txt {* |
416 txt {* |
352 \noindent Now the third subgoal is a dead end, since we have no |
417 \noindent Now the third subgoal is a dead end, since we have no |
353 useful induction hypothesis: |
418 useful induction hypothesis available: |
354 |
419 |
355 @{subgoals[display,indent=0]} |
420 @{subgoals[display,indent=0]} |
356 *} |
421 *} |
357 |
422 |
358 oops |
423 oops |
359 |
424 |
360 section {* More general patterns *} |
425 section {* General pattern matching *} |
361 |
426 |
362 subsection {* Avoiding pattern splitting *} |
427 subsection {* Avoiding automatic pattern splitting *} |
363 |
428 |
364 text {* |
429 text {* |
365 |
430 |
366 Up to now, we used pattern matching only on datatypes, and the |
431 Up to now, we used pattern matching only on datatypes, and the |
367 patterns were always disjoint and complete, and if they weren't, |
432 patterns were always disjoint and complete, and if they weren't, |
368 they were made disjoint automatically like in the definition of |
433 they were made disjoint automatically like in the definition of |
369 @{const "sep"} in \S\ref{patmatch}. |
434 @{const "sep"} in \S\ref{patmatch}. |
370 |
435 |
371 This splitting can significantly increase the number of equations |
436 This automatic splitting can significantly increase the number of |
372 involved, and is not always necessary. The following simple example |
437 equations involved, and this is not always desirable. The following |
373 shows the problem: |
438 example shows the problem: |
374 |
439 |
375 Suppose we are modelling incomplete knowledge about the world by a |
440 Suppose we are modelling incomplete knowledge about the world by a |
376 three-valued datatype, which has values @{term "T"}, @{term "F"} |
441 three-valued datatype, which has values @{term "T"}, @{term "F"} |
377 and @{term "X"} for true, false and uncertain propositions, respectively. |
442 and @{term "X"} for true, false and uncertain propositions, respectively. |
378 *} |
443 *} |
379 |
444 |
380 datatype P3 = T | F | X |
445 datatype P3 = T | F | X |
381 |
446 |
382 text {* Then the conjunction of such values can be defined as follows: *} |
447 text {* \noindent Then the conjunction of such values can be defined as follows: *} |
383 |
448 |
384 fun And :: "P3 \<Rightarrow> P3 \<Rightarrow> P3" |
449 fun And :: "P3 \<Rightarrow> P3 \<Rightarrow> P3" |
385 where |
450 where |
386 "And T p = p" |
451 "And T p = p" |
387 | "And p T = p" |
452 | "And p T = p" |
405 |
470 |
406 \vspace*{1em} |
471 \vspace*{1em} |
407 \noindent There are several problems with this: |
472 \noindent There are several problems with this: |
408 |
473 |
409 \begin{enumerate} |
474 \begin{enumerate} |
410 \item When datatypes have many constructors, there can be an |
475 \item If the datatype has many constructors, there can be an |
411 explosion of equations. For @{const "And"}, we get seven instead of |
476 explosion of equations. For @{const "And"}, we get seven instead of |
412 five equations, which can be tolerated, but this is just a small |
477 five equations, which can be tolerated, but this is just a small |
413 example. |
478 example. |
414 |
479 |
415 \item Since splitting makes the equations "less general", they |
480 \item Since splitting makes the equations \qt{less general}, they |
416 do not always match in rewriting. While the term @{term "And x F"} |
481 do not always match in rewriting. While the term @{term "And x F"} |
417 can be simplified to @{term "F"} by the original specification, a |
482 can be simplified to @{term "F"} with the original equations, a |
418 (manual) case split on @{term "x"} is now necessary. |
483 (manual) case split on @{term "x"} is now necessary. |
419 |
484 |
420 \item The splitting also concerns the induction rule @{text |
485 \item The splitting also concerns the induction rule @{text |
421 "And.induct"}. Instead of five premises it now has seven, which |
486 "And.induct"}. Instead of five premises it now has seven, which |
422 means that our induction proofs will have more cases. |
487 means that our induction proofs will have more cases. |
423 |
488 |
424 \item In general, it increases clarity if we get the same definition |
489 \item In general, it increases clarity if we get the same definition |
425 back which we put in. |
490 back which we put in. |
426 \end{enumerate} |
491 \end{enumerate} |
427 |
492 |
428 On the other hand, a definition needs to be consistent and defining |
493 If we do not want the automatic splitting, we can switch it off by |
429 both @{term "f x = True"} and @{term "f x = False"} is a bad |
494 leaving out the \cmd{sequential} option. However, we will have to |
430 idea. So if we don't want Isabelle to mangle our definitions, we |
495 prove that our pattern matching is consistent\footnote{This prevents |
431 will have to prove that this is not necessary. By using the full |
496 us from defining something like @{term "f x = True"} and @{term "f x |
432 definition form without the \cmd{sequential} option, we get this |
497 = False"} simultaneously.}: |
433 behaviour: |
|
434 *} |
498 *} |
435 |
499 |
436 function And2 :: "P3 \<Rightarrow> P3 \<Rightarrow> P3" |
500 function And2 :: "P3 \<Rightarrow> P3 \<Rightarrow> P3" |
437 where |
501 where |
438 "And2 T p = p" |
502 "And2 T p = p" |
440 | "And2 p F = F" |
504 | "And2 p F = F" |
441 | "And2 F p = F" |
505 | "And2 F p = F" |
442 | "And2 X X = X" |
506 | "And2 X X = X" |
443 |
507 |
444 txt {* |
508 txt {* |
445 Now it is also time to look at the subgoals generated by a |
509 \noindent Now let's look at the proof obligations generated by a |
446 function definition. In this case, they are: |
510 function definition. In this case, they are: |
447 |
511 |
448 @{subgoals[display,indent=0]} |
512 @{subgoals[display,indent=0]}\vspace{-1.2em}\hspace{3cm}\vdots\vspace{1.2em} |
449 |
513 |
450 The first subgoal expresses the completeness of the patterns. It has |
514 The first subgoal expresses the completeness of the patterns. It has |
451 the form of an elimination rule and states that every @{term x} of |
515 the form of an elimination rule and states that every @{term x} of |
452 the function's input type must match one of the patterns. It could |
516 the function's input type must match at least one of the patterns\footnote{Completeness could |
453 be equivalently stated as a disjunction of existential statements: |
517 be equivalently stated as a disjunction of existential statements: |
454 @{term "(\<exists>p. x = (T, p)) \<or> (\<exists>p. x = (p, T)) \<or> (\<exists>p. x = (p, F)) \<or> |
518 @{term "(\<exists>p. x = (T, p)) \<or> (\<exists>p. x = (p, T)) \<or> (\<exists>p. x = (p, F)) \<or> |
455 (\<exists>p. x = (F, p)) \<or> (x = (X, X))"} If the patterns just involve |
519 (\<exists>p. x = (F, p)) \<or> (x = (X, X))"}.}. If the patterns just involve |
456 datatypes, we can solve it with the @{text "pat_completeness"} method: |
520 datatypes, we can solve it with the @{text "pat_completeness"} |
|
521 method: |
457 *} |
522 *} |
458 |
523 |
459 apply pat_completeness |
524 apply pat_completeness |
460 |
525 |
461 txt {* |
526 txt {* |
462 The remaining subgoals express \emph{pattern compatibility}. We do |
527 The remaining subgoals express \emph{pattern compatibility}. We do |
463 allow that a value is matched by more than one patterns, but in this |
528 allow that an input value matches multiple patterns, but in this |
464 case, the result (i.e.~the right hand sides of the equations) must |
529 case, the result (i.e.~the right hand sides of the equations) must |
465 also be equal. For each pair of two patterns, there is one such |
530 also be equal. For each pair of two patterns, there is one such |
466 subgoal. Usually this needs injectivity of the constructors, which |
531 subgoal. Usually this needs injectivity of the constructors, which |
467 is used automatically by @{text "auto"}. |
532 is used automatically by @{text "auto"}. |
468 *} |
533 *} |
470 by auto |
535 by auto |
471 |
536 |
472 |
537 |
473 subsection {* Non-constructor patterns *} |
538 subsection {* Non-constructor patterns *} |
474 |
539 |
475 text {* FIXME *} |
540 text {* |
476 |
541 Most of Isabelle's basic types take the form of inductive data types |
477 |
542 with constructors. However, this is not true for all of them. The |
|
543 integers, for instance, are defined using the usual algebraic |
|
544 quotient construction, thus they are not an \qt{official} datatype. |
|
545 |
|
546 Of course, we might want to do pattern matching there, too. So |
|
547 |
|
548 |
|
549 |
|
550 *} |
|
551 |
|
552 function Abs :: "int \<Rightarrow> nat" |
|
553 where |
|
554 "Abs (int n) = n" |
|
555 | "Abs (- int (Suc n)) = n" |
|
556 by (erule int_cases) auto |
|
557 termination by (relation "{}") simp |
|
558 |
|
559 text {* |
|
560 This kind of matching is again justified by the proof of pattern |
|
561 completeness and compatibility. Here, the existing lemma @{text |
|
562 int_cases} is used: |
|
563 |
|
564 \begin{center}@{thm int_cases}\hfill(@{text "int_cases"})\end{center} |
|
565 *} |
|
566 text {* |
|
567 One well-known instance of non-constructor patterns are the |
|
568 so-called \emph{$n+k$-patterns}, which are a little controversial in |
|
569 the functional programming world. Here is the initial fibonacci |
|
570 example with $n+k$-patterns: |
|
571 *} |
|
572 |
|
573 function fib2 :: "nat \<Rightarrow> nat" |
|
574 where |
|
575 "fib2 0 = 1" |
|
576 | "fib2 1 = 1" |
|
577 | "fib2 (n + 2) = fib2 n + fib2 (Suc n)" |
|
578 |
|
579 (*<*)ML "goals_limit := 1"(*>*) |
|
580 txt {* |
|
581 The proof obligation for pattern completeness states that every natural number is |
|
582 either @{term "0::nat"}, @{term "1::nat"} or @{term "n + |
|
583 (2::nat)"}: |
|
584 |
|
585 @{subgoals[display,indent=0]} |
|
586 |
|
587 This is an arithmetic triviality, but unfortunately the |
|
588 @{text arith} method cannot handle this specific form of an |
|
589 elimination rule. We have to do a case split on @{text P} first, |
|
590 which can be conveniently done using the @{text |
|
591 classical} rule. Pattern compatibility and termination are automatic as usual. |
|
592 *} |
|
593 (*<*)ML "goals_limit := 10"(*>*) |
|
594 |
|
595 apply (rule classical, simp, arith) |
|
596 apply auto |
|
597 done |
|
598 termination by lexicographic_order |
|
599 |
|
600 text {* |
|
601 We can stretch the notion of pattern matching even more. The |
|
602 following function is not a sensible functional program, but a |
|
603 perfectly valid mathematical definition: |
|
604 *} |
|
605 |
|
606 function ev :: "nat \<Rightarrow> bool" |
|
607 where |
|
608 "ev (2 * n) = True" |
|
609 | "ev (2 * n + 1) = False" |
|
610 by (rule classical, simp) arith+ |
|
611 termination by (relation "{}") simp |
|
612 |
|
613 text {* |
|
614 This general notion of pattern matching gives you the full freedom |
|
615 of mathematical specifications. However, as always, freedom should |
|
616 be used with care: |
|
617 |
|
618 If we leave the area of constructor |
|
619 patterns, we have effectively departed from the world of functional |
|
620 programming. This means that it is no longer possible to use the |
|
621 code generator, and expect it to generate ML code for our |
|
622 definitions. Also, such a specification might not work very well together with |
|
623 simplification. Your mileage may vary. |
|
624 *} |
|
625 |
|
626 |
|
627 subsection {* Conditional equations *} |
|
628 |
|
629 text {* |
|
630 The function package also supports conditional equations, which are |
|
631 similar to guards in a language like Haskell. Here is Euclid's |
|
632 algorithm written with conditional patterns\footnote{Note that the |
|
633 patterns are also overlapping in the base case}: |
|
634 *} |
|
635 |
|
636 function gcd :: "nat \<Rightarrow> nat \<Rightarrow> nat" |
|
637 where |
|
638 "gcd x 0 = x" |
|
639 | "gcd 0 y = y" |
|
640 | "x < y \<Longrightarrow> gcd (Suc x) (Suc y) = gcd (Suc x) (y - x)" |
|
641 | "\<not> x < y \<Longrightarrow> gcd (Suc x) (Suc y) = gcd (x - y) (Suc y)" |
|
642 by (rule classical, auto, arith) |
|
643 termination by lexicographic_order |
|
644 |
|
645 text {* |
|
646 By now, you can probably guess what the proof obligations for the |
|
647 pattern completeness and compatibility look like. |
|
648 |
|
649 Again, functions with conditional patterns are not supported by the |
|
650 code generator. |
|
651 *} |
|
652 |
|
653 |
|
654 subsection {* Pattern matching on strings *} |
|
655 |
|
656 text {* |
|
657 As strings (as lists of characters) are normal data types, pattern |
|
658 matching on them is possible, but somewhat problematic. Consider the |
|
659 following definition: |
|
660 |
|
661 \end{isamarkuptext} |
|
662 \noindent\cmd{fun} @{text "check :: \"string \<Rightarrow> bool\""}\\% |
|
663 \cmd{where}\\% |
|
664 \hspace*{2ex}@{text "\"check (''good'') = True\""}\\% |
|
665 @{text "| \"check s = False\""} |
|
666 \begin{isamarkuptext} |
|
667 |
|
668 An invocation of the above \cmd{fun} command does not |
|
669 terminate. What is the problem? Strings are lists of characters, and |
|
670 characters are a data type with a lot of constructors. Splitting the |
|
671 catch-all pattern thus leads to an explosion of cases, which cannot |
|
672 be handled by Isabelle. |
|
673 |
|
674 There are two things we can do here. Either we write an explicit |
|
675 @{text "if"} on the right hand side, or we can use conditional patterns: |
|
676 *} |
|
677 |
|
678 function check :: "string \<Rightarrow> bool" |
|
679 where |
|
680 "check (''good'') = True" |
|
681 | "s \<noteq> ''good'' \<Longrightarrow> check s = False" |
|
682 by auto |
478 |
683 |
479 |
684 |
480 section {* Partiality *} |
685 section {* Partiality *} |
481 |
686 |
482 text {* |
687 text {* |
483 In HOL, all functions are total. A function @{term "f"} applied to |
688 In HOL, all functions are total. A function @{term "f"} applied to |
484 @{term "x"} always has a value @{term "f x"}, and there is no notion |
689 @{term "x"} always has the value @{term "f x"}, and there is no notion |
485 of undefinedness. |
690 of undefinedness. |
486 |
691 |
487 This property of HOL is the reason why we have to do termination |
692 This is why we have to do termination |
488 proofs when defining functions: The termination proof justifies the |
693 proofs when defining functions: The proof justifies that the |
489 definition of the function by wellfounded recursion. |
694 function can be defined by wellfounded recursion. |
490 |
695 |
491 However, the \cmd{function} package still supports partiality. Let's |
696 However, the \cmd{function} package does support partiality to a |
492 look at the following function which searches for a zero in the |
697 certain extent. Let's look at the following function which looks |
493 function f. |
698 for a zero of a given function f. |
494 *} |
699 *} |
495 |
700 |
496 function (*<*)(domintros, tailrec)(*>*)findzero :: "(nat \<Rightarrow> nat) \<Rightarrow> nat \<Rightarrow> nat" |
701 function (*<*)(domintros, tailrec)(*>*)findzero :: "(nat \<Rightarrow> nat) \<Rightarrow> nat \<Rightarrow> nat" |
497 where |
702 where |
498 "findzero f n = (if f n = 0 then n else findzero f (Suc n))" |
703 "findzero f n = (if f n = 0 then n else findzero f (Suc n))" |
528 text {* |
734 text {* |
529 @{thm[display] findzero.pinduct} |
735 @{thm[display] findzero.pinduct} |
530 *} |
736 *} |
531 |
737 |
532 text {* |
738 text {* |
533 As already mentioned, HOL does not support true partiality. All we |
739 Remember that all we |
534 are doing here is using some tricks to make a total function appear |
740 are doing here is use some tricks to make a total function appear |
535 as if it was partial. We can still write the term @{term "findzero |
741 as if it was partial. We can still write the term @{term "findzero |
536 (\<lambda>x. 1) 0"} and like any other term of type @{typ nat} it is equal |
742 (\<lambda>x. 1) 0"} and like any other term of type @{typ nat} it is equal |
537 to some natural number, although we might not be able to find out |
743 to some natural number, although we might not be able to find out |
538 which one (we will discuss this further in \S\ref{default}). The |
744 which one. The function is \emph{underdefined}. |
539 function is \emph{underdefined}. |
745 |
540 |
746 But it is enough defined to prove something interesting about it. We |
541 But it is enough defined to prove something about it. We can prove |
747 can prove that if @{term "findzero f n"} |
542 that if @{term "findzero f n"} |
|
543 it terminates, it indeed returns a zero of @{term f}: |
748 it terminates, it indeed returns a zero of @{term f}: |
544 *} |
749 *} |
545 |
750 |
546 lemma findzero_zero: "findzero_dom (f, n) \<Longrightarrow> f (findzero f n) = 0" |
751 lemma findzero_zero: "findzero_dom (f, n) \<Longrightarrow> f (findzero f n) = 0" |
547 |
752 |
573 is applied when calls to @{term findzero} are unfolded. |
778 is applied when calls to @{term findzero} are unfolded. |
574 *} |
779 *} |
575 |
780 |
576 text_raw {* |
781 text_raw {* |
577 \begin{figure} |
782 \begin{figure} |
578 \begin{center} |
783 \hrule\vspace{6pt} |
579 \begin{minipage}{0.8\textwidth} |
784 \begin{minipage}{0.8\textwidth} |
580 \isabellestyle{it} |
785 \isabellestyle{it} |
581 \isastyle\isamarkuptrue |
786 \isastyle\isamarkuptrue |
582 *} |
787 *} |
583 lemma "\<lbrakk>findzero_dom (f, n); x \<in> {n ..< findzero f n}\<rbrakk> \<Longrightarrow> f x \<noteq> 0" |
788 lemma "\<lbrakk>findzero_dom (f, n); x \<in> {n ..< findzero f n}\<rbrakk> \<Longrightarrow> f x \<noteq> 0" |
584 proof (induct rule: findzero.pinduct) |
789 proof (induct rule: findzero.pinduct) |
585 fix f n assume dom: "findzero_dom (f, n)" |
790 fix f n assume dom: "findzero_dom (f, n)" |
586 and IH: "\<lbrakk>f n \<noteq> 0; x \<in> {Suc n..<findzero f (Suc n)}\<rbrakk> |
791 and IH: "\<lbrakk>f n \<noteq> 0; x \<in> {Suc n ..< findzero f (Suc n)}\<rbrakk> \<Longrightarrow> f x \<noteq> 0" |
587 \<Longrightarrow> f x \<noteq> 0" |
792 and x_range: "x \<in> {n ..< findzero f n}" |
588 and x_range: "x \<in> {n..<findzero f n}" |
|
589 |
|
590 have "f n \<noteq> 0" |
793 have "f n \<noteq> 0" |
591 proof |
794 proof |
592 assume "f n = 0" |
795 assume "f n = 0" |
593 with dom have "findzero f n = n" by simp |
796 with dom have "findzero f n = n" by simp |
594 with x_range show False by auto |
797 with x_range show False by auto |
623 lemmas with @{term False} as a premise. |
826 lemmas with @{term False} as a premise. |
624 |
827 |
625 Essentially, we need some introduction rules for @{text |
828 Essentially, we need some introduction rules for @{text |
626 findzero_dom}. The function package can prove such domain |
829 findzero_dom}. The function package can prove such domain |
627 introduction rules automatically. But since they are not used very |
830 introduction rules automatically. But since they are not used very |
628 often (they are almost never needed if the function is total), they |
831 often (they are almost never needed if the function is total), this |
629 are disabled by default for efficiency reasons. So we have to go |
832 functionality is disabled by default for efficiency reasons. So we have to go |
630 back and ask for them explicitly by passing the @{text |
833 back and ask for them explicitly by passing the @{text |
631 "(domintros)"} option to the function package: |
834 "(domintros)"} option to the function package: |
632 |
835 |
|
836 \vspace{1ex} |
633 \noindent\cmd{function} @{text "(domintros) findzero :: \"(nat \<Rightarrow> nat) \<Rightarrow> nat \<Rightarrow> nat\""}\\% |
837 \noindent\cmd{function} @{text "(domintros) findzero :: \"(nat \<Rightarrow> nat) \<Rightarrow> nat \<Rightarrow> nat\""}\\% |
634 \cmd{where}\isanewline% |
838 \cmd{where}\isanewline% |
635 \ \ \ldots\\ |
839 \ \ \ldots\\ |
636 \cmd{by} @{text "pat_completeness auto"}\\% |
840 |
637 |
841 \noindent Now the package has proved an introduction rule for @{text findzero_dom}: |
638 |
|
639 Now the package has proved an introduction rule for @{text findzero_dom}: |
|
640 *} |
842 *} |
641 |
843 |
642 thm findzero.domintros |
844 thm findzero.domintros |
643 |
845 |
644 text {* |
846 text {* |
653 Since our function increases its argument at recursive calls, we |
855 Since our function increases its argument at recursive calls, we |
654 need an induction principle which works \qt{backwards}. We will use |
856 need an induction principle which works \qt{backwards}. We will use |
655 @{text inc_induct}, which allows to do induction from a fixed number |
857 @{text inc_induct}, which allows to do induction from a fixed number |
656 \qt{downwards}: |
858 \qt{downwards}: |
657 |
859 |
658 @{thm[display] inc_induct} |
860 \begin{center}@{thm inc_induct}\hfill(@{text "inc_induct"})\end{center} |
659 |
861 |
660 Fig.~\ref{findzero_term} gives a detailed Isar proof of the fact |
862 Figure \ref{findzero_term} gives a detailed Isar proof of the fact |
661 that @{text findzero} terminates if there is a zero which is greater |
863 that @{text findzero} terminates if there is a zero which is greater |
662 or equal to @{term n}. First we derive two useful rules which will |
864 or equal to @{term n}. First we derive two useful rules which will |
663 solve the base case and the step case of the induction. The |
865 solve the base case and the step case of the induction. The |
664 induction is then straightforward, except for the unusal induction |
866 induction is then straightforward, except for the unusal induction |
665 principle. |
867 principle. |
666 |
868 |
667 *} |
869 *} |
668 |
870 |
669 text_raw {* |
871 text_raw {* |
670 \begin{figure} |
872 \begin{figure} |
671 \begin{center} |
873 \hrule\vspace{6pt} |
672 \begin{minipage}{0.8\textwidth} |
874 \begin{minipage}{0.8\textwidth} |
673 \isabellestyle{it} |
875 \isabellestyle{it} |
674 \isastyle\isamarkuptrue |
876 \isastyle\isamarkuptrue |
675 *} |
877 *} |
676 lemma findzero_termination: |
878 lemma findzero_termination: |
677 assumes "x >= n" |
879 assumes "x \<ge> n" and "f x = 0" |
678 assumes "f x = 0" |
|
679 shows "findzero_dom (f, n)" |
880 shows "findzero_dom (f, n)" |
680 proof - |
881 proof - |
681 have base: "findzero_dom (f, x)" |
882 have base: "findzero_dom (f, x)" |
682 by (rule findzero.domintros) (simp add:`f x = 0`) |
883 by (rule findzero.domintros) (simp add:`f x = 0`) |
683 |
884 |
684 have step: "\<And>i. findzero_dom (f, Suc i) |
885 have step: "\<And>i. findzero_dom (f, Suc i) |
685 \<Longrightarrow> findzero_dom (f, i)" |
886 \<Longrightarrow> findzero_dom (f, i)" |
686 by (rule findzero.domintros) simp |
887 by (rule findzero.domintros) simp |
687 |
888 |
688 from `x \<ge> n` |
889 from `x \<ge> n` show ?thesis |
689 show ?thesis |
|
690 proof (induct rule:inc_induct) |
890 proof (induct rule:inc_induct) |
691 show "findzero_dom (f, x)" |
891 show "findzero_dom (f, x)" by (rule base) |
692 by (rule base) |
|
693 next |
892 next |
694 fix i assume "findzero_dom (f, Suc i)" |
893 fix i assume "findzero_dom (f, Suc i)" |
695 thus "findzero_dom (f, i)" |
894 thus "findzero_dom (f, i)" by (rule step) |
696 by (rule step) |
|
697 qed |
895 qed |
698 qed |
896 qed |
699 text_raw {* |
897 text_raw {* |
700 \isamarkupfalse\isabellestyle{tt} |
898 \isamarkupfalse\isabellestyle{tt} |
701 \end{minipage}\end{center} |
899 \end{minipage}\vspace{6pt}\hrule |
702 \caption{Termination proof for @{text findzero}}\label{findzero_term} |
900 \caption{Termination proof for @{text findzero}}\label{findzero_term} |
703 \end{figure} |
901 \end{figure} |
704 *} |
902 *} |
705 |
903 |
706 text {* |
904 text {* |
732 predicate actually is. Actually, @{text findzero_dom} is just an |
930 predicate actually is. Actually, @{text findzero_dom} is just an |
733 abbreviation: |
931 abbreviation: |
734 |
932 |
735 @{abbrev[display] findzero_dom} |
933 @{abbrev[display] findzero_dom} |
736 |
934 |
737 The domain predicate is the accessible part of a relation @{const |
935 The domain predicate is the \emph{accessible part} of a relation @{const |
738 findzero_rel}, which was also created internally by the function |
936 findzero_rel}, which was also created internally by the function |
739 package. @{const findzero_rel} is just a normal |
937 package. @{const findzero_rel} is just a normal |
740 inductively defined predicate, so we can inspect its definition by |
938 inductive predicate, so we can inspect its definition by |
741 looking at the introduction rules @{text findzero_rel.intros}. |
939 looking at the introduction rules @{text findzero_rel.intros}. |
742 In our case there is just a single rule: |
940 In our case there is just a single rule: |
743 |
941 |
744 @{thm[display] findzero_rel.intros} |
942 @{thm[display] findzero_rel.intros} |
745 |
943 |
746 The relation @{const findzero_rel}, expressed as a binary predicate, |
944 The predicate @{const findzero_rel} |
747 describes the \emph{recursion relation} of the function |
945 describes the \emph{recursion relation} of the function |
748 definition. The recursion relation is a binary relation on |
946 definition. The recursion relation is a binary relation on |
749 the arguments of the function that relates each argument to its |
947 the arguments of the function that relates each argument to its |
750 recursive calls. In general, there is one introduction rule for each |
948 recursive calls. In general, there is one introduction rule for each |
751 recursive call. |
949 recursive call. |
752 |
950 |
753 The predicate @{term "acc findzero_rel"} is the \emph{accessible part} of |
951 The predicate @{term "acc findzero_rel"} is the accessible part of |
754 that relation. An argument belongs to the accessible part, if it can |
952 that relation. An argument belongs to the accessible part, if it can |
755 be reached in a finite number of steps. |
953 be reached in a finite number of steps (cf.~its definition in @{text |
|
954 "Accessible_Part.thy"}). |
756 |
955 |
757 Since the domain predicate is just an abbreviation, you can use |
956 Since the domain predicate is just an abbreviation, you can use |
758 lemmas for @{const acc} and @{const findzero_rel} directly. Some |
957 lemmas for @{const acc} and @{const findzero_rel} directly. Some |
759 lemmas which are occasionally useful are @{text accI}, @{text |
958 lemmas which are occasionally useful are @{text accI}, @{text |
760 acc_downward}, and of course the introduction and elimination rules |
959 acc_downward}, and of course the introduction and elimination rules |
772 text {* |
971 text {* |
773 The domain predicate is our trick that allows us to model partiality |
972 The domain predicate is our trick that allows us to model partiality |
774 in a world of total functions. The downside of this is that we have |
973 in a world of total functions. The downside of this is that we have |
775 to carry it around all the time. The termination proof above allowed |
974 to carry it around all the time. The termination proof above allowed |
776 us to replace the abstract @{term "findzero_dom (f, n)"} by the more |
975 us to replace the abstract @{term "findzero_dom (f, n)"} by the more |
777 concrete @{term "(x \<ge> n \<and> f x = 0)"}, but the condition is still |
976 concrete @{term "(x \<ge> n \<and> f x = (0::nat))"}, but the condition is still |
778 there and it won't go away soon. |
977 there and can only be discharged for special cases. |
779 |
978 In particular, the domain predicate guards the unfolding of our |
780 In particular, the domain predicate guard the unfolding of our |
|
781 function, since it is there as a condition in the @{text psimp} |
979 function, since it is there as a condition in the @{text psimp} |
782 rules. |
980 rules. |
783 |
|
784 On the other hand, we must be happy about the domain predicate, |
|
785 since it guarantees that all this is at all possible without losing |
|
786 consistency. |
|
787 |
981 |
788 Now there is an important special case: We can actually get rid |
982 Now there is an important special case: We can actually get rid |
789 of the condition in the simplification rules, \emph{if the function |
983 of the condition in the simplification rules, \emph{if the function |
790 is tail-recursive}. The reason is that for all tail-recursive |
984 is tail-recursive}. The reason is that for all tail-recursive |
791 equations there is a total function satisfying them, even if they |
985 equations there is a total function satisfying them, even if they |
792 are non-terminating. |
986 are non-terminating. |
793 |
987 |
|
988 % A function is tail recursive, if each call to the function is either |
|
989 % equal |
|
990 % |
|
991 % So the outer form of the |
|
992 % |
|
993 %if it can be written in the following |
|
994 % form: |
|
995 % {term[display] "f x = (if COND x then BASE x else f (LOOP x))"} |
|
996 |
|
997 |
794 The function package internally does the right construction and can |
998 The function package internally does the right construction and can |
795 derive the unconditional simp rules, if we ask it to do so. Luckily, |
999 derive the unconditional simp rules, if we ask it to do so. Luckily, |
796 our @{const "findzero"} function is tail-recursive, so we can just go |
1000 our @{const "findzero"} function is tail-recursive, so we can just go |
797 back and add another option to the \cmd{function} command: |
1001 back and add another option to the \cmd{function} command: |
798 |
1002 |
|
1003 \vspace{1ex} |
799 \noindent\cmd{function} @{text "(domintros, tailrec) findzero :: \"(nat \<Rightarrow> nat) \<Rightarrow> nat \<Rightarrow> nat\""}\\% |
1004 \noindent\cmd{function} @{text "(domintros, tailrec) findzero :: \"(nat \<Rightarrow> nat) \<Rightarrow> nat \<Rightarrow> nat\""}\\% |
800 \cmd{where}\isanewline% |
1005 \cmd{where}\isanewline% |
801 \ \ \ldots\\% |
1006 \ \ \ldots\\% |
802 |
1007 |
803 |
1008 |
804 Now, we actually get the unconditional simplification rules, even |
1009 \noindent Now, we actually get unconditional simplification rules, even |
805 though the function is partial: |
1010 though the function is partial: |
806 *} |
1011 *} |
807 |
1012 |
808 thm findzero.simps |
1013 thm findzero.simps |
809 |
1014 |
810 text {* |
1015 text {* |
811 @{thm[display] findzero.simps} |
1016 @{thm[display] findzero.simps} |
812 |
1017 |
813 Of course these would make the simplifier loop, so we better remove |
1018 \noindent Of course these would make the simplifier loop, so we better remove |
814 them from the simpset: |
1019 them from the simpset: |
815 *} |
1020 *} |
816 |
1021 |
817 declare findzero.simps[simp del] |
1022 declare findzero.simps[simp del] |
818 |
1023 |
819 |
1024 text {* |
820 text {* \fixme{Code generation ???} *} |
1025 Getting rid of the domain conditions in the simplification rules is |
|
1026 not only useful because it simplifies proofs. It is also required in |
|
1027 order to use Isabelle's code generator to generate ML code |
|
1028 from a function definition. |
|
1029 Since the code generator only works with equations, it cannot be |
|
1030 used with @{text "psimp"} rules. Thus, in order to generate code for |
|
1031 partial functions, they must be defined as a tail recursion. |
|
1032 Luckily, many functions have a relatively natural tail recursive |
|
1033 definition. |
|
1034 *} |
821 |
1035 |
822 section {* Nested recursion *} |
1036 section {* Nested recursion *} |
823 |
1037 |
824 text {* |
1038 text {* |
825 Recursive calls which are nested in one another frequently cause |
1039 Recursive calls which are nested in one another frequently cause |
1042 |
1257 |
1043 @{thm[display] mapeven.simps} |
1258 @{thm[display] mapeven.simps} |
1044 \end{exercise} |
1259 \end{exercise} |
1045 |
1260 |
1046 \begin{exercise} |
1261 \begin{exercise} |
1047 What happens if the congruence rule for @{const If} is |
1262 Try what happens if the congruence rule for @{const If} is |
1048 disabled by declaring @{text "if_cong[fundef_cong del]"}? |
1263 disabled by declaring @{text "if_cong[fundef_cong del]"}? |
1049 \end{exercise} |
1264 \end{exercise} |
1050 |
1265 |
1051 Note that in some cases there is no \qt{best} congruence rule. |
1266 Note that in some cases there is no \qt{best} congruence rule. |
1052 \fixme |
1267 \fixme{} |
1053 |
1268 |
1054 *} |
1269 *} |
1055 |
1270 |
1056 |
|
1057 |
|
1058 |
|
1059 |
|
1060 |
|
1061 |
|
1062 section {* Appendix: Predefined Congruence Rules *} |
|
1063 |
|
1064 (*<*) |
|
1065 syntax (Rule output) |
|
1066 "==>" :: "prop \<Rightarrow> prop \<Rightarrow> prop" |
|
1067 ("\<^raw:\mbox{}\inferrule{\mbox{>_\<^raw:}}>\<^raw:{\mbox{>_\<^raw:}}>") |
|
1068 |
|
1069 "_bigimpl" :: "asms \<Rightarrow> prop \<Rightarrow> prop" |
|
1070 ("\<^raw:\mbox{}\inferrule{>_\<^raw:}>\<^raw:{\mbox{>_\<^raw:}}>") |
|
1071 |
|
1072 "_asms" :: "prop \<Rightarrow> asms \<Rightarrow> asms" |
|
1073 ("\<^raw:\mbox{>_\<^raw:}\\>/ _") |
|
1074 |
|
1075 "_asm" :: "prop \<Rightarrow> asms" ("\<^raw:\mbox{>_\<^raw:}>") |
|
1076 |
|
1077 definition |
|
1078 FixImp :: "prop \<Rightarrow> prop \<Rightarrow> prop" |
|
1079 where |
|
1080 "FixImp (PROP A) (PROP B) \<equiv> (PROP A \<Longrightarrow> PROP B)" |
|
1081 notation (output) |
|
1082 FixImp (infixr "\<Longrightarrow>" 1) |
|
1083 |
|
1084 setup {* |
|
1085 let |
|
1086 val fix_imps = map_aterms (fn Const ("==>", T) => Const ("Functions.FixImp", T) | t => t) |
|
1087 fun transform t = Logic.list_implies (map fix_imps (Logic.strip_imp_prems t), Logic.strip_imp_concl t) |
|
1088 in |
|
1089 TermStyle.add_style "topl" (K transform) |
|
1090 end |
1271 end |
1091 *} |
|
1092 (*>*) |
|
1093 |
|
1094 subsection {* Basic Control Structures *} |
|
1095 |
|
1096 text {* |
|
1097 |
|
1098 @{thm_style[mode=Rule] topl if_cong} |
|
1099 |
|
1100 @{thm_style [mode=Rule] topl let_cong} |
|
1101 |
|
1102 *} |
|
1103 |
|
1104 subsection {* Data Types *} |
|
1105 |
|
1106 text {* |
|
1107 |
|
1108 For each \cmd{datatype} definition, a congruence rule for the case |
|
1109 combinator is registeres automatically. Here are the rules for |
|
1110 @{text "nat"} and @{text "list"}: |
|
1111 |
|
1112 \begin{center}@{thm_style[mode=Rule] topl nat.case_cong}\end{center} |
|
1113 |
|
1114 \begin{center}@{thm_style[mode=Rule] topl list.case_cong}\end{center} |
|
1115 |
|
1116 *} |
|
1117 |
|
1118 subsection {* List combinators *} |
|
1119 |
|
1120 |
|
1121 text {* |
|
1122 |
|
1123 @{thm_style[mode=Rule] topl map_cong} |
|
1124 |
|
1125 @{thm_style[mode=Rule] topl filter_cong} |
|
1126 |
|
1127 @{thm_style[mode=Rule] topl foldr_cong} |
|
1128 |
|
1129 @{thm_style[mode=Rule] topl foldl_cong} |
|
1130 |
|
1131 Similar: takewhile, dropwhile |
|
1132 |
|
1133 *} |
|
1134 |
|
1135 subsection {* Sets *} |
|
1136 |
|
1137 |
|
1138 text {* |
|
1139 |
|
1140 @{thm_style[mode=Rule] topl ball_cong} |
|
1141 |
|
1142 @{thm_style[mode=Rule] topl bex_cong} |
|
1143 |
|
1144 @{thm_style[mode=Rule] topl UN_cong} |
|
1145 |
|
1146 @{thm_style[mode=Rule] topl INT_cong} |
|
1147 |
|
1148 @{thm_style[mode=Rule] topl image_cong} |
|
1149 |
|
1150 |
|
1151 *} |
|
1152 |
|
1153 |
|
1154 |
|
1155 |
|
1156 |
|
1157 |
|
1158 end |
|