Skip to content

Instantly share code, notes, and snippets.

Created July 18, 2022 15:41
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
\chapter{The {\sf Gallina} specification language}\label{Gallina}\index{Gallina}
\section{Lexical conventions}\label{lexical}\index{Lexical conventions}
Space, newline and horizontal tabulation are considered as blanks.
Blanks are ignored but they separate tokens.
Comments in {\Coq} are enclosed between {\tt (*} and {\tt
*)}\index{Comments}, and can be nested. Comments are treated as
Identifiers are sequences of letters, digits, \verb!_!, \verb!$! %$
and \verb!'!, that do not start with a digit or \verb!'!. That is,
they are recognized by the following regular expression
\begin{tabular}{r@{\ ::=\ }l}
{\sl ident} & $(\,\ml{a..z}\op\ml{A..Z}\op\ml{\_}\op\ml{\$}\,) %$
\op\ml{\$}\op\ml{'}\,\}^+$ %$
Identifiers can contain at most 80 characters, and all characters are
Integers are sequences of digits, optionally preceded by a minus sign,
that is
{\sl integer} & $[\ml{-}]\,\{\,\ml{0..9}\,\}^+$
Strings are delimited by \verb!"! (double quote), and enclose a
sequence of any characters different from \verb!"! and \verb!\!, or
one of the following sequences
Sequence & Character denoted \\
\verb"\\" & backslash (\verb"\") \\
\verb'\"' & double quote (\verb'"') \\
\verb"\n" & newline (LF) \\
\verb"\r" & return (CR) \\
\verb"\t" & horizontal tabulation (TAB) \\
\verb"\b" & backspace (BS) \\
\verb"\"$ddd$ & the character with ASCII code $ddd$ in decimal \\
Strings can be split on several lines using a backslash (\verb!\!) at
the end of each line, just before the newline. For instance,
AddPath "$COQTOP/\
is correctly parsed, and equivalent to
AddPath "$COQTOP/contrib/Rocq/LAMBDA".
The following identifiers are reserved keywords, and cannot be
employed otherwise:
\verb!AddPath! &
\verb!Definition! &
\verb!DelPath! &
\verb!Dependent! &
\verb!end! \\
\verb!Grammar! &
\verb!Inductive! &
\verb!CoInductive! &
\verb!in! &
\verb!Load! \\
\verb!LoadPath! &
\verb!NewSyntax! &
\verb!Non! &
\verb!Orelse! &
\verb!Proof! \\
\verb!Qed! &
\verb!Quit! &
\verb!Remove! &
\verb!Reset! &
\verb!Restore! \\
\verb!State! &
\verb!Syntax! &
\verb!with! &
Although they are not considered as keywords, it is inadvisable to use
words of the following list as identifiers:
\verb!Abort! &
\verb!Abstraction! &
\verb!All! &
\verb!Axiom! &
\verb!Begin! \\
\verb!Cd! &
\verb!Chapter! &
\verb!Check! &
\verb!CheckGuard! &
\verb!CoFixpoint! \\
\verb!Compute! &
\verb!Defined! &
\verb!Definition! &
\verb!Drop! &
\verb!Elimination! \\
\verb!End! &
\verb!Eval! &
\verb!Explain! &
\verb!Extraction! &
\verb!Fact! \\
\verb!Fixpoint! &
\verb!Focus! &
\verb!for! &
\verb!Go! &
\verb!Goal! \\
\verb!Hint! &
\verb!Hypothesis! &
\verb!Immediate! &
\verb!Induction! &
\verb!Infix! \\
\verb!Inspect! &
\verb!Lemma! &
\verb!Let! &
\verb!Local! &
\verb!Minimality! \\
\verb!ML! &
\verb!Module! &
\verb!Modules! &
\verb!Mutual! &
\verb!Node! \\
\verb!Opaque! &
\verb!Parameter! &
\verb!Parameters! &
\verb!Print! &
\verb!Proofs! \\
\verb!Prop! &
\verb!Pwd! &
\verb!Qed! &
\verb!Remark! &
\verb!Require! \\
\verb!Restart! &
\verb!Resume! &
\verb!Save! &
\verb!Scheme! &
\verb!Script! \\
\verb!Search! &
\verb!Section! &
\verb!Set! &
\verb!Show! &
\verb!Silent! \\
\verb!States! &
\verb!Suspend! &
\verb!Syntactic! &
\verb!Theorem! &
\verb!Token! \\
\verb!Transparent! &
\verb!Tree! &
\verb!Type! &
\verb!Typeset! &
\verb!Undo! \\
\verb!Unfocus! &
\verb!Variable! &
\verb!Variables! &
\paragraph{Other keywords and user's tokens}
The following sequences of characters are also keywords:
\verb!|! &
\verb!:! &
\verb!:=! &
\verb!=! &
\verb!>! &
\verb!>>! &
\verb!<>! \\
\verb!<<! &
\verb!<! &
\verb!->! &
\verb!;! &
\verb!#! &
\verb!*! &
\verb!,! \\
\verb!?! &
\verb!@! &
\verb!::! &
\verb!/! &
\verb!<-! & &
You can add new tokens with the command {\tt Token} (see
section~\ref{Token}). New tokens must be sequences, without blanks,
of characters taken from the following list:
\verb"< > / \ - + = ; , | ! @ # % ^ & ? * : ~ $ _ a..z A..Z ' 0..9" %$
that do not start with a character from
\verb!$ _ a..z A..Z ' 0..9! %$
Lexical ambiguities are resolved according to the ``longest match''
rule: when a sequence of the previous characters can be decomposed
into several different ways, then the first token is the longest
possible one (among all tokens defined at this moment), and so on.
\section{Basic syntax of terms}\label{term}\index{Terms}
The basic set of terms form the {\em Calculus of Inductive
Constructions} also called {\sc Cic}. The formal presentation of
{\sc Cic} is given in chapter \ref{Cic}. We give here (an
approximation of) the syntax available in \Coq.
{\term} & ::= & \ident\\
& $|$ & \sort \\
& $|$ & {\tt (} {\binder} {\tt )} {\term}\\
& $|$ & {\tt [} {\binder} {\tt ]} {\term}\\
& $|$ & {\tt [} {\lident} {\tt ]} {\term}\\
& $|$ & {\tt [} {\ident} {\tt =} {\term} {\tt ]} {\term}\\
& $|$ & {\tt (} {\terms} {\tt )}\\
& $|$ & {\tt <} {\term} {\tt >Case} {\term} {\tt of}
{\terms} {\tt end}\\
& $|$ & {\tt Fix} {\ident} \verb.{. {\rm\sl fixdecls} \verb.}.\\
& $|$ & {\tt <} {\term} {\tt >Match} {\term} {\tt with}
{\terms} {\tt end}\\
& $|$ & {\tt <} {\term} {\tt >let (} {\params} {\tt ) =}
{\term} {\tt in} {\term} \\
& $|$ & {\tt <} {\term} {\tt >let (} {\lident} {\tt ) =}
{\term} {\tt in} {\term} \\
& $|$ & {\tt <} {\term} {\tt >if} {\term} {\tt then}
{\term} {\tt else} {\term}\\
{\terms} & ::= & \term \\
& $|$ & {\term} {\terms}\\
{\lident} & ::= & \ident \\
& $|$ & {\ident} {\tt ,} {\lident}\\
{\binder} & ::= & {\lident} {\tt :} {\term}\\
{\params} & ::= & {\binder} \\
& $|$ & {\binder} {\tt ;} {\params}\\
{\sort} & ::= & {\tt Prop} \\
& $|$ & {\tt Set} \\
& $|$ & {\tt Type} \\
& $|$ & {\tt Typeset} \\
{\rm\sl fixdecls} & ::= & {\rm\sl fixdecl} \\
& $|$ & {\rm\sl fixdecl} \verb.with. {\rm\sl fixdecls} \\
{\rm\sl fixdecl} & ::= & {\ident} \verb./. {\num} \verb.:. {\term}
\verb.:=. {\term}
\noindent {\bf Remarks : }
\item {\tt (} {\terms} {\tt )} associates to the left.
\item The syntax {\tt [} {\lident} {\tt ]} {\term} allows not to
give types in abstractions.
\item The syntax {\tt [} {\ident} {\tt =} {\term} {\tt ]}
{\term} allows to define a $\beta$-redex.
[x=T$_1$]T$_2$ is equivalent to ([x]T$_2$~T$_1$).
\item The syntax {\tt <} {\term} {\tt >Case} {\term} {\tt of}
{\terms} {\tt end} does case analysis over a term in an
inductive definition. The rules are explained in
\item The syntax {\tt Fix} is used for the internal representation of
fixpoints. It is intended to be used by the commands {\tt Fixpoint}
(see section~\ref{Fixpoint}), {\tt Recursive Definition}
(see section \ref{Recursive-Definition}) and {\tt Scheme} (see
section~\ref{Scheme}). A more precise description of terms built
with {\tt Fix} can be found in section~\ref{Fix-term}.
\item The syntax {\tt <} {\term} {\tt >Match} {\term} {\tt with}
{\terms} {\tt end} is a macro generating a combination of
{\tt Case} with {\tt Fix} implementing a combinator for
primitive recursion equivalent to the {\tt Match}
construction of \Coq\ V5.8. It is explained in
\item The syntax {\tt <} {\term} {\tt >let (} {\params}
{\tt ) =} {\term} {\tt in} {\term} is a macro for
a {\tt Case} with one only case.
The syntax {\tt <} {\term} {\tt >let (} {\lident} {\tt ) =}
{\term} {\tt in} {\term} is a variant of the precedent but
types are not needed in {\lident}.
\item The syntax {\tt <} \term {\tt >if} \term {\tt then}
\term {\tt else} \term is a macro for
a {\tt Case} with two only cases.
The declaration mechanism allows the user to specify his own basic
objects. Declared objects play the role of axioms or parameters in
mathematics. A declared object is an {\ident} associated to a \term. A
declaration is accepted by {\Coq} iff this {\term} is a well-typed
specification in the current context of the declaration and \ident\ was
not previously defined in the same module. This {\term}
is considered to be the type, or specification, of the \ident.
\subsection{{\tt Axiom {\ident} : {\term}}.}
\index{Axiom@{\tt Axiom}}
\index{Parameter@{\tt Parameter}}
This command links {\term} to the name {\ident} as its specification in the
global context. The fact asserted by {\term} is thus assumed
%without any proof of it.\\
as a postulate.
\item {\tt Clash with previous constant {\ident}}
%\item {\tt Axiom {\lident} : {\term}.}\\
% links {\term} to the names comprising the list {\lident}
% Non documented - useless
\item {\tt Parameter {\ident} : {\term}.}\\ Is equivalent to {\tt
Axiom {\ident} : {\term}}
\item {\tt Parameters {\lident} : {\term}.} \\
% Is equivalent to {\tt Axiom {\lident} : {\term}}
Links {\term} to the names comprising the list {\lident}
\subsection{{\tt Variable {\ident} : {\term}}.}
\index{Variable@{\tt Variable}}
\index{Variables@{\tt Variables}}
This command links {\term} to the name {\ident} in the context of the
current section. The name {\ident} will be unknown when the current
section will be closed. One says that the variable is {\em
discharged}. Using the {\tt Variable} command out of any section is
equivalent to {\tt Axiom}.
\item {\tt Clash with previous constant {\ident}}
\item {\tt Variables {\lident} : {\term}.}\\ Links {\term} to the
names comprising the list {\lident}
\item {\tt Hypothesis {\lident} : {\term}.} \\ Is equivalent to {\tt
Variables {\lident} : {\term}}
\SeeAlso section \ref{Section}
It is advised to use the keywords \verb:Axiom: and \verb:Hypothesis:
for logical postulates (i.e. when the assertion {\term} is of sort
\verb:Prop:), and to use the keywords \verb:Parameter: and
\verb:Variable: in other cases (corresponding to the declaration of an
abstract mathematical entity).
Definitions differ from declarations since they allow to give a name
to a term whereas declarations were just giving a type to a name. That
is to say that the name of a defined object can be replaced at any
time by its definition. This replacement is called
$\delta$-conversion\index{delta-reduction@$\delta$-reduction} (see section
\ref{delta}). A defined object is accepted by the system iff the
defining term is well-typed in the current context of the definition.
Then the type of the name is the type of term. The defined name is
called a {\em constant}\index{Constant} and one says that {\it the
constant is added to the environment}\index{Environment}.
A formal presentation of constants and environment is given in
section \ref{Cic-definitions}.
\subsection{\tt Definition {\ident} := {\term}.}
\index{Definition@{\tt Definition}}
This command binds the value {\term} to the name {\ident} in the
environment, providing that {\term} is well-typed.
\item {\tt Clash with previous constant {\ident}}
\item {\tt Definition {\ident} : {\term$_1$} := {\term$_2$}.} It
checks that the type of {\term$_2$} is definitionally equal to
{\term$_1$}, and registers {\ident} as being of type {\term$_1$},
and bound to value {\term$_2$}.
\item {\tt In environment the term: {\term$_2$} does not have type
{\term$_1$}. Ac\-tu\-al\-ly, it has \\ ty\-pe {\term$_3$}}.
\SeeAlso sections \ref{Transparent}, \ref{Unfold}
\subsection{\tt Local {\ident} := {\term}.}\index{Local@{\tt Local}}
This command binds the value {\term} to the name {\ident} in the
environment of the current section. The name {\ident} will be unknown
when the current section will be closed and all occurrences of
{\ident} in persistent objects (such as theorems) defined within the
section will be replaced by \term. One can say that the {\tt Local}
definition is a kind of {\em macro}.
\item {\tt Clash with previous constant {\ident}}
\item {\tt Local {\ident} : {\term$_1$} := {\term$_2$}.}\\ Checks that
the type of {\term$_2$} is definitionally equal to {\term$_1$}, and
registers {\ident} as being of type {\term$_1$}.
\SeeAlso sections \ref{Section}, \ref{Transparent}, \ref{Unfold}
%\subsection{\tt Let {\ident} := {\term}.}
%Not yet documented.
\section{Inductive definitions}\index{Inductive definitions} \label{gal_Inductive_Definitions}
This version of {\Coq} contains a new implementation of inductive
definitions. It is formally presented in section
%We also refer the reader
%to \ref{Addoc-mutual} which contains commented examples
%and some useful comments about the difference between the
%previous version {\Coq} V5.8 and the present one.
\subsection{\tt Inductive {\ident} : {\term} := {\ident$_1$} : {\term$_1$} | .. | {\ident$_n$} : {\term$_n$}.}\index{Inductive@{\tt Inductive}}\label{Inductive}
This command is used to define inductive types and inductive families
such as inductively defined relations. The name {\ident} is the name
of the inductively defined object and {\term} is its type. The names
{\ident$_1$}, .., {\ident$_n$} are the names of its constructors and
{\term$_1$}, .., {\term$_n$} their respective types. The types of the
constructors have to satisfy a {\em positivity condition} (see section
\ref{Positivity}) for {\ident}. This condition ensures the
well-foundedness of the inductive definition. If this is the case,
the constants {\ident}, {\ident$_1$}, .., {\ident$_n$} are added to
the environment with their respective types. According to the arity
of the aimed inductive type ({\it e.g.} the type of {\term}), {\Coq}
provides a number of destructors for {\ident}. Destructors are named
{\ident}{\tt\_ind}, {\ident}{\tt \_rec} or {\ident}{\tt \_rect} which
respectively correspond to elimination principles on {\tt Prop}, {\tt
Set} and {\tt Type}. Note that {\ident}{\tt \_ind} is always
provided whereas {\ident}{\tt \_rec} and {\ident}{\tt \_rect} are not.
The type of the destructors expresses structural induction/recursion
principles over objects of {\ident}. The inductive definitions are
formally detailed in section \ref{Cic-inductive-definitions}. We give
below two examples of the use of the {\tt Inductive} definitions.
The set of natural numbers is defined as :
Inductive nat : Set := O : nat | S : nat -> nat.
The type {\tt nat} is defined as the least \verb:Set: containing {\tt
O} and closed by the {\tt S} constructor. The constants {\tt nat},
{\tt O} and {\tt S} are added to the environment.
Now let us have a look at the elimination principles. They are three :
{\tt nat\_ind}, {\tt nat\_rec} and {\tt nat\_rect}. The type of {\tt
nat\_ind} is~:
Check nat_ind.
This is the well known structural induction principle over natural
numbers, i.e. the second-order form of Peano's induction principle.
It allows to prove some universal property of natural numbers ({\tt
(n:nat)(P n)}) by induction on {\tt n}. Recall that {\tt (n:nat)(P
n)} is {\sf Gallina}'s syntax for the universal quantification
$\forall n:nat\cdot P(n).$\\
The types of {\tt nat\_rec} and {\tt nat\_rect} are similar, except
that they pertain to {\tt (P:nat->Set)} and {\tt (P:nat->Type)}
respectively . They correspond to primitive induction principles
(allowing dependent types) respectively over sorts \verb:Set: and
As a second example, let us define the $even$ predicate :
Inductive even : nat->Prop :=
even_0 : (even O)
| even_SS : (n:nat)(even n)->(even (S (S n))).
The type {\tt nat->Prop} means that {\tt even} is a unary predicate
(inductively defined) over natural numbers. The type of its two
constructors are the defining clauses of the predicate {\tt even}. The
type of {\tt even\_ind} is~:
Check even_ind.
From a mathematical point of vue it asserts that the natural numbers
satisfying the predicate {\tt even} are just the naturals satisfying
the clauses {\tt even\_0} or {\tt even\_SS}. This is why, when we want
to prove any predicate {\tt P} over elements of {\tt even}, it is
enough to prove it for {\tt O} and to prove that if any natural number
{\tt n} satisfies {\tt P} its double successor {\tt (S (S n))}
satisfies also {\tt P}. This is indeed analogous to the structural
induction principle we got for {\tt nat}.
\item {\tt Non positive Occurrence in {\term$_i$}}
\item {\tt Type of Constructor not well-formed}
\item {\tt Inductive {\ident} [ {\params} ] : {\term} :=
{\ident$_1$}:{\term$_1$} | .. | {\ident$_n$}:\term$_n$.}\\ Allows
to define parameterized inductive types (see section~\ref{term} for
the syntax of \params).\\
For instance, one can define
parameterized lists as~:
Inductive list [X:Set] : Set :=
Nil : (list X) | Cons : X->(list X)->(list X).
Note that, in the type of {\tt Nil} and {\tt Cons}, we write {\tt
(list X)} and not just {\tt list}.\\ The constants {\tt Nil} and
{\tt Cons} will have respectively types
Check Nil.
Check Cons.
Types of destructors will be also quantified with {\tt (X:Set)}.
\item {\tt Inductive {\sort} {\ident} :=
{\ident$_1$}:{\term$_1$} | .. | {\ident$_n$}:\term$_n$.}\\
with {\sort} being one of {\tt Prop, Type, Set, Typeset} is
equivalent to \\ {\tt Inductive {\ident} : {\sort} :=
{\ident$_1$}:{\term$_1$} | .. | {\ident$_n$}:\term$_n$.}
\item {\tt Inductive {\sort} {\ident} [ {\params} ]:=
{\ident$_1$}:{\term$_1$} | .. | {\ident$_n$}:\term$_n$.}\\
Same as before but with parameters.
\SeeAlso sections \ref{Cic-inductive-definitions}, \ref{Elim}
\subsection{\tt Mutual Inductive}\index{Mutual Inductive@{\tt Mutual Inductive}}\label{Mutual-Inductive}
This command is a new feature of {\Coq} V5.10. It allows to define
mutually recursive inductive types. Its syntax is :\\[0.3cm]
Mutual Inductive {\ident$_1$} : {\term$_1$} := \\
\mbox{}\hspace{0.4cm} {\ident$_1^1$} : {\term$_1^1$} \\
\mbox{}\hspace{0.1cm}| .. \\
\mbox{}\hspace{0.1cm}| {\ident$_{n_1}^1$} : {\term$_{n_1}^1$} \\
\mbox{}\hspace{0.1cm} .. \\
with {\ident$_m$} : {\term$_m$} := \\
\mbox{}\hspace{0.4cm}{\ident$_1^m$} : {\term$_1^m$} \\
\mbox{}\hspace{0.1cm}| .. \\
\mbox{}\hspace{0.1cm}| {\ident$_{n_m}^m$} : {\term$_{n_m}^m$}.
It has the same semantics as the above {\tt Inductive} definition for
each \ident$_1$, .., \ident$_m$. All names \ident$_1$, .., \ident$_m$
are simultaneously added to the environment. Then well-typing of
constructors can be checked. Each one of the \ident$_1$, ..,
\ident$_m$ can be used on its own.
It is also possible to parameterize these inductive definitions.
However, one should remark that parameters correspond to a local
context in which the whole set of inductive declarations is done. For
this reason, the parameters are shared between all inductive types and
this context syntactically appears between the {\tt Mutual} and the
{\tt Inductive} keywords and not after the identifier as it is the
case for a single inductive declaration. The syntax is thus:\\[0.3cm]
Mutual [{\rm\sl params} ] Inductive {{\ident$_1$} : {\term$_1$} := \\
\mbox{}\hspace{0.4cm} {\ident$_1^1$} : {\term$_1^1$} \\
\mbox{}\hspace{0.1cm}| .. \\
\mbox{}\hspace{0.1cm}| {\ident$_{n_1}^1$} : {\term$_{n_1}^1$} \\
\mbox{}\hspace{0.1cm} .. \\
with {\ident$_m$} : {\term$_m$} := \\
\mbox{}\hspace{0.4cm}{\ident$_1^m$} : {\term$_1^m$} \\
\mbox{}\hspace{0.1cm}| .. \\
\mbox{}\hspace{0.1cm}| {\ident$_{n_m}^m$} : {\term$_{n_m}^m$}.
The typical example of a mutual inductive data type is the one for
trees and forests. We assume given two types $A$ and $B$ as variables.
It can be declared the following way.
Variables A,B:Set.
Mutual Inductive tree : Set := node : A -> forest -> tree
with forest : Set := leaf : B -> forest
| cons : tree -> forest -> forest.
This declaration generates automatically six induction principles
called respectively {\tt tree\_rec}, {\tt tree\_ind}, {\tt
tree\_rect}, {\tt forest\_rec}, {\tt forest\_ind}, {\tt
forest\_rect}. These ones are not the most general ones but are
just the induction principles corresponding to each inductive part
seen as a single inductive definition.
To illustrate this point on our example, we give the types of {\tt
tree\_rec} and {\tt forest\_rec}.
Check tree_rec.
Check forest_rec.
Assume we want to parameterized our mutual inductive definitions with
the two type variables $A$ and $B$, the declaration should be done the
following way:
Reset tree.
Mutual [A,B:Set] Inductive
tree : Set := node : A -> (forest A B) -> (tree A B)
with forest : Set := leaf : B -> (forest A B)
| cons : (tree A B) -> (forest A B) -> (forest A B).
Save State toto.
Assume we define an inductive definition inside a section. When the
section is closed, the variables declared in the section and occuring
free in the declaration are added as parameters to the inductive
\subsection{The Record Macro}\index{Record@{\tt Record}}
This version of {\Coq} contains a macro called \verb+Record+ allowing
the definition of records as is done in many programming languages.
Its syntax is~: \\[0.3cm]
{\tt Record {\ident} [ {\params} ] : {\sort} := {\ident$_0$} \verb+{+ \\
\mbox{}\hspace{0.4cm} {\ident$_1$} : {\term$_1$}; \\
\mbox{}\hspace{0.4cm} ... \\
\mbox{}\hspace{0.4cm} {\ident$_n$} : {\term$_n$} \verb+}+.}\\[0.3cm]
The identifier {\ident} is the name of the defined record and {\sort}
is its type. The identifier {\ident$_0$} is the name of its
constructor. The identifiers {\ident$_1$}, .., {\ident$_n$} are the
names of its fields and {\term$_1$}, .., {\term$_n$} their respective
types. Note that the records may have parameters.
The set of rational numbers is defined by~:
Restore State Initial.
Record Rat : Set := mkRat {
top : nat;
bottom : nat;
Rat_cond : (gt bottom O) }.
An important difference between our records and those of most
programming languages is that a field may depend on other fields
appearing before it. For instance in the above example, the field
\verb+Rat_cond+ depends on the field \verb+bottom+. Thus the order of
the fields is important.
Let us now see the work done by the {\tt Record} macro.
First the macro generates a one-constructor inductive definition
of the following form~:\\[0.3cm]
{\tt Inductive {\ident} [ {\params} ] : {\sort} := \\
\mbox{}\hspace{0.4cm} {\ident$_0$} : ({\ident$_1$}:{\term$_1$}) ..
({\ident$_n$}:{\term$_n$})({\ident} {\rm\sl params}).}\\[0.3cm]
To build an object of type {\ident}, one should provide the
constructor {\ident$_0$} with $n$ terms filling the fields of
the record.
Let us define the rational $1/2$. Following our definition, a rational
number is defined by two natural numbers and a proof that the second
is strictly positive. Thus we must prove that $2$ is strictly
positive. Let us just assume it as axiom. Try to prove it using
tactics (see the chapter \ref{Proof-handling}).
Axiom two_is_positive : (gt (S (S O)) O).
We have now all the ingredients to define $1/2$ (we call it
Definition half := (mkRat (S O) (S (S O)) two_is_positive).
Check half.
The macro generates also, when it is possible, the projection
functions for destructuring an object of type {\ident} into its
constituent fields. We give the field names to these projection
For our example, these functions are \verb+top+, \verb+bottom+ and
\verb+Rat_cond+. Let us show their behavior on \verb+half+.
Compute (top half).
Compute (bottom half).
Compute (Rat_cond half).
Restore State toto.
In the case where the definition of a projection function {\ident$_i$}
is impossible, a warning is printed.
\noindent {\bf Warning :}
\item {\tt Warning: {\ident$_i$} cannot be defined.}\\
This message is followed by an explanation of this impossibility.\\
There may be three reasons~:
\item The name {\ident$_i$} already exists in environment (see
section \ref{Axiom}).
\item The body of {\ident$_i$} uses a incorrect elimination for
{\ident} (see sections \ref{Fixpoint} and \ref{Caseexpr}).
\item {\tt The projections [ {\rm\sl idents} ] were not defined.}\\
The body of {\term$_i$} uses the projections {\rm\sl idents}
which are not defined for one of these three reasons listed here.
\item {\tt A record cannot be recursive}\\
The record name {\ident} appears in the type of its fields.
During the definition of the one-constructor inductive definition,
all the errors of inductive definitions, as described in section
\ref{gal_Inductive_Definitions}, may occur.
{\tt Record {\ident} [ {\rm\sl params} ] : {\sort} := \verb+{+ \\
\mbox{}\hspace{0.4cm} {\ident$_1$} : {\term$_1$}; \\
\mbox{}\hspace{0.4cm} ... \\
\mbox{}\hspace{0.4cm} {\ident$_n$} : {\term$_n$} \verb+}+.}\\
One can omit the constructor name in which case the system will use
the name {\tt Build\_{\ident}}.
\subsection{\tt Fixpoint {\ident} [ \ident$_1$ : \term$_1$ ] : \term$_2$ := \term$_3$.}\index{Fixpoint@{\tt Fixpoint}}\label{Fixpoint}
This command is a new feature of {\Coq} V5.10. It may be used to
define inductive objects using a fixed point construction instead of
the {\tt Match} recursion operator. The meaning of this declaration is
to define {\it ident} a recursive function with one argument
\ident$_1$ of type \term$_1$ such that ({\it ident}~\ident$_1$) has
type \term$_2$ and is equivalent to the expression \term$_3$. The
type of the {\ident} is consequentely {(\ident$_1$ :
\term$_1$)\term$_2$} and the value is equivalent to [\ident$_1$ :
\term$_1$]\term$_3$. The argument {\ident$_1$} (of type {\term$_1$})
is called the {\em recursive variable} of {\ident}. Its type should
be an inductive definition.
To be accepted, a {\tt Fixpoint} definition has to satisfy some
syntactical constraints on this recursive variable. They are needed to
ensure that the {\tt Fixpoint} definition always terminates. For
instance, one can define the addition function as :
Fixpoint add [n:nat] : nat->nat
:= [m:nat]<nat>Case n of m [p:nat](S (add p m)) end.
The {\tt Case} operator matches a value (here \verb:n:) with the
various constructors of its (inductive) type. The remaining arguments
give the respective values to be returned, as functions of the
parameters of the corresponding constructor. Thus here when \verb:n:
equals \verb:O: we return \verb:m:, and when \verb:n: equals \verb:(S
p): we return \verb:(S (add p m)):. The {\tt Case} operator is described
in detail in section \ref{Caseexpr}. The system recognizes that in
the inductive call {\tt (add p m)} the first argument actually
decreases because it is a {\em pattern variable} coming from {\tt Case
n of}.
\item {\tt Fixpoint {\ident} [ {\params} ] : \term$_1$ :=
See section \ref{term} for a syntactic descrrption of
\params. It declares a list of identifiers with their type
usable in the type \term$_1$ and the definition body \term$_2$
and the last identifier in \ident$_0$ is the recursion variable.
\item {\tt Fixpoint {\ident$_1$} [ {\params$_1$} ] :
{\term$_1$} := {\term$_1'$}\\
\mbox{}\hspace{0.1cm} .. \\
with {\ident$_m$} [ {\params$_m$} ] : {\term$_m$} :=
Allows to define simultaneously {\ident$_1$}, ..,
\Example The following definition is not correct and generates an
error message:
Fixpoint wrongplus [n:nat] : nat->nat
:= [m:nat]<nat>Case m of n [p:nat](S (wrongplus n p)) end.
because the declared decreasing argument {\tt n} actually does not
decrease in the recursive call. The function computing the addition
over the second argument should rather be written:
Fixpoint plus [n,m:nat] : nat
:= <nat>Case m of n [p:nat](S (plus n p)) end.
The ordinary match operation on natural numbers can be mimicked the
following way.
Fixpoint nat_match [C:Set;f0:C;fS:nat->C->C;n:nat] : C
:= <C>Case n of f0 [p:nat](fS p (nat_match C f0 fS p)) end.
The recursive call may not only be on direct subterms of the recursive
variable {\tt n} but also on a deeper subterm and we can directly
write the function {\tt mod2} which gives the remainder modulo 2 of a
natural number.
Fixpoint mod2 [n:nat] : nat
:= <nat>Case n of O [p:nat]<nat>Case p of (S O) [q:nat](mod2 q) end end.
In order to keep the strong normalisation property, the fixed point
reduction will only be performed when the argument in position of the
recursive variable (whose type should be in an inductive definition)
starts with a constructor.
The {\tt Fixpoint} construction enjoys also the {\tt with} extension
to define functions over mutually defined inductive types or more
generally any mutually recursive definitions.
The size of trees and forests can be defined the following
Restore State Initial.
Variables A,B:Set.
Mutual Inductive tree : Set := node : A -> forest -> tree
with forest : Set := leaf : B -> forest
| cons : tree -> forest -> forest.
Fixpoint tree_size [t:tree] : nat :=
<nat>Case t of [a:A][f:forest](S (forest_size f)) end
with forest_size [f:forest] : nat :=
<nat>Case f of [b:B](S O)
[t:tree][f':forest](plus (tree_size t) (forest_size f'))
A generic command {\tt Scheme} is able to build automatically various
mutual induction principles. It is described in section \ref{Scheme}.
\subsection{\tt Recursive Definition ...}\index{Recursive Definition@{\tt Recursive Definition}}\label{Recursive-Definition}
This command is a new feature of {\Coq} V5.10. It is a high level tool
for defining recursive functions. Its syntax follows the schema :
{\tt Recursive Definition {\ident} : {\form} :=\\
{\pattern$_1^1$} .. {\pattern$_n^1$} \verb.=>. {\term$_1$}\\
\verb.|. .. \\
\verb.|. {\pattern$_1^m$} .. {\pattern$_n^m$} \verb.=>.
It can be compared to functions declarations in ML languages (see, for
instance \cite{Caml}).\\ The {\tt Recursive Definition} command uses a
heuristic which tries to derive a term satisfying the specification.
That is to say that {\Coq} tries to find a term {\tt T} such that for
each $i\in [1..m]$,\\
\centerline{{\tt (T {\pattern$_1^i$} \ldots
If such a term can be inferred then {\ident} is defined as being {\tt
T} and all corresponding equational theorems are provided. We refer
the reader to section \ref{Addoc-recdef} for more details.
% Useless it is loaded automatically.
%\Rem Since the {\tt Recursive Definition} command allows to define
%propositional functions, it requires the module
%{\tt Logic\_Type} to be loaded.
\section{Section mechanism}\index{Sections}\label{Section}
The sectioning mechanism allows to organize a proof in structured
sections. Then local declarations become available (see section
\subsection{\tt Section {\ident}}\index{Section@{\tt Section}}
This command is used to open a section named {\ident}.
\begin{enumerate}\index{Chapter@{\tt Chapter}}
\item{\tt Chapter {\ident}}\\
Same as {\tt Section {\ident}}
\subsection{\tt End {\ident}}
This command closes the section named {\ident}. When a section is
closed, all local declarations are discharged. This means that all
global objects defined in the section are {\it closed} (in the sense
of $\lambda$-calculus) with as many abstractions as there were local
declarations in the section explicitely occuring in the term. A local
object in the section is not exported and its value will be
substituted in the other definitions.
Here is an example :
Section s1.
Variables x,y : nat.
Local y' := y.
Definition x' := (S x).
Print x'.
End s1.
Print x'.
Note the difference between the value of {\tt x'} inside section {\tt
s1} and outside.
\item {\tt Section {\ident} does not exist (or is already closed)}
\item {\tt Section {\ident} is not the innermost section}
\Rem Some commands such as {\tt Hint \ident} or {\tt Syntactic
Definition} which appear inside a section are cancelled when the
section is closed.
% Local Variables:
% mode: LaTeX
% TeX-master: "Reference-Manual"
% End:
This document is the Reference Manual of version V5.10 of the \Coq\
proof assistant. A companion volume, the \Coq\ Tutorial, is provided
for the beginners. It is advised to read the Tutorial first.
Additional documentation is described in chapter \ref{Addoc}.
All services of the \Coq\ proof assistant are accessible by
interpretation of a command language. A command is a string ended
with a period.
\Coq\ has an interactive mode in which commands are interpreted as the
user types them in from the keyboard and a compiled mode where
commands are processed from a file. Other modes of interaction with
\Coq\ are possible, through an emacs shell window, or through a
customized interface with the Centaur environment (CTCoq). These
facilities are not documented here.
\item The interactive mode may be used as a debugging mode in which
the user can develop his theories and proofs step by step,
backtracking if needed and so on. The interactive mode is run with
the {\tt coqtop} command from the operating system (which we shall
assume to be some variety of UNIX in the rest of this document).
\item The compiled mode acts as a proof checker taking a file
containing a whole development in order to ensure its correctness.
Moreover, \Coq's compiler provides an output file containing a
compact representation of its input. The compiled mode is run with
the {\tt coqc} command from the operating system. Its use is
documented in chapter \ref{Addoc-coqc}.
\Coq\ offers two kinds of services : logical services and operating
We divide the logical services in two main parts :
\item a specification language in which the user axiomatizes his own
theories. This specification language is known as {\sf Gallina}
which mainly provides declaration and definition mechanisms. It is
documented in chapter \ref{Gallina}.
\item a proof editing mode providing tools for proof development.
Proofs services are again of two kinds :
\item proofs pragmas such as switching on and off the proof editor,
restarting a proof, etc ... They are documented in chapter
\item tactics which are the implementation of logical reasoning steps.
The whole chapter \ref{Tactics} is devoted to their documentation.
For a more fundamental understanding of the logical framework, we urge
the user of \Coq\ to read chapter \ref{Cic}.
The so-called operating services are :
\item a file system service including modules facilities
\item displaying features
\item user's syntax handling
\item miscellaneous pragmas
They are documented in chapter \ref{Other-commands}.
\paragraph{Notations} In the rest of this document, \Coq's grammar
terminals will be written in {\tt typewriter} font. Non-terminals are
\item {\Fwterm}\index{Fomega term@$F_\omega$ term} which denotes an
$F_\omega$ term (see section \ref{Extraction}).
\item {\ident} \index{ident@{\rm\sl ident}} which denotes an {\it
identifier} in the usual sense. Characters such as {\tt \_} and
{\tt '} are allowed to appear in identifiers, besides
alpha-numerical characters.
\item {\num}\index{num@{\rm\sl num}} which denotes a positive natural
number ({\it e.g.} a sequence of digits with no blanks).
\item {\pattern}\index{pattern@{\rm\sl pattern}} which denotes any {\sc
Cic}-term belonging to a restricted class (see section
\item {\vref}\index{ref@{\rm\sl ref}} which is either an {\ident} or a
\item {\str}\index{string@{\rm\sl string}} which denotes any sequence
of characters enclosed between two \verb!"!.
\item {\tac} which denotes any simple tactic's name or composed
tactical (see section \ref{Tacticals}).
\item {\term}\index{term@{\rm\sl term}} which denotes any {\sc
Cic}-term (see section \ref{term}).
\item {\sort}\index{sort@{\rm\sl sort}} which denotes one of the
special {\sc Cic}-constants called a sort (see section \ref{Sorts}).
\newcommand{\real}{{\sf Real}}
%\newcommand{\Prop}{{\it Prop}}
%\newcommand{\Type}{{\it Type}}
\newcommand{\Spec}{{\it Spec}}
\newcommand{\Data}{{\it Data}}
%\coverpage{The Program Tactic}{Catherine PARENT}
\chapter{The Program Tactic}\label{Addoc-program}
The facilities described in this chapter pertain to a special aspect of
the \Coq\ system: how to associate to a functional program, whose
specification is written in Gallina, a proof of its correctness.
This methodology is based on the Curry-Howard isomorphism between
functional programs and constructive proofs. This isomorphism allows
the synthesis of a functional program from the constructive part of its
proof of correctness. That is, it is possible to analyze a \Coq\ proof,
to erase all its non-informative parts (roughly speaking, removing the
parts pertaining to sort \Prop, considered as comments, to keep only the
parts pertaining to sort \Set).
This {\sl realizability interpretation}
was defined by Christine Paulin-Mohring in her PhD dissertation, and
implemented as a {\sl program extraction} facility in previous versions of
\Coq~ by Benjamin Werner. However, the corresponding certified program
development methodology was very awkward: the user had to understand very
precisely the extraction mechanism in order to guide the proof construction
towards the desired algorithm. The facilities described in this chapter
attempt to do the reverse: i.e. to try and generate the proof of correctness
from the program itself, given as argument to a specialized tactic.
This work is based on the PhD dissertation of
Catherine Parent \cite{CPar95}.
\section{Developing certified programs: Motivations}
We want to develop certified programs automatically proved by the
system. That is to say, instead of giving a specification, an
interactive proof and then extracting a program, the user gives the
program he wants to prove and the corresponding specification. Using
this information, an automatic proof is developed which solves the
``informative'' goals without the help of the user. When the proof is
finished, the extracted program is guaranteed to be correct and
corresponds to the one given by the user. The tactic uses the fact
that the extracted program is a skeleton of its corresponding proof.
\section{Syntax for tactics}
The user has to give two things~: the specification (given as usual by
a goal) and the program (see section \ref{syntax}). Then, this program
is associated to the current goal (to know which specification it
corresponds to) and the user can use different tactics to develop an
automatic proof.
First, the program is associated to the current goal by using the
\verb=Realizer= \index{Realizer@{\tt Realizer}} command. With this
command, the program has to be given with the syntax indicated in
section \ref{syntax} and it is associated to the current goal.
\subsection{Show Program}
The command \verb=Show Program= shows the program associated to the
current goal. \verb=Show Program n= shows the program associated to
the nth subgoal.
Then, an automatic process may be started. A program is associated to
a goal by the user (for the initial goal) and by the tactic
\verb!Program! itself (for the subgoals). If no program is associated
to the current goal, the \verb=Program= tactic fails. This tactic
generates a sequence of \verb=Intro=, \verb=Apply= or \verb=Elim=
tactics depending on the syntax of the program. For instance, if the
program starts with a $\lambda$-abstraction, the \verb=Intro= tactic
is generated several times depending on the goal.
The \verb=Program= tactic generates a list of subgoals which can be
either logical or informative. Subprograms are associated to the
informative subgoals.
The \verb=Program_all= tactic is equivalent to the following tactic~:
\verb=Repeat (Program OrElse Auto)=. It repeats the \verb=Program=
tactic on every informative subgoal and tries the \verb=Auto= tactic
on the logical subgoals. Note that the work of the \verb=Program=
tactic is considered to be finished when all the informative subgoals
have been solved. This implies that logical lemmas can stay at the end
of the automatic proof which have to be solved by the user.
The \verb=Program_Expand= tactic transforms the current program into
the same program with the head constant expanded. This tactic
particularly allows the user to force a program to be reduced before
each application of the \verb=Program= tactic.
\section{Syntax for programs}
\subsection{Pure programs}
The language to express programs is called \real\footnote{It
corresponds to \FW\ plus inductive definitions}. Programs are
explicitly typed\footnote{This information is not strictly needed but
was useful for type checking in a first experiment.} like terms
extracted from proofs. Some extra expressions have been added to have
a simpler syntax.
This is the raw form of what we call pure programs. But, in fact, it
appeared that this simple type of programs is not sufficient. Indeed,
all the logical part useful for the proof is not contained in these
programs. That is why annotated programs are introduced.
\subsection{Annotated programs}
The notion of annotation introduces in a program a logical assertion
that will be used for the proof. The aim of the \verb=Program= tactic
is to start from a specification and a program and to generate
subgoals either logical or associated with programs. However, to find
the good specification for subprograms is not at all trivial in
general. For instance, if we have to find an invariant for a loop, or
a well founded order in a recursive call.
So, annotations add in a program the logical part which is needed for
the proof and which cannot be automatically retrieved. This allows the
system to do proofs it could not do otherwise.
For this, a particular syntax is needed which is the following~: since
they are specifications, annotations follow the same internal syntax
as \Coq~terms. We indicate they are annotations by putting them
between \verb={= and \verb=}= and preceding them with \verb=:: ::=.
Since annotations are \Coq~terms, they can involve abstractions over
logical propositions that have to be declared. Annotated-$\lambda$
have to be written between \verb=[{= and \verb=}]=.
Annotated-$\lambda$ can be seen like usual $\lambda$-bindings but
concerning just annotations and not \Coq~programs.
\subsection{Recursive Programs}
Programs can be recursively defined using the syntax~: \verb=<={\it
type-of-the-result}\verb=> rec= \index{rec@{\tt rec}} {\it
name-of-the-induction-hypothesis} \verb=:: :: {= {\it
well-founded-order-of-the-recursion} \verb=}= and then the body of
the program (see section \ref{examples}) which must always begin with
an abstraction [x:A] where A is the type of the arguments of the
function (also on which the ordering relation acts).
Two abbreviations have been defined~:
\verb!<P>let (p:X;q:Y)=Q in S! is syntactic sugar for \verb=<P>Case Q of [p:X][q:Y]S=
\verb=<P>if B then Q else R= abbreviates matching on boolean
expressions, that is to say it abbreviates \verb=<P>Case B of Q R=.
Moreover, a synthesis of implicit arguments has been added in order to
allow the user to write a minimum of types in a program. Then, it is
possible not to write a type inside a program term. This type has then
to be automatically synthesized. For this, it is necessary to indicate
where the implicit type to be synthesized appears. The syntax is the
current one of implicit arguments in \Coq~: the question mark
This synthesis of implicit arguments is not possible everywhere in a
program. In fact, the synthesis is only available inside a
\verb+Match+, a \verb+Case+ or a \verb+Fix+ construction (where
\verb+Fix+ is a syntax for defining fixpoints).
Then, two macros have been introduced to suppress some question
\verb!<P>let (p,q:?)=Q in S! can be abbreviate into \verb!<P>let
(p,q)=Q in S! and \verb+[x,y:?]T+ can be abbreviate into
The grammar for programs is the following (see the section \ref{term}
for more explanation)~:
pg::= \= ~~ident $|$ ? \\
\> $|$ [x:pg]pg \\
\> $|$ [x]pg \\
\> $|$ (x:pg)pg \\
\> $|$ pg\verb=->=pg \\
\> $|$ (pg pg \ldots pg) \\
\> $|$ \verb=<=pg\verb=>=Match pg with pg-list end \\
\> $|$ \verb=<=pg\verb=>=Case pg of pg-list end \\
\> $|$ Fix ident \{ident/num : pg := pg with \ldots with
ident/num : pg := pg\} \\
\> $|$ pg :: :: \{ coqterm \} \\
\> $|$ [\{x:coqterm\}]pg \\
\> $|$ \verb=<=pg\verb=>=let (x$_1^1$,\ldots,x$_1^{k_1}$:A$_1$;\ldots ;x$_n^1$,\ldots,x$_n^{k_n}$:A$_n$) = pg in pg \\
\> $|$ \verb=<=pg\verb=>=let (x$_1^1$,\ldots,x$_1^{k_1}$,\ldots,x$_n^1$,\ldots,x$_n^{k_n}$) = pg in pg \\
\> $|$ \verb=<=pg\verb=>=if pg then pg else pg \\
\> $|$ \verb=<=pg\verb=>=rec ident :: :: \{ coqterm \} [x:pg]pg
The reference to an identifier of the \Coq\ context (in particular a
constant) inside a program of the
language \real\ is a reference to its extracted contents.
\subsection{Ackermann Function}
Let us give the specification of Ackermann's function. We want to
prove that for every $n$ and $m$, there exists a $p$ such that
$ack(n,m)=p$ with~:
ack(0,n) & = & n+1 \\
ack(n+1,0) & = & ack(n,1) \\
ack(n+1,m+1) & = & ack(n,ack(n+1,m))
An ML program following this specification can be~:
let rec ack = function
0 -> (function m -> Sm)
| Sn -> (function 0 -> ack n 1
| Sm -> ack n (ack Sn m))
Suppose we give the following definition in \Coq~of a ternary relation
\verb=(Ack n m p)= in a Prolog like form representing $p=ack(n,m)$~:
Inductive Ack : nat->nat->nat->Prop :=
AckO : (n:nat)(Ack O n (S n))
| AcknO : (n,p:nat)(Ack n (S O) p)->(Ack (S n) O p)
| AckSS : (n,m,p,q:nat)(Ack (S n) m q)->(Ack n q p)
->(Ack (S n) (S m) p).
Then the goal is to prove that $\forall n,m .\exists p.(Ack~n~m~p)$, so
the specification is~:
\verb!(n,m:nat){p:nat|(Ack n m p)}!.
The associated {\real} program corresponding to the above ML program can be defined as a fixpoint~:
Fixpoint ack_func [n:nat] : nat -> nat :=
<nat->nat>Case n of
(* 0 *) [m:nat](S m)
(* (S n) *) [n':nat]
Fix ack_func2 {ack_func2/1 : nat -> nat :=
[m:nat]<nat>Case m of
(* 0 *) (ack_func n' (S O))
(* S m *) [m':nat](ack_func n' (ack_func2 m'))
The program is associated by using \verb=Realizer ack_func=. The
program is automatically expanded. Each realizer which is a constant
is automatically expanded. Then, by repeating the \verb=Program=
tactic, three logical lemmas are generated and are easily solved by
using the property Ack0, Ackn0 and AckSS.
Goal (n,m:nat){p:nat|(Ack n m p)}.
Realizer ack_func.
Repeat Program.
\subsection{Euclidean Division}
This example shows the use of {\bf recursive programs}. Let us
give the specification of the euclidean division algorithm. We want to
prove that for $a$ and $b$ ($b>0$), there exist $q$ and $r$ such that
$a=b*q+r$ and $b>r$.
An ML program following this specification can be~:
let div b a = divrec a where rec divrec = function
if (b<=a) then let (q,r) = divrec (a-b) in (Sq,r)
else (0,a)
Suppose we give the following definition in \Coq~which describes what
has to be proved, ie, $\exists q \exists r.~(a=b*q+r \wedge ~b>r)$~:
Require Compare_dec.
Require Minus.
Require Wf_nat.
Require Plus.
Require Le.
Require Gt.
Inductive diveucl [a,b:nat] : Set
:= divex : (q,r:nat)(a=(plus (mult q b) r))->(gt b r)
->(diveucl a b).
The decidability of the ordering relation has to be proved first, by
giving the associated function of type \verb!nat->nat->bool!~:
Theorem le_gt_dec : (n,m:nat){(le n m)}+{(gt n m)}.
Realizer [n:nat]<nat->bool> Match n with
(* O *) [m]true
(* S *) [n',H,m]<bool> Case m of
(* O *) false
(* S *) [m'](H m')
Then the specification is \verb!(b:nat)(gt b O)->(a:nat)(diveucl a b)!.
The associated program corresponding to the ML program will be~:
Definition lt := [n,m:nat](gt m n).
Theorem eucl_dev : (b:nat)(gt b O)->(a:nat)(diveucl a b).
[b:nat](<nat*nat>rec div :: :: { lt }
[a:nat]<nat*nat>if (le_gt_dec b a)
then <nat*nat>let (q,r) = (div (minus a b))
in ((S q),r)
else (O,a)).
Where \verb=lt= is the well-founded ordering relation defined by~:
Coq < Definition lt := [n,m:nat](gt m n).
Note the syntax for recursive programs as explained before. The
\verb=rec= construction needs 4 arguments~: the type result of the
function (\verb=nat*nat= because it returns two natural numbers)
between \verb=<= and \verb=>=, the name of the induction hypothesis
(which can be used for recursive calls), the ordering relation
\verb=lt= (as an annotation because it is a specification), and the
program itself which must begin with a $\lambda$-abstraction. The
specification of \verb=le_gt_dec= is known because it is a previous
The term \verb!(le_gt_dec b a)! is seen by the \verb!Program! tactic
as a term of type \verb!bool! which satisfies the specification
\verb!{(le a b)}+{(gt a b)}!.
The tactics \verb=Program_all= or \verb=Program= can be used, and the
following logical lemmas are obtained~:
Repeat Program.
The subgoals 4, 5 and 6 are resolved by \verb=Auto= (if you use
\verb=Program_all= they don't appear, because \verb=Program_all= tries
to apply \verb=Auto=). The other ones have to be solved by the user.
\subsection{Insertion sort}
This example shows the use of {\bf annotations}. Let us give the
specification of a sorting algorithm. We want to prove that for a
sorted list of natural numbers $l$ and a natural number $a$, we can
build another sorted list $l'$, containing all the elements of $l$
plus $a$.
An ML program implementing the insertion sort and following this
specification can be~:
let sort a l = sortrec l where rec sortrec = function
[] -> [a]
| b::l' -> if a<b then a::b::l' else b::(sortrec l')
Suppose we give the following definitions in \Coq~:
First, the decidability of the ordering relation~:
Restore State Initial.
Require Le.
Require Gt.
Fixpoint inf_dec [n:nat] : nat -> bool :=
[m:nat]<bool>Case n of
[n':nat]<bool>Case m of
[m':nat](inf_dec n' m')
The definition of the type \verb=list=~:
Inductive list : Set := nil : list | cons : nat -> list -> list.
We define the property for an element \verb=x= to be {\bf in} a list
\verb=l= as the smallest relation such that~: $\forall a \forall
l~(In~x~l) \Ra (In~x~(a::l))$ and $\forall l~(In~x~(x::l))$.
Inductive In [x:nat] : list->Prop
:= Inl : (a:nat)(l:list)(In x l) -> (In x (cons a l))
| Ineq : (l:list)(In x (cons x l)).
A list \verb=t'= is equivalent to a list \verb=t= with one added
element \verb=y= iff~: $(\forall x~(In~x~t) \Ra (In~x~t'))$ and
$(In~y~t')$ and $\forall x~(In~x~t') \Ra ((In~x~t) \vee y=x)$. The
following definition implements this ternary conjunction.
Inductive equiv [y:nat;t,t':list]: Prop :=
equiv_cons :
((x:nat)(In x t)->(In x t'))
-> (In y t')
->((x:nat)(In x t')->((In x t)\/y=x))
-> (equiv y t t').
Definition of the property of list to be sorted, still defined
Inductive sorted : list->Prop
:= sorted_nil : (sorted nil)
| sorted_trans : (a:nat)(sorted (cons a nil))
| sorted_cons : (a,b:nat)(l:list)(sorted (cons b l)) -> (le a b)
-> (sorted (cons a (cons b l))).
Then the specification is:\\
\verb!(a:nat)(l:list)(sorted l)->{l':list|(equiv a l l')&(sorted l')}!.
The associated \real\ program corresponding to the ML program will be~:
Lemma toto : (a:nat)(l:list)(sorted l)->{l':list|(equiv a l l')&(sorted l')}.
<list>Match l with
(cons a nil)
[b,m,H]<list>if (inf_dec b a) :: :: { {(le b a)}+{(gt b a)} }
then (cons b H)
else (cons a (cons b m))
Note that we have defined \verb=inf_dec= as the program realizing the
decidability of the ordering relation on natural numbers. But, it has
no specification, so an annotation is needed to give this
specification. This specification is used and then the decidability of
the ordering relation on natural numbers has to be proved using the
index program.
Suppose \verb=Program_all= is used, a few logical
lemmas are obtained (which have to be solved by the user)~:
This example shows the use of {\bf programs using previous
programs}. Let us give the specification of Quicksort. We want to
prove that for a list of natural numbers $l$, we can build a sorted
list $l'$, which is a permutation of the previous one.
An ML program following this specification can be~:
let rec quicksort l = function
[] -> []
| a::m -> let (l1,l2) = splitting a m in
let m1 = quicksort l1 and
let m2 = quicksort l2 in m1@[a]@m2
Where \verb=splitting= is defined by~:
let rec splitting a l = function
[] -> ([],[])
| b::m -> let (l1,l2) = splitting a m in
if a<b then (l1,b::l2)
else (b::l1,l2)
Suppose we give the following definitions in \Coq~:
Declaration of the ordering relation~:
Restore State Initial.
Require List.
Require Gt.
Variable inf : A -> A -> Prop.
Definition sup := [x,y:A]~(inf x y).
Hypothesis inf_sup : (x,y:A){(inf x y)}+{(sup x y)}.
Definition of the concatenation of two lists~:
Save State toto.
Fixpoint app [l:list] : list -> list
:= [m:list]<list>Case l of
(* nil *) m
(* cons a l1 *) [a:A][l1:list](cons a (app l1 m)) end.
Restore State toto.
Definition of the permutation of two lists~:
Definition mil := [a:A][l,m:list](app l (cons a m)) : A->list->list->list.
Lemma mil_app : (a:A)(l,m,n:list)(mil a l (app m n))=(app (mil a l m) n).
Unfold mil.
Elim (ass_app l (cons a m) n).
Inductive permut : list->list->Prop :=
permut_nil : (permut nil nil)
|permut_tran : (l,m,n:list)(permut l m)->(permut m n)->(permut l n)
|permut_cmil : (a:A)(l,m,n:list)
(permut l (app m n))->(permut (cons a l) (mil a m n))
|permut_milc : (a:A)(l,m,n:list)
(permut (app m n) l)->(permut (mil a m n) (cons a l)).
Hint permut_nil permut_cmil permut_milc.
Lemma permut_cons : (a:A)(l,m:list)(permut l m)->(permut (cons a l) (cons a m)).
Change (permut (cons a l) (mil a nil m)).
Hint permut_cons.
Lemma permut_refl : (l:list)(permut l l).
Induction l ; Auto.
Hint permut_refl.
Lemma permut_sym : (l,m:list)(permut l m)->(permut m l).
Intros l m h1 ; Elim h1 ; Auto.
Intros l0 m0 n h2 h3 h4 h5.
Apply permut_tran with m0 ; Auto.
Immediate permut_sym.
Lemma permut_app1 : (m1,n1,l:list)(permut m1 n1)->(permut (app l m1) (app l n1)).
Intros ; Elim l ; Simpl ; Auto.
Hint permut_app1.
Lemma permut_app_mil : (a:A)(l1,m1,l2,m2,n2:list)
(permut (app l1 m1) (app (app l2 m2) n2))
-> (permut (app (cons a l1) m1) (app (mil a l2 m2) n2)).
Intros ; Simpl.
Elim (mil_app a l2 m2 n2).
Apply permut_cmil.
Elim (app_ass l2 m2 n2) ; Auto.
Hint permut_app_mil.
Lemma permut_app_app : (m1,m2,n1,n2 :list)
(permut m1 n1)->(permut m2 n2)->(permut (app m1 m2) (app n1 n2)).
Intros m1 m2 n1 n2 h1 h2.
Elim h1 ; Intros.
Exact h2.
Apply permut_tran with (app m n2) ; Auto.
Apply permut_tran with (app m m2) ; Auto.
Apply permut_sym ; Auto.
Hint permut_app_app.
Lemma permut_app : (m,m1,m2,n1,n2 :list)(permut m1 n1)->(permut m2 n2)->
(permut m (app m1 m2))->(permut m (app n1 n2)).
Apply permut_tran with (app m1 m2) ; Auto.
The definitions \verb=inf_list= and \verb=sup_list= allow to know if
an element is lower or greater than all the elements of a list~:
Section Rlist_.
Variable R : A->Prop.
Inductive Rlist : list -> Prop :=
Rnil : (Rlist nil)
| Rcons : (x:A)(l:list)(R x)->(Rlist l)->(Rlist (cons x l)).
Hint Rnil Rcons.
Lemma Rlist_app : (m,n:list)(Rlist m)->(Rlist n)->(Rlist (app m n)).
Intros m n h1 h2 ; Elim h1 ; Simpl ; Auto.
Hint Rlist_app.
Section Rlist_cons_.
Variable a : A.
Variable l : list.
Hypothesis Rc : (Rlist (cons a l)).
Lemma Rlist_cons : (R a)/\(Rlist l).
Inversion_clear Rc; Auto.
End Rlist_cons_.
Section Rlist_append.
Variable n,m : list.
Lemma Rlist_appd : (Rlist (app n m))->((Rlist n)/\(Rlist m)).
Elim n ; Simpl; Auto.
Intros a y h1 h2.
Elim (Rlist_cons a (app y m)) ; Auto.
Intros h3 h4; Elim h1 ; Auto.
End Rlist_append.
Hint Rlist_appd.
Lemma Rpermut : (m,n:list)(permut m n)->(Rlist m)->(Rlist n).
Intros m n h1 ; Elim h1 ; Unfold mil ; Auto.
Intros a l m0 n0 h2 h3 h4.
Elim (Rlist_cons a l); Auto.
Intros h5 h6; Elim (Rlist_appd m0 n0); Auto.
Intros a l m0 n0 h2 h3 h4.
Elim (Rlist_appd m0 (cons a n0)) ; Auto.
Intros h5 h6; Elim (Rlist_cons a n0) ; Auto.
End Rlist_.
Hint Rnil Rcons.
Hint Rlist_app.
Section Inf_Sup.
Hypothesis x : A.
Hypothesis l : list.
Definition inf_list := (Rlist (inf x) l).
Definition sup_list := (Rlist (sup x) l).
End Inf_Sup.
Hint Unfold inf_list sup_list.
Definition of the property of a list to be sorted~:
Inductive sort : list->Prop :=
sort_nil : (sort nil)
| sort_mil : (a:A)(l,m:list)(sup_list a l)->(inf_list a m)
->(sort l)->(sort m)->(sort (mil a l m)).
Hint sort_nil sort_mil.
Lemma permutapp : (a0:A)(y,l1,l2:list)(permut y (app l1 l2))->(permut (cons a0 y) (app l1 (cons a0 l2))).
Exact (permut_cmil a0 y l1 l2 H).
Hint permutapp.
Lemma sortmil : (a:A)(x,x0,l1,l2:list)(sup_list a l1)->(inf_list a l2)->(sort x)->(sort x0)->(permut l1 x)->(permut l2 x0)->(sort (mil a x x0)).
Apply sort_mil ; Auto.
Unfold sup_list ; Apply Rpermut with l1 ; Auto.
Unfold inf_list ; Apply Rpermut with l2 ; Auto.
Then the goal to prove is $\forall l~\exists m~(sort~m) \wedge
(permut~l~m)$ and the specification is
\verb!(l:list){m:list|(sort m)&(permut l m)!.
Let us first prove a preliminary lemma. Let us define \verb=ltl= a
well-founded ordering relation.
Definition ltl := [l,m:list](gt (length m) (length l)).
Hint Unfold ltl.
Lemma ltl_cons : (a,a0:A)(l1,y:list)(ltl l1 (cons a y))->(ltl l1 (cons a (cons a0 y))).
Unfold ltl; Simpl; Auto.
Hint ltl_cons.
Lemma ltl_cons_cons : (a,a0:A)(l2,y:list)(ltl l2 (cons a y))->(ltl (cons a0 l2) (cons a (cons a0 y))).
Unfold ltl; Simpl; Auto.
Hint ltl_cons_cons.
Require Wf_nat.
Let us then give a definition of \verb=Splitting_spec= corresponding
$\exists l_1 \exists l_2.~(sup\_list~a~l_1) \wedge (inf\_list~a~l_2)
\wedge (l \equiv l_1@l_2) \wedge (ltl~l_1~(a::l)) \wedge
(ltl~l2~(a::l))$ and a theorem on this definition.
Inductive Splitting_spec [a:A; l:list] : Set :=
Split_intro : (l1,l2:list)(sup_list a l1)->(inf_list a l2)
->(permut l (app l1 l2))
->(ltl l1 (cons a l))->(ltl l2 (cons a l))
->(Splitting_spec a l).
Theorem Splitting : (a:A)(l:list)(Splitting_spec a l).
Realizer [a:A][l:list]
<list*list>Match l with
(* nil *) (nil,nil)
(* cons *) [b,m,ll]<list*list>let (l1,l2) = ll in
<list*list>if (inf_sup a b)
then (* inf a b *) (l1,(cons b l2))
else (* sup a b *) ((cons b l1),l2)
Simpl; Auto.
The associated {\real} program to the specification we wanted to first
prove and corresponding to the ML program will be~:
Lemma Quicksort: (l:list){m:list|(sort m)&(permut l m)}.
Realizer <list>rec quick :: :: { ltl }
[l:list]<list>Case l of
(* nil *) nil
(* cons *) [a,m]<list>let (l1,l2) = (Splitting a m) in
(mil a (quick l1) (quick l2))
Then \verb=Program_all= gives the following logical lemmas (they have
to be resolved by the user)~:
% chapter ``Utilities'' (JCF, 21.6.95) %
%\def\Coq{{\sf Coq}}
\def\camllight{{\rm Caml Light}}
\def\emacs{{\rm GNU Emacs}}
The distribution provides utilities to simplify some tedious works
beside proof development, tactics writing or documentation.
\section{Modules dependencies}\label{Dependencies}\index{Dependencies}
\index{Coqdep@{\tt coqdep}}
In order to compute modules dependencies (so to use {\tt make}),
\Coq\ comes with an appropriate tool, {\tt coqdep}.
{\tt coqdep} computes inter-module dependencies for \Coq\ and
\camllight\ programs, and prints the dependencies on the standard
output in a format readable by make. When a directory is given as
argument, it is recursively looked at.
Dependencies of \Coq\ modules are computed by looking at {\tt Require}
commands ({\tt Require}, {\tt Requi\-re Export}, {\tt Require Import},
{\tt Require Implementation}), and {\tt Declare ML Module} commands.
Dependencies of \camllight\ modules are computed by looking at
\verb!#open! directives and the double underscore notation {\em
See the man page of {\tt coqdep} for more details and options.
\section{{\tt Makefile}}\label{Makefile}\index{Makefile@{\tt Makefile}}
When a proof development becomes large and is split into several files,
it becomes crucial to use a tool like {\tt make} to compile \Coq\
The writing of a generic and complete {\tt Makefile} may seem tedious
and that's why \Coq\ provides a tool to automate its creation,
{\tt do\_Makefile}. Given the path to \verb!$COQTOP! (the main directory %$
of \Coq) and the files to compile, {\tt do\_Makefile} prints a
{\tt Makefile} on the standard output. So one has just to run the
$$\mbox{\verb!do\_Makefile! {\em Coq-path file$_1$ \dots\
file$_n$} \verb!> Makefile!}$$ %$$
The resulted {\tt Makefile} has a target {\tt depend} which computes the
dependencies and adds them to the end of the {\tt Makefile}. So each time
you want to update the modules dependencies, type in~:
$$\mbox{\verb!make depend!}$$
There is also a target {\tt all} to compile all the files {\em file$_1$
\dots\ file$_n$}, and a generic target to produce a {\tt .vo} file from
the corresponding {\tt .v} file (so you can do {\tt make} {\em file}{\tt.vo}
to compile the file {\em file}{\tt.v}).
%See the man page of {\tt do\_Makefile} for more details.
\section{\Coq\ and \LaTeX}\label{Latex}\index{Coqtex@{\tt coq-tex}}
When writing a documentation about a proof development, we provide a
mechanical way to process \Coq\ phrases embedded in \LaTeX\ files~: the
{\tt coq-tex} filter. This filter extracts Coq phrases embedded in
LaTeX files, evaluates them, and insert the outcome of the evaluation
after each phrase.
Starting with a file {\em file}{\tt.tex} containing \Coq\ phrases,
the {\tt coq-tex} filter produces a file {\em file}{\tt.v.tex} with
the \Coq\ outcome. This \LaTeX\ file must be compiled using the {\tt coq}
or {\tt coq-sl} document style option (provided together with {\tt coq-tex}).
See the man page of {\tt coq-tex} for more details and options. \\[0.3cm]
\noindent{\bf Remark.} This Reference Manual and the Tutorial have been
completely produced with {\tt coq-tex}.
\section{\Coq\ and \emacs}\label{Emacs}\index{Emacs}
\Coq\ comes with a Major mode for \emacs, {\tt coq.el}. This mode provides
syntax highlighting (assuming your \emacs\ library provides
{\tt hilit19.el}) and also a rudimentary indentation facility.
See the file {\tt tools/emacs/README} for more details.
\section{Module specification}\label{gallina}\index{Gallina@{\tt gallina}}
Given a \Coq\ vernacular file, the {\tt gallina} filter extracts its
specification (inductive types declarations, definitions, type of
lemmas and theorems), removing the proofs parts of the file. The \Coq\
file {\em file}{\tt.v} gives birth to the specification file
{\em file}{\tt.g} (where the suffix {\tt.g} stands for {\sf Gallina}).
See the man page of {\tt gallina} for more details and options.
\section{Man pages}\label{ManPages}\index{Man pages}
There are man pages for {\tt coqtop}, {\tt coq}, {\tt coqc},
{\tt coqdep}, {\tt gallina} and {\tt coq-tex}.
Man pages are optionally installed (see installation instructions in
file {\tt INSTALL}, step 6).
\newcommand{\Prop}{{\it Prop}}
\newcommand{\Type}{{\it Type}}
\newcommand{\Spec}{{\it Spec}}
\newcommand{\Data}{{\it Data}}
\newcommand{\Coq}{{\sf Coq}}
\coverpage{A Tutorial}{G\'erard Huet, Gilles Kahn and Christine Paulin-Mohring}
\chapter*{Getting started}
\Coq~ is a Proof Assistant for a Logical Framework known as the Calculus
of Inductive Constructions. It allows the interactive construction of
formal proofs, and also the manipulation of functional programs
consistently with their specifications. It runs as a computer program
on many architectures, and mainly on Unix machines. It is available
with a variety of user interfaces. The present document does not attempt
to present a comprehensive view of all the possibilities of \Coq, but rather
to present in the most elementary manner a tutorial on the basic
specification language, called Gallina, in which formal axiomatisations
may be developed, and on the main proof tools.
We assume here that the potential user has installed \Coq~ on his workstation,
that he calls \Coq~ from a standard teletype-like shell window, and that
he does not use any special interface such as Emacs or Centaur.
Instructions on installation procedures, as well as more comprehensive
documentation, may be found in the standard distribution of \Coq,
which may be obtained by anonymous FTP from site \,
directory \verb:INRIA/coq/V5.10:.
In the following, all examples preceded by the prompting sequence
\verb:Coq < : represent user input, terminated by a period. The
following lines usually show \Coq's answer as it appears on the users's
screen. The sequence of such examples is a valid \Coq~ session, unless
otherwise specified. This version of the tutorial has been prepared
on a SPARC station running UNIX. It assumes that the user
has prepared in his home directory an initialisation file
\verb".coqrc.5.10" containing the following lines:
AddPath ".".
AddPath "$COQTH/SETS".
AddPath "$COQTH/BOOL".
so that the standard invocation of \Coq~ delivers a message such as:
unix: coqtop
> Caml Light version 0.61
Welcome to Coq V5.10 - Thu Nov 10 18:27:12 MET 1994
Coq <
The first line gives a banner stating the precise version of \Coq~
used. You should always return this banner when you report an
anomaly to our hotline \
%The next lines are warnings which may be safely ignored for the time being.
\chapter{Basic Predicate Calculus}
\section{An overview of the specification language Gallina}
A formal development in Gallina consists in a sequence of {\sl declarations}
and {\sl definitions}. You may also send \Coq~ {\sl commands} which are
not really part of the formal development, but correspond to information
requests, or service routine invocations. For instance, the command:
Coq < Quit.
terminates the current session.
A declaration associates a {\sl name} with
a {\sl specification}.
A name corresponds roughly to an identifier in a programming
language, i.e. to a string of letters, digits, and a few ASCII symbols like
underscore (\verb"_") and prime (\verb"'"), starting with a letter.
We use case distinction, so that the names \verb"A" and \verb"a" are distinct.
Certain strings are reserved as key-words of \Coq, and thus are forbidden
as user identifiers.
A specification is a formal expression which classifies the notion which is
being declared. There are basically three kinds of specifications:
{\sl logical propositions}, {\sl mathematical collections}, and
{\sl abstract types}. They are classified by the three basic sorts
of the system, called respectively \verb:Prop:, \verb:Set:, and
\verb:Type:, which are themselves atomic abstract types.
Every valid expression $e$ in Gallina is associated with a specification,
itself a valid expression, called its {\sl type} $\tau(E)$. We write
$e:\tau(E)$ for the judgement that $e$ is of type $E$.
%CP Le role de \tau n'est pas clair.
You may request \Coq~ to return to you the type of a valid expression by using
the command \verb:Check::
Check O.
Thus we know that the identifier \verb:O: (the name `O', not to be
confused with the numeral `0' which is not a proper identifier!) is
known in the current context, and that its type is the specification
\verb:nat:. This specification is itself classified as a mathematical
collection, as we may readily check:
Check nat.
The specification \verb:Set: is an abstract type, one of the basic sorts
of the Gallina language, whereas the notions $nat$ and $O$ are axiomatised
which are defined in the arithmetic prelude, automatically loaded
when executing the command `\verb:Require Basis.:' in the initialisation file
With what we already know, we may now enter in the system a declaration,
corresponding to the informal mathematics {\sl let n be a natural number}:
Variable n:nat.
If we want to translate a more precise statement, such as
{\sl let n be a positive natural number},
we have to add another declaration, which will declare explicitly the
hypothesis \verb:Pos_n:, with specification the proper logical
Hypothesis Pos_n : (gt n O).
Indeed we may check that the relation \verb:gt: is known with the right type
in the current context:
Check gt.
which tells us that \verb:gt: is a function expecting two arguments of
type \verb:nat: in order to build a logical proposition.
What happens here is similar to what we are used to in a functional
programming language: we may compose the (specification) type \verb:nat:
with the (abstract) type \verb:Prop: of logical propositions through the
arrow function constructor, in order to get a functional type
Check nat->Prop.
which may be composed again with \verb:nat: in order to obtain the
type \verb:nat->nat->Prop: of binary relations over natural numbers.
Actually \verb:nat->nat->Prop: is an abbreviation for
Functional notions may be composed in the usual way. An expression $f$
of type $A\ra B$ may be applied to an expression $e$ of type $A$ in order
to form the expression $(f~e)$ of type $B$. Here we get that
the expression \verb:(gt n): is well-formed of type \verb:nat->Prop:,
and thus that the expression \verb:(gt n O):, which abbreviates
\verb:((gt n) O):, is a well-formed proposition.
Check (gt n O).
The initial prelude \verb:Basis: contains a few arithmetic definitions:
\verb:nat: is defined as a mathematical collection (type \verb:Set:), constants
\verb:O:, \verb:S:, \verb:plus:, are defined as objects of types
respectively \verb:nat:, \verb:nat->nat:, and \verb:nat->nat->nat:.
You may introduce new definitions, which link a name to a well-typed value.
For instance, we may introduce the constant \verb:one: as being defined
to be equal to the successor of zero:
Definition one := (S O).
We may optionally indicate the required type:
Definition two : nat := (S one).
Actually \Coq~ allows several possible syntaxes:
Definition three := (S two) : nat.
Here is a way to define the doubling function, which expects an
argument \verb:m: of type \verb:nat: in order to build its result as
\verb:(plus m m)::
Definition double := [m:nat](plus m m).
The abstraction brackets are explained as follows. The expression
\verb+[x:A]e+ is well formed of type \verb+A->B+ in a context
whenever the expression \verb+e+ is well-formed of type \verb+B+ in
the given context to which we add the declaration that \verb+x+
is of type \verb+A+. Here $x$ is a bound, or dummy variable in
the expression \verb+[x:A]e+. For instance we could as well have
defined \verb:double: as \verb+[n:nat](plus n n)+.
Bound (local) variables and free (global) variables may be mixed.
For instance, we may define the function which adds the constant \verb:n:
to its argument as
Definition add_n := [m:nat](plus m n).
However, note that here we may not rename the formal argument $m$ into $n$
without capturing the free occurrence of $n$, and thus changing the meaning
of the defined notion.
Binding operations are well known for instance in logic, where they
are called quantifiers.
Thus we may universally quantify a proposition such as $m>0$ in order
to get a universal proposition $\forall m\cdot m>0$. Indeed this
operator is available in \Coq, with the following syntax:
\verb+(m:nat)(gt m O)+. Similarly to the case of the functional abstraction
binding, we are obliged to declare explicitly the type of the quantified
variable. We check:
Check (m:nat)(gt m O).
\section{Introduction to the proof engine: Minimal Logic}
In the following, we are going to consider various propositions, built
from atomic propositions $A, B, C$. This may be done easily, by
introducing these atoms as global variables declared of type \verb:Prop:.
It is easy to declare several names with the same specification:
Variables A,B,C:Prop.
We shall consider simple implications, such as $A\ra B$, read as
``$A$ implies $B$''. Remark that we overload the arrow symbol, which
has been used above as the functionality type constructor, and which
may be used as well as propositional connective:
Check A->B.
Let us now embark on a simple proof. We want to prove the easy tautology
$((A\ra (B\ra C))\ra (A\ra B)\ra (A\ra C)$.
We enter the proof engine by the command
\verb:Goal:, followed by the conjecture we want to verify:
Goal (A->(B->C))->(A->B)->(A->C).
The system displays the current goal below a double line, local hypotheses
(there are none initially) being displayed above the line. We call
the combination of local hypotheses with a goal a {\sl judgement}.
The new prompt \verb:Unnamed_thm <: indicates that we are now in an inner
loop of the system, in proof mode. New commands are available in this
mode, such as {\sl tactics}, which are proof combining primitives.
A tactic operates on the current goal by attempting to construct a proof
of the corresponding judgement, possibly from proofs of some
hypothetical judgements, which are then added to the current
list of conjectured judgements.
For instance, the \verb:Intro: tactic is applicable to any judgement
whose goal is an implication, by moving the proposition to the left
of the application to the list of local hypotheses:
Intro H.
{\bf Warning} to users of \Coq~ previous versions: The display of a sequent in
older versions of \Coq~ is inverse of this convention: the goal is displayed
above the double line, the hypotheses below.
Several introductions may be done in one step:
Intros H' HA.
We notice that $C$, the current goal, may be obtained from hypothesis
\verb:H:, provided the truth of $A$ and $B$ are established.
The tactic \verb:Apply: implements this piece of reasoning:
Apply H.
We are now in the situation where we have two judgements as conjectures
that remain to be proved. Only the first is listed in full, for the
others the system displays only the corresponding subgoal, without its
local hypotheses list. Remark that \verb:Apply: has kept the local
hypotheses of its father judgement, which are still available for
the judgements it generated.
In order to solve the current goal, we just have to notice that it is
exactly available as hypothesis $HA$:
Exact HA.
Now $H'$ applies:
Apply H'.
And we may now conclude the proof as before, with \verb:Exact HA.:
Actually, we may not bother with the name \verb:HA:, and just state that
the current goal is solvable from the current local assumptions:
The proof is now finished. We may either discard it, by using the
command \verb:Abort: which returns to the standard \Coq~ toplevel loop
without further ado, or else save it as a lemma in the current context,
under name say \verb:trivial_lemma::
Save trivial_lemma.
As a comment, the system shows the proof script listing all tactic
commands used in the proof. % ligne blanche apres Exact HA??
Let us redo the same proof with a few variations. First of all we may name
the initial goal as a conjectured lemma:
Lemma distr_impl : (A->(B->C))->(A->B)->(A->C).
{\bf Warning} to users of \Coq~ older versions: In order to enter the proof
engine, at this point a dummy \verb:Goal.: command had to be typed in.
Next, we may omit the names of local assumptions created by the introduction
tactics, they can be automatically created by the proof engine as new
non-clashing names.
The \verb:Intros: tactic, with no arguments, effects as many individual
applications of \verb:Intro: as is legal.
Then, we may compose several tactics together in sequence, or in parallel,
through {\sl tacticals}, that is tactic combinators. The main constructions
are the following:
\item $T_1 ; T_2$ (read $T_1$ then $T_2$) applies tactic $T_1$ to the current
goal, and then tactic $T_2$ to all the subgoals generated by $T_1$.
\item $T; [T_1 | T_2 | ... | T_n]$ applies tactic $T$ to the current
goal, and then tactic $T_1$ to the first newly generated subgoal,
..., $T_n$ to the nth.
We may thus complete the proof of \verb:distr_impl: with one composite tactic:
Apply H; [Assumption | Apply H0; Assumption].
Let us now save lemma \verb:distr_impl::
Here \verb:Save: needs no argument, since we gave the name \verb:distr_impl:
in advance;
it is however possible to override the given name by giving a different
argument to command \verb:Save:.
Actually, such an easy combination of tactics \verb:Intro:, \verb:Apply:
and \verb:Assumption: may be found completely automatically by an automatic
tactic, called \verb:Auto:, without user guidance:
Lemma distr_imp : (A->(B->C))->(A->B)->(A->C).
This time, we do not save the proof, we just discard it with the \verb:Abort:
At any point during a proof, we may use \verb:Abort: to exit the proof mode
and go back to Coq's main loop. We may also use \verb:Restart: to restart
from scratch the proof of the same lemma. We may also use \verb:Undo: to
backtrack one step, and more generally \verb:Undo n: to
backtrack n steps.
We end this section by showing a useful command, \verb:Inspect n.:,
which inspects the global \Coq~ environment, showing the last \verb:n: declared
notions: % Attention ici ??
Inspect 3.
The declarations, whether global parameters or axioms, are shown preceded by
\verb:***:; definitions and lemmas are stated with their specification, but
their value (or proof-term) is omitted.
\section{Propositional Calculus}
We have seen that how \verb:Intro: and \verb:Apply: tactics could be combined
in order to prove implicational statements. More generally, \Coq~ favors a style
of reasoning, called {\sl Natural Deduction}, which decomposes reasoning into
so called {\sl introduction rules}, which tell how to prove a goal whose main
operator is a given propositional connective, and {\sl elimination rules},
which tell how to use an hypothesis whose main operator is the propositional
connective. Let us show how to use these ideas for the propositional connectives
\verb:/\: and \verb:\/:.
Lemma and_commutative : A /\ B -> B /\ A.
We make use of the conjunctive hypothesis \verb:H: with the \verb:Elim: tactic,
which breaks it into its components:
Elim H.
We now use the conjuction introduction tactic \verb:Split:, which splits the
conjunctive goal into the two subgoals:
and the proof is now trivial. Indeed, the whole proof is obtainable as follows:
Intro H; Elim H; Auto.
The tactic \verb:Auto: succeeded here because it knows as a hint the
conjunction introduction operator \verb+conj+
Check conj.
Actually, the tactic \verb+Split+ is just an abbreviation for \verb+Apply conj.+
What we have just seen is that the \verb:Auto: tactic is more powerful than
just a simple application of local hypotheses; it tries to apply as well
lemmas which have been specified as hints. A \verb:Hint: command registers a
lemma as a hint to be used from now on by the \verb:Auto: tactic, whose power
may thus be incrementally augmented.
In a similar fashion, let us consider disjunction:
Lemma or_commutative : A \/ B -> B \/ A.
Intro H; Elim H.
Let us prove the first subgoal in detail. We use \verb:Intro: in order to
be left to prove \verb:B\/A: from \verb:A::
Intro HA.
Here the hypothesis \verb:H: is not needed anymore. We could choose to
actually erase it with the tactic \verb:Clear:; in this simple proof it
does not really matter, but in bigger proof developments it is useful to
clear away unnecessary hypotheses which may clutter your screen.
Clear H.
The disjunction connective has two introduction rules, since \verb:P\/Q:
may be obtained from \verb:P: or from \verb:Q:; the two corresponding
proof constructors are called respectively \verb:or_introl: and
\verb:or_intror:; they are applied to the current goal by tactics
\verb:Left: and \verb:Right: respectively. For instance:
%CP Documenter Trivial ou mettre Assumption.
As before, all these tedious elementary steps may be performed automatically,
as shown for the second symmetric case:
However, \verb:Auto: alone does not succeed in proving the full lemma, because
it does not try any elimination step.
It is a bit disappointing that \verb:Auto: is not able to prove automatically
such a simple tautology. The reason is that we want to keep Auto efficient,
so that it is always effective to use.
A complete tactic for propositional
tautologies is indeed available in \Coq~ as the \verb:Tauto: tactic.
%In order to get this facility, we have to import a library module
%called ``Dyckhoff'':
It is possible to inspect the actual proof tree constructed by \verb:Tauto:,
using a standard command of the system, which prints the value of any notion
currently defined in the context:
Print or_commutative.
It is not easy to understand the notation for proof terms without a few
explanations. The square brackets, such as \verb+[HH1:A\/B]+, correspond
to \verb:Intro HH1:, whereas a subterm such as
\verb:(or_intror: \linebreak \verb:B A HH6):
corresponds to the sequence \verb:Apply or_intror; Exact HH6:. The extra
arguments \verb:B: and \verb:A: correspond to instanciations to the generic
combinator \verb:or_intror:, which are effected automatically by the tactic
\verb:Apply: when pattern-matching a goal. The specialist will of course
recognize our proof term as a $\lambda$-term, used as notation for the
natural deduction proof term through the Curry-Howard isomorphism. The
naive user of \Coq~ may safely ignore these formal details.
Let us exercise the \verb:Tauto: tactic on a more complex example:
Lemma distr_and : A->(B/\C) -> (A->B /\ A->C).
\subsection{Classical reasoning}
\verb:Tauto: always comes back with an answer. Here is an example where it
Lemma Peirce : ((A->B)->A)->A.
Try Tauto.
Note the use of the \verb:Try: tactical, which does nothing if its tactic
argument fails.
This may come as a surprise to someone familiar with classical reasoning.
Peirce's lemma is true in Boolean logic, i.e. it evaluates to \verb:true: for
every truth-assignment to \verb:A: and \verb:B:. Indeed the double negation
of Peirce's law may be proved in \Coq~ using \verb:Tauto::
Lemma NNPeirce : ~~(((A->B)->A)->A).
In classical logic, the double negation of a proposition is equivalent to this
proposition, but in the constructive logic of \Coq~ this is not so. If you
want to use classical logic in \Coq, you have to import explicitly the
\verb:Classical: module, which will declare the axiom \verb:classic:
of excluded middle, and classical tautologies such as de Morgan's laws.
The \verb:Require: command is used to import a module from \Coq's library:
Require Classical.
Check NNPP.
and it is now easy (although admittedly not the most direct way) to prove
a classical law such as Peirce's:
Lemma Peirce : ((A->B)->A)->A.
Apply NNPP; Tauto.
Here is one more example of propositional reasoning, in the shape of
a scottish puzzle. A private club has the following rules:
\item Every non-scottish member wears red socks
\item Every member wears a kilt or doesn't wear red socks
\item The married members don't go out on sunday
\item A member goes out on sunday if and only if he is scottish
\item Every member who wears a kilt is scottish and married
\item Every scottish member wears a kilt
Now, we show that these rules are so strict that no one can be accepted.
Section club.
Variable Scottish, RedSocks, WearKilt, Married, GoOutSunday : Prop.
Hypothesis rule1 : ~Scottish -> RedSocks.
Hypothesis rule2 : WearKilt \/ ~RedSocks.
Hypothesis rule3 : Married -> ~GoOutSunday.
Hypothesis rule4 : GoOutSunday <-> Scottish.
Hypothesis rule5 : WearKilt -> (Scottish /\ Married).
Hypothesis rule6 : Scottish -> WearKilt.
Lemma NoMember : False.
End club.
\section{Predicate Calculus}
Let us now move into predicate logic, and first of all into first-order
predicate calculus. The essence of predicate calculus is that to try to prove
theorems in the most abstract possible way, without using the definitions of
the mathematical notions, but by formal manipulations of uninterpreted
function and predicate symbols.
\subsection{Sections and signatures}
Usually one works in some domain of discourse, over which range the individual
variables and function symbols. In \Coq~ we speak in a language with a rich
variety of types, so me may mix several domains of discourse, in our
multi-sorted language. For the moment, we just do a few exercises, over a
domain of discourse \verb:D: axiomatised as a \verb:Set:, and we consider two
predicate symbols \verb:P: and \verb:R: over \verb:D:, of arities
respectively 1 and 2. Such abstract entities may be entered in the context
as global variables. But we must be careful about the pollution of our
global environment by such declarations. For instance, we have already
polluted our \Coq~ session by declaring the variables
\verb:n:, \verb:Pos_n:, \verb:A:, \verb:B:, and \verb:C:. If we want to revert to the clean state of
our initial session, we may use the \Coq~ \verb:Reset: command, which returns
to the state just prior the given global notion.
Reset n.
%CP-Parler de Reset Initial.
We shall now declare a new \verb:Section:, which will allow us to define
notions local to a well-delimited scope. We start by assuming a domain of
discourse \verb:D:, and a binary relation \verb:R: over \verb:D::
Section Predicate_calculus.
Variable D:Set.
Variable R: D -> D -> Prop.
As a simple example of predicate calculus reasoning, let us assume
that relation \verb:R: is symmetric and transitive, and let us show that
\verb:R: is reflexive in any point \verb:x: which has an \verb:R: successor.
Since we do not want to make the assumptions about \verb:R: global axioms of
a theory, but rather local hypotheses to a theorem, we open a specific
section to this effect.
Section R_sym_trans.
Hypothesis R_symmetric : (x,y:D) (R x y) -> (R y x).
Hypothesis R_transitive : (x,y,z:D) (R x y) -> (R y z) -> (R x z).
Remark the syntax \verb+(x:D)+ which stands for universal quantification
$\forall x : D$.
\subsection{Existential quantification}
We now state our lemma, and enter proof mode.
Lemma refl_if : (x:D)(Ex [y:D](R x y)) -> (R x x).
Remark that the hypotheses which are local to the currently opened sections
are listed as local hypotheses to the current goals.
The rationale is that these hypotheses are going to be discharged, as we
shall see, when we shall close the corresponding sections.
Note the functional syntax for existential quantification. The existential
quantifier is built from the operator \verb:ex:, which expects a
predicate as argument:
Check ex.
and the notation \verb+(Ex [x:D](P x))+ is just concrete syntax for
\verb+(ex D [x:D](P x))+.
Existential quantification is handled in \Coq~ in a similar
fashion to the connectives \verb:/\: and \verb:\/: : it is introduced by
the proof combinator \verb:ex_intro:, which is invoked by the specific
tactic \verb:Exists:, and its elimination provides a witness \verb+a:D+ to
\verb:P:, together with an assumption \verb+h:(P a)+ that indeed \verb+a+
verifies \verb:P:. Let us see how this works on this simple example.
Intros x x_Rlinked.
Remark that \verb:Intro: treats universal quantification in the same way
as the premisses of implications. Renaming of bound variables occurs
when it is needed; for instance, had we started with \verb:Intro y:,
we would have obtained the goal:
Intro y.
Intros x x_Rlinked.
Let us now use the existential hypothesis \verb:x_Rlinked: to
exhibit an R-successor y of x. This is done in two steps, first with
\verb:Elim:, then with \verb:Intros:
Elim x_Rlinked.
Intros y Rxy.
Now we want to use \verb:R_transitive:. The \verb:Apply: tactic will know
how to match \verb:x: with \verb:x:, and \verb:z: with \verb:x:, but needs
help on how to instanciate \verb:y:, which appear in the hypotheses of
\verb:R_transitive:, but not in its conclusion. We give the proper hint
to \verb:Apply: in a \verb:with: clause, as follows:
Apply R_transitive with y.
The rest of the proof is routine:
Apply R_symmetric; Assumption.
Let us now close the current section.
End R_sym_trans.
Here \Coq's printout is a warning that all local hypotheses have been
discharged in the statement of \verb:refl_if:, which now becomes a general
theorem in the first-order language declared in section
\verb:Predicate_calculus:. In this particular example, the use of section
\verb:R_sym_trans: has not been really significant, since we could have
instead stated theorem \verb:refl_if: in its general form, and done
basically the same proof, obtaining \verb:R_symmetric: and
\verb:R_transitive: as local hypotheses by initial \verb:Intros: rather
than as global hypotheses in the context. But if we had pursued the
theory by proving more theorems about relation \verb:R:,
we would have obtained all general statements at the closing of the section,
with minimal dependencies on the hypotheses of symmetry and transitivity.
\subsection{Paradoxes of classical predicate calculus}
Let us illustrate this feature by pursuing our \verb:Predicate_calculus:
section with an enrichment of our language: we declare a unary predicate
\verb:P: and a constant \verb:d::
Variable P:D->Prop.
Variable d:D.
We shall now prove a well-known fact from first-order logic: a universal
predicate is non-empty, or in other terms existential quantification
follows from universal quantification.
Lemma weird : ((x:D)(P x)) -> (Ex [a:D](P a)).
Intro UnivP.
First of all, notice the pair of parentheses around \verb+(x:D)(P x)+ in
the statement of lemma \verb:weird:.
If we had ommitted them, \Coq's parser would have interpreted the
statement as a truly trivial fact, since we would
postulate an \verb:x: verifying \verb:(P x):. Here the situation is indeed
more problematic. If we have some element in \verb:Set: \verb:D:, we may
apply \verb:UnivP: to it and conclude, otherwise we are stuck. Indeed
such an element \verb:d: exists, but this is just by virtue of our
new signature. This points out a subtle difference between standard
predicate calculus and \Coq. In standard first-order logic,
the equivalent of lemma \verb:weird: always holds,
because such a rule is wired in the inference rules for quantifiers, the
semantic justification being that the interpretation domain is assumed to
be non-empty. Whereas in \Coq, where types are not assumed to be
systematically inhabited, lemma \verb:weird: only holds in signatures
which allow the explicit construction of an element in the domain of
the predicate.
Let us conclude the proof, in order to show the use of the \verb:Exists:
Exists d; Trivial.
Another fact which illustrates the sometimes disconcerting rules of
predicate calculus is Smullyan's drinkers' paradox: ``In any non-empty
bar, there is a person such that if she drinks, then everyone drinks''.
We modelize the bar by Set \verb:D:, drinking by predicate \verb:P:.
We shall need classical reasoning. Instead of loading the \verb:Classical:
module as we did above, we just state the law of excluded middle as a
local hypothesis schema at this point:
Hypothesis EM : (A:Prop) A \/ ~A.
Lemma drinker : (Ex [x:D](P x) -> (x:D)(P x)).
The proof goes by cases on whether or not
there is someone who does not drink. Such reasoning by cases proceeds
by invoking the excluded middle principle, via \verb:Elim: of the
proper instance of \verb:EM::
Elim (EM (Ex [x:D] ~(P x))).
We first look at the first case. Let Tom be the non-drinker:
Intro Non_drinker; Elim Non_drinker; Intros Tom Tom_does_not_drink.
We conclude in that case by considering Tom, since his drinking leads to
a contradiction:
Exists Tom; Intro Tom_drinks.
There are several ways in which we may eliminate a contradictory case;
a simple one is to use the \verb:Absurd: tactic as follows:
Absurd (P Tom); Trivial.
We now proceed with the second case, in which actually any person will do;
such a John Doe is given by the non-emptyness witness \verb:d::
Intro No_nondrinker; Exists d; Intro d_drinks.
Now we consider any Dick in the bar, and reason by cases according to its
drinking or not:
Intro Dick; Elim (EM (P Dick)); Trivial.
The only non-trivial case is again treated by contradiction:
Intro Dick_does_not_drink; Absurd (Ex [x:D]~(P x)); Trivial.
Exists Dick; Trivial.
Now, let us close the main section:
End Predicate_calculus.
Remark how the three theorems are completely generic is the most general
the domain \verb:D: is discharged in all of them, \verb:R: is discharged in
\verb:refl_if: only, \verb:P: is discharged only in \verb:weird: and
\verb:drinker:, along with the hypothesis that \verb:D: is inhabited.
Finally, the excluded middle hypothesis is discharged only in
Note that the name \verb:d: has vanished as well from
the statements of \verb:weird: and \verb:drinker:,
since \Coq's prettyprinter replaces
systematically a quantification such as \verb+(d:D)E+, where \verb:d:
does not occur in \verb:E:, by the functional notation \verb:D->E:.
Similarly the name \verb:EM: does not appear in \verb:drinker:.
Actually, universal quantification, implication,
as well as function formation, are
all special cases of one general construct of type theory called
{\sl dependent product}. This is the mathematical construction
corresponding to an indexed family of functions. A function
$f\in \Pi x:D\cdot Cx$ maps an element $x$ of its domain $D$ to its
(indexed) codomain $Cx$. Thus a proof of $\forall x:D\cdot Px$ is
a function mapping an element $x$ of $D$ to a proof of proposition $Px$.
\subsection{Flexible use of local assumptions}
Very often during the course of a proof we want to retrieve a local
assumption and reintroduce it explicitly in the goal, for instance
in order to get a more general induction hypothesis. The tactic
\verb:Generalize: is what is needed here:
Variable P,Q:nat->Prop. Variable R: nat->nat->Prop.
Lemma PQR : (x,y:nat)((R x x)->(P x)->(Q x))->(P x)->(R x y)->(Q x).
Generalize H0.
Sometimes it may be convenient to use a lemma, although we do not have
a direct way to appeal to such an already proven fact. The tactic \verb:Cut:
permits to use the lemma at this point, keeping the corresponding proof
obligation as a new subgoal:
Cut (R x x); Trivial.
%CP pourquoi ne pas montrer les deux sous-buts engendres par Cut.
The basic equality provided in \Coq~ is Leibniz equality, noted infix like
\verb+x=y+, when \verb:x: and \verb:y: are two expressions of
type the same Set. The replacement of \verb:x: by \verb:y: in any
term is effected by a variety of tactics, such as \verb:Rewrite:
and \verb:Replace:.
Let us give a few examples of equality replacement. Let us assume that
some arithmetic function \verb:f: is null in zero:
Variable f:nat->nat.
Hypothesis foo : (f O)=O.
We want to prove the following conditional equality:
Lemma L1 : (k:nat)k=O->(f k)=k.
As usual, we first get rid of local assumptions with \verb:Intro::
Intros k E.
Let us now use equation \verb:E: as a left-to-right rewriting:
Rewrite E.
This replaced both occurrences of \verb:k: by \verb:O:.
{\bf Warning} to users of \Coq~ old versions: In \Coq V5.8 only the second
occurrence of \verb:k: would have been replaced, and we would have had
to use \verb:Rewrite: twice in order to get the same effect.
%Actually, it is possible to rewrite both occurrences of \verb:k: at the
%same time, provided one abstracts \verb:k: in the goal with tactic
%\verb:Pattern:. Let us go back two steps:
%L1 < Undo 2.
%1 subgoal
% k : nat
% E : k=O
% ============================
% (f k)=k
%L1 < Pattern k.
%1 subgoal
% k : nat
% E : k=O
% ============================
% ([n:nat](f n)=n k)
%What just happened is that \verb:Pattern: replaced the goal
%\verb:(f k)=k: by the equivalent one:
%\verb+([n:nat](f n)=n k)+, which has the form \verb+(P k)+, with
%\verb+P+ the predicate which maps \verb+n+ to proposition
%\verb+(f n)=n+. The two goals are equivalent in the sense that
%\verb+([n:nat](f n)=n k)+ {\sl reduces} to \verb:(f k)=k:
%by the following computation rule:
%$$ ([x:A]M~N) \leftarrow M\{x/N\} \eqno \beta$$
%We may now proceed with our rewriting:
%L1 < Rewrite E.
%1 subgoal
% k : nat
% E : k=O
% ============================
% (f O)=O
Now \verb:Apply foo: will finish the proof:
Apply foo.
When one wants to rewrite an equality in a right to left fashion, we should
use \verb:Rewrite <- E: rather than \verb:Rewrite E: or the equivalent
\verb:Rewrite -> E:.
Let us now illustrate the tactic \verb:Replace:.
Lemma L2 : (f (f O))=O.
Replace (f O) with O.
What happened here is that the replacement left the first subgoal to be
proved, but another proof obligation was generated by the \verb:Replace:
tactic, as the second subgoal. The first subgoal is solved immediately
by appying lemma \verb:foo:; the second one too, provided we apply first
symmetry of equality, for instance with tactic \verb:Symmetry::
Apply foo.
Symmetry; Apply foo.
\subsection{Predicate calculus over Type}
We just explained the basis of first-order reasoning in the universe
of mathematical Sets. Similar reasoning is available at the level of
abstract Types. In order to develop such abtract reasoning, one must
load the library \verb:Logic_Type:.
Require Logic_Type.
New proof combinators are now available, such as the existential
quantification \verb:exT: over a Type, available with syntax
\verb:(ExT P):. The corresponding introduction
combinator may be invoked by the tactic \verb:Exists: as above.
Check exT_intro.
Similarly, equality over Type is available, with notation
\verb:M==N:. The equality tactics process \verb:==: in the same way
as \verb:=:.
\section{Using definitions}
The development of mathematics does not simply proceed by logical
argumentation from first principles: definitions are used in an essential way.
A formal development proceeds by a dual process of abstraction, where one
proves abstract statements in predicate calculus, and use of definitions,
which in the contrary one instanciates general statements with particular
notions in order to use the structure of mathematical values for the proof of
more specialised properties.
\subsection{Unfolding definitions}
Assume that we want to develop the theory of sets represented as characteristic
predicates over some universe \verb:U:. For instance:
%CP Une petite explication pour le codage de element ?
Variable U:Type.
Definition set := U->Prop.
Definition element := [x:U][S:set](S x).
Definition subset := [A,B:set](x:U)(element x A)->(element x B).
Now, assume that we have loaded a module of general properties about
relations over some abstract type \verb:T:, such as transitivity:
Definition transitive := [T:Type][R:T->T->Prop]
(x,y,z:T)(R x y)->(R y z)->(R x z).
Now, assume that we want to prove that \verb:subset: is a \verb:transitive:
Lemma subset_transitive : (transitive set subset).
In order to make any progress, one needs to use the definition of
\verb:transitive:. The \verb:Unfold: tactic, which replaces all occurrences of a
defined notion by its definition in the current goal, may be used here.
Unfold transitive.
Now, we must unfold \verb:subset::
Unfold subset.
Now, unfolding \verb:element: would be a mistake, because indeed a simple proof
can be found by \verb:Auto:, keeping \verb:element: an abstract predicate:
Many variations on \verb:Unfold: are provided in \Coq. For instance,
we may selectively unfold one designated occurrence:
Undo 2.
Unfold 2 subset.
One may also unfold a definition in a given local hypothesis, using the
\verb:in: notation:
Unfold subset in H.
Finally, the tactic \verb:Red: does only unfolding of the head occurrence
of the current goal:
Auto. Save.
\subsection{Principle of proof irrelevance}
Even though in principle the proof term associated with a verified lemma
corresponds to a defined value of the corresponding specification, such
definitions cannot be unfolded in \Coq: a lemma is considered an {\sl opaque}
definition. This conforms to the mathematical tradition of {\sl proof
irrelevance}: the proof of a logical proposition does not matter, and the
mathematical justification of a logical development relies only on
{\sl provability} of the lemmas used in the formal proof.
Conversely, ordinary mathematical definitions can be unfolded at will, they
are {\sl transparent}. It is possible to enforce the reverse convention by
declaring a definition as {\sl opaque} or a lemma as {\sl transparent}.
\section{Data Types as Inductively Defined Mathematical Collections}
All the notions which were studied until now pertain to traditional
mathematical logic. Specifications of objects were abstract properties
used in reasoning more or less constructively; we are now entering
the realm of inductive types, which specify the existence of concrete
mathematical constructions.
Let us start with the collection of booleans, as they are specified
in the \Coq's \verb:Prelude: module:
Inductive bool : Set := true : bool | false : bool.
Such a declaration defines several objects at once. First, a new
\verb:Set: is declared, with name \verb:bool:. Then the {\sl constructors}
of this \verb:Set: are declared, called \verb:true: and \verb:false:.
Those are analogous to introduction rules of the new Set \verb:bool:.
Finally, a specific elimination rule for \verb:bool: is now available, which
permits to reason by cases on \verb:bool: values. Three instances are
indeed defined as new combinators in the global context: \verb:bool_ind:,
a proof combinator corresponding to reasoning by cases,
\verb:bool_rec:, an if-then-else programming construct,
and \verb:bool_rect:, a similar combinator at the level of types.
Check bool_ind.
Check bool_rec.
Check bool_rect.
Let us for instance prove that every Boolean is true or false.
Lemma duality : (b:bool)(b=true \/ b=false).
Intro b.
We use the knowledge that \verb:b: is a \verb:bool: by calling tactic
\verb:Elim:, which is this case will appeal to combinator \verb:bool_ind:
in order to split the proof according to the two cases:
Elim b.
It is easy to conclude in each case:
Left; Trivial.
Right; Trivial.
Indeed, the whole proof can be done with the combination of the
\verb:Induction: tactic, which combines \verb:Intro: and \verb:Elim:,
with good old \verb:Auto::
Induction b; Auto.
\subsection{Natural numbers}
Similarly to Booleans, natural numbers are defined in the \verb:Prelude:
module with constructors \verb:S: and \verb:O::
Inductive nat : Set := O : nat | S : nat->nat.
The elimination principles which are automatically generated are Peano's
induction principle, and a recursion operator:
Check nat_ind.
Check nat_rec.
Let us start by showing how to program the standard primitive recursion
operator \verb:prim_rec: from the more general \verb:nat_rec::
Definition prim_rec := (nat_rec [i:nat]nat).
That is, instead of computing for natural \verb:i: an element of the indexed
\verb:Set: \verb:(P i):, \verb:prim_rec: computes uniformly an element of
\verb:nat:. Let us check the type of \verb:prim_rec::
Check prim_rec.
Oops! Instead of the expected type \verb+nat->(nat->nat->nat)->nat->nat+ we
get an apparently more complicated expression. Indeed the type of
\verb:prim_rec: is equivalent by rule $\beta$ to its expected type; this may
be checked in \Coq~ by command \verb:Eval:, which $\beta$-reduces an expression
to its {\sl normal form}:
Eval ([_:nat]nat O)
->((y:nat)([_:nat]nat y)->([_:nat]nat (S y)))
->(n:nat)([_:nat]nat n).
Let us now show how to program addition with primitive recursion:
Definition addition := [n,m:nat](prim_rec m [p:nat][rec:nat](S rec) n).
That is, we specify that \verb+(addition n m)+ computes by cases on \verb:n:
according to its main constructor; when \verb:n=O:, we get \verb:m:;
when \verb:n=(S p):, we get \verb:(S rec):, where \verb:rec: is the result
of the recursive computation \verb+(addition p m)+. Let us verify it by
asking \Coq~to compute for us say $2+3$:
Compute (addition (S (S O)) (S (S (S O)))).
Actually, we do not have to do all this explicitly. \Coq~ provides a special
syntax \verb:Fixpoint/Case: for generic primitive recursion, and we could thus
have defined directly addition as:
Fixpoint plus [n:nat] : nat -> nat :=
[m:nat]<nat>Case n of
(* O *) m
(* S p *) [p:nat](S (plus p m)) end.
Here the strings \verb:(* ... *): are just comments to help understand the
Indeed in \Coq~ version V5.10 an easier syntax is available to describe
directly simple recursions, as follows:
Recursive Definition pluss : nat->nat->nat :=
O m => m
| (S p) m => (S (pluss p m)).
{\bf Warning} This facility was NOT available in earlier versions of \Coq.
The names \verb:pluss_eq1: and \verb:pluss_eq2: are the defining equations of
\verb:pluss:, entered as equalities. For instance:
Check pluss_eq1.
For the rest of the session, we shall clean up what we did so far with
types \verb:bool: and \verb:nat:, in order to use the initial definitions
given in \Coq's \verb:Prelude: module, and not to get confusing error
messages due to our redefinitions. We thus revert to the state before
our definition of \verb:bool: with the \verb:Reset: command:
Reset bool.
\subsection{Simple proofs by induction}
%CP Pourquoi ne pas commencer par des preuves d'egalite entre termes
% convertibles.
Let us now show how to do proofs by structural induction. We start with easy
properties of the \verb:plus: function we just defined. Let us first
show that $n=n+0$.
Lemma plus_n_O : (n:nat)n=(plus n O).
Intro n; Elim n.
What happened was that \verb:Elim n:, in order to construct a \verb:Prop:
(the initial goal) from a \verb:nat: (i.e. \verb:n:), appealed to the
corresponding induction principle \verb:nat_ind: which we saw was indeed
excactly Peano's induction scheme. Pattern-matching instanciated the
corresponding predicate \verb:P: to \verb+[n:nat]n=(plus n O)+, and we get
as subgoals the corresponding instanciations of the base case \verb:(P O): ,
and of the inductive step \verb+(y:nat)(P y)->(P (S y))+.
In each case we get an instance of function \verb:plus: in which its second
argument starts with a constructor, and is thus amenable to simplification
by primitive recursion. The \Coq~tactic \verb:Simpl: can be used for
this purpose:
We proceed in the same way for the base step:
Simpl; Auto.
Here \verb:Auto: succeded, because it used as a hint lemma \verb:eq_S:,
which say that successor preserves equality:
Check eq_S.
Actually, let us see how to declare our lemma \verb:plus_n_O: as a hint
to be used by \verb:Auto::
Hint plus_n_O.
We now proceed to the similar property concerning the other constructor
Lemma plus_n_S : (n,m:nat)(S (plus n m))=(plus n (S m)).
We now go faster, remembering that tactic \verb:Induction: does the
necessary \verb:Intros: before applying \verb:Elim:. Factoring simplification
and automation in both cases thanks to tactic composition, we prove this
lemma in one line:
Induction n; Simpl; Auto.
Hint plus_n_S.
Let us end this exercise with the commutativity of \verb:plus::