A proof of a theorem in the Nuprl system implicitly provides directions for constructing a witness for the truth of the theorem. These directions arise from the fact that every Nuprl rule has associated with it an extraction form, a term template which yields a term when various parameters to the form are instantiated with terms. These forms may give rise either to canonical or noncanonical terms depending on the nature of the rule corresponding to the form. Figure 5.1 lists the noncanonical forms, while the canonical forms and the extraction form corresponding to each proof rule are listed in chapter 8.
A proof gives rise to a term in that each rule used in the proof
produces an extract form whose parameters are instantiated
with the terms
inductively extracted from the subgoals generated by the rule invocation.
For example, if we wish to prove a theorem of the form A|B using the
intro rule for disjoint union we must prove either A or B as
a subgoal.
Assuming we prove B and assuming b is the term inductively extracted
from the proof of B then inr(b) becomes the term extracted
from the proof of A|B, for inr() is the extraction form
for the right intro rule for disjoint unions.
Note that if b is in type B then inr(b) is in A|B, so the
extraction makes sense.
Similarly, if we prove something of the form
x:A|B >> T
using the elim rule for disjoint union on the hypothesis,
then Nuprl
generates two subgoals.
The first requires us to show that if A is true (i.e.,
appears in
the hypothesis list)
then T is true.
The second requires us to show that if B is true (i.e.,
appears in
the hypothesis list)
then T is true.
If
is the term extracted from the the first subgoal
(
is a term with y a free variable whose type is A;
recall that y represents our assumption of the truth of A in the
first subgoal)
and
is the term extracted from the second subgoal,
then
decide(
)
is the term extracted from the proof of
x:A|B >> T.
Note that if x corresponds to inl(a) for some a in A
then from the computation rules the extracted term is equivalent to
; since
proves T under the assumption of A
and A holds (since a is in A) the extracted term works as
desired.
Similarly, the term behaves properly if x has value inr(b)
for some b in B; thus this extraction form is justified.
One should note that certain standard
programming
constructs have
analogs as Nuprl
terms.
In particular, recursive definition corresponds to the ind()
form, which is extracted from proofs which use induction via the elim
rule on integers.
decide(
) represents a kind of if--then--else
construct,
while the functional terms extracted from proofs using functional intro
correspond to function constructs in a standard programming language.
To display the term corresponding to a theorem t one evaluates a special Nuprl term, term_of(t) , which constructs the extracted term of t in a recursive fashion. Briefly, the extraction form of the top refinement rule becomes the outermost form of the term being constructed. The parameters of the form then become the terms constructed from the subgoals generated by the refinement rule.
Many Nuprl
rules require the user to prove that a type is
well--formed ,
i.e., that the type resides in some universe .
These subgoals, when proved, yield the extraction term
axiom
and are usually ignored by term_of as it builds the term for
a theorem.
We should note here that one can manipulate canonical and noncanonical terms explicitly in the system. For example, the following definition defines an absolute value function.
abs(<x:int>) == less (<x>; 0; -<x>; <x>)We may now use abs as a definition in the statement and proof of theorems. This capability adds a great deal of flexibility to the system.