2 \part{Advanced Methods}
3 Before continuing, it might be wise to try some of your own examples in
4 Isabelle, reinforcing your knowledge of the basic functions.
6 Look through {\em Isabelle's Object-Logics\/} and try proving some simple
7 theorems. You probably should begin with first-order logic ({\tt FOL}
8 or~{\tt LK}). Try working some of the examples provided, and others from
9 the literature. Set theory~({\tt ZF}) and Constructive Type Theory~({\tt
10 CTT}) form a richer world for mathematical reasoning and, again, many
11 examples are in the literature. Higher-order logic~({\tt HOL}) is
12 Isabelle's most sophisticated logic because its types and functions are
13 identified with those of the meta-logic.
15 Choose a logic that you already understand. Isabelle is a proof
16 tool, not a teaching tool; if you do not know how to do a particular proof
17 on paper, then you certainly will not be able to do it on the machine.
18 Even experienced users plan large proofs on paper.
20 We have covered only the bare essentials of Isabelle, but enough to perform
21 substantial proofs. By occasionally dipping into the {\em Reference
22 Manual}, you can learn additional tactics, subgoal commands and tacticals.
25 \section{Deriving rules in Isabelle}
27 A mathematical development goes through a progression of stages. Each
28 stage defines some concepts and derives rules about them. We shall see how
29 to derive rules, perhaps involving definitions, using Isabelle. The
30 following section will explain how to declare types, constants, rules and
34 \subsection{Deriving a rule using tactics and meta-level assumptions}
35 \label{deriving-example}
36 \index{examples!of deriving rules}\index{assumptions!of main goal}
38 The subgoal module supports the derivation of rules, as discussed in
39 \S\ref{deriving}. The \ttindex{goal} command, when supplied a goal of the
40 form $\List{\theta@1; \ldots; \theta@k} \Imp \phi$, creates $\phi\Imp\phi$
41 as the initial proof state and returns a list consisting of the theorems
42 ${\theta@i\;[\theta@i]}$, for $i=1$, \ldots,~$k$. These meta-assumptions
43 are also recorded internally, allowing {\tt result} to discharge them
44 in the original order.
46 Let us derive $\conj$ elimination using Isabelle.
47 Until now, calling {\tt goal} has returned an empty list, which we have
48 thrown away. In this example, the list contains the two premises of the
49 rule. We bind them to the \ML\ identifiers {\tt major} and {\tt
50 minor}:\footnote{Some ML compilers will print a message such as {\em
51 binding not exhaustive}. This warns that {\tt goal} must return a
52 2-element list. Otherwise, the pattern-match will fail; ML will
53 raise exception \xdx{Match}.}
55 val [major,minor] = goal FOL.thy
56 "[| P&Q; [| P; Q |] ==> R |] ==> R";
60 {\out val major = "P & Q [P & Q]" : thm}
61 {\out val minor = "[| P; Q |] ==> R [[| P; Q |] ==> R]" : thm}
63 Look at the minor premise, recalling that meta-level assumptions are
64 shown in brackets. Using {\tt minor}, we reduce $R$ to the subgoals
67 by (resolve_tac [minor] 1);
73 Deviating from~\S\ref{deriving}, we apply $({\conj}E1)$ forwards from the
74 assumption $P\conj Q$ to obtain the theorem~$P\;[P\conj Q]$.
77 {\out val it = "P [P & Q]" : thm}
79 by (resolve_tac [major RS conjunct1] 1);
84 Similarly, we solve the subgoal involving~$Q$.
87 {\out val it = "Q [P & Q]" : thm}
88 by (resolve_tac [major RS conjunct2] 1);
93 Calling \ttindex{topthm} returns the current proof state as a theorem.
94 Note that it contains assumptions. Calling \ttindex{result} discharges the
95 assumptions --- both occurrences of $P\conj Q$ are discharged as one ---
96 and makes the variables schematic.
99 {\out val it = "R [P & Q, P & Q, [| P; Q |] ==> R]" : thm}
100 val conjE = result();
101 {\out val conjE = "[| ?P & ?Q; [| ?P; ?Q |] ==> ?R |] ==> ?R" : thm}
105 \subsection{Definitions and derived rules} \label{definitions}
106 \index{rules!derived}\index{definitions!and derived rules|(}
108 Definitions are expressed as meta-level equalities. Let us define negation
109 and the if-and-only-if connective:
111 \neg \Var{P} & \equiv & \Var{P}\imp\bot \\
112 \Var{P}\bimp \Var{Q} & \equiv &
113 (\Var{P}\imp \Var{Q}) \conj (\Var{Q}\imp \Var{P})
115 \index{meta-rewriting}%
116 Isabelle permits {\bf meta-level rewriting} using definitions such as
117 these. {\bf Unfolding} replaces every instance
118 of $\neg \Var{P}$ by the corresponding instance of ${\Var{P}\imp\bot}$. For
119 example, $\forall x.\neg (P(x)\conj \neg R(x,0))$ unfolds to
120 \[ \forall x.(P(x)\conj R(x,0)\imp\bot)\imp\bot. \]
121 {\bf Folding} a definition replaces occurrences of the right-hand side by
122 the left. The occurrences need not be free in the entire formula.
124 When you define new concepts, you should derive rules asserting their
125 abstract properties, and then forget their definitions. This supports
126 modularity: if you later change the definitions without affecting their
127 abstract properties, then most of your proofs will carry through without
128 change. Indiscriminate unfolding makes a subgoal grow exponentially,
131 Taking this point of view, Isabelle does not unfold definitions
132 automatically during proofs. Rewriting must be explicit and selective.
133 Isabelle provides tactics and meta-rules for rewriting, and a version of
134 the {\tt goal} command that unfolds the conclusion and premises of the rule
137 For example, the intuitionistic definition of negation given above may seem
138 peculiar. Using Isabelle, we shall derive pleasanter negation rules:
139 \[ \infer[({\neg}I)]{\neg P}{\infer*{\bot}{[P]}} \qquad
140 \infer[({\neg}E)]{Q}{\neg P & P} \]
141 This requires proving the following meta-formulae:
142 $$ (P\Imp\bot) \Imp \neg P \eqno(\neg I)$$
143 $$ \List{\neg P; P} \Imp Q. \eqno(\neg E)$$
146 \subsection{Deriving the $\neg$ introduction rule}
147 To derive $(\neg I)$, we may call {\tt goal} with the appropriate
148 formula. Again, {\tt goal} returns a list consisting of the rule's
149 premises. We bind this one-element list to the \ML\ identifier {\tt
152 val prems = goal FOL.thy "(P ==> False) ==> ~P";
156 {\out val prems = ["P ==> False [P ==> False]"] : thm list}
158 Calling \ttindex{rewrite_goals_tac} with \tdx{not_def}, which is the
159 definition of negation, unfolds that definition in the subgoals. It leaves
163 {\out val it = "~?P == ?P --> False" : thm}
164 by (rewrite_goals_tac [not_def]);
167 {\out 1. P --> False}
169 Using \tdx{impI} and the premise, we reduce subgoal~1 to a triviality:
171 by (resolve_tac [impI] 1);
174 {\out 1. P ==> False}
176 by (resolve_tac prems 1);
181 The rest of the proof is routine. Note the form of the final result.
189 {\out val notI = "(?P ==> False) ==> ~?P" : thm}
191 \indexbold{*notI theorem}
193 There is a simpler way of conducting this proof. The \ttindex{goalw}
194 command starts a backward proof, as does {\tt goal}, but it also
195 unfolds definitions. Thus there is no need to call
196 \ttindex{rewrite_goals_tac}:
198 val prems = goalw FOL.thy [not_def]
199 "(P ==> False) ==> ~P";
202 {\out 1. P --> False}
203 {\out val prems = ["P ==> False [P ==> False]"] : thm list}
207 \subsection{Deriving the $\neg$ elimination rule}
208 Let us derive the rule $(\neg E)$. The proof follows that of~{\tt conjE}
209 above, with an additional step to unfold negation in the major premise.
210 Although the {\tt goalw} command is best for this, let us
211 try~{\tt goal} to see another way of unfolding definitions. After
212 binding the premises to \ML\ identifiers, we apply \tdx{FalseE}:
214 val [major,minor] = goal FOL.thy "[| ~P; P |] ==> R";
218 {\out val major = "~ P [~ P]" : thm}
219 {\out val minor = "P [P]" : thm}
221 by (resolve_tac [FalseE] 1);
226 Everything follows from falsity. And we can prove falsity using the
227 premises and Modus Ponens:
229 by (resolve_tac [mp] 1);
232 {\out 1. ?P1 --> False}
235 For subgoal~1, we transform the major premise from~$\neg P$
236 to~${P\imp\bot}$. The function \ttindex{rewrite_rule}, given a list of
237 definitions, unfolds them in a theorem. Rewriting does not
238 affect the theorem's hypothesis, which remains~$\neg P$:
240 rewrite_rule [not_def] major;
241 {\out val it = "P --> False [~P]" : thm}
242 by (resolve_tac [it] 1);
247 The subgoal {\tt?P1} has been instantiated to~{\tt P}, which we can prove
248 using the minor premise:
250 by (resolve_tac [minor] 1);
255 {\out val notE = "[| ~?P; ?P |] ==> ?R" : thm}
257 \indexbold{*notE theorem}
260 Again, there is a simpler way of conducting this proof. Recall that
261 the \ttindex{goalw} command unfolds definitions the conclusion; it also
262 unfolds definitions in the premises:
264 val [major,minor] = goalw FOL.thy [not_def]
266 {\out val major = "P --> False [~ P]" : thm}
267 {\out val minor = "P [P]" : thm}
269 Observe the difference in {\tt major}; the premises are unfolded without
270 calling~\ttindex{rewrite_rule}. Incidentally, the four calls to
271 \ttindex{resolve_tac} above can be collapsed to one, with the help
272 of~\ttindex{RS}; this is a typical example of forward reasoning from a
275 minor RS (major RS mp RS FalseE);
276 {\out val it = "?P [P, ~P]" : thm}
277 by (resolve_tac [it] 1);
282 \index{definitions!and derived rules|)}
284 \goodbreak\medskip\index{*"!"! symbol!in main goal}
285 Finally, here is a trick that is sometimes useful. If the goal
286 has an outermost meta-quantifier, then \ttindex{goal} and \ttindex{goalw}
287 do not return the rule's premises in the list of theorems; instead, the
288 premises become assumptions in subgoal~1.
289 %%%It does not matter which variables are quantified over.
291 goalw FOL.thy [not_def] "!!P R. [| ~P; P |] ==> R";
293 {\out !!P R. [| ~ P; P |] ==> R}
294 {\out 1. !!P R. [| P --> False; P |] ==> R}
295 val it = [] : thm list
297 The proof continues as before. But instead of referring to \ML\
298 identifiers, we refer to assumptions using {\tt eresolve_tac} or
301 by (resolve_tac [FalseE] 1);
303 {\out !!P R. [| ~ P; P |] ==> R}
304 {\out 1. !!P R. [| P --> False; P |] ==> False}
306 by (eresolve_tac [mp] 1);
308 {\out !!P R. [| ~ P; P |] ==> R}
309 {\out 1. !!P R. P ==> P}
313 {\out !!P R. [| ~ P; P |] ==> R}
316 Calling \ttindex{result} strips the meta-quantifiers, so the resulting
317 theorem is the same as before.
320 {\out val notE = "[| ~?P; ?P |] ==> ?R" : thm}
322 Do not use the {\tt!!}\ trick if the premises contain meta-level
323 connectives, because \ttindex{eresolve_tac} and \ttindex{assume_tac} would
324 not be able to handle the resulting assumptions. The trick is not suitable
325 for deriving the introduction rule~$(\neg I)$.
328 \section{Defining theories}\label{sec:defining-theories}
329 \index{theories!defining|(}
331 Isabelle makes no distinction between simple extensions of a logic --- like
332 defining a type~$bool$ with constants~$true$ and~$false$ --- and defining
333 an entire logic. A theory definition has the form
335 \(T\) = \(S@1\) + \(\cdots\) + \(S@n\) +
336 classes {\it class declarations}
338 types {\it type declarations and synonyms}
339 arities {\it arity declarations}
340 consts {\it constant declarations}
341 rules {\it rule declarations}
342 translations {\it translation declarations}
346 This declares the theory $T$ to extend the existing theories
347 $S@1$,~\ldots,~$S@n$. It may declare new classes, types, arities
348 (overloadings of existing types), constants and rules; it can specify the
349 default sort for type variables. A constant declaration can specify an
350 associated concrete syntax. The translations section specifies rewrite
351 rules on abstract syntax trees, for defining notations and abbreviations.
353 The {\tt ML} section contains code to perform arbitrary syntactic
354 transformations. The main declaration forms are discussed below.
355 The full syntax can be found in \iflabelundefined{app:TheorySyntax}{the
356 appendix of the {\it Reference Manual}}{App.\ts\ref{app:TheorySyntax}}.
358 All the declaration parts can be omitted. In the simplest case, $T$ is
359 just the union of $S@1$,~\ldots,~$S@n$. New theories always extend one
360 or more other theories, inheriting their types, constants, syntax, etc.
361 The theory \thydx{Pure} contains nothing but Isabelle's meta-logic.
363 Each theory definition must reside in a separate file, whose name is the
364 theory's with {\tt.thy} appended. For example, theory {\tt ListFn} resides
365 on a file named {\tt ListFn.thy}. Isabelle uses this convention to locate the
366 file containing a given theory; \ttindexbold{use_thy} automatically loads a
367 theory's parents before loading the theory itself.
369 Calling \ttindexbold{use_thy}~{\tt"{\it T\/}"} reads a theory from the
370 file {\it T}{\tt.thy}, writes the corresponding {\ML} code to the file
371 {\tt.{\it T}.thy.ML}, reads the latter file, and deletes it if no errors
372 occurred. This declares the {\ML} structure~$T$, which contains a component
373 {\tt thy} denoting the new theory, a component for each rule, and everything
374 declared in {\it ML code}.
376 Errors may arise during the translation to {\ML} (say, a misspelled keyword)
377 or during creation of the new theory (say, a type error in a rule). But if
378 all goes well, {\tt use_thy} will finally read the file {\it T}{\tt.ML}, if
379 it exists. This file typically begins with the {\ML} declaration {\tt
380 open}~$T$ and contains proofs that refer to the components of~$T$.
382 When a theory file is modified, many theories may have to be reloaded.
383 Isabelle records the modification times and dependencies of theory files.
385 \iflabelundefined{sec:reloading-theories}{the {\em Reference Manual\/}}%
386 {\S\ref{sec:reloading-theories}}
390 \subsection{Declaring constants and rules}
391 \indexbold{constants!declaring}\index{rules!declaring}
393 Most theories simply declare constants and rules. The {\bf constant
394 declaration part} has the form
396 consts \(c@1\) :: "\(\tau@1\)"
398 \(c@n\) :: "\(\tau@n\)"
400 where $c@1$, \ldots, $c@n$ are constants and $\tau@1$, \ldots, $\tau@n$ are
401 types. Each type {\em must\/} be enclosed in quotation marks. Each
402 constant must be enclosed in quotation marks unless it is a valid
403 identifier. To declare $c@1$, \ldots, $c@n$ as constants of type $\tau$,
404 the $n$ declarations may be abbreviated to a single line:
406 \(c@1\), \ldots, \(c@n\) :: "\(\tau\)"
408 The {\bf rule declaration part} has the form
410 rules \(id@1\) "\(rule@1\)"
412 \(id@n\) "\(rule@n\)"
414 where $id@1$, \ldots, $id@n$ are \ML{} identifiers and $rule@1$, \ldots,
415 $rule@n$ are expressions of type~$prop$. Each rule {\em must\/} be
416 enclosed in quotation marks.
418 \indexbold{definitions}
419 {\bf Definitions} are rules of the form $t\equiv u$. Normally definitions
420 should be conservative, serving only as abbreviations. As of this writing,
421 Isabelle does not provide a separate declaration part for definitions; it
422 is your responsibility to ensure that your definitions are conservative.
423 However, Isabelle's rewriting primitives will reject $t\equiv u$ unless all
424 variables free in~$u$ are also free in~$t$.
426 \index{examples!of theories}
427 This theory extends first-order logic with two constants {\em nand} and
428 {\em xor}, and declares rules to define them:
431 consts nand,xor :: "[o,o] => o"
432 rules nand_def "nand(P,Q) == ~(P & Q)"
433 xor_def "xor(P,Q) == P & ~Q | ~P & Q"
438 \subsection{Declaring type constructors}
439 \indexbold{types!declaring}\indexbold{arities!declaring}
441 Types are composed of type variables and {\bf type constructors}. Each
442 type constructor takes a fixed number of arguments. They are declared
443 with an \ML-like syntax. If $list$ takes one type argument, $tree$ takes
444 two arguments and $nat$ takes no arguments, then these type constructors
452 The {\bf type declaration part} has the general form
454 types \(tids@1\) \(id@1\)
458 where $id@1$, \ldots, $id@n$ are identifiers and $tids@1$, \ldots, $tids@n$
459 are type argument lists as shown in the example above. It declares each
460 $id@i$ as a type constructor with the specified number of argument places.
462 The {\bf arity declaration part} has the form
464 arities \(tycon@1\) :: \(arity@1\)
466 \(tycon@n\) :: \(arity@n\)
468 where $tycon@1$, \ldots, $tycon@n$ are identifiers and $arity@1$, \ldots,
469 $arity@n$ are arities. Arity declarations add arities to existing
470 types; they do not declare the types themselves.
471 In the simplest case, for an 0-place type constructor, an arity is simply
472 the type's class. Let us declare a type~$bool$ of class $term$, with
473 constants $tt$ and~$ff$. (In first-order logic, booleans are
474 distinct from formulae, which have type $o::logic$.)
475 \index{examples!of theories}
480 consts tt,ff :: "bool"
483 A $k$-place type constructor may have arities of the form
484 $(s@1,\ldots,s@k)c$, where $s@1,\ldots,s@n$ are sorts and $c$ is a class.
485 Each sort specifies a type argument; it has the form $\{c@1,\ldots,c@m\}$,
486 where $c@1$, \dots,~$c@m$ are classes. Mostly we deal with singleton
487 sorts, and may abbreviate them by dropping the braces. The arity
488 $(term)term$ is short for $(\{term\})term$. Recall the discussion in
491 A type constructor may be overloaded (subject to certain conditions) by
492 appearing in several arity declarations. For instance, the function type
493 constructor~$fun$ has the arity $(logic,logic)logic$; in higher-order
494 logic, it is declared also to have arity $(term,term)term$.
496 Theory {\tt List} declares the 1-place type constructor $list$, gives
497 it arity $(term)term$, and declares constants $Nil$ and $Cons$ with
499 \footnote{In the {\tt consts} part, type variable {\tt'a} has the default
500 sort, which is {\tt term}. See the {\em Reference Manual\/}
501 \iflabelundefined{sec:ref-defining-theories}{}%
502 {(\S\ref{sec:ref-defining-theories})} for more information.}
503 \index{examples!of theories}
507 arities list :: (term)term
508 consts Nil :: "'a list"
509 Cons :: "['a, 'a list] => 'a list"
512 Multiple arity declarations may be abbreviated to a single line:
514 arities \(tycon@1\), \ldots, \(tycon@n\) :: \(arity\)
518 Arity declarations resemble constant declarations, but there are {\it no\/}
519 quotation marks! Types and rules must be quoted because the theory
520 translator passes them verbatim to the {\ML} output file.
523 \subsection{Type synonyms}\indexbold{type synonyms}
524 Isabelle supports {\bf type synonyms} ({\bf abbreviations}) which are similar
525 to those found in \ML. Such synonyms are defined in the type declaration part
526 and are fairly self explanatory:
528 types gate = "[o,o] => o"
530 ('a,'b)nuf = "'b => 'a"
532 Type declarations and synonyms can be mixed arbitrarily:
535 'a stream = "nat => 'a"
536 signal = "nat stream"
539 A synonym is merely an abbreviation for some existing type expression. Hence
540 synonyms may not be recursive! Internally all synonyms are fully expanded. As
541 a consequence Isabelle output never contains synonyms. Their main purpose is
542 to improve the readability of theories. Synonyms can be used just like any
545 consts and,or :: "gate"
546 negate :: "signal => signal"
549 \subsection{Infix and mixfix operators}
550 \index{infixes}\index{examples!of theories}
552 Infix or mixfix syntax may be attached to constants. Consider the
556 consts "~&" :: "[o,o] => o" (infixl 35)
557 "#" :: "[o,o] => o" (infixl 30)
558 rules nand_def "P ~& Q == ~(P & Q)"
559 xor_def "P # Q == P & ~Q | ~P & Q"
562 The constant declaration part declares two left-associating infix operators
563 with their priorities, or precedences; they are $\nand$ of priority~35 and
564 $\xor$ of priority~30. Hence $P \xor Q \xor R$ is parsed as $(P\xor Q)
565 \xor R$ and $P \xor Q \nand R$ as $P \xor (Q \nand R)$. Note the quotation
566 marks in \verb|"~&"| and \verb|"#"|.
568 The constants \hbox{\verb|op ~&|} and \hbox{\verb|op #|} are declared
569 automatically, just as in \ML. Hence you may write propositions like
570 \verb|op #(True) == op ~&(True)|, which asserts that the functions $\lambda
571 Q.True \xor Q$ and $\lambda Q.True \nand Q$ are identical.
573 \bigskip\index{mixfix declarations}
574 {\bf Mixfix} operators may have arbitrary context-free syntaxes. Let us
575 add a line to the constant declaration part:
577 If :: "[o,o,o] => o" ("if _ then _ else _")
579 This declares a constant $If$ of type $[o,o,o] \To o$ with concrete syntax {\tt
580 if~$P$ then~$Q$ else~$R$} as well as {\tt If($P$,$Q$,$R$)}. Underscores
581 denote argument positions.
583 The declaration above does not allow the {\tt if}-{\tt then}-{\tt else}
584 construct to be split across several lines, even if it is too long to fit
585 on one line. Pretty-printing information can be added to specify the
586 layout of mixfix operators. For details, see
587 \iflabelundefined{Defining-Logics}%
588 {the {\it Reference Manual}, chapter `Defining Logics'}%
589 {Chap.\ts\ref{Defining-Logics}}.
591 Mixfix declarations can be annotated with priorities, just like
592 infixes. The example above is just a shorthand for
594 If :: "[o,o,o] => o" ("if _ then _ else _" [0,0,0] 1000)
596 The numeric components determine priorities. The list of integers
597 defines, for each argument position, the minimal priority an expression
598 at that position must have. The final integer is the priority of the
599 construct itself. In the example above, any argument expression is
600 acceptable because priorities are non-negative, and conditionals may
601 appear everywhere because 1000 is the highest priority. On the other
602 hand, the declaration
604 If :: "[o,o,o] => o" ("if _ then _ else _" [100,0,0] 99)
606 defines concrete syntax for a conditional whose first argument cannot have
607 the form {\tt if~$P$ then~$Q$ else~$R$} because it must have a priority
608 of at least~100. We may of course write
610 if (if $P$ then $Q$ else $R$) then $S$ else $T$
612 because expressions in parentheses have maximal priority.
614 Binary type constructors, like products and sums, may also be declared as
615 infixes. The type declaration below introduces a type constructor~$*$ with
616 infix notation $\alpha*\beta$, together with the mixfix notation
617 ${<}\_,\_{>}$ for pairs.
618 \index{examples!of theories}\index{mixfix declarations}
621 types ('a,'b) "*" (infixl 20)
622 arities "*" :: (term,term)term
623 consts fst :: "'a * 'b => 'a"
624 snd :: "'a * 'b => 'b"
625 Pair :: "['a,'b] => 'a * 'b" ("(1<_,/_>)")
626 rules fst "fst(<a,b>) = a"
632 The name of the type constructor is~{\tt *} and not {\tt op~*}, as it would
633 be in the case of an infix constant. Only infix type constructors can have
634 symbolic names like~{\tt *}. There is no general mixfix syntax for types.
638 \subsection{Overloading}
639 \index{overloading}\index{examples!of theories}
640 The {\bf class declaration part} has the form
642 classes \(id@1\) < \(c@1\)
646 where $id@1$, \ldots, $id@n$ are identifiers and $c@1$, \ldots, $c@n$ are
647 existing classes. It declares each $id@i$ as a new class, a subclass
648 of~$c@i$. In the general case, an identifier may be declared to be a
649 subclass of $k$ existing classes:
651 \(id\) < \(c@1\), \ldots, \(c@k\)
653 Type classes allow constants to be overloaded. As suggested in
654 \S\ref{polymorphic}, let us define the class $arith$ of arithmetic
655 types with the constants ${+} :: [\alpha,\alpha]\To \alpha$ and $0,1 {::}
656 \alpha$, for $\alpha{::}arith$. We introduce $arith$ as a subclass of
657 $term$ and add the three polymorphic constants of this class.
658 \index{examples!of theories}\index{constants!overloaded}
662 consts "0" :: "'a::arith" ("0")
663 "1" :: "'a::arith" ("1")
664 "+" :: "['a::arith,'a] => 'a" (infixl 60)
667 No rules are declared for these constants: we merely introduce their
668 names without specifying properties. On the other hand, classes
669 with rules make it possible to prove {\bf generic} theorems. Such
670 theorems hold for all instances, all types in that class.
672 We can now obtain distinct versions of the constants of $arith$ by
673 declaring certain types to be of class $arith$. For example, let us
674 declare the 0-place type constructors $bool$ and $nat$:
675 \index{examples!of theories}
679 arities bool, nat :: arith
680 consts Suc :: "nat=>nat"
682 rules add0 "0 + n = n::nat"
683 addS "Suc(m)+n = Suc(m+n)"
685 or0l "0 + x = x::bool"
686 or0r "x + 0 = x::bool"
687 or1l "1 + x = 1::bool"
688 or1r "x + 1 = 1::bool"
691 Because $nat$ and $bool$ have class $arith$, we can use $0$, $1$ and $+$ at
692 either type. The type constraints in the axioms are vital. Without
693 constraints, the $x$ in $1+x = x$ would have type $\alpha{::}arith$
694 and the axiom would hold for any type of class $arith$. This would
695 collapse $nat$ to a trivial type:
696 \[ Suc(1) = Suc(0+1) = Suc(0)+1 = 1+1 = 1! \]
699 \section{Theory example: the natural numbers}
701 We shall now work through a small example of formalized mathematics
702 demonstrating many of the theory extension features.
705 \subsection{Extending first-order logic with the natural numbers}
706 \index{examples!of theories}
708 Section\ts\ref{sec:logical-syntax} has formalized a first-order logic,
709 including a type~$nat$ and the constants $0::nat$ and $Suc::nat\To nat$.
710 Let us introduce the Peano axioms for mathematical induction and the
711 freeness of $0$ and~$Suc$:\index{axioms!Peano}
712 \[ \vcenter{\infer[(induct)]{P[n/x]}{P[0/x] & \infer*{P[Suc(x)/x]}{[P]}}}
713 \qquad \parbox{4.5cm}{provided $x$ is not free in any assumption except~$P$}
715 \[ \infer[(Suc\_inject)]{m=n}{Suc(m)=Suc(n)} \qquad
716 \infer[(Suc\_neq\_0)]{R}{Suc(m)=0}
718 Mathematical induction asserts that $P(n)$ is true, for any $n::nat$,
719 provided $P(0)$ holds and that $P(x)$ implies $P(Suc(x))$ for all~$x$.
720 Some authors express the induction step as $\forall x. P(x)\imp P(Suc(x))$.
721 To avoid making induction require the presence of other connectives, we
722 formalize mathematical induction as
723 $$ \List{P(0); \Forall x. P(x)\Imp P(Suc(x))} \Imp P(n). \eqno(induct) $$
726 Similarly, to avoid expressing the other rules using~$\forall$, $\imp$
727 and~$\neg$, we take advantage of the meta-logic;\footnote
728 {On the other hand, the axioms $Suc(m)=Suc(n) \bimp m=n$
729 and $\neg(Suc(m)=0)$ are logically equivalent to those given, and work
730 better with Isabelle's simplifier.}
732 an elimination rule for $Suc(m)=0$:
733 $$ Suc(m)=Suc(n) \Imp m=n \eqno(Suc\_inject) $$
734 $$ Suc(m)=0 \Imp R \eqno(Suc\_neq\_0) $$
737 We shall also define a primitive recursion operator, $rec$. Traditionally,
738 primitive recursion takes a natural number~$a$ and a 2-place function~$f$,
739 and obeys the equations
741 rec(0,a,f) & = & a \\
742 rec(Suc(m),a,f) & = & f(m, rec(m,a,f))
744 Addition, defined by $m+n \equiv rec(m,n,\lambda x\,y.Suc(y))$,
748 Suc(m)+n & = & Suc(m+n)
750 Primitive recursion appears to pose difficulties: first-order logic has no
751 function-valued expressions. We again take advantage of the meta-logic,
752 which does have functions. We also generalise primitive recursion to be
753 polymorphic over any type of class~$term$, and declare the addition
756 rec & :: & [nat, \alpha{::}term, [nat,\alpha]\To\alpha] \To\alpha \\
757 + & :: & [nat,nat]\To nat
761 \subsection{Declaring the theory to Isabelle}
762 \index{examples!of theories}
763 Let us create the theory \thydx{Nat} starting from theory~\verb$FOL$,
764 which contains only classical logic with no natural numbers. We declare
765 the 0-place type constructor $nat$ and the associated constants. Note that
766 the constant~0 requires a mixfix annotation because~0 is not a legal
767 identifier, and could not otherwise be written in terms:
768 \begin{ttbox}\index{mixfix declarations}
772 consts "0" :: "nat" ("0")
774 rec :: "[nat, 'a, [nat,'a]=>'a] => 'a"
775 "+" :: "[nat, nat] => nat" (infixl 60)
776 rules Suc_inject "Suc(m)=Suc(n) ==> m=n"
777 Suc_neq_0 "Suc(m)=0 ==> R"
778 induct "[| P(0); !!x. P(x) ==> P(Suc(x)) |] ==> P(n)"
779 rec_0 "rec(0,a,f) = a"
780 rec_Suc "rec(Suc(m), a, f) = f(m, rec(m,a,f))"
781 add_def "m+n == rec(m, n, \%x y. Suc(y))"
784 In axiom {\tt add_def}, recall that \verb|%| stands for~$\lambda$.
785 Loading this theory file creates the \ML\ structure {\tt Nat}, which
786 contains the theory and axioms. Opening structure {\tt Nat} lets us write
787 {\tt induct} instead of {\tt Nat.induct}, and so forth.
792 \subsection{Proving some recursion equations}
793 File {\tt FOL/ex/Nat.ML} contains proofs involving this theory of the
794 natural numbers. As a trivial example, let us derive recursion equations
795 for \verb$+$. Here is the zero case:
797 goalw Nat.thy [add_def] "0+n = n";
800 {\out 1. rec(0,n,\%x y. Suc(y)) = n}
802 by (resolve_tac [rec_0] 1);
806 val add_0 = result();
808 And here is the successor case:
810 goalw Nat.thy [add_def] "Suc(m)+n = Suc(m+n)";
812 {\out Suc(m) + n = Suc(m + n)}
813 {\out 1. rec(Suc(m),n,\%x y. Suc(y)) = Suc(rec(m,n,\%x y. Suc(y)))}
815 by (resolve_tac [rec_Suc] 1);
817 {\out Suc(m) + n = Suc(m + n)}
819 val add_Suc = result();
821 The induction rule raises some complications, which are discussed next.
822 \index{theories!defining|)}
825 \section{Refinement with explicit instantiation}
826 \index{resolution!with instantiation}
827 \index{instantiation|(}
829 In order to employ mathematical induction, we need to refine a subgoal by
830 the rule~$(induct)$. The conclusion of this rule is $\Var{P}(\Var{n})$,
831 which is highly ambiguous in higher-order unification. It matches every
832 way that a formula can be regarded as depending on a subterm of type~$nat$.
833 To get round this problem, we could make the induction rule conclude
834 $\forall n.\Var{P}(n)$ --- but putting a subgoal into this form requires
835 refinement by~$(\forall E)$, which is equally hard!
837 The tactic {\tt res_inst_tac}, like {\tt resolve_tac}, refines a subgoal by
838 a rule. But it also accepts explicit instantiations for the rule's
841 \item[\ttindex{res_inst_tac} {\it insts} {\it thm} {\it i}]
842 instantiates the rule {\it thm} with the instantiations {\it insts}, and
843 then performs resolution on subgoal~$i$.
845 \item[\ttindex{eres_inst_tac}]
846 and \ttindex{dres_inst_tac} are similar, but perform elim-resolution
847 and destruct-resolution, respectively.
849 The list {\it insts} consists of pairs $[(v@1,e@1), \ldots, (v@n,e@n)]$,
850 where $v@1$, \ldots, $v@n$ are names of schematic variables in the rule ---
851 with no leading question marks! --- and $e@1$, \ldots, $e@n$ are
852 expressions giving their instantiations. The expressions are type-checked
853 in the context of a particular subgoal: free variables receive the same
854 types as they have in the subgoal, and parameters may appear. Type
855 variable instantiations may appear in~{\it insts}, but they are seldom
856 required: {\tt res_inst_tac} instantiates type variables automatically
857 whenever the type of~$e@i$ is an instance of the type of~$\Var{v@i}$.
859 \subsection{A simple proof by induction}
860 \index{examples!of induction}
861 Let us prove that no natural number~$k$ equals its own successor. To
862 use~$(induct)$, we instantiate~$\Var{n}$ to~$k$; Isabelle finds a good
863 instantiation for~$\Var{P}$.
865 goal Nat.thy "~ (Suc(k) = k)";
868 {\out 1. ~Suc(k) = k}
870 by (res_inst_tac [("n","k")] induct 1);
873 {\out 1. ~Suc(0) = 0}
874 {\out 2. !!x. ~Suc(x) = x ==> ~Suc(Suc(x)) = Suc(x)}
876 We should check that Isabelle has correctly applied induction. Subgoal~1
877 is the base case, with $k$ replaced by~0. Subgoal~2 is the inductive step,
878 with $k$ replaced by~$Suc(x)$ and with an induction hypothesis for~$x$.
879 The rest of the proof demonstrates~\tdx{notI}, \tdx{notE} and the
880 other rules of theory {\tt Nat}. The base case holds by~\ttindex{Suc_neq_0}:
882 by (resolve_tac [notI] 1);
885 {\out 1. Suc(0) = 0 ==> False}
886 {\out 2. !!x. ~Suc(x) = x ==> ~Suc(Suc(x)) = Suc(x)}
888 by (eresolve_tac [Suc_neq_0] 1);
891 {\out 1. !!x. ~Suc(x) = x ==> ~Suc(Suc(x)) = Suc(x)}
893 The inductive step holds by the contrapositive of~\ttindex{Suc_inject}.
894 Negation rules transform the subgoal into that of proving $Suc(x)=x$ from
895 $Suc(Suc(x)) = Suc(x)$:
897 by (resolve_tac [notI] 1);
900 {\out 1. !!x. [| ~Suc(x) = x; Suc(Suc(x)) = Suc(x) |] ==> False}
902 by (eresolve_tac [notE] 1);
905 {\out 1. !!x. Suc(Suc(x)) = Suc(x) ==> Suc(x) = x}
907 by (eresolve_tac [Suc_inject] 1);
914 \subsection{An example of ambiguity in {\tt resolve_tac}}
915 \index{examples!of induction}\index{unification!higher-order}
916 If you try the example above, you may observe that {\tt res_inst_tac} is
917 not actually needed. Almost by chance, \ttindex{resolve_tac} finds the right
918 instantiation for~$(induct)$ to yield the desired next state. With more
919 complex formulae, our luck fails.
921 goal Nat.thy "(k+m)+n = k+(m+n)";
923 {\out k + m + n = k + (m + n)}
924 {\out 1. k + m + n = k + (m + n)}
926 by (resolve_tac [induct] 1);
928 {\out k + m + n = k + (m + n)}
929 {\out 1. k + m + n = 0}
930 {\out 2. !!x. k + m + n = x ==> k + m + n = Suc(x)}
932 This proof requires induction on~$k$. The occurrence of~0 in subgoal~1
933 indicates that induction has been applied to the term~$k+(m+n)$; this
934 application is sound but will not lead to a proof here. Fortunately,
935 Isabelle can (lazily!) generate all the valid applications of induction.
936 The \ttindex{back} command causes backtracking to an alternative outcome of
941 {\out k + m + n = k + (m + n)}
942 {\out 1. k + m + n = k + 0}
943 {\out 2. !!x. k + m + n = k + x ==> k + m + n = k + Suc(x)}
945 Now induction has been applied to~$m+n$. This is equally useless. Let us
946 call \ttindex{back} again.
950 {\out k + m + n = k + (m + n)}
951 {\out 1. k + m + 0 = k + (m + 0)}
952 {\out 2. !!x. k + m + x = k + (m + x) ==>}
953 {\out k + m + Suc(x) = k + (m + Suc(x))}
955 Now induction has been applied to~$n$. What is the next alternative?
959 {\out k + m + n = k + (m + n)}
960 {\out 1. k + m + n = k + (m + 0)}
961 {\out 2. !!x. k + m + n = k + (m + x) ==> k + m + n = k + (m + Suc(x))}
963 Inspecting subgoal~1 reveals that induction has been applied to just the
964 second occurrence of~$n$. This perfectly legitimate induction is useless
967 The main goal admits fourteen different applications of induction. The
968 number is exponential in the size of the formula.
970 \subsection{Proving that addition is associative}
971 Let us invoke the induction rule properly, using~{\tt
972 res_inst_tac}. At the same time, we shall have a glimpse at Isabelle's
973 simplification tactics, which are described in
974 \iflabelundefined{simp-chap}%
975 {the {\em Reference Manual}}{Chap.\ts\ref{simp-chap}}.
977 \index{simplification}\index{examples!of simplification}
979 Isabelle's simplification tactics repeatedly apply equations to a subgoal,
980 perhaps proving it. For efficiency, the rewrite rules must be
981 packaged into a {\bf simplification set},\index{simplification sets}
982 or {\bf simpset}. We take the standard simpset for first-order logic and
983 insert the equations proved in the previous section, namely
984 $0+n=n$ and ${\tt Suc}(m)+n={\tt Suc}(m+n)$:
986 val add_ss = FOL_ss addrews [add_0, add_Suc];
988 We state the goal for associativity of addition, and
989 use \ttindex{res_inst_tac} to invoke induction on~$k$:
991 goal Nat.thy "(k+m)+n = k+(m+n)";
993 {\out k + m + n = k + (m + n)}
994 {\out 1. k + m + n = k + (m + n)}
996 by (res_inst_tac [("n","k")] induct 1);
998 {\out k + m + n = k + (m + n)}
999 {\out 1. 0 + m + n = 0 + (m + n)}
1000 {\out 2. !!x. x + m + n = x + (m + n) ==>}
1001 {\out Suc(x) + m + n = Suc(x) + (m + n)}
1003 The base case holds easily; both sides reduce to $m+n$. The
1004 tactic~\ttindex{simp_tac} rewrites with respect to the given simplification
1005 set, applying the rewrite rules for addition:
1007 by (simp_tac add_ss 1);
1009 {\out k + m + n = k + (m + n)}
1010 {\out 1. !!x. x + m + n = x + (m + n) ==>}
1011 {\out Suc(x) + m + n = Suc(x) + (m + n)}
1013 The inductive step requires rewriting by the equations for addition
1014 together the induction hypothesis, which is also an equation. The
1015 tactic~\ttindex{asm_simp_tac} rewrites using a simplification set and any
1018 by (asm_simp_tac add_ss 1);
1020 {\out k + m + n = k + (m + n)}
1023 \index{instantiation|)}
1026 \section{A Prolog interpreter}
1027 \index{Prolog interpreter|bold}
1028 To demonstrate the power of tacticals, let us construct a Prolog
1029 interpreter and execute programs involving lists.\footnote{To run these
1030 examples, see the file {\tt FOL/ex/Prolog.ML}.} The Prolog program
1031 consists of a theory. We declare a type constructor for lists, with an
1032 arity declaration to say that $(\tau)list$ is of class~$term$
1035 list & :: & (term)term
1037 We declare four constants: the empty list~$Nil$; the infix list
1038 constructor~{:}; the list concatenation predicate~$app$; the list reverse
1039 predicate~$rev$. (In Prolog, functions on lists are expressed as
1042 Nil & :: & \alpha list \\
1043 {:} & :: & [\alpha,\alpha list] \To \alpha list \\
1044 app & :: & [\alpha list,\alpha list,\alpha list] \To o \\
1045 rev & :: & [\alpha list,\alpha list] \To o
1047 The predicate $app$ should satisfy the Prolog-style rules
1048 \[ {app(Nil,ys,ys)} \qquad
1049 {app(xs,ys,zs) \over app(x:xs, ys, x:zs)} \]
1050 We define the naive version of $rev$, which calls~$app$:
1051 \[ {rev(Nil,Nil)} \qquad
1052 {rev(xs,ys)\quad app(ys, x:Nil, zs) \over
1056 \index{examples!of theories}
1057 Theory \thydx{Prolog} extends first-order logic in order to make use
1058 of the class~$term$ and the type~$o$. The interpreter does not use the
1063 arities list :: (term)term
1064 consts Nil :: "'a list"
1065 ":" :: "['a, 'a list]=> 'a list" (infixr 60)
1066 app :: "['a list, 'a list, 'a list] => o"
1067 rev :: "['a list, 'a list] => o"
1068 rules appNil "app(Nil,ys,ys)"
1069 appCons "app(xs,ys,zs) ==> app(x:xs, ys, x:zs)"
1070 revNil "rev(Nil,Nil)"
1071 revCons "[| rev(xs,ys); app(ys,x:Nil,zs) |] ==> rev(x:xs,zs)"
1074 \subsection{Simple executions}
1075 Repeated application of the rules solves Prolog goals. Let us
1076 append the lists $[a,b,c]$ and~$[d,e]$. As the rules are applied, the
1077 answer builds up in~{\tt ?x}.
1079 goal Prolog.thy "app(a:b:c:Nil, d:e:Nil, ?x)";
1081 {\out app(a : b : c : Nil, d : e : Nil, ?x)}
1082 {\out 1. app(a : b : c : Nil, d : e : Nil, ?x)}
1084 by (resolve_tac [appNil,appCons] 1);
1086 {\out app(a : b : c : Nil, d : e : Nil, a : ?zs1)}
1087 {\out 1. app(b : c : Nil, d : e : Nil, ?zs1)}
1089 by (resolve_tac [appNil,appCons] 1);
1091 {\out app(a : b : c : Nil, d : e : Nil, a : b : ?zs2)}
1092 {\out 1. app(c : Nil, d : e : Nil, ?zs2)}
1094 At this point, the first two elements of the result are~$a$ and~$b$.
1096 by (resolve_tac [appNil,appCons] 1);
1098 {\out app(a : b : c : Nil, d : e : Nil, a : b : c : ?zs3)}
1099 {\out 1. app(Nil, d : e : Nil, ?zs3)}
1101 by (resolve_tac [appNil,appCons] 1);
1103 {\out app(a : b : c : Nil, d : e : Nil, a : b : c : d : e : Nil)}
1107 Prolog can run functions backwards. Which list can be appended
1108 with $[c,d]$ to produce $[a,b,c,d]$?
1109 Using \ttindex{REPEAT}, we find the answer at once, $[a,b]$:
1111 goal Prolog.thy "app(?x, c:d:Nil, a:b:c:d:Nil)";
1113 {\out app(?x, c : d : Nil, a : b : c : d : Nil)}
1114 {\out 1. app(?x, c : d : Nil, a : b : c : d : Nil)}
1116 by (REPEAT (resolve_tac [appNil,appCons] 1));
1118 {\out app(a : b : Nil, c : d : Nil, a : b : c : d : Nil)}
1123 \subsection{Backtracking}\index{backtracking!Prolog style}
1124 Prolog backtracking can answer questions that have multiple solutions.
1125 Which lists $x$ and $y$ can be appended to form the list $[a,b,c,d]$? This
1126 question has five solutions. Using \ttindex{REPEAT} to apply the rules, we
1127 quickly find the first solution, namely $x=[]$ and $y=[a,b,c,d]$:
1129 goal Prolog.thy "app(?x, ?y, a:b:c:d:Nil)";
1131 {\out app(?x, ?y, a : b : c : d : Nil)}
1132 {\out 1. app(?x, ?y, a : b : c : d : Nil)}
1134 by (REPEAT (resolve_tac [appNil,appCons] 1));
1136 {\out app(Nil, a : b : c : d : Nil, a : b : c : d : Nil)}
1139 Isabelle can lazily generate all the possibilities. The \ttindex{back}
1140 command returns the tactic's next outcome, namely $x=[a]$ and $y=[b,c,d]$:
1144 {\out app(a : Nil, b : c : d : Nil, a : b : c : d : Nil)}
1147 The other solutions are generated similarly.
1151 {\out app(a : b : Nil, c : d : Nil, a : b : c : d : Nil)}
1156 {\out app(a : b : c : Nil, d : Nil, a : b : c : d : Nil)}
1161 {\out app(a : b : c : d : Nil, Nil, a : b : c : d : Nil)}
1166 \subsection{Depth-first search}
1167 \index{search!depth-first}
1168 Now let us try $rev$, reversing a list.
1169 Bundle the rules together as the \ML{} identifier {\tt rules}. Naive
1170 reverse requires 120 inferences for this 14-element list, but the tactic
1171 terminates in a few seconds.
1173 goal Prolog.thy "rev(a:b:c:d:e:f:g:h:i:j:k:l:m:n:Nil, ?w)";
1175 {\out rev(a : b : c : d : e : f : g : h : i : j : k : l : m : n : Nil, ?w)}
1176 {\out 1. rev(a : b : c : d : e : f : g : h : i : j : k : l : m : n : Nil,}
1179 val rules = [appNil,appCons,revNil,revCons];
1181 by (REPEAT (resolve_tac rules 1));
1183 {\out rev(a : b : c : d : e : f : g : h : i : j : k : l : m : n : Nil,}
1184 {\out n : m : l : k : j : i : h : g : f : e : d : c : b : a : Nil)}
1187 We may execute $rev$ backwards. This, too, should reverse a list. What
1188 is the reverse of $[a,b,c]$?
1190 goal Prolog.thy "rev(?x, a:b:c:Nil)";
1192 {\out rev(?x, a : b : c : Nil)}
1193 {\out 1. rev(?x, a : b : c : Nil)}
1195 by (REPEAT (resolve_tac rules 1));
1197 {\out rev(?x1 : Nil, a : b : c : Nil)}
1198 {\out 1. app(Nil, ?x1 : Nil, a : b : c : Nil)}
1200 The tactic has failed to find a solution! It reached a dead end at
1201 subgoal~1: there is no~$\Var{x@1}$ such that [] appended with~$[\Var{x@1}]$
1202 equals~$[a,b,c]$. Backtracking explores other outcomes.
1206 {\out rev(?x1 : a : Nil, a : b : c : Nil)}
1207 {\out 1. app(Nil, ?x1 : Nil, b : c : Nil)}
1209 This too is a dead end, but the next outcome is successful.
1213 {\out rev(c : b : a : Nil, a : b : c : Nil)}
1216 \ttindex{REPEAT} goes wrong because it is only a repetition tactical, not a
1217 search tactical. {\tt REPEAT} stops when it cannot continue, regardless of
1218 which state is reached. The tactical \ttindex{DEPTH_FIRST} searches for a
1219 satisfactory state, as specified by an \ML{} predicate. Below,
1220 \ttindex{has_fewer_prems} specifies that the proof state should have no
1223 val prolog_tac = DEPTH_FIRST (has_fewer_prems 1)
1224 (resolve_tac rules 1);
1226 Since Prolog uses depth-first search, this tactic is a (slow!)
1227 Prolog interpreter. We return to the start of the proof using
1228 \ttindex{choplev}, and apply {\tt prolog_tac}:
1232 {\out rev(?x, a : b : c : Nil)}
1233 {\out 1. rev(?x, a : b : c : Nil)}
1235 by (DEPTH_FIRST (has_fewer_prems 1) (resolve_tac rules 1));
1237 {\out rev(c : b : a : Nil, a : b : c : Nil)}
1240 Let us try {\tt prolog_tac} on one more example, containing four unknowns:
1242 goal Prolog.thy "rev(a:?x:c:?y:Nil, d:?z:b:?u)";
1244 {\out rev(a : ?x : c : ?y : Nil, d : ?z : b : ?u)}
1245 {\out 1. rev(a : ?x : c : ?y : Nil, d : ?z : b : ?u)}
1249 {\out rev(a : b : c : d : Nil, d : c : b : a : Nil)}
1252 Although Isabelle is much slower than a Prolog system, Isabelle
1253 tactics can exploit logic programming techniques.