Theories are defined in MetaPRL as modules. Logical modules can be expressed as extensions of previous modules, forming an object-oriented logical construction, and theories can be related using the module system.
Each logical module defines syntax, display, computational rewriting, and inference rules, defined in the previous pages. Theories are extended and related with the extends directive, discussed here. The extends directive is the logical equivalent of the open directive in OCaml. The extends directive "opens" the logical namespace, and it establishes a logical dependence between modules. The general form form of the include directive is as follows:
extends module-path
Multiple extends directives may appear in interfaces and implementations, establishing multiple dependencies that establish a logical inheritance graph. For example, the following module uses the basic logical definitions, and reasoning about numbers to express a well-known problem in number theory:
extends Itt_logic
extends Itt_int
interactive fermat 'H : :
sequent ['ext] { 'H >-
all i: nat. (i >= 3) =>
not (exst a: nat. exst b: nat. exst c: nat.
power{a; i} + power{b; i} = power{c; i} in nat)
The included modules Itt_logic and Itt_int provide the logical context. Itt_logic provides logical definitions for all and exst, implication, and the Itt_int modules provides reasoning about numbers. These modules have extends directives of their own. The Itt_logic module contains the following logical dependencies:
extends Itt_equal extends Itt_rfun extends Itt_dfun extends Itt_fun extends Itt_dprod extends Itt_prod extends Itt_union extends Itt_void extends Itt_unit extends Itt_struct
Each of the modules used in Itt_logic are recursively included in the Fermat theory. In general, an extends recursively opens all ancestors of the module included.
The extends directive performs the following operations for each included module:
The extends does not open the ML namespace. That operation must be performed separately for ML content, including tactics and conversions.
Modules may define operators with the same name. For example, two theories (say A and B) may both declare a conjunction
declare "and"{'a; 'b}
and they may impose different logical interpretations of the "and" term. The general rule for solving conflicts is the following:
A theory that relates the theories A and B must refer to both terms. Qualified names are expressed by module paths composed with the ! symbol. Here is an example, showing an interpretation of A.and as the "conditional" form of B.and. (The "and" operator is quoted because it is an ML keyword.)
extends A
extends B
rewrite a_and_interp : (A!"and"{'a; 'b}) <--> (B!"and"{'a; B!implies{'a; 'b}})