doc-src/TutorialI/Fun/fun0.thy
author nipkow
Fri, 02 Nov 2007 08:59:15 +0100
changeset 25261 3dc292be0b54
parent 25260 71b2a1fefb84
child 25263 b54744935036
permissions -rw-r--r--
recdef -> fun
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     1
(*<*)
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     2
theory fun0 imports Main begin
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     3
(*>*)
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     4
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     5
text{*
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     6
\subsection{Definition}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     7
\label{sec:fun-examples}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     8
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     9
Here is a simple example, the \rmindex{Fibonacci function}:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    10
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    11
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    12
fun fib :: "nat \<Rightarrow> nat" where
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    13
  "fib 0 = 0" |
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    14
  "fib (Suc 0) = 1" |
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    15
  "fib (Suc(Suc x)) = fib x + fib (Suc x)"
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    16
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    17
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    18
This resembles ordinary functional programming languages. Note the obligatory
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    19
\isacommand{where} and \isa{|}. Command \isacommand{fun} declares and
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    20
defines the function in one go. Isabelle establishes termination automatically
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    21
because @{const fib}'s argument decreases in every recursive call.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    22
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    23
Slightly more interesting is the insertion of a fixed element
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    24
between any two elements of a list:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    25
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    26
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    27
fun sep :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    28
  "sep a []     = []" |
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    29
  "sep a [x]    = [x]" |
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    30
  "sep a (x#y#zs) = x # a # sep a (y#zs)";
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    31
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    32
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    33
This time the length of the list decreases with the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    34
recursive call; the first argument is irrelevant for termination.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    35
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    36
Pattern matching\index{pattern matching!and \isacommand{fun}}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    37
need not be exhaustive and may employ wildcards:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    38
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    39
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    40
fun last :: "'a list \<Rightarrow> 'a" where
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    41
  "last [x]      = x" |
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    42
  "last (_#y#zs) = last (y#zs)"
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    43
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    44
text{*
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    45
Overlapping patterns are disambiguated by taking the order of equations into
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    46
account, just as in functional programming:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    47
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    48
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    49
fun sep1 :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    50
  "sep1 a (x#y#zs) = x # a # sep1 a (y#zs)" |
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    51
  "sep1 _ xs       = xs"
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    52
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    53
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    54
To guarantee that the second equation can only be applied if the first
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    55
one does not match, Isabelle internally replaces the second equation
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    56
by the two possibilities that are left: @{prop"sep1 a [] = []"} and
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    57
@{prop"sep1 a [x] = [x]"}.  Thus the functions @{const sep} and
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    58
@{const sep1} are identical.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    59
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    60
Because of its pattern-matching syntax, \isacommand{fun} is also useful
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    61
for the definition of non-recursive functions:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    62
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    63
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    64
fun swap12 :: "'a list \<Rightarrow> 'a list" where
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    65
  "swap12 (x#y#zs) = y#x#zs" |
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    66
  "swap12 zs       = zs"
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    67
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    68
text{*
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    69
After a function~$f$ has been defined via \isacommand{fun},
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    70
its defining equations (or variants derived from them) are available
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    71
under the name $f$@{text".simps"} as theorems.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    72
For example, look (via \isacommand{thm}) at
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    73
@{thm[source]sep.simps} and @{thm[source]sep1.simps} to see that they define
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    74
the same function. What is more, those equations are automatically declared as
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    75
simplification rules.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    76
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    77
\subsection{Termination}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    78
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    79
Isabelle's automatic termination prover for \isacommand{fun} has a
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    80
fixed notion of the \emph{size} (of type @{typ nat}) of an
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    81
argument. The size of a natural number is the number itself. The size
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    82
of a list is its length. In general, every datatype @{text t} comes
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    83
with its own size function (named @{text"t.size"}) which counts the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    84
number of constructors in a term of type @{text t} --- more precisely
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    85
those constructors where one of the arguments is of the type itself:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    86
@{const Suc} in the case of @{typ nat} and @{const "op #"} in the case
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    87
of lists. A recursive function is accepted if \isacommand{fun} can
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    88
show that the size of one fixed argument becomes smaller with each
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    89
recursive call.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    90
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
    91
More generally, \isacommand{fun} allows any \emph{lexicographic
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    92
combination} of size measures in case there are multiple
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
    93
arguments. For example, the following version of \rmindex{Ackermann's
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    94
function} is accepted: *}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    95
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    96
fun ack2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    97
  "ack2 n 0 = Suc n" |
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    98
  "ack2 0 (Suc m) = ack2 (Suc 0) m" |
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    99
  "ack2 (Suc n) (Suc m) = ack2 (ack2 n (Suc m)) m"
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   100
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   101
text{* Thus the order of arguments has no influence on whether
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   102
\isacommand{fun} can prove termination of a function. For more details
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   103
see elsewhere~\cite{bulwahnKN07}.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   104
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   105
\subsection{Simplification}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   106
\label{sec:fun-simplification}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   107
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   108
Upon successful termination proof, the recursion equations become
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   109
simplification rules, just as with \isacommand{primrec}.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   110
In most cases this works fine, but there is a subtle
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   111
problem that must be mentioned: simplification may not
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   112
terminate because of automatic splitting of @{text "if"}.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   113
\index{*if expressions!splitting of}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   114
Let us look at an example:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   115
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   116
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   117
fun gcd :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   118
  "gcd m n = (if n=0 then m else gcd n (m mod n))"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   119
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   120
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   121
The second argument decreases with each recursive call.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   122
The termination condition
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   123
@{prop[display]"n ~= (0::nat) ==> m mod n < n"}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   124
is proved automatically because it is already present as a lemma in
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   125
HOL\@.  Thus the recursion equation becomes a simplification
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   126
rule. Of course the equation is nonterminating if we are allowed to unfold
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   127
the recursive call inside the @{text else} branch, which is why programming
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   128
languages and our simplifier don't do that. Unfortunately the simplifier does
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   129
something else that leads to the same problem: it splits 
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   130
each @{text "if"}-expression unless its
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   131
condition simplifies to @{term True} or @{term False}.  For
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   132
example, simplification reduces
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   133
@{prop[display]"gcd m n = k"}
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   134
in one step to
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   135
@{prop[display]"(if n=0 then m else gcd n (m mod n)) = k"}
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   136
where the condition cannot be reduced further, and splitting leads to
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   137
@{prop[display]"(n=0 --> m=k) & (n ~= 0 --> gcd n (m mod n)=k)"}
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   138
Since the recursive call @{term"gcd n (m mod n)"} is no longer protected by
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   139
an @{text "if"}, it is unfolded again, which leads to an infinite chain of
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   140
simplification steps. Fortunately, this problem can be avoided in many
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   141
different ways.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   142
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   143
The most radical solution is to disable the offending theorem
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   144
@{thm[source]split_if},
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   145
as shown in \S\ref{sec:AutoCaseSplits}.  However, we do not recommend this
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   146
approach: you will often have to invoke the rule explicitly when
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   147
@{text "if"} is involved.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   148
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   149
If possible, the definition should be given by pattern matching on the left
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   150
rather than @{text "if"} on the right. In the case of @{term gcd} the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   151
following alternative definition suggests itself:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   152
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   153
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   154
fun gcd1 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   155
  "gcd1 m 0 = m" |
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   156
  "gcd1 m n = gcd1 n (m mod n)"
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   157
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   158
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   159
The order of equations is important: it hides the side condition
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   160
@{prop"n ~= (0::nat)"}.  Unfortunately, in general the case distinction
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   161
may not be expressible by pattern matching.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   162
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   163
A simple alternative is to replace @{text "if"} by @{text case}, 
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   164
which is also available for @{typ bool} and is not split automatically:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   165
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   166
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   167
fun gcd2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   168
  "gcd2 m n = (case n=0 of True \<Rightarrow> m | False \<Rightarrow> gcd2 n (m mod n))"
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   169
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   170
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   171
This is probably the neatest solution next to pattern matching, and it is
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   172
always available.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   173
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   174
A final alternative is to replace the offending simplification rules by
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   175
derived conditional ones. For @{term gcd} it means we have to prove
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   176
these lemmas:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   177
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   178
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   179
lemma [simp]: "gcd m 0 = m"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   180
apply(simp)
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   181
done
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   182
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   183
lemma [simp]: "n \<noteq> 0 \<Longrightarrow> gcd m n = gcd n (m mod n)"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   184
apply(simp)
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   185
done
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   186
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   187
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   188
Simplification terminates for these proofs because the condition of the @{text
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   189
"if"} simplifies to @{term True} or @{term False}.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   190
Now we can disable the original simplification rule:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   191
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   192
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   193
declare gcd.simps [simp del]
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   194
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   195
text{*
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   196
\index{induction!recursion|(}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   197
\index{recursion induction|(}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   198
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   199
\subsection{Induction}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   200
\label{sec:fun-induction}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   201
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   202
Having defined a function we might like to prove something about it.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   203
Since the function is recursive, the natural proof principle is
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   204
again induction. But this time the structural form of induction that comes
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   205
with datatypes is unlikely to work well --- otherwise we could have defined the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   206
function by \isacommand{primrec}. Therefore \isacommand{fun} automatically
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   207
proves a suitable induction rule $f$@{text".induct"} that follows the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   208
recursion pattern of the particular function $f$. We call this
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   209
\textbf{recursion induction}. Roughly speaking, it
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   210
requires you to prove for each \isacommand{fun} equation that the property
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   211
you are trying to establish holds for the left-hand side provided it holds
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   212
for all recursive calls on the right-hand side. Here is a simple example
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   213
involving the predefined @{term"map"} functional on lists:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   214
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   215
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   216
lemma "map f (sep x xs) = sep (f x) (map f xs)"
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   217
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   218
txt{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   219
Note that @{term"map f xs"}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   220
is the result of applying @{term"f"} to all elements of @{term"xs"}. We prove
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   221
this lemma by recursion induction over @{term"sep"}:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   222
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   223
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   224
apply(induct_tac x xs rule: sep.induct);
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   225
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   226
txt{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   227
The resulting proof state has three subgoals corresponding to the three
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   228
clauses for @{term"sep"}:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   229
@{subgoals[display,indent=0]}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   230
The rest is pure simplification:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   231
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   232
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   233
apply simp_all;
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   234
done
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   235
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   236
text{*
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   237
Try proving the above lemma by structural induction, and you find that you
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   238
need an additional case distinction.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   239
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   240
In general, the format of invoking recursion induction is
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   241
\begin{quote}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   242
\isacommand{apply}@{text"(induct_tac"} $x@1 \dots x@n$ @{text"rule:"} $f$@{text".induct)"}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   243
\end{quote}\index{*induct_tac (method)}%
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   244
where $x@1~\dots~x@n$ is a list of free variables in the subgoal and $f$ the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   245
name of a function that takes an $n$-tuple. Usually the subgoal will
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   246
contain the term $f(x@1,\dots,x@n)$ but this need not be the case. The
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   247
induction rules do not mention $f$ at all. Here is @{thm[source]sep.induct}:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   248
\begin{isabelle}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   249
{\isasymlbrakk}~{\isasymAnd}a.~P~a~[];\isanewline
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   250
~~{\isasymAnd}a~x.~P~a~[x];\isanewline
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   251
~~{\isasymAnd}a~x~y~zs.~P~a~(y~\#~zs)~{\isasymLongrightarrow}~P~a~(x~\#~y~\#~zs){\isasymrbrakk}\isanewline
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   252
{\isasymLongrightarrow}~P~u~v%
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   253
\end{isabelle}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   254
It merely says that in order to prove a property @{term"P"} of @{term"u"} and
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   255
@{term"v"} you need to prove it for the three cases where @{term"v"} is the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   256
empty list, the singleton list, and the list with at least two elements.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   257
The final case has an induction hypothesis:  you may assume that @{term"P"}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   258
holds for the tail of that list.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   259
\index{induction!recursion|)}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   260
\index{recursion induction|)}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   261
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   262
(*<*)
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   263
end
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   264
(*>*)