1 (* Title: HOL/ex/Fundefs.thy |
1 (* Title: HOL/ex/Fundefs.thy |
2 Author: Alexander Krauss, TU Muenchen |
2 Author: Alexander Krauss, TU Muenchen |
3 *) |
3 *) |
4 |
4 |
5 section {* Examples of function definitions *} |
5 section \<open>Examples of function definitions\<close> |
6 |
6 |
7 theory Fundefs |
7 theory Fundefs |
8 imports Main "~~/src/HOL/Library/Monad_Syntax" |
8 imports Main "~~/src/HOL/Library/Monad_Syntax" |
9 begin |
9 begin |
10 |
10 |
11 subsection {* Very basic *} |
11 subsection \<open>Very basic\<close> |
12 |
12 |
13 fun fib :: "nat \<Rightarrow> nat" |
13 fun fib :: "nat \<Rightarrow> nat" |
14 where |
14 where |
15 "fib 0 = 1" |
15 "fib 0 = 1" |
16 | "fib (Suc 0) = 1" |
16 | "fib (Suc 0) = 1" |
17 | "fib (Suc (Suc n)) = fib n + fib (Suc n)" |
17 | "fib (Suc (Suc n)) = fib n + fib (Suc n)" |
18 |
18 |
19 text {* partial simp and induction rules: *} |
19 text \<open>partial simp and induction rules:\<close> |
20 thm fib.psimps |
20 thm fib.psimps |
21 thm fib.pinduct |
21 thm fib.pinduct |
22 |
22 |
23 text {* There is also a cases rule to distinguish cases along the definition *} |
23 text \<open>There is also a cases rule to distinguish cases along the definition\<close> |
24 thm fib.cases |
24 thm fib.cases |
25 |
25 |
26 |
26 |
27 text {* total simp and induction rules: *} |
27 text \<open>total simp and induction rules:\<close> |
28 thm fib.simps |
28 thm fib.simps |
29 thm fib.induct |
29 thm fib.induct |
30 |
30 |
31 text {* elimination rules *} |
31 text \<open>elimination rules\<close> |
32 thm fib.elims |
32 thm fib.elims |
33 |
33 |
34 subsection {* Currying *} |
34 subsection \<open>Currying\<close> |
35 |
35 |
36 fun add |
36 fun add |
37 where |
37 where |
38 "add 0 y = y" |
38 "add 0 y = y" |
39 | "add (Suc x) y = Suc (add x y)" |
39 | "add (Suc x) y = Suc (add x y)" |
40 |
40 |
41 thm add.simps |
41 thm add.simps |
42 thm add.induct -- {* Note the curried induction predicate *} |
42 thm add.induct -- \<open>Note the curried induction predicate\<close> |
43 |
43 |
44 |
44 |
45 subsection {* Nested recursion *} |
45 subsection \<open>Nested recursion\<close> |
46 |
46 |
47 function nz |
47 function nz |
48 where |
48 where |
49 "nz 0 = 0" |
49 "nz 0 = 0" |
50 | "nz (Suc x) = nz (nz x)" |
50 | "nz (Suc x) = nz (nz x)" |
51 by pat_completeness auto |
51 by pat_completeness auto |
52 |
52 |
53 lemma nz_is_zero: -- {* A lemma we need to prove termination *} |
53 lemma nz_is_zero: -- \<open>A lemma we need to prove termination\<close> |
54 assumes trm: "nz_dom x" |
54 assumes trm: "nz_dom x" |
55 shows "nz x = 0" |
55 shows "nz x = 0" |
56 using trm |
56 using trm |
57 by induct (auto simp: nz.psimps) |
57 by induct (auto simp: nz.psimps) |
58 |
58 |
84 fix n::nat assume "~ 100 < n" (* Inner call *) |
84 fix n::nat assume "~ 100 < n" (* Inner call *) |
85 thus "(n + 11, n) : ?R" by simp |
85 thus "(n + 11, n) : ?R" by simp |
86 |
86 |
87 assume inner_trm: "f91_dom (n + 11)" (* Outer call *) |
87 assume inner_trm: "f91_dom (n + 11)" (* Outer call *) |
88 with f91_estimate have "n + 11 < f91 (n + 11) + 11" . |
88 with f91_estimate have "n + 11 < f91 (n + 11) + 11" . |
89 with `~ 100 < n` show "(f91 (n + 11), n) : ?R" by simp |
89 with \<open>~ 100 < n\<close> show "(f91 (n + 11), n) : ?R" by simp |
90 qed |
90 qed |
91 |
91 |
92 text{* Now trivial (even though it does not belong here): *} |
92 text\<open>Now trivial (even though it does not belong here):\<close> |
93 lemma "f91 n = (if 100 < n then n - 10 else 91)" |
93 lemma "f91 n = (if 100 < n then n - 10 else 91)" |
94 by (induct n rule:f91.induct) auto |
94 by (induct n rule:f91.induct) auto |
95 |
95 |
96 |
96 |
97 subsection {* More general patterns *} |
97 subsection \<open>More general patterns\<close> |
98 |
98 |
99 subsubsection {* Overlapping patterns *} |
99 subsubsection \<open>Overlapping patterns\<close> |
100 |
100 |
101 text {* Currently, patterns must always be compatible with each other, since |
101 text \<open>Currently, patterns must always be compatible with each other, since |
102 no automatic splitting takes place. But the following definition of |
102 no automatic splitting takes place. But the following definition of |
103 gcd is ok, although patterns overlap: *} |
103 gcd is ok, although patterns overlap:\<close> |
104 |
104 |
105 fun gcd2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" |
105 fun gcd2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" |
106 where |
106 where |
107 "gcd2 x 0 = x" |
107 "gcd2 x 0 = x" |
108 | "gcd2 0 y = y" |
108 | "gcd2 0 y = y" |
129 |
129 |
130 thm gcd3.simps |
130 thm gcd3.simps |
131 thm gcd3.induct |
131 thm gcd3.induct |
132 |
132 |
133 |
133 |
134 text {* General patterns allow even strange definitions: *} |
134 text \<open>General patterns allow even strange definitions:\<close> |
135 |
135 |
136 function ev :: "nat \<Rightarrow> bool" |
136 function ev :: "nat \<Rightarrow> bool" |
137 where |
137 where |
138 "ev (2 * n) = True" |
138 "ev (2 * n) = True" |
139 | "ev (2 * n + 1) = False" |
139 | "ev (2 * n + 1) = False" |
140 proof - -- {* completeness is more difficult here \dots *} |
140 proof - -- \<open>completeness is more difficult here \dots\<close> |
141 fix P :: bool |
141 fix P :: bool |
142 and x :: nat |
142 and x :: nat |
143 assume c1: "\<And>n. x = 2 * n \<Longrightarrow> P" |
143 assume c1: "\<And>n. x = 2 * n \<Longrightarrow> P" |
144 and c2: "\<And>n. x = 2 * n + 1 \<Longrightarrow> P" |
144 and c2: "\<And>n. x = 2 * n + 1 \<Longrightarrow> P" |
145 have divmod: "x = 2 * (x div 2) + (x mod 2)" by auto |
145 have divmod: "x = 2 * (x div 2) + (x mod 2)" by auto |
152 assume "x mod 2 \<noteq> 0" |
152 assume "x mod 2 \<noteq> 0" |
153 hence "x mod 2 = 1" by simp |
153 hence "x mod 2 = 1" by simp |
154 with divmod have "x = 2 * (x div 2) + 1" by simp |
154 with divmod have "x = 2 * (x div 2) + 1" by simp |
155 with c2 show "P" . |
155 with c2 show "P" . |
156 qed |
156 qed |
157 qed presburger+ -- {* solve compatibility with presburger *} |
157 qed presburger+ -- \<open>solve compatibility with presburger\<close> |
158 termination by lexicographic_order |
158 termination by lexicographic_order |
159 |
159 |
160 thm ev.simps |
160 thm ev.simps |
161 thm ev.induct |
161 thm ev.induct |
162 thm ev.cases |
162 thm ev.cases |
163 |
163 |
164 |
164 |
165 subsection {* Mutual Recursion *} |
165 subsection \<open>Mutual Recursion\<close> |
166 |
166 |
167 fun evn od :: "nat \<Rightarrow> bool" |
167 fun evn od :: "nat \<Rightarrow> bool" |
168 where |
168 where |
169 "evn 0 = True" |
169 "evn 0 = True" |
170 | "od 0 = False" |
170 | "od 0 = False" |
211 end |
211 end |
212 |
212 |
213 thm my_monoid.foldL.simps |
213 thm my_monoid.foldL.simps |
214 thm my_monoid.foldR_foldL |
214 thm my_monoid.foldR_foldL |
215 |
215 |
216 subsection {* @{text fun_cases} *} |
216 subsection \<open>@{text fun_cases}\<close> |
217 |
217 |
218 subsubsection {* Predecessor *} |
218 subsubsection \<open>Predecessor\<close> |
219 |
219 |
220 fun pred :: "nat \<Rightarrow> nat" where |
220 fun pred :: "nat \<Rightarrow> nat" where |
221 "pred 0 = 0" | |
221 "pred 0 = 0" | |
222 "pred (Suc n) = n" |
222 "pred (Suc n) = n" |
223 |
223 |
225 |
225 |
226 lemma assumes "pred x = y" |
226 lemma assumes "pred x = y" |
227 obtains "x = 0" "y = 0" | "n" where "x = Suc n" "y = n" |
227 obtains "x = 0" "y = 0" | "n" where "x = Suc n" "y = n" |
228 by (fact pred.elims[OF assms]) |
228 by (fact pred.elims[OF assms]) |
229 |
229 |
230 text {* If the predecessor of a number is 0, that number must be 0 or 1. *} |
230 text \<open>If the predecessor of a number is 0, that number must be 0 or 1.\<close> |
231 |
231 |
232 fun_cases pred0E[elim]: "pred n = 0" |
232 fun_cases pred0E[elim]: "pred n = 0" |
233 |
233 |
234 lemma "pred n = 0 \<Longrightarrow> n = 0 \<or> n = Suc 0" |
234 lemma "pred n = 0 \<Longrightarrow> n = 0 \<or> n = Suc 0" |
235 by (erule pred0E) metis+ |
235 by (erule pred0E) metis+ |
236 |
236 |
237 |
237 |
238 text {* Other expressions on the right-hand side also work, but whether the |
238 text \<open>Other expressions on the right-hand side also work, but whether the |
239 generated rule is useful depends on how well the simplifier can |
239 generated rule is useful depends on how well the simplifier can |
240 simplify it. This example works well: *} |
240 simplify it. This example works well:\<close> |
241 |
241 |
242 fun_cases pred42E[elim]: "pred n = 42" |
242 fun_cases pred42E[elim]: "pred n = 42" |
243 |
243 |
244 lemma "pred n = 42 \<Longrightarrow> n = 43" |
244 lemma "pred n = 42 \<Longrightarrow> n = 43" |
245 by (erule pred42E) |
245 by (erule pred42E) |
246 |
246 |
247 subsubsection {* List to option *} |
247 subsubsection \<open>List to option\<close> |
248 |
248 |
249 fun list_to_option :: "'a list \<Rightarrow> 'a option" where |
249 fun list_to_option :: "'a list \<Rightarrow> 'a option" where |
250 "list_to_option [x] = Some x" | |
250 "list_to_option [x] = Some x" | |
251 "list_to_option _ = None" |
251 "list_to_option _ = None" |
252 |
252 |
254 and list_to_option_SomeE: "list_to_option xs = Some x" |
254 and list_to_option_SomeE: "list_to_option xs = Some x" |
255 |
255 |
256 lemma "list_to_option xs = Some y \<Longrightarrow> xs = [y]" |
256 lemma "list_to_option xs = Some y \<Longrightarrow> xs = [y]" |
257 by (erule list_to_option_SomeE) |
257 by (erule list_to_option_SomeE) |
258 |
258 |
259 subsubsection {* Boolean Functions *} |
259 subsubsection \<open>Boolean Functions\<close> |
260 |
260 |
261 fun xor :: "bool \<Rightarrow> bool \<Rightarrow> bool" where |
261 fun xor :: "bool \<Rightarrow> bool \<Rightarrow> bool" where |
262 "xor False False = False" | |
262 "xor False False = False" | |
263 "xor True True = False" | |
263 "xor True True = False" | |
264 "xor _ _ = True" |
264 "xor _ _ = True" |
265 |
265 |
266 thm xor.elims |
266 thm xor.elims |
267 |
267 |
268 text {* @{text fun_cases} does not only recognise function equations, but also works with |
268 text \<open>@{text fun_cases} does not only recognise function equations, but also works with |
269 functions that return a boolean, e.g.: *} |
269 functions that return a boolean, e.g.:\<close> |
270 |
270 |
271 fun_cases xor_TrueE: "xor a b" and xor_FalseE: "\<not>xor a b" |
271 fun_cases xor_TrueE: "xor a b" and xor_FalseE: "\<not>xor a b" |
272 print_theorems |
272 print_theorems |
273 |
273 |
274 subsubsection {* Many parameters *} |
274 subsubsection \<open>Many parameters\<close> |
275 |
275 |
276 fun sum4 :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat" where |
276 fun sum4 :: "nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat" where |
277 "sum4 a b c d = a + b + c + d" |
277 "sum4 a b c d = a + b + c + d" |
278 |
278 |
279 fun_cases sum40E: "sum4 a b c d = 0" |
279 fun_cases sum40E: "sum4 a b c d = 0" |
280 |
280 |
281 lemma "sum4 a b c d = 0 \<Longrightarrow> a = 0" |
281 lemma "sum4 a b c d = 0 \<Longrightarrow> a = 0" |
282 by (erule sum40E) |
282 by (erule sum40E) |
283 |
283 |
284 |
284 |
285 subsection {* Partial Function Definitions *} |
285 subsection \<open>Partial Function Definitions\<close> |
286 |
286 |
287 text {* Partial functions in the option monad: *} |
287 text \<open>Partial functions in the option monad:\<close> |
288 |
288 |
289 partial_function (option) |
289 partial_function (option) |
290 collatz :: "nat \<Rightarrow> nat list option" |
290 collatz :: "nat \<Rightarrow> nat list option" |
291 where |
291 where |
292 "collatz n = |
292 "collatz n = |
297 |
297 |
298 declare collatz.simps[code] |
298 declare collatz.simps[code] |
299 value "collatz 23" |
299 value "collatz 23" |
300 |
300 |
301 |
301 |
302 text {* Tail-recursive functions: *} |
302 text \<open>Tail-recursive functions:\<close> |
303 |
303 |
304 partial_function (tailrec) fixpoint :: "('a \<Rightarrow> 'a) \<Rightarrow> 'a \<Rightarrow> 'a" |
304 partial_function (tailrec) fixpoint :: "('a \<Rightarrow> 'a) \<Rightarrow> 'a \<Rightarrow> 'a" |
305 where |
305 where |
306 "fixpoint f x = (if f x = x then x else fixpoint f (f x))" |
306 "fixpoint f x = (if f x = x then x else fixpoint f (f x))" |
307 |
307 |
308 |
308 |
309 subsection {* Regression tests *} |
309 subsection \<open>Regression tests\<close> |
310 |
310 |
311 text {* The following examples mainly serve as tests for the |
311 text \<open>The following examples mainly serve as tests for the |
312 function package *} |
312 function package\<close> |
313 |
313 |
314 fun listlen :: "'a list \<Rightarrow> nat" |
314 fun listlen :: "'a list \<Rightarrow> nat" |
315 where |
315 where |
316 "listlen [] = 0" |
316 "listlen [] = 0" |
317 | "listlen (x#xs) = Suc (listlen xs)" |
317 | "listlen (x#xs) = Suc (listlen xs)" |