doc-src/Intro/advanced.tex
author lcp
Fri, 26 Nov 1993 12:31:48 +0100
changeset 156 ab4dcb9285e0
parent 109 0872fd327440
child 284 1072b18b2caa
permissions -rw-r--r--
Corrected errors found by Marcus Wenzel.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
105
216d6ed87399 Initial revision
lcp
parents:
diff changeset
     1
%% $Id$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
     2
\part{Advanced methods}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
     3
Before continuing, it might be wise to try some of your own examples in
216d6ed87399 Initial revision
lcp
parents:
diff changeset
     4
Isabelle, reinforcing your knowledge of the basic functions.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
     5
This paper is merely an introduction to Isabelle.  Two other documents
216d6ed87399 Initial revision
lcp
parents:
diff changeset
     6
exist:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
     7
\begin{itemize}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
     8
  \item {\em The Isabelle Reference Manual\/} contains information about
216d6ed87399 Initial revision
lcp
parents:
diff changeset
     9
most of the facilities of Isabelle, apart from particular object-logics.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    10
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    11
  \item {\em Isabelle's Object-Logics\/} describes the various logics
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    12
distributed with Isabelle.  It also explains how to define new logics in
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    13
Isabelle.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    14
\end{itemize}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    15
Look through {\em Isabelle's Object-Logics\/} and try proving some simple
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    16
theorems.  You probably should begin with first-order logic ({\tt FOL}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    17
or~{\tt LK}).  Try working some of the examples provided, and others from
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    18
the literature.  Set theory~({\tt ZF}) and Constructive Type Theory~({\tt
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    19
  CTT}) form a richer world for mathematical reasoning and, again, many
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    20
examples are in the literature.  Higher-order logic~({\tt HOL}) is
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    21
Isabelle's most sophisticated logic, because its types and functions are
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    22
identified with those of the meta-logic; this may cause difficulties for
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    23
beginners.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    24
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    25
Choose a logic that you already understand.  Isabelle is a proof
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    26
tool, not a teaching tool; if you do not know how to do a particular proof
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    27
on paper, then you certainly will not be able to do it on the machine.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    28
Even experienced users plan large proofs on paper.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    29
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    30
We have covered only the bare essentials of Isabelle, but enough to perform
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    31
substantial proofs.  By occasionally dipping into the {\em Reference
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    32
Manual}, you can learn additional tactics, subgoal commands and tacticals.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    33
Isabelle's simplifier and classical theorem prover are
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    34
difficult to learn, and can be ignored at first.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    35
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    36
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    37
\section{Deriving rules in Isabelle}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    38
\index{rules!derived}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    39
A mathematical development goes through a progression of stages.  Each
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    40
stage defines some concepts and derives rules about them.  We shall see how
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    41
to derive rules, perhaps involving definitions, using Isabelle.  The
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    42
following section will explain how to declare types, constants, axioms and
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    43
definitions.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    44
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    45
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    46
\subsection{Deriving a rule using tactics} \label{deriving-example}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    47
\index{examples!of deriving rules}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    48
The subgoal module supports the derivation of rules.  The \ttindex{goal}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    49
command, when supplied a goal of the form $\List{\theta@1; \ldots;
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    50
\theta@k} \Imp \phi$, creates $\phi\Imp\phi$ as the initial proof state and
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    51
returns a list consisting of the theorems 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    52
${\theta@i\;[\theta@i]}$, for $i=1$, \ldots,~$k$.  These assumptions are
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    53
also recorded internally, allowing \ttindex{result} to discharge them in the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    54
original order.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    55
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    56
Let us derive $\conj$ elimination~(\S\ref{deriving}) using Isabelle.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    57
Until now, calling \ttindex{goal} has returned an empty list, which we have
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    58
thrown away.  In this example, the list contains the two premises of the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    59
rule.  We bind them to the \ML\ identifiers {\tt major} and {\tt
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    60
minor}:\footnote{Some ML compilers will print a message such as {\em
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    61
binding not exhaustive}.  This warns that {\tt goal} must return a
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    62
2-element list.  Otherwise, the pattern-match will fail; ML will
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    63
raise exception \ttindex{Match}.}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    64
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    65
val [major,minor] = goal FOL.thy
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    66
    "[| P&Q;  [| P; Q |] ==> R |] ==> R";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    67
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    68
{\out R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    69
{\out  1. R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    70
{\out val major = "P & Q  [P & Q]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    71
{\out val minor = "[| P; Q |] ==> R  [[| P; Q |] ==> R]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    72
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    73
Look at the minor premise, recalling that meta-level assumptions are
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    74
shown in brackets.  Using {\tt minor}, we reduce $R$ to the subgoals
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    75
$P$ and~$Q$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    76
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    77
by (resolve_tac [minor] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    78
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    79
{\out R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    80
{\out  1. P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    81
{\out  2. Q}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    82
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    83
Deviating from~\S\ref{deriving}, we apply $({\conj}E1)$ forwards from the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    84
assumption $P\conj Q$ to obtain the theorem~$P\;[P\conj Q]$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    85
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    86
major RS conjunct1;
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    87
{\out val it = "P  [P & Q]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    88
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    89
by (resolve_tac [major RS conjunct1] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    90
{\out Level 2}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    91
{\out R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    92
{\out  1. Q}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    93
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    94
Similarly, we solve the subgoal involving~$Q$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    95
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    96
major RS conjunct2;
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    97
{\out val it = "Q  [P & Q]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    98
by (resolve_tac [major RS conjunct2] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
    99
{\out Level 3}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   100
{\out R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   101
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   102
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   103
Calling \ttindex{topthm} returns the current proof state as a theorem.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   104
Note that it contains assumptions.  Calling \ttindex{result} discharges the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   105
assumptions --- both occurrences of $P\conj Q$ are discharged as one ---
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   106
and makes the variables schematic.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   107
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   108
topthm();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   109
{\out val it = "R  [P & Q, P & Q, [| P; Q |] ==> R]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   110
val conjE = result();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   111
{\out val conjE = "[| ?P & ?Q; [| ?P; ?Q |] ==> ?R |] ==> ?R" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   112
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   113
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   114
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   115
\subsection{Definitions and derived rules} \label{definitions}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   116
\index{rules!derived}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   117
\index{Isabelle!definitions in}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   118
\index{definitions!reasoning about|bold}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   119
Definitions are expressed as meta-level equalities.  Let us define negation
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   120
and the if-and-only-if connective:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   121
\begin{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   122
  \neg \Var{P}          & \equiv & \Var{P}\imp\bot \\
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   123
  \Var{P}\bimp \Var{Q}  & \equiv & 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   124
                (\Var{P}\imp \Var{Q}) \conj (\Var{Q}\imp \Var{P})
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   125
\end{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   126
\index{rewriting!meta-level|bold}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   127
\index{unfolding|bold}\index{folding|bold}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   128
Isabelle permits {\bf meta-level rewriting} using definitions such as
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   129
these.  {\bf Unfolding} replaces every instance
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   130
of $\neg \Var{P}$ by the corresponding instance of $\Var{P}\imp\bot$.  For
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   131
example, $\forall x.\neg (P(x)\conj \neg R(x,0))$ unfolds to
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   132
\[ \forall x.(P(x)\conj R(x,0)\imp\bot)\imp\bot.  \]
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   133
{\bf Folding} a definition replaces occurrences of the right-hand side by
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   134
the left.  The occurrences need not be free in the entire formula.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   135
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   136
\begin{warn}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   137
Isabelle does not distinguish sensible definitions, like $1\equiv Suc(0)$, from
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   138
equations like $1\equiv Suc(1)$.  However, meta-rewriting fails for
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   139
equations like ${f(\Var{x})\equiv g(\Var{x},\Var{y})}$: all variables on
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   140
the right-hand side must also be present on the left.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   141
\index{rewriting!meta-level}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   142
\end{warn}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   143
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   144
When you define new concepts, you should derive rules asserting their
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   145
abstract properties, and then forget their definitions.  This supports
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   146
modularity: if you later change the definitions, without affecting their
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   147
abstract properties, then most of your proofs will carry through without
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   148
change.  Indiscriminate unfolding makes a subgoal grow exponentially,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   149
becoming unreadable.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   150
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   151
Taking this point of view, Isabelle does not unfold definitions
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   152
automatically during proofs.  Rewriting must be explicit and selective.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   153
Isabelle provides tactics and meta-rules for rewriting, and a version of
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   154
the {\tt goal} command that unfolds the conclusion and premises of the rule
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   155
being derived.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   156
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   157
For example, the intuitionistic definition of negation given above may seem
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   158
peculiar.  Using Isabelle, we shall derive pleasanter negation rules:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   159
\[  \infer[({\neg}I)]{\neg P}{\infer*{\bot}{[P]}}   \qquad
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   160
    \infer[({\neg}E)]{Q}{\neg P & P}  \]
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   161
This requires proving the following formulae:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   162
$$ (P\Imp\bot)    \Imp \neg P   \eqno(\neg I)$$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   163
$$ \List{\neg P; P} \Imp Q.       \eqno(\neg E)$$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   164
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   165
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   166
\subsubsection{Deriving the introduction rule}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   167
To derive $(\neg I)$, we may call \ttindex{goal} with the appropriate
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   168
formula.  Again, {\tt goal} returns a list consisting of the rule's
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   169
premises.  We bind this list, which contains the one element $P\Imp\bot$,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   170
to the \ML\ identifier {\tt prems}.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   171
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   172
val prems = goal FOL.thy "(P ==> False) ==> ~P";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   173
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   174
{\out ~P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   175
{\out  1. ~P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   176
{\out val prems = ["P ==> False  [P ==> False]"] : thm list}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   177
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   178
Calling \ttindex{rewrite_goals_tac} with \ttindex{not_def}, which is the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   179
definition of negation, unfolds that definition in the subgoals.  It leaves
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   180
the main goal alone.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   181
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   182
not_def;
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   183
{\out val it = "~?P == ?P --> False" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   184
by (rewrite_goals_tac [not_def]);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   185
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   186
{\out ~P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   187
{\out  1. P --> False}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   188
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   189
Using \ttindex{impI} and the premise, we reduce subgoal~1 to a triviality:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   190
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   191
by (resolve_tac [impI] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   192
{\out Level 2}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   193
{\out ~P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   194
{\out  1. P ==> False}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   195
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   196
by (resolve_tac prems 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   197
{\out Level 3}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   198
{\out ~P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   199
{\out  1. P ==> P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   200
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   201
The rest of the proof is routine.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   202
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   203
by (assume_tac 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   204
{\out Level 4}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   205
{\out ~P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   206
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   207
val notI = result();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   208
{\out val notI = "(?P ==> False) ==> ~?P" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   209
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   210
\indexbold{*notI}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   211
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   212
\medskip
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   213
There is a simpler way of conducting this proof.  The \ttindex{goalw}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   214
command starts a backward proof, as does \ttindex{goal}, but it also
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   215
unfolds definitions:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   216
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   217
val prems = goalw FOL.thy [not_def]
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   218
    "(P ==> False) ==> ~P";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   219
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   220
{\out ~P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   221
{\out  1. P --> False}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   222
{\out val prems = ["P ==> False  [P ==> False]"] : thm list}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   223
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   224
The proof continues as above, but without calling \ttindex{rewrite_goals_tac}.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   225
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   226
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   227
\subsubsection{Deriving the elimination rule}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   228
Let us derive $(\neg E)$.  The proof follows that of~{\tt conjE}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   229
(\S\ref{deriving-example}), with an additional step to unfold negation in
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   230
the major premise.  Although the {\tt goalw} command is best for this, let
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   231
us try~\ttindex{goal}.  As usual, we bind the premises to \ML\ identifiers.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   232
We then apply \ttindex{FalseE}, which stands for~$(\bot E)$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   233
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   234
val [major,minor] = goal FOL.thy "[| ~P;  P |] ==> R";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   235
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   236
{\out R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   237
{\out  1. R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   238
{\out val major = "~ P  [~ P]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   239
{\out val minor = "P  [P]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   240
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   241
by (resolve_tac [FalseE] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   242
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   243
{\out R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   244
{\out  1. False}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   245
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   246
by (resolve_tac [mp] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   247
{\out Level 2}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   248
{\out R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   249
{\out  1. ?P1 --> False}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   250
{\out  2. ?P1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   251
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   252
For subgoal~1, we transform the major premise from~$\neg P$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   253
to~${P\imp\bot}$.  The function \ttindex{rewrite_rule}, given a list of
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   254
definitions, unfolds them in a theorem.  Rewriting does {\bf not}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   255
affect the theorem's hypothesis, which remains~$\neg P$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   256
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   257
rewrite_rule [not_def] major;
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   258
{\out val it = "P --> False  [~P]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   259
by (resolve_tac [it] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   260
{\out Level 3}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   261
{\out R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   262
{\out  1. P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   263
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   264
Now {\tt?P1} has changed to~{\tt P}; we need only use the minor premise:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   265
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   266
by (resolve_tac [minor] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   267
{\out Level 4}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   268
{\out R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   269
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   270
val notE = result();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   271
{\out val notE = "[| ~?P; ?P |] ==> ?R" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   272
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   273
\indexbold{*notE}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   274
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   275
\medskip
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   276
Again, there is a simpler way of conducting this proof.  The
156
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
   277
\ttindex{goalw} command unfolds definitions in the premises as well
105
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   278
as the conclusion:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   279
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   280
val [major,minor] = goalw FOL.thy [not_def]
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   281
    "[| ~P;  P |] ==> R";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   282
{\out val major = "P --> False  [~ P]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   283
{\out val minor = "P  [P]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   284
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   285
Observe the difference in {\tt major}; the premises are now {\bf unfolded}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   286
and we need not call~\ttindex{rewrite_rule}.  Incidentally, the four calls
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   287
to \ttindex{resolve_tac} above can be collapsed to one, with the help
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   288
of~\ttindex{RS}\@:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   289
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   290
minor RS (major RS mp RS FalseE);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   291
{\out val it = "?P  [P, ~P]" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   292
by (resolve_tac [it] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   293
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   294
{\out R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   295
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   296
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   297
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   298
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   299
\medskip Finally, here is a trick that is sometimes useful.  If the goal
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   300
has an outermost meta-quantifier, then \ttindex{goal} and \ttindex{goalw}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   301
do not return the rule's premises in the list of theorems.  Instead, the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   302
premises become assumptions in subgoal~1:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   303
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   304
goalw FOL.thy [not_def] "!!P R. [| ~P;  P |] ==> R";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   305
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   306
{\out !!P R. [| ~ P; P |] ==> R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   307
{\out  1. !!P R. [| P --> False; P |] ==> R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   308
val it = [] : thm list
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   309
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   310
The proof continues as before.  But instead of referring to \ML\
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   311
identifiers, we refer to assumptions using \ttindex{eresolve_tac} or
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   312
\ttindex{assume_tac}: 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   313
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   314
by (resolve_tac [FalseE] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   315
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   316
{\out !!P R. [| ~ P; P |] ==> R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   317
{\out  1. !!P R. [| P --> False; P |] ==> False}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   318
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   319
by (eresolve_tac [mp] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   320
{\out Level 2}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   321
{\out !!P R. [| ~ P; P |] ==> R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   322
{\out  1. !!P R. P ==> P}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   323
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   324
by (assume_tac 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   325
{\out Level 3}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   326
{\out !!P R. [| ~ P; P |] ==> R}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   327
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   328
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   329
Calling \ttindex{result} strips the meta-quantifiers, so the resulting
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   330
theorem is the same as before.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   331
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   332
val notE = result();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   333
{\out val notE = "[| ~?P; ?P |] ==> ?R" : thm}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   334
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   335
Do not use the {\tt!!}\ trick if the premises contain meta-level
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   336
connectives, because \ttindex{eresolve_tac} and \ttindex{assume_tac} would
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   337
not be able to handle the resulting assumptions.  The trick is not suitable
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   338
for deriving the introduction rule~$(\neg I)$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   339
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   340
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   341
\section{Defining theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   342
\index{theories!defining|(}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   343
Isabelle makes no distinction between simple extensions of a logic --- like
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   344
defining a type~$bool$ with constants~$true$ and~$false$ --- and defining
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   345
an entire logic.  A theory definition has the form
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   346
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   347
\(T\) = \(S@1\) + \(\cdots\) + \(S@n\) +
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   348
classes      {\it class declarations}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   349
default      {\it sort}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   350
types        {\it type declarations}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   351
arities      {\it arity declarations}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   352
consts       {\it constant declarations}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   353
rules        {\it rule declarations}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   354
translations {\it translation declarations}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   355
end
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   356
ML           {\it ML code}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   357
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   358
This declares the theory $T$ to extend the existing theories
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   359
$S@1$,~\ldots,~$S@n$.  It may declare new classes, types, arities
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   360
(overloadings of existing types), constants and rules; it can specify the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   361
default sort for type variables.  A constant declaration can specify an
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   362
associated concrete syntax.  The translations section specifies rewrite
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   363
rules on abstract syntax trees, for defining notations and abbreviations.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   364
The {\ML} section contains code to perform arbitrary syntactic
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   365
transformations.  The main declaration forms are discussed below; see {\em
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   366
  Isabelle's Object-Logics} for full details and examples.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   367
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   368
All the declaration parts can be omitted.  In the simplest case, $T$ is
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   369
just the union of $S@1$,~\ldots,~$S@n$.  New theories always extend one
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   370
or more other theories, inheriting their types, constants, syntax, etc.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   371
The theory \ttindexbold{Pure} contains nothing but Isabelle's meta-logic.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   372
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   373
Each theory definition must reside in a separate file, whose name is
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   374
determined as follows: the theory name, say {\tt ListFn}, is converted to
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   375
lower case and {\tt.thy} is appended, yielding the filename {\tt
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   376
  listfn.thy}.  Isabelle uses this convention to locate the file containing
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   377
a given theory; \ttindexbold{use_thy} automatically loads a theory's
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   378
parents before loading the theory itself.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   379
109
0872fd327440 adapted "Defining theories" to new use_thy
clasohm
parents: 105
diff changeset
   380
Calling \ttindexbold{use_thy}~{\tt"}{\it T\/}{\tt"} reads a theory from the
0872fd327440 adapted "Defining theories" to new use_thy
clasohm
parents: 105
diff changeset
   381
file {\it t}{\tt.thy}, writes the corresponding {\ML} code to the file
0872fd327440 adapted "Defining theories" to new use_thy
clasohm
parents: 105
diff changeset
   382
{\tt.}{\it t}{\tt.thy.ML}, reads the latter file, and deletes it if no errors
0872fd327440 adapted "Defining theories" to new use_thy
clasohm
parents: 105
diff changeset
   383
occured.  This declares the {\ML} structure~$T$, which contains a component
0872fd327440 adapted "Defining theories" to new use_thy
clasohm
parents: 105
diff changeset
   384
{\tt thy} denoting the new theory, a component for each rule, and everything
0872fd327440 adapted "Defining theories" to new use_thy
clasohm
parents: 105
diff changeset
   385
declared in {\it ML code}.
105
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   386
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   387
Errors may arise during the translation to {\ML} (say, a misspelled keyword)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   388
or during creation of the new theory (say, a type error in a rule).  But if
109
0872fd327440 adapted "Defining theories" to new use_thy
clasohm
parents: 105
diff changeset
   389
all goes well, {\tt use_thy} will finally read the file {\it t}{\tt.ML}, if
105
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   390
it exists.  This file typically begins with the {\ML} declaration {\tt
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   391
open}~$T$ and contains proofs that refer to the components of~$T$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   392
Theories can be defined directly by issuing {\ML} declarations to Isabelle,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   393
but the calling sequences are extremely cumbersome.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   394
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   395
If theory~$T$ is later redeclared in order to delete an incorrect rule,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   396
bindings to the old rule may persist.  Isabelle ensures that the old and
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   397
new versions of~$T$ are not involved in the same proof.  Attempting to
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   398
combine different versions of~$T$ yields the fatal error
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   399
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   400
Attempt to merge different versions of theory: \(T\)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   401
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   402
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   403
\subsection{Declaring constants and rules}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   404
\indexbold{constants!declaring}\indexbold{rules!declaring}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   405
Most theories simply declare constants and some rules.  The {\bf constant
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   406
declaration part} has the form
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   407
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   408
consts  \(c@1\) :: "\(\tau@1\)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   409
        \vdots
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   410
        \(c@n\) :: "\(\tau@n\)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   411
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   412
where $c@1$, \ldots, $c@n$ are constants and $\tau@1$, \ldots, $\tau@n$ are
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   413
types.  Each type {\em must\/} be enclosed in quotation marks.  Each
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   414
constant must be enclosed in quotation marks unless it is a valid
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   415
identifier.  To declare $c@1$, \ldots, $c@n$ as constants of type $\tau$,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   416
the $n$ declarations may be abbreviated to a single line:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   417
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   418
        \(c@1\), \ldots, \(c@n\) :: "\(\tau\)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   419
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   420
The {\bf rule declaration part} has the form
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   421
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   422
rules   \(id@1\) "\(rule@1\)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   423
        \vdots
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   424
        \(id@n\) "\(rule@n\)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   425
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   426
where $id@1$, \ldots, $id@n$ are \ML{} identifiers and $rule@1$, \ldots,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   427
$rule@n$ are expressions of type~$prop$.  {\bf Definitions} are rules of
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   428
the form $t\equiv u$.  Each rule {\em must\/} be enclosed in quotation marks.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   429
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   430
\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   431
This theory extends first-order logic with two constants {\em nand} and
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   432
{\em xor}, and two rules defining them:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   433
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   434
Gate = FOL +
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   435
consts  nand,xor :: "[o,o] => o"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   436
rules   nand_def "nand(P,Q) == ~(P & Q)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   437
        xor_def  "xor(P,Q)  == P & ~Q | ~P & Q"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   438
end
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   439
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   440
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   441
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   442
\subsection{Declaring type constructors}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   443
\indexbold{type constructors!declaring}\indexbold{arities!declaring}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   444
Types are composed of type variables and {\bf type constructors}.  Each
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   445
type constructor has a fixed number of argument places.  For example,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   446
$list$ is a 1-place type constructor and $nat$ is a 0-place type
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   447
constructor.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   448
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   449
The {\bf type declaration part} has the form
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   450
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   451
types   \(id@1\) \(k@1\)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   452
        \vdots
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   453
        \(id@n\) \(k@n\)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   454
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   455
where $id@1$, \ldots, $id@n$ are identifiers and $k@1$, \ldots, $k@n$ are
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   456
natural numbers.  It declares each $id@i$ as a type constructor with $k@i$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   457
argument places.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   458
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   459
The {\bf arity declaration part} has the form
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   460
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   461
arities \(tycon@1\) :: \(arity@1\)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   462
        \vdots
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   463
        \(tycon@n\) :: \(arity@n\)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   464
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   465
where $tycon@1$, \ldots, $tycon@n$ are identifiers and $arity@1$, \ldots,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   466
$arity@n$ are arities.  Arity declarations add arities to existing
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   467
types; they complement type declarations.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   468
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   469
In the simplest case, for an 0-place type constructor, an arity is simply
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   470
the type's class.  Let us declare a type~$bool$ of class $term$, with
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   471
constants $tt$ and~$ff$:\footnote{In first-order logic, booleans are
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   472
distinct from formulae, which have type $o::logic$.}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   473
\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   474
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   475
Bool = FOL +
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   476
types   bool 0
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   477
arities bool    :: term
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   478
consts  tt,ff   :: "bool"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   479
end
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   480
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   481
In the general case, type constructors take arguments.  Each type
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   482
constructor has an {\bf arity} with respect to
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   483
classes~(\S\ref{polymorphic}).  A $k$-place type constructor may have
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   484
arities of the form $(s@1,\ldots,s@k)c$, where $s@1,\ldots,s@n$ are sorts
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   485
and $c$ is a class.  Each sort specifies a type argument; it has the form
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   486
$\{c@1,\ldots,c@m\}$, where $c@1$, \dots,~$c@m$ are classes.  Mostly we
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   487
deal with singleton sorts, and may abbreviate them by dropping the braces.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   488
The arity declaration $list{::}(term)term$ is short for
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   489
$list{::}(\{term\})term$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   490
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   491
A type constructor may be overloaded (subject to certain conditions) by
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   492
appearing in several arity declarations.  For instance, the built-in type
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   493
constructor~$\To$ has the arity $(logic,logic)logic$; in higher-order
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   494
logic, it is declared also to have arity $(term,term)term$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   495
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   496
Theory {\tt List} declares the 1-place type constructor $list$, gives
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   497
it arity $list{::}(term)term$, and declares constants $Nil$ and $Cons$ with
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   498
polymorphic types:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   499
\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   500
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   501
List = FOL +
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   502
types   list 1
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   503
arities list    :: (term)term
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   504
consts  Nil     :: "'a list"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   505
        Cons    :: "['a, 'a list] => 'a list" 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   506
end
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   507
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   508
Multiple type and arity declarations may be abbreviated to a single line:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   509
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   510
types   \(id@1\), \ldots, \(id@n\) \(k\)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   511
arities \(tycon@1\), \ldots, \(tycon@n\) :: \(arity\)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   512
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   513
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   514
\begin{warn}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   515
Arity declarations resemble constant declarations, but there are {\it no\/}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   516
quotation marks!  Types and rules must be quoted because the theory
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   517
translator passes them verbatim to the {\ML} output file.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   518
\end{warn}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   519
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   520
\subsection{Infixes and Mixfixes}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   521
\indexbold{infix operators}\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   522
The constant declaration part of the theory
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   523
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   524
Gate2 = FOL +
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   525
consts  "~&"     :: "[o,o] => o"         (infixl 35)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   526
        "#"      :: "[o,o] => o"         (infixl 30)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   527
rules   nand_def "P ~& Q == ~(P & Q)"    
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   528
        xor_def  "P # Q  == P & ~Q | ~P & Q"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   529
end
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   530
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   531
declares two left-associating infix operators: $\nand$ of precedence~35 and
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   532
$\xor$ of precedence~30.  Hence $P \xor Q \xor R$ is parsed as $(P\xor
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   533
Q) \xor R$ and $P \xor Q \nand R$ as $P \xor (Q \nand R)$.  Note the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   534
quotation marks in \verb|"~&"| and \verb|"#"|.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   535
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   536
The constants \hbox{\verb|op ~&|} and \hbox{\verb|op #|} are declared
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   537
automatically, just as in \ML.  Hence you may write propositions like
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   538
\verb|op #(True) == op ~&(True)|, which asserts that the functions $\lambda
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   539
Q.True \xor Q$ and $\lambda Q.True \nand Q$ are identical.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   540
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   541
\indexbold{mixfix operators}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   542
{\bf Mixfix} operators may have arbitrary context-free syntaxes.  For example
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   543
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   544
    If :: "[o,o,o] => o"       ("if _ then _ else _")
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   545
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   546
declares a constant $If$ of type $[o,o,o] \To o$ with concrete syntax
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   547
$if~P~then~Q~else~R$ instead of $If(P,Q,R)$.  Underscores denote argument
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   548
positions.  Pretty-printing information can be specified in order to
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   549
improve the layout of formulae with mixfix operations.  For details, see
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   550
{\em Isabelle's Object-Logics}.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   551
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   552
Mixfix declarations can be annotated with precedences, just like
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   553
infixes.  The example above is just a shorthand for
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   554
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   555
    If :: "[o,o,o] => o"       ("if _ then _ else _" [0,0,0] 1000)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   556
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   557
The numeric components determine precedences.  The list of integers
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   558
defines, for each argument position, the minimal precedence an expression
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   559
at that position must have.  The final integer is the precedence of the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   560
construct itself.  In the example above, any argument expression is
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   561
acceptable because precedences are non-negative, and conditionals may
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   562
appear everywhere because 1000 is the highest precedence.  On the other
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   563
hand,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   564
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   565
    If :: "[o,o,o] => o"       ("if _ then _ else _" [100,0,0] 99)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   566
\end{ttbox}
156
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
   567
defines concrete syntax for a
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
   568
conditional whose first argument cannot have the form $if~P~then~Q~else~R$
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
   569
because it must have a precedence of at least~100.  Since expressions put in
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
   570
parentheses have maximal precedence, we may of course write 
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
   571
\begin{quote}
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
   572
\it  if (if P then Q else R) then S else T
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
   573
\end{quote}
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
   574
Conditional expressions can also be written using the constant {\tt If}.
105
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   575
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   576
Binary type constructors, like products and sums, may also be declared as
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   577
infixes.  The type declaration below introduces a type constructor~$*$ with
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   578
infix notation $\alpha*\beta$, together with the mixfix notation
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   579
${<}\_,\_{>}$ for pairs.  
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   580
\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   581
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   582
Prod = FOL +
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   583
types   "*" 2                                 (infixl 20)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   584
arities "*"     :: (term,term)term
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   585
consts  fst     :: "'a * 'b => 'a"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   586
        snd     :: "'a * 'b => 'b"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   587
        Pair    :: "['a,'b] => 'a * 'b"       ("(1<_,/_>)")
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   588
rules   fst     "fst(<a,b>) = a"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   589
        snd     "snd(<a,b>) = b"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   590
end
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   591
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   592
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   593
\begin{warn}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   594
The name of the type constructor is~{\tt *} and not {\tt op~*}, as it would
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   595
be in the case of an infix constant.  Only infix type constructors can have
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   596
symbolic names like~{\tt *}.  There is no general mixfix syntax for types.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   597
\end{warn}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   598
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   599
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   600
\subsection{Overloading}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   601
\index{overloading}\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   602
The {\bf class declaration part} has the form
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   603
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   604
classes \(id@1\) < \(c@1\)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   605
        \vdots
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   606
        \(id@n\) < \(c@n\)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   607
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   608
where $id@1$, \ldots, $id@n$ are identifiers and $c@1$, \ldots, $c@n$ are
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   609
existing classes.  It declares each $id@i$ as a new class, a subclass
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   610
of~$c@i$.  In the general case, an identifier may be declared to be a
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   611
subclass of $k$ existing classes:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   612
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   613
        \(id\) < \(c@1\), \ldots, \(c@k\)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   614
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   615
Type classes allow constants to be overloaded~(\S\ref{polymorphic}).  As an
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   616
example, we define the class $arith$ of ``arithmetic'' types with the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   617
constants ${+} :: [\alpha,\alpha]\To \alpha$ and $0,1 :: \alpha$, for
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   618
$\alpha{::}arith$.  We introduce $arith$ as a subclass of $term$ and add
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   619
the three polymorphic constants of this class.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   620
\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   621
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   622
Arith = FOL +
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   623
classes arith < term
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   624
consts  "0"     :: "'a::arith"                  ("0")
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   625
        "1"     :: "'a::arith"                  ("1")
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   626
        "+"     :: "['a::arith,'a] => 'a"       (infixl 60)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   627
end
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   628
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   629
No rules are declared for these constants: we merely introduce their
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   630
names without specifying properties.  On the other hand, classes
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   631
with rules make it possible to prove {\bf generic} theorems.  Such
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   632
theorems hold for all instances, all types in that class.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   633
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   634
We can now obtain distinct versions of the constants of $arith$ by
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   635
declaring certain types to be of class $arith$.  For example, let us
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   636
declare the 0-place type constructors $bool$ and $nat$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   637
\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   638
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   639
BoolNat = Arith +
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   640
types   bool,nat    0
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   641
arities bool,nat    :: arith
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   642
consts  Suc         :: "nat=>nat"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   643
rules   add0        "0 + n = n::nat"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   644
        addS        "Suc(m)+n = Suc(m+n)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   645
        nat1        "1 = Suc(0)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   646
        or0l        "0 + x = x::bool"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   647
        or0r        "x + 0 = x::bool"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   648
        or1l        "1 + x = 1::bool"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   649
        or1r        "x + 1 = 1::bool"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   650
end
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   651
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   652
Because $nat$ and $bool$ have class $arith$, we can use $0$, $1$ and $+$ at
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   653
either type.  The type constraints in the axioms are vital.  Without
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   654
constraints, the $x$ in $1+x = x$ would have type $\alpha{::}arith$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   655
and the axiom would hold for any type of class $arith$.  This would
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   656
collapse $nat$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   657
\[ Suc(1) = Suc(0+1) = Suc(0)+1 = 1+1 = 1! \]
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   658
The class $arith$ as defined above is more specific than necessary.  Many
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   659
types come with a binary operation and identity~(0).  On lists,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   660
$+$ could be concatenation and 0 the empty list --- but what is 1?  Hence it
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   661
may be better to define $+$ and 0 on $arith$ and introduce a separate
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   662
class, say $k$, containing~1.  Should $k$ be a subclass of $term$ or of
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   663
$arith$?  This depends on the structure of your theories; the design of an
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   664
appropriate class hierarchy may require some experimentation.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   665
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   666
We will now work through a small example of formalized mathematics
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   667
demonstrating many of the theory extension features.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   668
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   669
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   670
\subsection{Extending first-order logic with the natural numbers}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   671
\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   672
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   673
The early part of this paper defines a first-order logic, including a
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   674
type~$nat$ and the constants $0::nat$ and $Suc::nat\To nat$.  Let us
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   675
introduce the Peano axioms for mathematical induction and the freeness of
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   676
$0$ and~$Suc$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   677
\[ \vcenter{\infer[(induct)*]{P[n/x]}{P[0/x] & \infer*{P[Suc(x)/x]}{[P]}}}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   678
 \qquad \parbox{4.5cm}{provided $x$ is not free in any assumption except~$P$}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   679
\]
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   680
\[ \infer[(Suc\_inject)]{m=n}{Suc(m)=Suc(n)} \qquad
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   681
   \infer[(Suc\_neq\_0)]{R}{Suc(m)=0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   682
\]
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   683
Mathematical induction asserts that $P(n)$ is true, for any $n::nat$,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   684
provided $P(0)$ holds and that $P(x)$ implies $P(Suc(x))$ for all~$x$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   685
Some authors express the induction step as $\forall x. P(x)\imp P(Suc(x))$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   686
To avoid making induction require the presence of other connectives, we
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   687
formalize mathematical induction as
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   688
$$ \List{P(0); \Forall x. P(x)\Imp P(Suc(x))} \Imp P(n). \eqno(induct) $$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   689
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   690
\noindent
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   691
Similarly, to avoid expressing the other rules using~$\forall$, $\imp$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   692
and~$\neg$, we take advantage of the meta-logic;\footnote
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   693
{On the other hand, the axioms $Suc(m)=Suc(n) \bimp m=n$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   694
and $\neg(Suc(m)=0)$ are logically equivalent to those given, and work
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   695
better with Isabelle's simplifier.} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   696
$(Suc\_neq\_0)$ is
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   697
an elimination rule for $Suc(m)=0$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   698
$$ Suc(m)=Suc(n) \Imp m=n  \eqno(Suc\_inject) $$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   699
$$ Suc(m)=0      \Imp R    \eqno(Suc\_neq\_0) $$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   700
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   701
\noindent
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   702
We shall also define a primitive recursion operator, $rec$.  Traditionally,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   703
primitive recursion takes a natural number~$a$ and a 2-place function~$f$,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   704
and obeys the equations
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   705
\begin{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   706
  rec(0,a,f)            & = & a \\
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   707
  rec(Suc(m),a,f)       & = & f(m, rec(m,a,f))
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   708
\end{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   709
Addition, defined by $m+n \equiv rec(m,n,\lambda x\,y.Suc(y))$,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   710
should satisfy
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   711
\begin{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   712
  0+n      & = & n \\
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   713
  Suc(m)+n & = & Suc(m+n)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   714
\end{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   715
This appears to pose difficulties: first-order logic has no functions.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   716
Following the previous examples, we take advantage of the meta-logic, which
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   717
does have functions.  We also generalise primitive recursion to be
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   718
polymorphic over any type of class~$term$, and declare the addition
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   719
function:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   720
\begin{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   721
  rec   & :: & [nat, \alpha{::}term, [nat,\alpha]\To\alpha] \To\alpha \\
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   722
  +     & :: & [nat,nat]\To nat 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   723
\end{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   724
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   725
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   726
\subsection{Declaring the theory to Isabelle}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   727
\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   728
Let us create the theory \ttindexbold{Nat} starting from theory~\verb$FOL$,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   729
which contains only classical logic with no natural numbers.  We declare
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   730
the 0-place type constructor $nat$ and the constants $rec$ and~$Suc$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   731
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   732
Nat = FOL +
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   733
types   nat 0
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   734
arities nat         :: term
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   735
consts  "0"         :: "nat"    ("0")
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   736
        Suc         :: "nat=>nat"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   737
        rec         :: "[nat, 'a, [nat,'a]=>'a] => 'a"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   738
        "+"         :: "[nat, nat] => nat"              (infixl 60)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   739
rules   induct      "[| P(0);  !!x. P(x) ==> P(Suc(x)) |]  ==> P(n)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   740
        Suc_inject  "Suc(m)=Suc(n) ==> m=n"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   741
        Suc_neq_0   "Suc(m)=0      ==> R"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   742
        rec_0       "rec(0,a,f) = a"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   743
        rec_Suc     "rec(Suc(m), a, f) = f(m, rec(m,a,f))"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   744
        add_def     "m+n == rec(m, n, %x y. Suc(y))"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   745
end
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   746
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   747
In axiom {\tt add_def}, recall that \verb|%| stands for~$\lambda$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   748
Opening the \ML\ structure {\tt Nat} permits reference to the axioms by \ML\
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   749
identifiers; we may write {\tt induct} instead of {\tt Nat.induct}.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   750
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   751
open Nat;
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   752
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   753
File {\tt FOL/ex/nat.ML} contains proofs involving this theory of the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   754
natural numbers.  As a trivial example, let us derive recursion equations
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   755
for \verb$+$.  Here is the zero case:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   756
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   757
goalw Nat.thy [add_def] "0+n = n";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   758
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   759
{\out 0 + n = n}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   760
{\out  1. rec(0,n,%x y. Suc(y)) = n}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   761
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   762
by (resolve_tac [rec_0] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   763
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   764
{\out 0 + n = n}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   765
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   766
val add_0 = result();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   767
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   768
And here is the successor case:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   769
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   770
goalw Nat.thy [add_def] "Suc(m)+n = Suc(m+n)";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   771
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   772
{\out Suc(m) + n = Suc(m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   773
{\out  1. rec(Suc(m),n,%x y. Suc(y)) = Suc(rec(m,n,%x y. Suc(y)))}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   774
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   775
by (resolve_tac [rec_Suc] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   776
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   777
{\out Suc(m) + n = Suc(m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   778
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   779
val add_Suc = result();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   780
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   781
The induction rule raises some complications, which are discussed next.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   782
\index{theories!defining|)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   783
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   784
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   785
\section{Refinement with explicit instantiation}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   786
\index{refinement!with instantiation|bold}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   787
\index{instantiation!explicit|bold}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   788
In order to employ mathematical induction, we need to refine a subgoal by
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   789
the rule~$(induct)$.  The conclusion of this rule is $\Var{P}(\Var{n})$,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   790
which is highly ambiguous in higher-order unification.  It matches every
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   791
way that a formula can be regarded as depending on a subterm of type~$nat$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   792
To get round this problem, we could make the induction rule conclude
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   793
$\forall n.\Var{P}(n)$ --- but putting a subgoal into this form requires
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   794
refinement by~$(\forall E)$, which is equally hard!
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   795
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   796
The tactic {\tt res_inst_tac}, like {\tt resolve_tac}, refines a subgoal by
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   797
a rule.  But it also accepts explicit instantiations for the rule's
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   798
schematic variables.  
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   799
\begin{description}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   800
\item[\ttindexbold{res_inst_tac} {\it insts} {\it thm} {\it i}]
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   801
instantiates the rule {\it thm} with the instantiations {\it insts}, and
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   802
then performs resolution on subgoal~$i$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   803
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   804
\item[\ttindexbold{eres_inst_tac}] 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   805
and \ttindexbold{dres_inst_tac} are similar, but perform elim-resolution
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   806
and destruct-resolution, respectively.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   807
\end{description}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   808
The list {\it insts} consists of pairs $[(v@1,e@1), \ldots, (v@n,e@n)]$,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   809
where $v@1$, \ldots, $v@n$ are names of schematic variables in the rule ---
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   810
with {\bf no} leading question marks!! --- and $e@1$, \ldots, $e@n$ are
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   811
expressions giving their instantiations.  The expressions are type-checked
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   812
in the context of a particular subgoal: free variables receive the same
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   813
types as they have in the subgoal, and parameters may appear.  Type
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   814
variable instantiations may appear in~{\it insts}, but they are seldom
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   815
required: {\tt res_inst_tac} instantiates type variables automatically
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   816
whenever the type of~$e@i$ is an instance of the type of~$\Var{v@i}$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   817
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   818
\subsection{A simple proof by induction}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   819
\index{proof!by induction}\index{examples!of induction}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   820
Let us prove that no natural number~$k$ equals its own successor.  To
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   821
use~$(induct)$, we instantiate~$\Var{n}$ to~$k$; Isabelle finds a good
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   822
instantiation for~$\Var{P}$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   823
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   824
goal Nat.thy "~ (Suc(k) = k)";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   825
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   826
{\out ~Suc(k) = k}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   827
{\out  1. ~Suc(k) = k}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   828
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   829
by (res_inst_tac [("n","k")] induct 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   830
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   831
{\out ~Suc(k) = k}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   832
{\out  1. ~Suc(0) = 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   833
{\out  2. !!x. ~Suc(x) = x ==> ~Suc(Suc(x)) = Suc(x)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   834
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   835
We should check that Isabelle has correctly applied induction.  Subgoal~1
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   836
is the base case, with $k$ replaced by~0.  Subgoal~2 is the inductive step,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   837
with $k$ replaced by~$Suc(x)$ and with an induction hypothesis for~$x$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   838
The rest of the proof demonstrates~\ttindex{notI}, \ttindex{notE} and the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   839
other rules of~\ttindex{Nat.thy}.  The base case holds by~\ttindex{Suc_neq_0}:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   840
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   841
by (resolve_tac [notI] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   842
{\out Level 2}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   843
{\out ~Suc(k) = k}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   844
{\out  1. Suc(0) = 0 ==> False}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   845
{\out  2. !!x. ~Suc(x) = x ==> ~Suc(Suc(x)) = Suc(x)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   846
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   847
by (eresolve_tac [Suc_neq_0] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   848
{\out Level 3}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   849
{\out ~Suc(k) = k}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   850
{\out  1. !!x. ~Suc(x) = x ==> ~Suc(Suc(x)) = Suc(x)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   851
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   852
The inductive step holds by the contrapositive of~\ttindex{Suc_inject}.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   853
Using the negation rule, we assume $Suc(Suc(x)) = Suc(x)$ and prove $Suc(x)=x$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   854
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   855
by (resolve_tac [notI] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   856
{\out Level 4}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   857
{\out ~Suc(k) = k}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   858
{\out  1. !!x. [| ~Suc(x) = x; Suc(Suc(x)) = Suc(x) |] ==> False}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   859
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   860
by (eresolve_tac [notE] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   861
{\out Level 5}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   862
{\out ~Suc(k) = k}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   863
{\out  1. !!x. Suc(Suc(x)) = Suc(x) ==> Suc(x) = x}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   864
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   865
by (eresolve_tac [Suc_inject] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   866
{\out Level 6}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   867
{\out ~Suc(k) = k}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   868
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   869
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   870
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   871
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   872
\subsection{An example of ambiguity in {\tt resolve_tac}}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   873
\index{examples!of induction}\index{unification!higher-order}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   874
If you try the example above, you may observe that {\tt res_inst_tac} is
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   875
not actually needed.  Almost by chance, \ttindex{resolve_tac} finds the right
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   876
instantiation for~$(induct)$ to yield the desired next state.  With more
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   877
complex formulae, our luck fails.  
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   878
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   879
goal Nat.thy "(k+m)+n = k+(m+n)";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   880
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   881
{\out k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   882
{\out  1. k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   883
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   884
by (resolve_tac [induct] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   885
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   886
{\out k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   887
{\out  1. k + m + n = 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   888
{\out  2. !!x. k + m + n = x ==> k + m + n = Suc(x)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   889
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   890
This proof requires induction on~$k$.  But the 0 in subgoal~1 indicates
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   891
that induction has been applied to the term~$k+(m+n)$.  The
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   892
\ttindex{back} command causes backtracking to an alternative
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   893
outcome of the tactic.  
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   894
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   895
back();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   896
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   897
{\out k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   898
{\out  1. k + m + n = k + 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   899
{\out  2. !!x. k + m + n = k + x ==> k + m + n = k + Suc(x)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   900
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   901
Now induction has been applied to~$m+n$.  Let us call \ttindex{back}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   902
again.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   903
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   904
back();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   905
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   906
{\out k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   907
{\out  1. k + m + 0 = k + (m + 0)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   908
{\out  2. !!x. k + m + x = k + (m + x) ==> k + m + Suc(x) = k + (m + Suc(x))}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   909
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   910
Now induction has been applied to~$n$.  What is the next alternative?
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   911
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   912
back();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   913
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   914
{\out k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   915
{\out  1. k + m + n = k + (m + 0)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   916
{\out  2. !!x. k + m + n = k + (m + x) ==> k + m + n = k + (m + Suc(x))}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   917
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   918
Inspecting subgoal~1 reveals that induction has been applied to just the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   919
second occurrence of~$n$.  This perfectly legitimate induction is useless
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   920
here.  The main goal admits fourteen different applications of induction.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   921
The number is exponential in the size of the formula.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   922
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   923
\subsection{Proving that addition is associative}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   924
\index{associativity of addition}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   925
\index{examples!of rewriting}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   926
Let us do the proof properly, using~\ttindex{res_inst_tac}.  At the same
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   927
time, we shall have a glimpse at Isabelle's rewriting tactics, which are
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   928
described in the {\em Reference Manual}.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   929
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   930
\index{rewriting!object-level} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   931
Isabelle's rewriting tactics repeatedly applies equations to a subgoal,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   932
simplifying or proving it.  For efficiency, the rewriting rules must be
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   933
packaged into a \bfindex{simplification set}.  Let us include the equations
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   934
for~{\tt add} proved in the previous section, namely $0+n=n$ and ${\tt
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   935
  Suc}(m)+n={\tt Suc}(m+n)$: 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   936
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   937
val add_ss = FOL_ss addrews [add_0, add_Suc];
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   938
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   939
We state the goal for associativity of addition, and
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   940
use \ttindex{res_inst_tac} to invoke induction on~$k$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   941
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   942
goal Nat.thy "(k+m)+n = k+(m+n)";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   943
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   944
{\out k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   945
{\out  1. k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   946
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   947
by (res_inst_tac [("n","k")] induct 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   948
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   949
{\out k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   950
{\out  1. 0 + m + n = 0 + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   951
{\out  2. !!x. x + m + n = x + (m + n) ==> Suc(x) + m + n = Suc(x) + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   952
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   953
The base case holds easily; both sides reduce to $m+n$.  The
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   954
tactic~\ttindex{simp_tac} rewrites with respect to the given simplification
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   955
set, applying the rewrite rules for~{\tt +}:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   956
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   957
by (simp_tac add_ss 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   958
{\out Level 2}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   959
{\out k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   960
{\out  1. !!x. x + m + n = x + (m + n) ==> Suc(x) + m + n = Suc(x) + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   961
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   962
The inductive step requires rewriting by the equations for~{\tt add}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   963
together the induction hypothesis, which is also an equation.  The
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   964
tactic~\ttindex{asm_simp_tac} rewrites using a simplification set and any
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   965
useful assumptions:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   966
\begin{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   967
by (asm_simp_tac add_ss 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   968
{\out Level 3}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   969
{\out k + m + n = k + (m + n)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   970
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   971
\end{ttbox} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   972
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   973
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   974
\section{A {\sc Prolog} interpreter}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   975
\index{Prolog interpreter|bold}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   976
To demonstrate the power of tacticals, let us construct a {\sc Prolog}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   977
interpreter and execute programs involving lists.\footnote{To run these
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   978
examples, see the file {\tt FOL/ex/prolog.ML}.} The {\sc Prolog} program
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   979
consists of a theory.  We declare a type constructor for lists, with an
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   980
arity declaration to say that $(\tau)list$ is of class~$term$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   981
provided~$\tau$ is:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   982
\begin{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   983
  list  & :: & (term)term
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   984
\end{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   985
We declare four constants: the empty list~$Nil$; the infix list
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   986
constructor~{:}; the list concatenation predicate~$app$; the list reverse
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   987
predicate~$rev$.  (In {\sc Prolog}, functions on lists are expressed as
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   988
predicates.)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   989
\begin{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   990
    Nil         & :: & \alpha list \\
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   991
    {:}         & :: & [\alpha,\alpha list] \To \alpha list \\
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   992
    app & :: & [\alpha list,\alpha list,\alpha list] \To o \\
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   993
    rev & :: & [\alpha list,\alpha list] \To o 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   994
\end{eqnarray*}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   995
The predicate $app$ should satisfy the {\sc Prolog}-style rules
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   996
\[ {app(Nil,ys,ys)} \qquad
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   997
   {app(xs,ys,zs) \over app(x:xs, ys, x:zs)} \]
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   998
We define the naive version of $rev$, which calls~$app$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
   999
\[ {rev(Nil,Nil)} \qquad
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1000
   {rev(xs,ys)\quad  app(ys, x:Nil, zs) \over
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1001
    rev(x:xs, zs)} 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1002
\]
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1003
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1004
\index{examples!of theories}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1005
Theory \ttindex{Prolog} extends first-order logic in order to make use
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1006
of the class~$term$ and the type~$o$.  The interpreter does not use the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1007
rules of~\ttindex{FOL}.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1008
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1009
Prolog = FOL +
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1010
types   list 1
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1011
arities list    :: (term)term
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1012
consts  Nil     :: "'a list"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1013
        ":"     :: "['a, 'a list]=> 'a list"            (infixr 60)
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1014
        app     :: "['a list, 'a list, 'a list] => o"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1015
        rev     :: "['a list, 'a list] => o"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1016
rules   appNil  "app(Nil,ys,ys)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1017
        appCons "app(xs,ys,zs) ==> app(x:xs, ys, x:zs)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1018
        revNil  "rev(Nil,Nil)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1019
        revCons "[| rev(xs,ys); app(ys,x:Nil,zs) |] ==> rev(x:xs,zs)"
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1020
end
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1021
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1022
\subsection{Simple executions}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1023
Repeated application of the rules solves {\sc Prolog} goals.  Let us
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1024
append the lists $[a,b,c]$ and~$[d,e]$.  As the rules are applied, the
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1025
answer builds up in~{\tt ?x}.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1026
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1027
goal Prolog.thy "app(a:b:c:Nil, d:e:Nil, ?x)";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1028
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1029
{\out app(a : b : c : Nil, d : e : Nil, ?x)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1030
{\out  1. app(a : b : c : Nil, d : e : Nil, ?x)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1031
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1032
by (resolve_tac [appNil,appCons] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1033
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1034
{\out app(a : b : c : Nil, d : e : Nil, a : ?zs1)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1035
{\out  1. app(b : c : Nil, d : e : Nil, ?zs1)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1036
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1037
by (resolve_tac [appNil,appCons] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1038
{\out Level 2}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1039
{\out app(a : b : c : Nil, d : e : Nil, a : b : ?zs2)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1040
{\out  1. app(c : Nil, d : e : Nil, ?zs2)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1041
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1042
At this point, the first two elements of the result are~$a$ and~$b$.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1043
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1044
by (resolve_tac [appNil,appCons] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1045
{\out Level 3}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1046
{\out app(a : b : c : Nil, d : e : Nil, a : b : c : ?zs3)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1047
{\out  1. app(Nil, d : e : Nil, ?zs3)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1048
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1049
by (resolve_tac [appNil,appCons] 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1050
{\out Level 4}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1051
{\out app(a : b : c : Nil, d : e : Nil, a : b : c : d : e : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1052
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1053
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1054
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1055
{\sc Prolog} can run functions backwards.  Which list can be appended
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1056
with $[c,d]$ to produce $[a,b,c,d]$?
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1057
Using \ttindex{REPEAT}, we find the answer at once, $[a,b]$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1058
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1059
goal Prolog.thy "app(?x, c:d:Nil, a:b:c:d:Nil)";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1060
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1061
{\out app(?x, c : d : Nil, a : b : c : d : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1062
{\out  1. app(?x, c : d : Nil, a : b : c : d : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1063
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1064
by (REPEAT (resolve_tac [appNil,appCons] 1));
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1065
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1066
{\out app(a : b : Nil, c : d : Nil, a : b : c : d : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1067
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1068
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1069
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1070
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1071
\subsection{Backtracking}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1072
\index{backtracking}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1073
Which lists $x$ and $y$ can be appended to form the list $[a,b,c,d]$?
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1074
Using \ttindex{REPEAT} to apply the rules, we quickly find the solution
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1075
$x=[]$ and $y=[a,b,c,d]$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1076
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1077
goal Prolog.thy "app(?x, ?y, a:b:c:d:Nil)";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1078
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1079
{\out app(?x, ?y, a : b : c : d : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1080
{\out  1. app(?x, ?y, a : b : c : d : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1081
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1082
by (REPEAT (resolve_tac [appNil,appCons] 1));
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1083
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1084
{\out app(Nil, a : b : c : d : Nil, a : b : c : d : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1085
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1086
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1087
The \ttindex{back} command returns the tactic's next outcome,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1088
$x=[a]$ and $y=[b,c,d]$:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1089
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1090
back();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1091
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1092
{\out app(a : Nil, b : c : d : Nil, a : b : c : d : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1093
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1094
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1095
The other solutions are generated similarly.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1096
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1097
back();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1098
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1099
{\out app(a : b : Nil, c : d : Nil, a : b : c : d : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1100
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1101
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1102
back();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1103
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1104
{\out app(a : b : c : Nil, d : Nil, a : b : c : d : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1105
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1106
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1107
back();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1108
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1109
{\out app(a : b : c : d : Nil, Nil, a : b : c : d : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1110
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1111
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1112
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1113
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1114
\subsection{Depth-first search}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1115
\index{search!depth-first}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1116
Now let us try $rev$, reversing a list.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1117
Bundle the rules together as the \ML{} identifier {\tt rules}.  Naive
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1118
reverse requires 120 inferences for this 14-element list, but the tactic
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1119
terminates in a few seconds.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1120
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1121
goal Prolog.thy "rev(a:b:c:d:e:f:g:h:i:j:k:l:m:n:Nil, ?w)";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1122
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1123
{\out rev(a : b : c : d : e : f : g : h : i : j : k : l : m : n : Nil, ?w)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1124
{\out  1. rev(a : b : c : d : e : f : g : h : i : j : k : l : m : n : Nil, ?w)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1125
val rules = [appNil,appCons,revNil,revCons];
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1126
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1127
by (REPEAT (resolve_tac rules 1));
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1128
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1129
{\out rev(a : b : c : d : e : f : g : h : i : j : k : l : m : n : Nil,}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1130
{\out     n : m : l : k : j : i : h : g : f : e : d : c : b : a : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1131
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1132
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1133
We may execute $rev$ backwards.  This, too, should reverse a list.  What
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1134
is the reverse of $[a,b,c]$?
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1135
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1136
goal Prolog.thy "rev(?x, a:b:c:Nil)";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1137
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1138
{\out rev(?x, a : b : c : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1139
{\out  1. rev(?x, a : b : c : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1140
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1141
by (REPEAT (resolve_tac rules 1));
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1142
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1143
{\out rev(?x1 : Nil, a : b : c : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1144
{\out  1. app(Nil, ?x1 : Nil, a : b : c : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1145
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1146
The tactic has failed to find a solution!  It reached a dead end at
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1147
subgoal~1: there is no~$\Var{x1}$ such that [] appended with~$[\Var{x1}]$
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1148
equals~$[a,b,c]$.  Backtracking explores other outcomes.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1149
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1150
back();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1151
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1152
{\out rev(?x1 : a : Nil, a : b : c : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1153
{\out  1. app(Nil, ?x1 : Nil, b : c : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1154
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1155
This too is a dead end, but the next outcome is successful.
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1156
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1157
back();
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1158
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1159
{\out rev(c : b : a : Nil, a : b : c : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1160
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1161
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1162
\ttindex{REPEAT} stops when it cannot continue, regardless of which state
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1163
is reached.  The tactical \ttindex{DEPTH_FIRST} searches for a satisfactory
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1164
state, as specified by an \ML{} predicate.  Below,
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1165
\ttindex{has_fewer_prems} specifies that the proof state should have no
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1166
subgoals.  
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1167
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1168
val prolog_tac = DEPTH_FIRST (has_fewer_prems 1) 
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1169
                             (resolve_tac rules 1);
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1170
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1171
Since {\sc Prolog} uses depth-first search, this tactic is a (slow!) {\sc
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1172
Prolog} interpreter.  We return to the start of the proof (using
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1173
\ttindex{choplev}), and apply {\tt prolog_tac}:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1174
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1175
choplev 0;
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1176
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1177
{\out rev(?x, a : b : c : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1178
{\out  1. rev(?x, a : b : c : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1179
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1180
by (DEPTH_FIRST (has_fewer_prems 1) (resolve_tac rules 1));
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1181
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1182
{\out rev(c : b : a : Nil, a : b : c : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1183
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1184
\end{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1185
Let us try {\tt prolog_tac} on one more example, containing four unknowns:
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1186
\begin{ttbox}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1187
goal Prolog.thy "rev(a:?x:c:?y:Nil, d:?z:b:?u)";
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1188
{\out Level 0}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1189
{\out rev(a : ?x : c : ?y : Nil, d : ?z : b : ?u)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1190
{\out  1. rev(a : ?x : c : ?y : Nil, d : ?z : b : ?u)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1191
\ttbreak
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1192
by prolog_tac;
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1193
{\out Level 1}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1194
{\out rev(a : b : c : d : Nil, d : c : b : a : Nil)}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1195
{\out No subgoals!}
216d6ed87399 Initial revision
lcp
parents:
diff changeset
  1196
\end{ttbox}
156
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
  1197
Although Isabelle is much slower than a {\sc Prolog} system, Isabelle
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
  1198
tactics can exploit logic programming techniques.  
ab4dcb9285e0 Corrected errors found by Marcus Wenzel.
lcp
parents: 109
diff changeset
  1199