2.1 Record types
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 [[ params ]] : sort
:= [ident] {
[field ; ... ; field]
} . |
|
|
|
field |
::= |
ident : type |
|
| |
ident := term |
|
| |
ident : type := 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:
Coq < Record Rat : Set := mkRat {
Coq < sign : bool;
Coq < top : nat;
Coq < bottom : nat;
Coq < Rat_bottom_cond : ~O=bottom;
Coq < Rat_irred_cond:(x,y,z:nat)(mult x y)=top/\(mult x z)=bottom->x=(S O)}.
Rat is defined
Rat_rect is defined
Rat_ind is defined
Rat_rec is defined
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 a inductive definition
with just one constructor:
Inductive ident [ params ] : sort :=
ident0 : (ident1:term1) ..
(identn:termn)(ident params).
To build an object of type ident, one should provide the
constructor ident0 with n terms filling the fields of
the record.
Let us define the rational 1/2.
Coq < Require Arith.
Coq < Theorem one_two_irred: (x,y,z:nat)(mult x y)=(1)/\(mult x z)=(2)->x=(1).
...
Coq < Qed.
Coq < Definition half := (mkRat true (1) (2) (O_S (1)) one_two_irred).
half is defined
Coq < Check half.
half
: Rat
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
this (anonymous) field. In our example:
Coq < Eval Compute in (top half).
= (1)
: nat
Coq < Eval Compute in (bottom half).
= (2)
: nat
Coq < Eval Compute in (Rat_bottom_cond half).
= (O_S (1))
: ~(0)=(bottom half)
Warnings:
-
Warning: identi cannot be defined.
It can happens that the definition of a projection is impossible.
This message is followed by an explanation of this impossibility.
There may be three reasons:
-
The name identi already exists in the environment (see
section 1.3.1).
- The body of identi uses a incorrect elimination for
ident (see sections 1.3.4 and 4.5.4).
- The projections [ idents ] were not defined.
The body of termi uses the projections idents
which are not defined for one of these three reasons listed here.
Error messages:
-
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
1.3.3, may also occur.
See also: Coercions and records in section 14.9
of the chapter devoted to coercions.