1 (*<*) |
1 (*<*) |
2 theory Itrev = Main:; |
2 theory Itrev = Main:; |
3 (*>*) |
3 (*>*) |
4 |
4 |
5 text{* |
5 text{* Function \isa{rev} has quadratic worst-case running time |
6 We define a tail-recursive version of list-reversal, |
6 because it calls function \isa{\at} for each element of the list and |
7 i.e.\ one that can be compiled into a loop: |
7 \isa{\at} is linear in its first argument. A linear time version of |
8 *}; |
8 \isa{rev} reqires an extra argument where the result is accumulated |
|
9 gradually, using only \isa{\#}:*} |
9 |
10 |
10 consts itrev :: "'a list \\<Rightarrow> 'a list \\<Rightarrow> 'a list"; |
11 consts itrev :: "'a list \\<Rightarrow> 'a list \\<Rightarrow> 'a list"; |
11 primrec |
12 primrec |
12 "itrev [] ys = ys" |
13 "itrev [] ys = ys" |
13 "itrev (x#xs) ys = itrev xs (x#ys)"; |
14 "itrev (x#xs) ys = itrev xs (x#ys)"; |
14 |
15 |
15 text{*\noindent |
16 text{*\noindent The behaviour of \isa{itrev} is simple: it reverses |
16 The behaviour of \isa{itrev} is simple: it reverses its first argument by |
17 its first argument by stacking its elements onto the second argument, |
17 stacking its elements onto the second argument, and returning that second |
18 and returning that second argument when the first one becomes |
18 argument when the first one becomes empty. |
19 empty. Note that \isa{itrev} is tail-recursive, i.e.\ it can be |
19 We need to show that \isa{itrev} does indeed reverse its first argument |
20 compiled into a loop. |
20 provided the second one is empty: |
21 |
21 *}; |
22 Naturally, we would like to show that \isa{itrev} does indeed reverse |
|
23 its first argument provided the second one is empty: *}; |
22 |
24 |
23 lemma "itrev xs [] = rev xs"; |
25 lemma "itrev xs [] = rev xs"; |
24 |
26 |
25 txt{*\noindent |
27 txt{*\noindent |
26 There is no choice as to the induction variable, and we immediately simplify: |
28 There is no choice as to the induction variable, and we immediately simplify: |