Gallina is the kernel language of Coq. We describe here extensions of the Gallina’s syntax.
The Record
construction is a macro allowing the definition of
records as is done in many programming languages. Its syntax is
described on Figure 2.1. In fact, the Record
macro is more general than the usual record types, since it allows
also for “manifest” expressions. In this sense, the Record
construction allows to define “signatures”.
sentence ++= record record ::= Record ident [binderlet … binderlet] : sort :=
[ident] {
[field ; … ; field]}
.
field ::= name : type | name [: term] := term
Figure 2.1: Syntax for the definition of Record
In the expression
Record ident params :
sort := ident0 {
ident1 : term1;
…identn : termn }
.
the identifier ident is the name of the defined record and sort is its type. The identifier ident0 is the name of its constructor. If ident0 is omitted, the default name Build_ident is used. The identifiers ident1, .., identn are the names of fields and term1, .., termn their respective types. Remark that the type of identi may depend on the previous identj (for j<i). Thus the order of the fields is important. Finally, params are the parameters of the record.
More generally, a record may have explicitly defined (a.k.a.
manifest) fields. For instance, Record ident [
params ] : sort := {
ident1
: type1 ;
ident2 := term2
;
ident3 : type3 }
in which case
the correctness of type3 may rely on the instance term2 of
ident2 and term2 in turn may depend on ident1.
Example: The set of rational numbers may be defined as:
Remark here that the field
Rat_cond
depends on the field bottom
.
Let us now see the work done by the Record macro. First the macro generates an inductive definition with just one constructor:
Inductive ident params :sort :=
ident0 (ident1:term1) .. (identn:termn).
To build an object of type ident, one should provide the constructor ident0 with n terms filling the fields of the record.
As an example, let us define the rational 1/2:
…
The macro generates also, when it is possible, the projection
functions for destructuring an object of type ident. These
projection functions have the same name that the corresponding
fields. If a field is named “_
” then no projection is built
for it. In our example:
Warnings:
It can happen that the definition of a projection is impossible. This message is followed by an explanation of this impossibility. There may be three reasons:
Error messages:
The record name ident appears in the type of its fields.
See also: Coercions and records in Section 16.9
of the chapter devoted to coercions.
Remark: Structure is a synonym of the keyword Record.
Remark: An experimental syntax for projections based on a dot notation is
available. The command to activate it is
Set Printing Projections.
term ++= term .( qualid ) | term .( qualid arg … arg ) | term .( @qualid term … term )
Figure 2.2: Syntax of Record projections
The corresponding grammar rules are given Figure 2.2. When qualid denotes a projection, the syntax term.(qualid) is equivalent to qualid term, the syntax term.(qualid arg1 … argn) to qualid arg1 …argn term, and the syntax term.(@qualid term1 … termn) to @qualid term1 …termn term. In each case, term is the object projected and the other arguments are the parameters of the inductive type.
To deactivate the printing of projections, use Unset Printing Projections.
The basic version of match
allows pattern-matching on simple
patterns. As an extension, multiple nested patterns or disjunction of
patterns are allowed, as in ML-like languages.
The extension just acts as a macro that is expanded during parsing into a sequence of match on simple patterns. Especially, a construction defined using the extended match is generally printed under its expanded form (see Set Printing Matching in section 2.2.4).
See also: Chapter 15.
For inductive types with exactly two constructors and for pattern-matchings expressions which do not depend on the arguments of the constructors, it is possible to use a if ... then ... else notation. For instance, the definition
can be alternatively written
More generally, for an inductive type with constructors C1 and C2, we have the following equivalence
if term [dep_ret_type] then term1 else term2 ≡
match term [dep_ret_type] with |
| C1 _ … _ => term1 |
| C2 _ … _ => term2 |
end |
Here is an example.
Notice that the printing uses the if syntax because sumbool is declared as such (see Section 2.2.4).
Closed terms (that is not relying on any axiom or variable) in an inductive type having only one constructor, say foo, have necessarily the form (foo ...). In this case, the match construction can be written with a syntax close to the let ... in ... construction. Expression let ( ident1,…,identn ) := term0 in term1 performs case analysis on term0 which must be in an inductive type with one constructor with n arguments. Variables ident1…identn are bound to the n arguments of the constructor in expression term1. For instance, the definition
can be alternatively written
Note however that reduction is slightly different from regular let ... in ... construction since it can occur only if term0 can be put in constructor form. Otherwise, reduction is blocked.
The pretty-printing of a definition by matching on a irrefutable pattern can either be done using match or the let construction (see Section 2.2.4).
The general equivalence for an inductive type with one constructors C is
let (ident1,…,identn) [dep_ret_type] := term in term’
≡
match term [dep_ret_type] with C ident1 … identn =>
term’ end
The following commands give some control over the pretty-printing of match expressions.
The Calculus of Inductive Constructions knows pattern-matching only over simple patterns. It is however convenient to re-factorize nested pattern-matching into a single pattern-matching over a nested pattern. Coq’s printer try to do such limited re-factorization.
Set Printing Matching.
This tells Coq to try to use nested patterns. This is the default behavior.
Unset Printing Matching.
This tells Coq to print only simple pattern-matching problems in the same way as the Coq kernel handles them.
Test Printing Matching.
This tells if the printing matching mode is on or off. The default is on.
Some variables in a pattern may not occur in the right-hand side of the pattern-matching clause. There are options to control the display of these variables.
Set Printing Wildcard.
The variables having no occurrences in the right-hand side of the pattern-matching clause are just printed using the wildcard symbol “_”.
Unset Printing Wildcard.
The variables, even useless, are printed using their usual name. But some non dependent variables have no name. These ones are still printed using a “_”.
Test Printing Wildcard.
This tells if the wildcard printing mode is on or off. The default is to print wildcard for useless variables.
In most of the cases, the type of the result of a matched term is mechanically synthesizable. Especially, if the result type does not depend of the matched term.
Set Printing Synth.
The result type is not printed when Coq knows that it can re-synthesize it.
Unset Printing Synth.
This forces the result type to be always printed.
Test Printing Synth.
This tells if the non-printing of synthesizable types is on or off. The default is to not print synthesizable types.
If an inductive type has just one constructor, pattern-matching can be written using let ... := ... in ...
Add Printing Let ident.
This adds ident to the list of inductive types for which pattern-matching is written using a let expression.
Remove Printing Let ident.
This removes ident from this list.
Test Printing Let ident.
This tells if ident belongs to the list.
Print Table Printing Let.
This prints the list of inductive types for which pattern-matching is written using a let expression.
The list of inductive types for which pattern-matching is written using a let expression is managed synchronously. This means that it is sensible to the command Reset.
If an inductive type is isomorphic to the boolean type, pattern-matching can be written using if ... then ... else ...
Add Printing If ident.
This adds ident to the list of inductive types for which pattern-matching is written using an if expression.
Remove Printing If ident.
This removes ident from this list.
Test Printing If ident.
This tells if ident belongs to the list.
Print Table Printing If.
This prints the list of inductive types for which pattern-matching is written using an if expression.
The list of inductive types for which pattern-matching is written using an if expression is managed synchronously. This means that it is sensible to the command Reset.
This example emphasizes what the printing options offer.
The experimental command
can be seen as a generalization of Fixpoint. It is actually a wrapper for several ways of defining a function and other useful related objects, namely: an induction principle that reflects the recursive structure of the function (see 8.7.6), and its fixpoint equality. The meaning of this declaration is to define a function ident, similarly to Fixpoint. Like in Fixpoint, the decreasing argument must be given (unless the function is not recursive), but it must not necessary be structurally decreasing. The point of the {} annotation is to name the decreasing argument and to describe which kind of decreasing criteria must be used to ensure termination of recursive calls.
The Function construction enjoys also the with extension to define mutually recursive definitions. However, this feature does not work for non structural recursive functions.
See the documentation of functional induction (see Section 8.7.6) and Functional Scheme (see Section 8.15 and 10.4) for how to use the induction principle to easily reason about the function.
Remark: To obtain the right principle, it is better to put rigid parameters of the function as first arguments. For example it is better to define plus like this:
than like this:
term0 must be build as a pure pattern-matching tree (match...with) with applications only at the end of each branch. For now dependent cases are not treated.
Error messages:
The generation of the graph relation (R_ident) used to compute the induction scheme of ident raised a typing error. Only the ident is defined, the induction scheme will not be generated.
This error happens generally when:
The generation of the graph relation (R_ident) succeeded but the induction principle could not be built. Only the ident is defined. Please report.
functional inversion will not be available for the function.
Depending on the {…} annotation, different definition mechanisms are used by Function. More precise description given below.
Variants:
Defines the not recursive function ident as if declared with Definition. Moreover the following are defined:
Defines the structural recursive function ident as if declared with Fixpoint. Moreover the following are defined:
Defines a recursive function by well founded recursion. The module Recdef of the standard library must be loaded for this feature. The {} annotation is mandatory and must be one of the following:
Depending on the annotation, the user is left with some proof obligations that will be used to define the function. These proofs are: proofs that each recursive call is actually decreasing with respect to the given criteria, and (if the criteria is wf) a proof that the ordering relation is well founded.
Once proof obligations are discharged, the following objects are defined:
The way this recursive function is defined is the subject of several papers by Yves Bertot and Antonia Balaa on one hand and Gilles Barthe, Julien Forest, David Pichardie and Vlad Rusu on the other hand.
Remark: Proof obligations are presented as several subgoals belonging to a Lemma ident_tcc.
The sectioning mechanism allows to organize a proof in structured sections. Then local declarations become available (see Section 1.3.2).
This command is used to open a section named ident.
This command closes the section named ident. When a section is closed, all local declarations (variables and local definitions) are discharged. This means that all global objects defined in the section are generalized with respect to all variables and local definitions it depends on in the section. None of the local declarations (considered as autonomous declarations) survive the end of the section.
Here is an example :
Notice the difference between the value of x’ and x’’ inside section s1 and outside.
Error messages:
Remarks:
The module system provides a way of packaging related elements together, as well as a mean of massive abstraction.
module_type ::= ident | module_type with Definition ident := term | module_type with Module ident := qualid module_binding ::= ( ident … ident : module_type ) module_bindings ::= module_binding … module_binding module_expression ::= qualid … qualid
Figure 2.3: Syntax of modules
This command is used to start an interactive module named ident.
Variants:
Starts an interactive functor with parameters given by module_bindings.
:
module_typeStarts an interactive module specifying its module type.
:
module_typeStarts an interactive functor with parameters given by module_bindings, and output module type module_type.
<:
module_typeStarts an interactive module satisfying module_type.
<:
module_typeStarts an interactive functor with parameters given by module_bindings. The output module type is verified against the module type module_type.
Behaves like Module, but automatically imports or exports the module.
This command closes the interactive module ident. If the module type was given the content of the module is matched against it and an error is signaled if the matching fails. If the module is basic (is not a functor) its components (constants, inductive types, submodules etc) are now available through the dot notation.
Error messages:
This command defines the module identifier ident to be equal to module_expression.
Variants:
Defines a functor with parameters given by module_bindings and body module_expression.
:
module_type :=
module_expressionDefines a functor with parameters given by module_bindings (possibly none), and output module type module_type, with body module_expression.
<:
module_type :=
module_expressionDefines a functor with parameters given by module_bindings (possibly none) with body module_expression. The body is checked against module_type.
This command is used to start an interactive module type ident.
Variants:
Starts an interactive functor type with parameters given by module_bindings.
This command closes the interactive module type ident.
Error messages:
Defines a module type ident equal to module_type.
Variants:
Defines a functor type ident specifying functors taking arguments module_bindings and returning module_type.
Declares a module ident of type module_type. This command is available only in module types.
Variants:
:
module_typeDeclares a functor with parameters module_bindings and output module type module_type.
Declares a module equal to the module qualid.
<:
module_type := qualidDeclares a module equal to the module qualid, verifying that the module type of the latter is a subtype of module_type.
Declares a modules ident of type module_type, and imports or exports it directly.
Let us define a simple module.
Inside a module one can define constants, prove theorems and do any other things that can be done in the toplevel. Components of a closed module can be accessed using the dot notation:
A simple module type:
Inside a module type the proof editing mode is not available. Consequently commands like Definition without body, Lemma, Theorem are not allowed. In order to declare constants, use Axiom and Parameter.
Now we can create a new module from M, giving it a less precise specification: the y component is dropped as well as the body of x.
The definition of N using the module type expression SIG with Definition T:=nat is equivalent to the following one:
If we just want to be sure that the our implementation satisfies a given module type without restricting the interface, we can use a transparent constraint
Now let us create a functor, i.e. a parametric module
and apply it to our modules and do some computations
In the end, let us define a module type with two sub-modules, sharing some of the fields and give one of its possible implementations:
Notice that M is a correct body for the component M2 since its T component is equal nat and hence M1.T as specified.
Remarks:
Module N : SIG := M.
or
Module N : SIG.
…
End N.
hints and the like valid for N are not those defined in M (or the module body) but the ones defined in SIG.
If qualid denotes a valid basic module (i.e. its module type is a signature), makes its components available by their short names.
Example:
Variants:
When the module containing the command Export qualid is imported, qualid is imported as well.
Error messages:
Warnings:
Prints the module type and (optionally) the body of the module ident.
Prints the module type corresponding to ident.
Prints the full name of the module qualid.
The theories developed in Coq are stored in libraries. A library is characterized by a name called root of the library. The standard library of Coq has root name Coq and is known by default when a Coq session starts.
Libraries have a tree structure. E.g., the Coq library contains the sub-libraries Init, Logic, Arith, Lists, ... The “dot notation” is used to separate the different component of a library name. For instance, the Arith library of Coq standard library is written “Coq.Arith”.
Remark: no blank is allowed between the dot and the identifier on its
right, otherwise the dot is interpreted as the full stop (period) of
the command!
Libraries and sub-libraries are denoted by logical directory paths (written dirpath and of which the syntax is the same as qualid, see 1.2.3). Logical directory paths can be mapped to physical directories of the operating system using the command (see 6.5.3)
Add LoadPath physical_path as dirpath.
A library can inherit the tree structure of a physical directory by using the -R option to coqtop or the command (see 6.5.4)
Add Rec LoadPath physical_path as dirpath.
Remark: When used interactively with coqtop command, Coq opens a
library called Top.
At some point, (sub-)libraries contain modules which coincide with files at the physical level. As for sublibraries, the dot notation is used to denote a specific module of a library. Typically, Coq.Init.Logic is the logical path associated to the file Logic.v of Coq standard library. Notice that compilation (see 12) is done at the level of files.
If the physical directory where a file File.v lies is mapped to the empty logical directory path (which is the default when using the simple form of Add LoadPath or -I option to coqtop), then the name of the module it defines is File.
Modules contain constructions (sub-modules, axioms, parameters, definitions, lemmas, theorems, remarks or facts). The (full) name of a construction starts with the logical name of the module in which it is defined followed by the (short) name of the construction. Typically, the full name Coq.Init.Logic.eq denotes Leibniz’ equality defined in the module Logic in the sublibrary Init of the standard library of Coq.
The full name of a library, module, section, definition, theorem, ... is its absolute name. The last identifier (eq in the previous example) is its short name (or sometimes base name). Any suffix of the absolute name is a partially qualified name (e.g. Logic.eq is a partially qualified name for Coq.Init.Logic.eq). Partially qualified names (shortly qualified name) are also built from identifiers separated by dots. They are written qualid in the documentation.
Coq does not accept two constructions (definition, theorem, ...) with the same absolute name but different constructions can have the same short name (or even same partially qualified names as soon as the full names are different).
Coq maintains a name table mapping qualified names to absolute names. This table is modified by the commands Require (see 6.4.1), Import and Export (see 2.5.8) and also each time a new declaration is added to the context.
An absolute name is called visible from a given short or partially qualified name when this name suffices to denote it. This means that the short or partially qualified name is mapped to the absolute name in Coq name table.
It may happen that a visible name is hidden by the short name or a qualified name of another construction. In this case, the name that has been hidden must be referred to using one more level of qualification. Still, to ensure that a construction always remains accessible, absolute names can never be hidden.
Examples:
Remark: There is also a name table for sublibraries, modules and sections.
Remark: In versions prior to Coq 7.4, lemmas declared with Remark and Fact kept in their full name the names of the
sections in which they were defined. Since Coq 7.4, they strictly
behaves as Theorem and Lemma do.
See also: Command Locate in Section 6.2.10.
A module compiled in a “.vo” file comes with a logical names (e.g.
physical file theories/Init/Datatypes.vo
in the Coq installation directory is bound to the logical module Coq.Init.Datatypes).
When requiring the file, the mapping between physical directories and logical library should be consistent with the mapping used to compile the file (for modules of the standard library, this is automatic – check it by typing Print LoadPath).
The command Add Rec LoadPath is also available from coqtop
and coqc by using option -R
.
An implicit argument of a function is an argument which can be inferred from the knowledge of the type of other arguments of the function, or of the type of the surrounding context of the application. Especially, an implicit argument corresponds to a parameter dependent in the type of the function. Typical implicit arguments are the type arguments in polymorphic functions. More precisely, there are several kinds of implicit arguments.
An implicit argument can be either strict or non strict. An implicit argument is said strict if, whatever the other arguments of the function are, it is still inferable from the type of some other argument. Technically, an implicit argument is strict if it corresponds to a parameter which is not applied to a variable which itself is another parameter of the function (since this parameter may erase its arguments), not in the body of a match, and not itself applied or matched against patterns (since the original form of the argument can be lost by reduction).
For instance, the first argument of
cons: forall A:Set, A -> list A -> list A
in module List.v is strict because list is an inductive type and A will always be inferable from the type list A of the third argument of cons. On the contrary, the second argument of a term of type
forall P:nat->Prop, forall n:nat, P n -> ex nat P
is implicit but not strict, since it can only be inferred from the type P n of the third argument and if P is e.g. fun _ => True, it reduces to an expression where n does not occur any longer. The first argument P is implicit but not strict either because it can only be inferred from P n and P is not canonically inferable from an arbitrary n and the normal form of P n (consider e.g. that n is 0 and the third argument has type True, then any P of the form fun n => match n with 0 => True | _ => anything end would be a solution of the inference problem).
An implicit argument can be contextual or not. An implicit argument is said contextual if it can be inferred only from the knowledge of the type of the context of the current expression. For instance, the only argument of
nil : forall A:Set, list A
is contextual. Similarly, both arguments of a term of type
forall P:nat->Prop, forall n:nat, P n \/ n = 0
are contextual (moreover, n is strict and P is not).
In a given expression, if it is clear that some argument of a function can be inferred from the type of the other arguments, the user can force the given argument to be guessed by replacing it by “_”. If possible, the correct argument will be automatically generated.
Error messages:
In case one wants that some arguments of a given object (constant, inductive types, constructors, assumptions, local or not) are always inferred by Coq, one may declare once for all which are the expected implicit arguments of this object. The syntax is
Implicit Arguments qualid [ ident … ident ]
where the list of ident is the list of parameters to be declared implicit. After this, implicit arguments can just (and have to) be skipped in any expression involving an application of qualid.
Example:
Remark: To know which are the implicit arguments of an object, use command
Print Implicit (see 2.7.8).
Remark: If the list of arguments is empty, the command removes the
implicit arguments of qualid.
Coq can also automatically detect what are the implicit arguments of a defined object. The command is just
Implicit Arguments qualid.
The auto-detection is governed by options telling if strict and contextual implicit arguments must be considered or not (see Sections 2.7.5 and 2.7.6).
Example:
The computation of implicit arguments takes account of the unfolding of constants. For instance, the variable p below has type (Transitivity R) which is reducible to forall x,y:U, R x y -> forall z:U, R y z -> R x z. As the variables x, y and z appear strictly in body of the type, they are implicit.
In case one wants to systematically declare implicit the arguments detectable as such, one may switch to the automatic declaration of implicit arguments mode by using the command
Set Implicit Arguments.
Conversely, one may unset the mode by using Unset Implicit Arguments. The mode is off by default. Auto-detection of implicit arguments is governed by options controlling whether strict and contextual implicit arguments have to be considered or not.
By default, Coq automatically set implicit only the strict implicit arguments. To relax this constraint, use command
Unset Strict Implicit.
Conversely, use command Set Strict Implicit to restore the strict implicit mode.
Remark: In versions of Coq prior to version 8.0, the default was to
declare the strict implicit arguments as implicit.
By default, Coq does not automatically set implicit the contextual implicit arguments. To tell Coq to infer also contextual implicit argument, use command
Set Contextual Implicit.
Conversely, use command Unset Contextual Implicit to unset the contextual implicit mode.
In presence of non strict or contextual argument, or in presence of partial applications, the synthesis of implicit arguments may fail, so one may have to give explicitly certain implicit arguments of an application. The syntax for this is (ident:=term) where ident is the name of the implicit argument and term is its corresponding explicit term. Alternatively, one can locally deactivate the hiding of implicit arguments of a function by using the notation @qualid term1..termn. This syntax extension is given Figure 2.4.
term ++= @ qualid term … term | @ qualid | qualid argument … argument argument ::= term | (ident:=term)
Figure 2.4: Syntax for explicitly giving implicit arguments
Example (continued):
To display the implicit arguments associated to an object use command
Print Implicit qualid.
By default the basic pretty-printing rules hide the inferable implicit arguments of an application. To force printing all implicit arguments, use command
Set Printing Implicit.
Conversely, to restore the hiding of implicit arguments, use command
Unset Printing Implicit.
See also: Set Printing All in Section 2.9.
When an implicit argument can be inferred from the type of more than one of the other arguments, then only the type of the first of these arguments is taken into account, and not an upper type of all of them. As a consequence, the inference of the implicit argument of “=” fails in
but succeeds in
A canonical structure is an instance of a record/structure type that can be used to solve equations involving implicit arguments. Assume that qualid denotes an object (Build_struc c1 … cn) in the structure struct of which the fields are x1, ..., xn. Assume that qualid is declared as a canonical structure using the command
Canonical Structure qualid.
Then, each time an equation of the form (xi _)=βδιζci has to be solved during the type-checking process, qualid is used as a solution. Otherwise said, qualid is canonically used to extend the field ci into a complete structure built on ci.
Canonical structures are particularly useful when mixed with coercions and strict implicit arguments. Here is an example.
Thanks to nat_setoid declared as canonical, the implicit arguments A and B can be synthesized in the next statement.
Remark: If a same field occurs in several canonical structure, then
only the structure declared first as canonical is considered.
Variants:
These are equivalent to a regular definition of ident followed by the declaration
Canonical Structure ident.
See also: more examples in user contribution category
(Rocq/ALGEBRA).
This displays the list of global names that are components of some canonical structure. For each of them, the canonical structure of which it is a projection is indicated. For instance, the above example gives the following output:
It is possible to bind variable names to a given type (e.g. in a development using arithmetic, it may be convenient to bind the names n or m to the type nat of natural numbers). The command for that is
Implicit Types ident … ident : type
The effect of the command is to automatically set the type of bound variables starting with ident (either ident itself or ident followed by one or more single quotes, underscore or digits) to be type (unless the bound variable is already declared with an explicit type in which case, this latter type is considered).
Example:
Variants:
Coercions can be used to implicitly inject terms from one class in which they reside into another one. A class is either a sort (denoted by the keyword Sortclass), a product type (denoted by the keyword Funclass), or a type constructor (denoted by its name), e.g. an inductive type or any constant with a type of the form forall (x1:A1) .. (xn:An), s where s is a sort.
Then the user is able to apply an object that is not a function, but can be coerced to a function, and more generally to consider that a term of type A is of type B provided that there is a declared coercion between A and B. The main command is
Coercion qualid : class1 >-> class2.
which declares the construction denoted by qualid as a coercion between class1 and class2.
More details and examples, and a description of the commands related to coercions are provided in Chapter 16.
Coercions, implicit arguments, the type of pattern-matching, but also notations (see Chapter 11) can obfuscate the behavior of some tactics (typically the tactics applying to occurrences of subterms are sensitive to the implicit arguments). The command
Set Printing All.
deactivates all high-level printing features such as coercions, implicit arguments, returned type of pattern-matching, notations and various syntactic sugar for pattern-matching or record projections. Otherwise said, Set Printing All includes the effects of the commands Set Printing Implicit, Set Printing Coercions, Set Printing Synth, Unset Printing Projections and Unset Printing Notations. To reactivate the high-level printing features, use the command
Unset Printing All.
The following command:
Set Printing Universes
activates the display of the actual level of each occurrence of Type. See Section 4.1.1 for details. This wizard option, in combination with Set Printing All (see section 2.9) can help to diagnose failures to unify terms apparently identical but internally different in the Calculus of Inductive Constructions. To reactivate the display of the actual level of the occurrences of Type, use
Unset Printing Universes.
The constraints on the internal level of the occurrences of Type (see Section 4.1.1) can be printed using the command
Print Universes.