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:
  1. 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:
    1. The name identi already exists in the environment (see section 1.3.1).
    2. The body of identi uses a incorrect elimination for ident (see sections 1.3.4 and 4.5.4).
    3. 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:
  1. A record cannot be recursive
    The record name ident appears in the type of its fields.

  2. 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.