From tfm%computer-lab.cambridge.ac.uk@NSFnet-Relay.AC.UK  Sat May  5 09:58:32 1990
Received: by iris.ucdavis.edu (5.57/UCD.EECS.2.0)
        id AA26395; Sat, 5 May 90 09:58:32 PDT
Received: from ucdavis.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
        id AA13185; Sat, 5 May 90 10:03:34 PDT
Received: from NSFNET-RELAY.AC.UK by ucdavis.ucdavis.edu (5.61/UCD2.03)
        id AA02193; Sat, 5 May 90 09:48:50 -0700
Received: from sun.nsfnet-relay.ac.uk by vax.NSFnet-Relay.AC.UK
           via Janet with NIFTP  id aa07719; 5 May 90 13:47 BST
Received: from moorhen.cl.cam.ac.uk by gnnt.Cl.Cam.AC.UK id aa29990;
          5 May 90 13:56 BST
Received: by uk.ac.cam.cl.moorhen (4.0/SMI-3.0DEV3)
        id AA11713; Sat, 5 May 90 13:56:11 BST
Date: Sat, 5 May 90 13:56:11 BST
From: tfm%computer-lab.cambridge.ac.uk@NSFnet-Relay.AC.UK
Message-Id: <9005051256.AA11713@uk.ac.cam.cl.moorhen>
To: info-hol%clover.ucdavis.edu@NSFnet-Relay.AC.UK
Subject: RE: SPECing simple polymorphic types

RE: Jim Alves-Foss's recent query about polymorphic types.

The following reply may be helpful to other HOL users, so I have posted it
here.  Advanced HOL users can ignore this message.


The problem had to do with specialising theorems which contain polymorphic
types. The example considered was the theorem defining EL:

    EL |- (!l. EL 0 l = HD l) /\ (!l. EL (SUC n) l = EL n (TL l))

In this theorem, the universally-quantified variables "l" have logical type
(*)list.  Now, it is a feature of the inference rule SPEC that it can be used
to specialize a universally-quantified variable of type ty only to a value of
precisely the same type ty.  For example it was observed in the original
message that

    SPEC "L:(*)list" (CONJUNCT1 EL)

works but that

    SPEC "L:(num)list" (CONJUNCT1 EL)

doesn't.  This is because "L:(*)list" has the same polymorphic type as "l" in
the left-hand conjunct of EL, but "L:(num)list" doesn't.


To specialize a universially-quantified variable to a value which has an
instance of the variable's polymorphic type, one must first obtain an
appropriately type-instantiated version of the theorem being specialized.  The
inference rule for doing this is called "INST_TYPE". For example:

    let thm = INST_TYPE [":num",":*"] (CONJUNCT1 EL)

instantiates ":*" in the left-hand conjunct of EL to ":num", and binds the ML
variable thm to the theorem:

    |- !l:(num)list. EL 0 l = HD l

Then specializing "l" to "L:(num)list" works.  That is:

    SPEC "L:(num)list" thm

yields the result:

    |- EL 0 L = HD L

as required.  It should be noted that using INST_TYPE at top-level and then
SPEC is not the only way of getting this result---see also INST_TY_TERM, INST
and related rules.


It could be argued that SPEC should do type-instantiation if necessary. But
this is probably undesirable, since the user won't ALWAYS want automatic type
instantiation to be done, and another inference rule would therefore be needed
to do the specialized job now done by SPEC.  Anyway, a specialization rule
which also does type-instantiation is trivial to program in ML:

    let ISPEC var thm =
        (let _,i = match (fst(dest_forall (concl thm))) var in
         SPEC var (INST_TYPE i thm)) ? failwith `ISPEC`;;

Adding user-defined rules of this kind to your (personal) HOL environment can
go a long way to making the system more suited to your own particular approach
to theorem-proving.


A final word about proof style.  For most kinds of day-to-day work in HOL, it
is relatively rare to have to make explicit calls to INST_TYPE (this does not
apply to tool-building).   Both the rewriting and resolution tools are
designed to take care of type-instantiation for you.  If you find that you are
frequently having to concern yourself with the low-level details of type
instantiation, you may be using an unfortunate approach to proofs in general.

Tom

