doc-src/TutorialI/fp.tex
author wenzelm
Mon, 21 Aug 2000 19:17:07 +0200
changeset 9673 1b2d4f995b13
parent 9644 6b0b6b471855
child 9689 751fde5307e4
permissions -rw-r--r--
updated;
nipkow@8743
     1
\chapter{Functional Programming in HOL}
nipkow@8743
     2
nipkow@8743
     3
Although on the surface this chapter is mainly concerned with how to write
nipkow@8743
     4
functional programs in HOL and how to verify them, most of the
nipkow@8743
     5
constructs and proof procedures introduced are general purpose and recur in
nipkow@8743
     6
any specification or verification task.
nipkow@8743
     7
nipkow@9541
     8
The dedicated functional programmer should be warned: HOL offers only
nipkow@9541
     9
\emph{total functional programming} --- all functions in HOL must be total;
nipkow@9541
    10
lazy data structures are not directly available. On the positive side,
nipkow@9541
    11
functions in HOL need not be computable: HOL is a specification language that
nipkow@9541
    12
goes well beyond what can be expressed as a program. However, for the time
nipkow@9541
    13
being we concentrate on the computable.
nipkow@8743
    14
nipkow@8743
    15
\section{An introductory theory}
nipkow@8743
    16
\label{sec:intro-theory}
nipkow@8743
    17
nipkow@8743
    18
Functional programming needs datatypes and functions. Both of them can be
nipkow@8743
    19
defined in a theory with a syntax reminiscent of languages like ML or
nipkow@8743
    20
Haskell. As an example consider the theory in figure~\ref{fig:ToyList}.
nipkow@8743
    21
We will now examine it line by line.
nipkow@8743
    22
nipkow@8743
    23
\begin{figure}[htbp]
nipkow@8743
    24
\begin{ttbox}\makeatother
nipkow@8743
    25
\input{ToyList2/ToyList1}\end{ttbox}
nipkow@8743
    26
\caption{A theory of lists}
nipkow@8743
    27
\label{fig:ToyList}
nipkow@8743
    28
\end{figure}
nipkow@8743
    29
nipkow@8743
    30
{\makeatother\input{ToyList/document/ToyList.tex}}
nipkow@8743
    31
nipkow@8743
    32
The complete proof script is shown in figure~\ref{fig:ToyList-proofs}. The
nipkow@8743
    33
concatenation of figures \ref{fig:ToyList} and \ref{fig:ToyList-proofs}
nipkow@8743
    34
constitutes the complete theory \texttt{ToyList} and should reside in file
nipkow@8743
    35
\texttt{ToyList.thy}. It is good practice to present all declarations and
nipkow@8743
    36
definitions at the beginning of a theory to facilitate browsing.
nipkow@8743
    37
nipkow@8743
    38
\begin{figure}[htbp]
nipkow@8743
    39
\begin{ttbox}\makeatother
nipkow@8743
    40
\input{ToyList2/ToyList2}\end{ttbox}
nipkow@8743
    41
\caption{Proofs about lists}
nipkow@8743
    42
\label{fig:ToyList-proofs}
nipkow@8743
    43
\end{figure}
nipkow@8743
    44
nipkow@8743
    45
\subsubsection*{Review}
nipkow@8743
    46
nipkow@8743
    47
This is the end of our toy proof. It should have familiarized you with
nipkow@8743
    48
\begin{itemize}
nipkow@8743
    49
\item the standard theorem proving procedure:
nipkow@8743
    50
state a goal (lemma or theorem); proceed with proof until a separate lemma is
nipkow@8743
    51
required; prove that lemma; come back to the original goal.
nipkow@8743
    52
\item a specific procedure that works well for functional programs:
nipkow@8743
    53
induction followed by all-out simplification via \isa{auto}.
nipkow@8743
    54
\item a basic repertoire of proof commands.
nipkow@8743
    55
\end{itemize}
nipkow@8743
    56
nipkow@8743
    57
nipkow@8743
    58
\section{Some helpful commands}
nipkow@8743
    59
\label{sec:commands-and-hints}
nipkow@8743
    60
nipkow@8743
    61
This section discusses a few basic commands for manipulating the proof state
nipkow@8743
    62
and can be skipped by casual readers.
nipkow@8743
    63
nipkow@8743
    64
There are two kinds of commands used during a proof: the actual proof
nipkow@8743
    65
commands and auxiliary commands for examining the proof state and controlling
nipkow@8743
    66
the display. Simple proof commands are of the form
nipkow@8743
    67
\isacommand{apply}\isa{(method)}\indexbold{apply} where \bfindex{method} is a
nipkow@8743
    68
synonym for ``theorem proving function''. Typical examples are
nipkow@8743
    69
\isa{induct_tac} and \isa{auto}. Further methods are introduced throughout
nipkow@8743
    70
the tutorial.  Unless stated otherwise you may assume that a method attacks
nipkow@8743
    71
merely the first subgoal. An exception is \isa{auto} which tries to solve all
nipkow@8743
    72
subgoals.
nipkow@8743
    73
nipkow@8743
    74
The most useful auxiliary commands are:
nipkow@8743
    75
\begin{description}
nipkow@8743
    76
\item[Undoing:] \isacommand{undo}\indexbold{*undo} undoes the effect of the
nipkow@8743
    77
  last command; \isacommand{undo} can be undone by
nipkow@8743
    78
  \isacommand{redo}\indexbold{*redo}.  Both are only needed at the shell
nipkow@8743
    79
  level and should not occur in the final theory.
nipkow@8743
    80
\item[Printing the current state:] \isacommand{pr}\indexbold{*pr} redisplays
nipkow@8743
    81
  the current proof state, for example when it has disappeared off the
nipkow@8743
    82
  screen.
nipkow@8743
    83
\item[Limiting the number of subgoals:] \isacommand{pr}~$n$ tells Isabelle to
nipkow@8743
    84
  print only the first $n$ subgoals from now on and redisplays the current
nipkow@8743
    85
  proof state. This is helpful when there are many subgoals.
nipkow@8743
    86
\item[Modifying the order of subgoals:]
nipkow@8743
    87
\isacommand{defer}\indexbold{*defer} moves the first subgoal to the end and
nipkow@8743
    88
\isacommand{prefer}\indexbold{*prefer}~$n$ moves subgoal $n$ to the front.
nipkow@8743
    89
\item[Printing theorems:]
nipkow@8743
    90
  \isacommand{thm}\indexbold{*thm}~\textit{name}$@1$~\dots~\textit{name}$@n$
nipkow@8743
    91
  prints the named theorems.
nipkow@8743
    92
\item[Displaying types:] We have already mentioned the flag
nipkow@8743
    93
  \ttindex{show_types} above. It can also be useful for detecting typos in
nipkow@8743
    94
  formulae early on. For example, if \texttt{show_types} is set and the goal
nipkow@8743
    95
  \isa{rev(rev xs) = xs} is started, Isabelle prints the additional output
nipkow@8743
    96
\par\noindent
nipkow@8743
    97
\begin{isabelle}%
nipkow@8743
    98
Variables:\isanewline
nipkow@8743
    99
~~xs~::~'a~list
nipkow@8743
   100
\end{isabelle}%
nipkow@8743
   101
\par\noindent
nipkow@8743
   102
which tells us that Isabelle has correctly inferred that
nipkow@8743
   103
\isa{xs} is a variable of list type. On the other hand, had we
nipkow@8743
   104
made a typo as in \isa{rev(re xs) = xs}, the response
nipkow@8743
   105
\par\noindent
nipkow@8743
   106
\begin{isabelle}%
nipkow@8743
   107
Variables:\isanewline
nipkow@8743
   108
~~re~::~'a~list~{\isasymRightarrow}~'a~list\isanewline
nipkow@8743
   109
~~xs~::~'a~list%
nipkow@8743
   110
\end{isabelle}%
nipkow@8743
   111
\par\noindent
nipkow@8743
   112
would have alerted us because of the unexpected variable \isa{re}.
nipkow@8743
   113
\item[Reading terms and types:] \isacommand{term}\indexbold{*term}
nipkow@8743
   114
  \textit{string} reads, type-checks and prints the given string as a term in
nipkow@8743
   115
  the current context; the inferred type is output as well.
nipkow@8743
   116
  \isacommand{typ}\indexbold{*typ} \textit{string} reads and prints the given
nipkow@8743
   117
  string as a type in the current context.
nipkow@8743
   118
\item[(Re)loading theories:] When you start your interaction you must open a
nipkow@8771
   119
  named theory with the line \isa{\isacommand{theory}~T~=~\dots~:}. Isabelle
nipkow@8771
   120
  automatically loads all the required parent theories from their respective
nipkow@8771
   121
  files (which may take a moment, unless the theories are already loaded and
nipkow@9541
   122
  the files have not been modified).
nipkow@8743
   123
  
nipkow@8743
   124
  If you suddenly discover that you need to modify a parent theory of your
nipkow@9494
   125
  current theory you must first abandon your current theory\indexbold{abandon
nipkow@9494
   126
  theory}\indexbold{theory!abandon} (at the shell
nipkow@8743
   127
  level type \isacommand{kill}\indexbold{*kill}). After the parent theory has
nipkow@8743
   128
  been modified you go back to your original theory. When its first line
nipkow@8743
   129
  \isacommand{theory}\texttt{~T~=}~\dots~\texttt{:} is processed, the
nipkow@8743
   130
  modified parent is reloaded automatically.
nipkow@9541
   131
  
nipkow@9541
   132
  The only time when you need to load a theory by hand is when you simply
nipkow@9541
   133
  want to check if it loads successfully without wanting to make use of the
nipkow@9541
   134
  theory itself. This you can do by typing
nipkow@9541
   135
  \isa{\isacommand{use\_thy}\indexbold{*use_thy}~"T"}.
nipkow@8743
   136
\end{description}
nipkow@8743
   137
Further commands are found in the Isabelle/Isar Reference Manual.
nipkow@8743
   138
nipkow@8771
   139
We now examine Isabelle's functional programming constructs systematically,
nipkow@8771
   140
starting with inductive datatypes.
nipkow@8771
   141
nipkow@8743
   142
nipkow@8743
   143
\section{Datatypes}
nipkow@8743
   144
\label{sec:datatype}
nipkow@8743
   145
nipkow@8743
   146
Inductive datatypes are part of almost every non-trivial application of HOL.
nipkow@8743
   147
First we take another look at a very important example, the datatype of
nipkow@8743
   148
lists, before we turn to datatypes in general. The section closes with a
nipkow@8743
   149
case study.
nipkow@8743
   150
nipkow@8743
   151
nipkow@8743
   152
\subsection{Lists}
nipkow@8743
   153
\indexbold{*list}
nipkow@8743
   154
nipkow@8743
   155
Lists are one of the essential datatypes in computing. Readers of this
nipkow@8743
   156
tutorial and users of HOL need to be familiar with their basic operations.
nipkow@8771
   157
Theory \isa{ToyList} is only a small fragment of HOL's predefined theory
nipkow@8771
   158
\isa{List}\footnote{\url{http://isabelle.in.tum.de/library/HOL/List.html}}.
nipkow@8743
   159
The latter contains many further operations. For example, the functions
nipkow@8771
   160
\isaindexbold{hd} (``head'') and \isaindexbold{tl} (``tail'') return the first
nipkow@8743
   161
element and the remainder of a list. (However, pattern-matching is usually
nipkow@8771
   162
preferable to \isa{hd} and \isa{tl}.)  Theory \isa{List} also contains
nipkow@8743
   163
more syntactic sugar: \isa{[}$x@1$\isa{,}\dots\isa{,}$x@n$\isa{]} abbreviates
nipkow@8743
   164
$x@1$\isa{\#}\dots\isa{\#}$x@n$\isa{\#[]}.  In the rest of the tutorial we
nipkow@8743
   165
always use HOL's predefined lists.
nipkow@8743
   166
nipkow@8743
   167
nipkow@8743
   168
\subsection{The general format}
nipkow@8743
   169
\label{sec:general-datatype}
nipkow@8743
   170
nipkow@8743
   171
The general HOL \isacommand{datatype} definition is of the form
nipkow@8743
   172
\[
nipkow@8743
   173
\isacommand{datatype}~(\alpha@1, \dots, \alpha@n) \, t ~=~
nipkow@8743
   174
C@1~\tau@{11}~\dots~\tau@{1k@1} ~\mid~ \dots ~\mid~
nipkow@8743
   175
C@m~\tau@{m1}~\dots~\tau@{mk@m}
nipkow@8743
   176
\]
nipkow@8771
   177
where $\alpha@i$ are distinct type variables (the parameters), $C@i$ are distinct
nipkow@8743
   178
constructor names and $\tau@{ij}$ are types; it is customary to capitalize
nipkow@8743
   179
the first letter in constructor names. There are a number of
nipkow@8743
   180
restrictions (such as that the type should not be empty) detailed
nipkow@8743
   181
elsewhere~\cite{isabelle-HOL}. Isabelle notifies you if you violate them.
nipkow@8743
   182
nipkow@8743
   183
Laws about datatypes, such as \isa{[] \isasymnoteq~x\#xs} and
nipkow@8743
   184
\isa{(x\#xs = y\#ys) = (x=y \isasymand~xs=ys)}, are used automatically
nipkow@8743
   185
during proofs by simplification.  The same is true for the equations in
nipkow@8743
   186
primitive recursive function definitions.
nipkow@8743
   187
nipkow@9644
   188
Every datatype $t$ comes equipped with a \isa{size} function from $t$ into
nipkow@9644
   189
the natural numbers (see~\S\ref{sec:nat} below). For lists, \isa{size} is
nipkow@9644
   190
just the length, i.e.\ \isa{size [] = 0} and \isa{size(x \# xs) = size xs +
nipkow@9644
   191
  1}.  In general, \isa{size} returns \isa{0} for all constructors that do
nipkow@9644
   192
not have an argument of type $t$, and for all other constructors \isa{1 +}
nipkow@9644
   193
the sum of the sizes of all arguments of type $t$. Note that because
nipkow@9644
   194
\isa{size} is defined on every datatype, it is overloaded; on lists
nipkow@9644
   195
\isa{size} is also called \isa{length}, which is not overloaded.
nipkow@9644
   196
nipkow@9644
   197
nipkow@8743
   198
\subsection{Primitive recursion}
nipkow@8743
   199
nipkow@8743
   200
Functions on datatypes are usually defined by recursion. In fact, most of the
nipkow@8743
   201
time they are defined by what is called \bfindex{primitive recursion}.
nipkow@8743
   202
The keyword \isacommand{primrec}\indexbold{*primrec} is followed by a list of
nipkow@8743
   203
equations
nipkow@8743
   204
\[ f \, x@1 \, \dots \, (C \, y@1 \, \dots \, y@k)\, \dots \, x@n = r \]
nipkow@8743
   205
such that $C$ is a constructor of the datatype $t$ and all recursive calls of
nipkow@8743
   206
$f$ in $r$ are of the form $f \, \dots \, y@i \, \dots$ for some $i$. Thus
nipkow@8743
   207
Isabelle immediately sees that $f$ terminates because one (fixed!) argument
nipkow@8743
   208
becomes smaller with every recursive call. There must be exactly one equation
nipkow@8743
   209
for each constructor.  Their order is immaterial.
nipkow@8771
   210
A more general method for defining total recursive functions is introduced in
nipkow@8743
   211
\S\ref{sec:recdef}.
nipkow@8743
   212
nipkow@9493
   213
\begin{exercise}\label{ex:Tree}
nipkow@8743
   214
\input{Misc/document/Tree.tex}%
nipkow@8743
   215
\end{exercise}
nipkow@8743
   216
nipkow@8743
   217
\subsection{Case expressions}
nipkow@8743
   218
\label{sec:case-expressions}
nipkow@8743
   219
nipkow@8743
   220
HOL also features \isaindexbold{case}-expressions for analyzing
nipkow@8743
   221
elements of a datatype. For example,
nipkow@8743
   222
% case xs of [] => 0 | y#ys => y
nipkow@8743
   223
\begin{isabellepar}%
nipkow@8743
   224
~~~case~xs~of~[]~{\isasymRightarrow}~0~|~y~\#~ys~{\isasymRightarrow}~y
nipkow@8743
   225
\end{isabellepar}%
nipkow@8743
   226
evaluates to \isa{0} if \isa{xs} is \isa{[]} and to \isa{y} if 
nipkow@8743
   227
\isa{xs} is \isa{y\#ys}. (Since the result in both branches must be of
nipkow@8743
   228
the same type, it follows that \isa{y::nat} and hence
nipkow@8743
   229
\isa{xs::(nat)list}.)
nipkow@8743
   230
nipkow@8743
   231
In general, if $e$ is a term of the datatype $t$ defined in
nipkow@8743
   232
\S\ref{sec:general-datatype} above, the corresponding
nipkow@8743
   233
\isa{case}-expression analyzing $e$ is
nipkow@8743
   234
\[
nipkow@8743
   235
\begin{array}{rrcl}
nipkow@8743
   236
\isa{case}~e~\isa{of} & C@1~x@{11}~\dots~x@{1k@1} & \To & e@1 \\
nipkow@8743
   237
                           \vdots \\
nipkow@8743
   238
                           \mid & C@m~x@{m1}~\dots~x@{mk@m} & \To & e@m
nipkow@8743
   239
\end{array}
nipkow@8743
   240
\]
nipkow@8743
   241
nipkow@8743
   242
\begin{warn}
nipkow@8743
   243
{\em All} constructors must be present, their order is fixed, and nested
nipkow@8743
   244
patterns are not supported.  Violating these restrictions results in strange
nipkow@8743
   245
error messages.
nipkow@8743
   246
\end{warn}
nipkow@8743
   247
\noindent
nipkow@8743
   248
Nested patterns can be simulated by nested \isa{case}-expressions: instead
nipkow@8743
   249
of
nipkow@8743
   250
% case xs of [] => 0 | [x] => x | x#(y#zs) => y
nipkow@8743
   251
\begin{isabellepar}%
nipkow@8743
   252
~~~case~xs~of~[]~{\isasymRightarrow}~0~|~[x]~{\isasymRightarrow}~x~|~x~\#~y~\#~zs~{\isasymRightarrow}~y
nipkow@8743
   253
\end{isabellepar}%
nipkow@8743
   254
write
nipkow@8743
   255
% term(latex xsymbols symbols)"case xs of [] => 0 | x#ys => (case ys of [] => x | y#zs => y)";
nipkow@8743
   256
\begin{isabellepar}%
nipkow@8743
   257
~~~case~xs~of~[]~{\isasymRightarrow}~0~|~x~\#~ys~{\isasymRightarrow}~(case~ys~of~[]~{\isasymRightarrow}~x~|~y~\#~zs~{\isasymRightarrow}~y)%
nipkow@8743
   258
\end{isabellepar}%
nipkow@8743
   259
Note that \isa{case}-expressions should be enclosed in parentheses to
nipkow@8743
   260
indicate their scope.
nipkow@8743
   261
nipkow@8743
   262
\subsection{Structural induction and case distinction}
nipkow@8743
   263
\indexbold{structural induction}
nipkow@8743
   264
\indexbold{induction!structural}
nipkow@8743
   265
\indexbold{case distinction}
nipkow@8743
   266
nipkow@8743
   267
Almost all the basic laws about a datatype are applied automatically during
nipkow@8743
   268
simplification. Only induction is invoked by hand via \isaindex{induct_tac},
nipkow@8743
   269
which works for any datatype. In some cases, induction is overkill and a case
nipkow@8743
   270
distinction over all constructors of the datatype suffices. This is performed
nipkow@8743
   271
by \isaindexbold{case_tac}. A trivial example:
nipkow@8743
   272
nipkow@8743
   273
\input{Misc/document/cases.tex}%
nipkow@8743
   274
nipkow@8743
   275
Note that we do not need to give a lemma a name if we do not intend to refer
nipkow@8743
   276
to it explicitly in the future.
nipkow@8743
   277
nipkow@8743
   278
\begin{warn}
nipkow@8743
   279
  Induction is only allowed on free (or \isasymAnd-bound) variables that
nipkow@9644
   280
  should not occur among the assumptions of the subgoal; see
nipkow@9644
   281
  \S\ref{sec:ind-var-in-prems} for details. Case distinction
nipkow@8743
   282
  (\isa{case_tac}) works for arbitrary terms, which need to be
nipkow@8743
   283
  quoted if they are non-atomic.
nipkow@8743
   284
\end{warn}
nipkow@8743
   285
nipkow@8743
   286
nipkow@8743
   287
\subsection{Case study: boolean expressions}
nipkow@8743
   288
\label{sec:boolex}
nipkow@8743
   289
nipkow@8743
   290
The aim of this case study is twofold: it shows how to model boolean
nipkow@8743
   291
expressions and some algorithms for manipulating them, and it demonstrates
nipkow@8743
   292
the constructs introduced above.
nipkow@8743
   293
nipkow@8743
   294
\input{Ifexpr/document/Ifexpr.tex}
nipkow@8771
   295
\medskip
nipkow@8743
   296
nipkow@8743
   297
How does one come up with the required lemmas? Try to prove the main theorems
nipkow@8743
   298
without them and study carefully what \isa{auto} leaves unproved. This has
nipkow@8743
   299
to provide the clue.  The necessity of universal quantification
nipkow@8743
   300
(\isa{\isasymforall{}t e}) in the two lemmas is explained in
nipkow@8743
   301
\S\ref{sec:InductionHeuristics}
nipkow@8743
   302
nipkow@8743
   303
\begin{exercise}
nipkow@8743
   304
  We strengthen the definition of a \isa{normal} If-expression as follows:
nipkow@8743
   305
  the first argument of all \isa{IF}s must be a variable. Adapt the above
nipkow@8743
   306
  development to this changed requirement. (Hint: you may need to formulate
nipkow@8743
   307
  some of the goals as implications (\isasymimp) rather than equalities
nipkow@8743
   308
  (\isa{=}).)
nipkow@8743
   309
\end{exercise}
nipkow@8743
   310
nipkow@8743
   311
\section{Some basic types}
nipkow@8743
   312
nipkow@8743
   313
nipkow@8743
   314
\subsection{Natural numbers}
nipkow@9644
   315
\label{sec:nat}
nipkow@8743
   316
\index{arithmetic|(}
nipkow@8743
   317
nipkow@8743
   318
\input{Misc/document/fakenat.tex}
nipkow@8743
   319
\input{Misc/document/natsum.tex}
nipkow@8743
   320
nipkow@8743
   321
The usual arithmetic operations \ttindexboldpos{+}{$HOL2arithfun},
nipkow@8743
   322
\ttindexboldpos{-}{$HOL2arithfun}, \ttindexboldpos{*}{$HOL2arithfun},
nipkow@8743
   323
\isaindexbold{div}, \isaindexbold{mod}, \isaindexbold{min} and
nipkow@8743
   324
\isaindexbold{max} are predefined, as are the relations
nipkow@8743
   325
\indexboldpos{\isasymle}{$HOL2arithrel} and
nipkow@8743
   326
\ttindexboldpos{<}{$HOL2arithrel}. There is even a least number operation
nipkow@8743
   327
\isaindexbold{LEAST}. For example, \isa{(LEAST n.$\,$1 < n) = 2}, although
nipkow@8743
   328
Isabelle does not prove this completely automatically. Note that \isa{1} and
nipkow@8743
   329
\isa{2} are available as abbreviations for the corresponding
nipkow@8743
   330
\isa{Suc}-expressions. If you need the full set of numerals,
nipkow@8743
   331
see~\S\ref{nat-numerals}.
nipkow@8743
   332
nipkow@8743
   333
\begin{warn}
nipkow@9494
   334
  The constant \ttindexbold{0} and the operations
nipkow@9494
   335
  \ttindexboldpos{+}{$HOL2arithfun}, \ttindexboldpos{-}{$HOL2arithfun},
nipkow@9494
   336
  \ttindexboldpos{*}{$HOL2arithfun}, \isaindexbold{min}, \isaindexbold{max},
nipkow@8743
   337
  \indexboldpos{\isasymle}{$HOL2arithrel} and
nipkow@8743
   338
  \ttindexboldpos{<}{$HOL2arithrel} are overloaded, i.e.\ they are available
nipkow@8743
   339
  not just for natural numbers but at other types as well (see
nipkow@9494
   340
  \S\ref{sec:TypeClasses}). For example, given the goal \isa{x+0 = x}, there
nipkow@9494
   341
  is nothing to indicate that you are talking about natural numbers.  Hence
nipkow@9494
   342
  Isabelle can only infer that \isa{x} is of some arbitrary type where
nipkow@9494
   343
  \isa{0} and \isa{+} are declared. As a consequence, you will be unable to
nipkow@9494
   344
  prove the goal (although it may take you some time to realize what has
nipkow@9494
   345
  happened if \texttt{show_types} is not set).  In this particular example,
nipkow@9494
   346
  you need to include an explicit type constraint, for example \isa{x+0 =
nipkow@9494
   347
    (x::nat)}.  If there is enough contextual information this may not be
nipkow@9494
   348
  necessary: \isa{Suc x = x} automatically implies \isa{x::nat} because
nipkow@9494
   349
  \isa{Suc} is not overloaded.
nipkow@8743
   350
\end{warn}
nipkow@8743
   351
nipkow@8743
   352
Simple arithmetic goals are proved automatically by both \isa{auto}
nipkow@8743
   353
and the simplification methods introduced in \S\ref{sec:Simplification}.  For
nipkow@8743
   354
example,
nipkow@8743
   355
nipkow@8743
   356
\input{Misc/document/arith1.tex}%
nipkow@8743
   357
is proved automatically. The main restriction is that only addition is taken
nipkow@8743
   358
into account; other arithmetic operations and quantified formulae are ignored.
nipkow@8743
   359
nipkow@8743
   360
For more complex goals, there is the special method
nipkow@8743
   361
\isaindexbold{arith} (which attacks the first subgoal). It proves
nipkow@8743
   362
arithmetic goals involving the usual logical connectives (\isasymnot,
nipkow@8743
   363
\isasymand, \isasymor, \isasymimp), the relations \isasymle\ and \isa{<}, and
nipkow@8743
   364
the operations \isa{+}, \isa{-}, \isa{min} and \isa{max}. For example,
nipkow@8743
   365
nipkow@8743
   366
\input{Misc/document/arith2.tex}%
nipkow@8743
   367
succeeds because \isa{k*k} can be treated as atomic.
nipkow@8743
   368
In contrast,
nipkow@8743
   369
nipkow@8743
   370
\input{Misc/document/arith3.tex}%
nipkow@8743
   371
is not even proved by \isa{arith} because the proof relies essentially
nipkow@8743
   372
on properties of multiplication.
nipkow@8743
   373
nipkow@8743
   374
\begin{warn}
nipkow@8743
   375
  The running time of \isa{arith} is exponential in the number of occurrences
nipkow@8743
   376
  of \ttindexboldpos{-}{$HOL2arithfun}, \isaindexbold{min} and
nipkow@8743
   377
  \isaindexbold{max} because they are first eliminated by case distinctions.
nipkow@8743
   378
nipkow@8743
   379
  \isa{arith} is incomplete even for the restricted class of formulae
nipkow@8743
   380
  described above (known as ``linear arithmetic''). If divisibility plays a
nipkow@8743
   381
  role, it may fail to prove a valid formula, for example $m+m \neq n+n+1$.
nipkow@8743
   382
  Fortunately, such examples are rare in practice.
nipkow@8743
   383
\end{warn}
nipkow@8743
   384
nipkow@8743
   385
\index{arithmetic|)}
nipkow@8743
   386
nipkow@8743
   387
nipkow@8743
   388
\subsection{Products}
nipkow@9541
   389
\input{Misc/document/pairs.tex}
nipkow@8743
   390
nipkow@8743
   391
%FIXME move stuff below into section on proofs about products?
nipkow@8743
   392
\begin{warn}
nipkow@8743
   393
  Abstraction over pairs and tuples is merely a convenient shorthand for a
nipkow@8743
   394
  more complex internal representation.  Thus the internal and external form
nipkow@8743
   395
  of a term may differ, which can affect proofs. If you want to avoid this
nipkow@8743
   396
  complication, use \isa{fst} and \isa{snd}, i.e.\ write
nipkow@8743
   397
  \isa{\isasymlambda{}p.~fst p + snd p} instead of
nipkow@8743
   398
  \isa{\isasymlambda(x,y).~x + y}.  See~\S\ref{proofs-about-products} for
nipkow@8743
   399
  theorem proving with tuple patterns.
nipkow@8743
   400
\end{warn}
nipkow@8743
   401
nipkow@9541
   402
Note that products, like natural numbers, are datatypes, which means
nipkow@8743
   403
in particular that \isa{induct_tac} and \isa{case_tac} are applicable to
nipkow@8743
   404
products (see \S\ref{proofs-about-products}).
nipkow@8743
   405
nipkow@9541
   406
Instead of tuples with many components (where ``many'' is not much above 2),
nipkow@9541
   407
it is far preferable to use record types (see \S\ref{sec:records}).
nipkow@9541
   408
nipkow@8743
   409
\section{Definitions}
nipkow@8743
   410
\label{sec:Definitions}
nipkow@8743
   411
nipkow@8743
   412
A definition is simply an abbreviation, i.e.\ a new name for an existing
nipkow@8743
   413
construction. In particular, definitions cannot be recursive. Isabelle offers
nipkow@8743
   414
definitions on the level of types and terms. Those on the type level are
nipkow@8743
   415
called type synonyms, those on the term level are called (constant)
nipkow@8743
   416
definitions.
nipkow@8743
   417
nipkow@8743
   418
nipkow@8743
   419
\subsection{Type synonyms}
nipkow@8771
   420
\indexbold{type synonym}
nipkow@8743
   421
nipkow@8743
   422
Type synonyms are similar to those found in ML. Their syntax is fairly self
nipkow@8743
   423
explanatory:
nipkow@8743
   424
nipkow@8743
   425
\input{Misc/document/types.tex}%
nipkow@8743
   426
nipkow@8743
   427
Note that pattern-matching is not allowed, i.e.\ each definition must be of
nipkow@8743
   428
the form $f\,x@1\,\dots\,x@n~\isasymequiv~t$.
nipkow@8743
   429
Section~\S\ref{sec:Simplification} explains how definitions are used
nipkow@8743
   430
in proofs.
nipkow@8743
   431
nipkow@8743
   432
\begin{warn}%
nipkow@8743
   433
A common mistake when writing definitions is to introduce extra free
nipkow@8743
   434
variables on the right-hand side as in the following fictitious definition:
nipkow@8743
   435
\input{Misc/document/prime_def.tex}%
nipkow@8743
   436
\end{warn}
nipkow@8743
   437
nipkow@8743
   438
nipkow@8743
   439
\chapter{More Functional Programming}
nipkow@8743
   440
nipkow@8743
   441
The purpose of this chapter is to deepen the reader's understanding of the
nipkow@8771
   442
concepts encountered so far and to introduce advanced forms of datatypes and
nipkow@8771
   443
recursive functions. The first two sections give a structured presentation of
nipkow@8771
   444
theorem proving by simplification (\S\ref{sec:Simplification}) and discuss
nipkow@8771
   445
important heuristics for induction (\S\ref{sec:InductionHeuristics}). They can
nipkow@8771
   446
be skipped by readers less interested in proofs. They are followed by a case
nipkow@8771
   447
study, a compiler for expressions (\S\ref{sec:ExprCompiler}). Advanced
nipkow@8771
   448
datatypes, including those involving function spaces, are covered in
nipkow@8771
   449
\S\ref{sec:advanced-datatypes}, which closes with another case study, search
nipkow@8771
   450
trees (``tries'').  Finally we introduce \isacommand{recdef}, a very general
nipkow@8771
   451
form of recursive function definition which goes well beyond what
nipkow@8771
   452
\isacommand{primrec} allows (\S\ref{sec:recdef}).
nipkow@8743
   453
nipkow@8743
   454
nipkow@8743
   455
\section{Simplification}
nipkow@8743
   456
\label{sec:Simplification}
nipkow@8743
   457
\index{simplification|(}
nipkow@8743
   458
nipkow@9541
   459
So far we have proved our theorems by \isa{auto}, which ``simplifies''
nipkow@9541
   460
\emph{all} subgoals. In fact, \isa{auto} can do much more than that, except
nipkow@9541
   461
that it did not need to so far. However, when you go beyond toy examples, you
nipkow@9541
   462
need to understand the ingredients of \isa{auto}.  This section covers the
nipkow@9541
   463
method that \isa{auto} always applies first, namely simplification.
nipkow@8743
   464
nipkow@8743
   465
Simplification is one of the central theorem proving tools in Isabelle and
nipkow@8743
   466
many other systems. The tool itself is called the \bfindex{simplifier}. The
nipkow@8743
   467
purpose of this section is twofold: to introduce the many features of the
nipkow@8743
   468
simplifier (\S\ref{sec:SimpFeatures}) and to explain a little bit how the
nipkow@8743
   469
simplifier works (\S\ref{sec:SimpHow}).  Anybody intending to use HOL should
nipkow@8743
   470
read \S\ref{sec:SimpFeatures}, and the serious student should read
nipkow@8743
   471
\S\ref{sec:SimpHow} as well in order to understand what happened in case
nipkow@8743
   472
things do not simplify as expected.
nipkow@8743
   473
nipkow@8743
   474
nipkow@8743
   475
\subsection{Using the simplifier}
nipkow@8743
   476
\label{sec:SimpFeatures}
nipkow@8743
   477
nipkow@9458
   478
\subsubsection{What is simplification}
nipkow@9458
   479
nipkow@8743
   480
In its most basic form, simplification means repeated application of
nipkow@8743
   481
equations from left to right. For example, taking the rules for \isa{\at}
nipkow@8743
   482
and applying them to the term \isa{[0,1] \at\ []} results in a sequence of
nipkow@8743
   483
simplification steps:
nipkow@8743
   484
\begin{ttbox}\makeatother
nipkow@8743
   485
(0#1#[]) @ []  \(\leadsto\)  0#((1#[]) @ [])  \(\leadsto\)  0#(1#([] @ []))  \(\leadsto\)  0#1#[]
nipkow@8743
   486
\end{ttbox}
nipkow@8743
   487
This is also known as \bfindex{term rewriting} and the equations are referred
nipkow@8771
   488
to as \bfindex{rewrite rules}. ``Rewriting'' is more honest than ``simplification''
nipkow@8743
   489
because the terms do not necessarily become simpler in the process.
nipkow@8743
   490
nipkow@8743
   491
\subsubsection{Simplification rules}
nipkow@8743
   492
\indexbold{simplification rules}
nipkow@8743
   493
nipkow@8743
   494
To facilitate simplification, theorems can be declared to be simplification
nipkow@8743
   495
rules (with the help of the attribute \isa{[simp]}\index{*simp
nipkow@8743
   496
  (attribute)}), in which case proofs by simplification make use of these
nipkow@8771
   497
rules automatically. In addition the constructs \isacommand{datatype} and
nipkow@8743
   498
\isacommand{primrec} (and a few others) invisibly declare useful
nipkow@8743
   499
simplification rules. Explicit definitions are \emph{not} declared
nipkow@8743
   500
simplification rules automatically!
nipkow@8743
   501
nipkow@8743
   502
Not merely equations but pretty much any theorem can become a simplification
nipkow@8743
   503
rule. The simplifier will try to make sense of it.  For example, a theorem
nipkow@8743
   504
\isasymnot$P$ is automatically turned into \isa{$P$ = False}. The details
nipkow@8743
   505
are explained in \S\ref{sec:SimpHow}.
nipkow@8743
   506
nipkow@8743
   507
The simplification attribute of theorems can be turned on and off as follows:
nipkow@8743
   508
\begin{ttbox}
nipkow@9541
   509
lemmas [simp] = \(list of theorem names\);
nipkow@9541
   510
lemmas [simp del] = \(list of theorem names\);
nipkow@8743
   511
\end{ttbox}
nipkow@8771
   512
As a rule of thumb, equations that really simplify (like \isa{rev(rev xs) =
nipkow@8743
   513
  xs} and \mbox{\isa{xs \at\ [] = xs}}) should be made simplification
nipkow@8743
   514
rules.  Those of a more specific nature (e.g.\ distributivity laws, which
nipkow@8743
   515
alter the structure of terms considerably) should only be used selectively,
nipkow@8743
   516
i.e.\ they should not be default simplification rules.  Conversely, it may
nipkow@8743
   517
also happen that a simplification rule needs to be disabled in certain
nipkow@8743
   518
proofs.  Frequent changes in the simplification status of a theorem may
nipkow@8771
   519
indicate a badly designed theory.
nipkow@8743
   520
\begin{warn}
nipkow@8743
   521
  Simplification may not terminate, for example if both $f(x) = g(x)$ and
nipkow@8743
   522
  $g(x) = f(x)$ are simplification rules. It is the user's responsibility not
nipkow@8743
   523
  to include simplification rules that can lead to nontermination, either on
nipkow@8743
   524
  their own or in combination with other simplification rules.
nipkow@8743
   525
\end{warn}
nipkow@8743
   526
nipkow@8743
   527
\subsubsection{The simplification method}
nipkow@8743
   528
\index{*simp (method)|bold}
nipkow@8743
   529
nipkow@8743
   530
The general format of the simplification method is
nipkow@8743
   531
\begin{ttbox}
nipkow@8743
   532
simp \(list of modifiers\)
nipkow@8743
   533
\end{ttbox}
nipkow@8743
   534
where the list of \emph{modifiers} helps to fine tune the behaviour and may
nipkow@8743
   535
be empty. Most if not all of the proofs seen so far could have been performed
nipkow@8743
   536
with \isa{simp} instead of \isa{auto}, except that \isa{simp} attacks
nipkow@8743
   537
only the first subgoal and may thus need to be repeated.
nipkow@8743
   538
Note that \isa{simp} fails if nothing changes.
nipkow@8743
   539
nipkow@8743
   540
\subsubsection{Adding and deleting simplification rules}
nipkow@8743
   541
nipkow@8743
   542
If a certain theorem is merely needed in a few proofs by simplification,
nipkow@8743
   543
we do not need to make it a global simplification rule. Instead we can modify
nipkow@8743
   544
the set of simplification rules used in a simplification step by adding rules
nipkow@8743
   545
to it and/or deleting rules from it. The two modifiers for this are
nipkow@8743
   546
\begin{ttbox}
nipkow@8743
   547
add: \(list of theorem names\)
nipkow@8743
   548
del: \(list of theorem names\)
nipkow@8743
   549
\end{ttbox}
nipkow@8743
   550
In case you want to use only a specific list of theorems and ignore all
nipkow@8743
   551
others:
nipkow@8743
   552
\begin{ttbox}
nipkow@8743
   553
only: \(list of theorem names\)
nipkow@8743
   554
\end{ttbox}
nipkow@8743
   555
nipkow@8743
   556
nipkow@8743
   557
\subsubsection{Assumptions}
nipkow@8743
   558
\index{simplification!with/of assumptions}
nipkow@8743
   559
nipkow@8743
   560
{\makeatother\input{Misc/document/asm_simp.tex}}
nipkow@8743
   561
nipkow@8743
   562
\subsubsection{Rewriting with definitions}
nipkow@8743
   563
\index{simplification!with definitions}
nipkow@8743
   564
nipkow@8743
   565
\input{Misc/document/def_rewr.tex}
nipkow@8743
   566
nipkow@8743
   567
\begin{warn}
nipkow@8743
   568
  If you have defined $f\,x\,y~\isasymequiv~t$ then you can only expand
nipkow@8743
   569
  occurrences of $f$ with at least two arguments. Thus it is safer to define
nipkow@8743
   570
  $f$~\isasymequiv~\isasymlambda$x\,y.\;t$.
nipkow@8743
   571
\end{warn}
nipkow@8743
   572
nipkow@8743
   573
\subsubsection{Simplifying let-expressions}
nipkow@8743
   574
\index{simplification!of let-expressions}
nipkow@8743
   575
nipkow@8743
   576
Proving a goal containing \isaindex{let}-expressions almost invariably
nipkow@8743
   577
requires the \isa{let}-con\-structs to be expanded at some point. Since
nipkow@8771
   578
\isa{let}-\isa{in} is just syntactic sugar for a predefined constant (called
nipkow@8743
   579
\isa{Let}), expanding \isa{let}-constructs means rewriting with
nipkow@8743
   580
\isa{Let_def}:
nipkow@8743
   581
nipkow@8743
   582
{\makeatother\input{Misc/document/let_rewr.tex}}
nipkow@8743
   583
nipkow@8743
   584
\subsubsection{Conditional equations}
nipkow@8743
   585
nipkow@8743
   586
\input{Misc/document/cond_rewr.tex}
nipkow@8743
   587
nipkow@8743
   588
nipkow@8743
   589
\subsubsection{Automatic case splits}
nipkow@8743
   590
\indexbold{case splits}
nipkow@8743
   591
\index{*split|(}
nipkow@8743
   592
nipkow@8743
   593
{\makeatother\input{Misc/document/case_splits.tex}}
nipkow@8743
   594
nipkow@8743
   595
\index{*split|)}
nipkow@8743
   596
nipkow@8743
   597
\begin{warn}
nipkow@8743
   598
  The simplifier merely simplifies the condition of an \isa{if} but not the
nipkow@8743
   599
  \isa{then} or \isa{else} parts. The latter are simplified only after the
nipkow@8743
   600
  condition reduces to \isa{True} or \isa{False}, or after splitting. The
nipkow@8743
   601
  same is true for \isaindex{case}-expressions: only the selector is
nipkow@8743
   602
  simplified at first, until either the expression reduces to one of the
nipkow@8743
   603
  cases or it is split.
nipkow@8743
   604
\end{warn}
nipkow@8743
   605
nipkow@8743
   606
\subsubsection{Arithmetic}
nipkow@8743
   607
\index{arithmetic}
nipkow@8743
   608
nipkow@8743
   609
The simplifier routinely solves a small class of linear arithmetic formulae
nipkow@8771
   610
(over type \isa{nat} and other numeric types): it only takes into account
nipkow@8743
   611
assumptions and conclusions that are (possibly negated) (in)equalities
nipkow@8743
   612
(\isa{=}, \isasymle, \isa{<}) and it only knows about addition. Thus
nipkow@8743
   613
nipkow@8743
   614
\input{Misc/document/arith1.tex}%
nipkow@8743
   615
is proved by simplification, whereas the only slightly more complex
nipkow@8743
   616
nipkow@8743
   617
\input{Misc/document/arith4.tex}%
nipkow@8743
   618
is not proved by simplification and requires \isa{arith}.
nipkow@8743
   619
nipkow@8743
   620
\subsubsection{Permutative rewrite rules}
nipkow@8743
   621
nipkow@8743
   622
A rewrite rule is {\bf permutative} if the left-hand side and right-hand side
nipkow@8743
   623
are the same up to renaming of variables.  The most common permutative rule
nipkow@8743
   624
is commutativity: $x+y = y+x$.  Another example is $(x-y)-z = (x-z)-y$.  Such
nipkow@8743
   625
rules are problematic because once they apply, they can be used forever.
nipkow@8743
   626
The simplifier is aware of this danger and treats permutative rules
nipkow@8743
   627
separately. For details see~\cite{isabelle-ref}.
nipkow@8743
   628
nipkow@8743
   629
\subsubsection{Tracing}
nipkow@8743
   630
\indexbold{tracing the simplifier}
nipkow@8743
   631
nipkow@8743
   632
{\makeatother\input{Misc/document/trace_simp.tex}}
nipkow@8743
   633
nipkow@8743
   634
\subsection{How it works}
nipkow@8743
   635
\label{sec:SimpHow}
nipkow@8743
   636
nipkow@8743
   637
\subsubsection{Higher-order patterns}
nipkow@8743
   638
nipkow@8743
   639
\subsubsection{Local assumptions}
nipkow@8743
   640
nipkow@8743
   641
\subsubsection{The preprocessor}
nipkow@8743
   642
nipkow@8743
   643
\index{simplification|)}
nipkow@8743
   644
nipkow@8743
   645
\section{Induction heuristics}
nipkow@8743
   646
\label{sec:InductionHeuristics}
nipkow@8743
   647
nipkow@8743
   648
The purpose of this section is to illustrate some simple heuristics for
nipkow@8743
   649
inductive proofs. The first one we have already mentioned in our initial
nipkow@8743
   650
example:
nipkow@8743
   651
\begin{quote}
nipkow@8743
   652
{\em 1. Theorems about recursive functions are proved by induction.}
nipkow@8743
   653
\end{quote}
nipkow@8743
   654
In case the function has more than one argument
nipkow@8743
   655
\begin{quote}
nipkow@8743
   656
{\em 2. Do induction on argument number $i$ if the function is defined by
nipkow@8743
   657
recursion in argument number $i$.}
nipkow@8743
   658
\end{quote}
nipkow@8743
   659
When we look at the proof of {\makeatother\isa{(xs @ ys) @ zs = xs @ (ys @
nipkow@8743
   660
  zs)}} in \S\ref{sec:intro-proof} we find (a) \isa{\at} is recursive in
nipkow@8743
   661
the first argument, (b) \isa{xs} occurs only as the first argument of
nipkow@8743
   662
\isa{\at}, and (c) both \isa{ys} and \isa{zs} occur at least once as
nipkow@8743
   663
the second argument of \isa{\at}. Hence it is natural to perform induction
nipkow@8743
   664
on \isa{xs}.
nipkow@8743
   665
nipkow@8743
   666
The key heuristic, and the main point of this section, is to
nipkow@8743
   667
generalize the goal before induction. The reason is simple: if the goal is
nipkow@8743
   668
too specific, the induction hypothesis is too weak to allow the induction
nipkow@8743
   669
step to go through. Let us now illustrate the idea with an example.
nipkow@8743
   670
nipkow@8743
   671
{\makeatother\input{Misc/document/Itrev.tex}}
nipkow@8743
   672
nipkow@8743
   673
A final point worth mentioning is the orientation of the equation we just
nipkow@8743
   674
proved: the more complex notion (\isa{itrev}) is on the left-hand
nipkow@8743
   675
side, the simpler \isa{rev} on the right-hand side. This constitutes
nipkow@8743
   676
another, albeit weak heuristic that is not restricted to induction:
nipkow@8743
   677
\begin{quote}
nipkow@8743
   678
  {\em 5. The right-hand side of an equation should (in some sense) be
nipkow@8743
   679
    simpler than the left-hand side.}
nipkow@8743
   680
\end{quote}
nipkow@8743
   681
The heuristic is tricky to apply because it is not obvious that
nipkow@8743
   682
\isa{rev xs \at\ ys} is simpler than \isa{itrev xs ys}. But see what
nipkow@8771
   683
happens if you try to prove \isa{rev xs \at\ ys = itrev xs ys}!
nipkow@8743
   684
nipkow@9493
   685
\begin{exercise}
nipkow@9493
   686
\input{Misc/document/Tree2.tex}%
nipkow@9493
   687
\end{exercise}
nipkow@8743
   688
nipkow@8743
   689
\section{Case study: compiling expressions}
nipkow@8743
   690
\label{sec:ExprCompiler}
nipkow@8743
   691
nipkow@8743
   692
{\makeatother\input{CodeGen/document/CodeGen.tex}}
nipkow@8743
   693
nipkow@8743
   694
nipkow@8743
   695
\section{Advanced datatypes}
nipkow@8743
   696
\label{sec:advanced-datatypes}
nipkow@8743
   697
\index{*datatype|(}
nipkow@8743
   698
\index{*primrec|(}
nipkow@8743
   699
%|)
nipkow@8743
   700
nipkow@8743
   701
This section presents advanced forms of \isacommand{datatype}s.
nipkow@8743
   702
nipkow@8743
   703
\subsection{Mutual recursion}
nipkow@8743
   704
\label{sec:datatype-mut-rec}
nipkow@8743
   705
nipkow@8743
   706
\input{Datatype/document/ABexpr.tex}
nipkow@8743
   707
nipkow@8743
   708
\subsection{Nested recursion}
nipkow@9644
   709
\label{sec:nested-datatype}
nipkow@8743
   710
nipkow@9644
   711
{\makeatother\input{Datatype/document/Nested.tex}}
nipkow@8743
   712
nipkow@8743
   713
nipkow@8743
   714
\subsection{The limits of nested recursion}
nipkow@8743
   715
nipkow@8743
   716
How far can we push nested recursion? By the unfolding argument above, we can
nipkow@8743
   717
reduce nested to mutual recursion provided the nested recursion only involves
nipkow@8743
   718
previously defined datatypes. This does not include functions:
nipkow@8743
   719
\begin{ttbox}
nipkow@8743
   720
datatype t = C (t => bool)
nipkow@8743
   721
\end{ttbox}
nipkow@8743
   722
is a real can of worms: in HOL it must be ruled out because it requires a type
nipkow@8743
   723
\isa{t} such that \isa{t} and its power set \isa{t \isasymFun\ bool} have the
nipkow@8743
   724
same cardinality---an impossibility. For the same reason it is not possible
nipkow@8743
   725
to allow recursion involving the type \isa{set}, which is isomorphic to
nipkow@8743
   726
\isa{t \isasymFun\ bool}.
nipkow@8743
   727
nipkow@8743
   728
Fortunately, a limited form of recursion
nipkow@8743
   729
involving function spaces is permitted: the recursive type may occur on the
nipkow@8743
   730
right of a function arrow, but never on the left. Hence the above can of worms
nipkow@8743
   731
is ruled out but the following example of a potentially infinitely branching tree is
nipkow@8743
   732
accepted:
nipkow@8771
   733
\smallskip
nipkow@8743
   734
nipkow@8743
   735
\input{Datatype/document/Fundata.tex}
nipkow@8743
   736
\bigskip
nipkow@8743
   737
nipkow@8743
   738
If you need nested recursion on the left of a function arrow,
nipkow@8743
   739
there are alternatives to pure HOL: LCF~\cite{paulson87} is a logic where types like
nipkow@8743
   740
\begin{ttbox}
nipkow@8743
   741
datatype lam = C (lam -> lam)
nipkow@8743
   742
\end{ttbox}
nipkow@8771
   743
do indeed make sense (note the intentionally different arrow \isa{->}).
nipkow@8743
   744
There is even a version of LCF on top of HOL, called
nipkow@8743
   745
HOLCF~\cite{MuellerNvOS99}.
nipkow@8743
   746
nipkow@8743
   747
\index{*primrec|)}
nipkow@8743
   748
\index{*datatype|)}
nipkow@8743
   749
nipkow@8743
   750
\subsection{Case study: Tries}
nipkow@8743
   751
nipkow@8743
   752
Tries are a classic search tree data structure~\cite{Knuth3-75} for fast
nipkow@8743
   753
indexing with strings. Figure~\ref{fig:trie} gives a graphical example of a
nipkow@8743
   754
trie containing the words ``all'', ``an'', ``ape'', ``can'', ``car'' and
nipkow@8743
   755
``cat''.  When searching a string in a trie, the letters of the string are
nipkow@8743
   756
examined sequentially. Each letter determines which subtrie to search next.
nipkow@8743
   757
In this case study we model tries as a datatype, define a lookup and an
nipkow@8743
   758
update function, and prove that they behave as expected.
nipkow@8743
   759
nipkow@8743
   760
\begin{figure}[htbp]
nipkow@8743
   761
\begin{center}
nipkow@8743
   762
\unitlength1mm
nipkow@8743
   763
\begin{picture}(60,30)
nipkow@8743
   764
\put( 5, 0){\makebox(0,0)[b]{l}}
nipkow@8743
   765
\put(25, 0){\makebox(0,0)[b]{e}}
nipkow@8743
   766
\put(35, 0){\makebox(0,0)[b]{n}}
nipkow@8743
   767
\put(45, 0){\makebox(0,0)[b]{r}}
nipkow@8743
   768
\put(55, 0){\makebox(0,0)[b]{t}}
nipkow@8743
   769
%
nipkow@8743
   770
\put( 5, 9){\line(0,-1){5}}
nipkow@8743
   771
\put(25, 9){\line(0,-1){5}}
nipkow@8743
   772
\put(44, 9){\line(-3,-2){9}}
nipkow@8743
   773
\put(45, 9){\line(0,-1){5}}
nipkow@8743
   774
\put(46, 9){\line(3,-2){9}}
nipkow@8743
   775
%
nipkow@8743
   776
\put( 5,10){\makebox(0,0)[b]{l}}
nipkow@8743
   777
\put(15,10){\makebox(0,0)[b]{n}}
nipkow@8743
   778
\put(25,10){\makebox(0,0)[b]{p}}
nipkow@8743
   779
\put(45,10){\makebox(0,0)[b]{a}}
nipkow@8743
   780
%
nipkow@8743
   781
\put(14,19){\line(-3,-2){9}}
nipkow@8743
   782
\put(15,19){\line(0,-1){5}}
nipkow@8743
   783
\put(16,19){\line(3,-2){9}}
nipkow@8743
   784
\put(45,19){\line(0,-1){5}}
nipkow@8743
   785
%
nipkow@8743
   786
\put(15,20){\makebox(0,0)[b]{a}}
nipkow@8743
   787
\put(45,20){\makebox(0,0)[b]{c}}
nipkow@8743
   788
%
nipkow@8743
   789
\put(30,30){\line(-3,-2){13}}
nipkow@8743
   790
\put(30,30){\line(3,-2){13}}
nipkow@8743
   791
\end{picture}
nipkow@8743
   792
\end{center}
nipkow@8743
   793
\caption{A sample trie}
nipkow@8743
   794
\label{fig:trie}
nipkow@8743
   795
\end{figure}
nipkow@8743
   796
nipkow@8743
   797
Proper tries associate some value with each string. Since the
nipkow@8743
   798
information is stored only in the final node associated with the string, many
nipkow@8743
   799
nodes do not carry any value. This distinction is captured by the
nipkow@8771
   800
following predefined datatype (from theory \isa{Option}, which is a parent
nipkow@8771
   801
of \isa{Main}):
nipkow@8771
   802
\smallskip
nipkow@8743
   803
\input{Trie/document/Option2.tex}
nipkow@8771
   804
\indexbold{*option}\indexbold{*None}\indexbold{*Some}%
nipkow@8743
   805
\input{Trie/document/Trie.tex}
nipkow@8743
   806
nipkow@8743
   807
\begin{exercise}
nipkow@8743
   808
  Write an improved version of \isa{update} that does not suffer from the
nipkow@8743
   809
  space leak in the version above. Prove the main theorem for your improved
nipkow@8743
   810
  \isa{update}.
nipkow@8743
   811
\end{exercise}
nipkow@8743
   812
nipkow@8743
   813
\begin{exercise}
nipkow@8743
   814
  Write a function to \emph{delete} entries from a trie. An easy solution is
nipkow@8743
   815
  a clever modification of \isa{update} which allows both insertion and
nipkow@8743
   816
  deletion with a single function.  Prove (a modified version of) the main
nipkow@8743
   817
  theorem above. Optimize you function such that it shrinks tries after
nipkow@8743
   818
  deletion, if possible.
nipkow@8743
   819
\end{exercise}
nipkow@8743
   820
nipkow@8743
   821
\section{Total recursive functions}
nipkow@8743
   822
\label{sec:recdef}
nipkow@8743
   823
\index{*recdef|(}
nipkow@8743
   824
nipkow@8743
   825
Although many total functions have a natural primitive recursive definition,
nipkow@8743
   826
this is not always the case. Arbitrary total recursive functions can be
nipkow@8743
   827
defined by means of \isacommand{recdef}: you can use full pattern-matching,
nipkow@8743
   828
recursion need not involve datatypes, and termination is proved by showing
nipkow@8743
   829
that the arguments of all recursive calls are smaller in a suitable (user
nipkow@8743
   830
supplied) sense.
nipkow@8743
   831
nipkow@8743
   832
\subsection{Defining recursive functions}
nipkow@8743
   833
nipkow@8743
   834
\input{Recdef/document/examples.tex}
nipkow@8743
   835
nipkow@8743
   836
\subsection{Proving termination}
nipkow@8743
   837
nipkow@8743
   838
\input{Recdef/document/termination.tex}
nipkow@8743
   839
nipkow@8743
   840
\subsection{Simplification with recdef}
nipkow@8743
   841
nipkow@8743
   842
\input{Recdef/document/simplification.tex}
nipkow@8743
   843
nipkow@8743
   844
\subsection{Induction}
nipkow@8743
   845
\index{induction!recursion|(}
nipkow@8743
   846
\index{recursion induction|(}
nipkow@8743
   847
nipkow@8743
   848
\input{Recdef/document/Induction.tex}
nipkow@9644
   849
\label{sec:recdef-induction}
nipkow@8743
   850
nipkow@8743
   851
\index{induction!recursion|)}
nipkow@8743
   852
\index{recursion induction|)}
nipkow@9644
   853
nipkow@9644
   854
%\subsection{Advanced forms of recursion}
nipkow@9644
   855
nipkow@9644
   856
%\input{Recdef/document/Nested0.tex}
nipkow@9644
   857
%\input{Recdef/document/Nested1.tex}
nipkow@9644
   858
nipkow@8743
   859
\index{*recdef|)}
nipkow@9644
   860
nipkow@9644
   861
\section{Advanced induction techniques}
nipkow@9644
   862
\label{sec:advanced-ind}
nipkow@9644
   863
\input{Misc/document/AdvancedInd.tex}
nipkow@9644
   864
wenzelm@9673
   865
%\input{Datatype/document/Nested2.tex}