*** HOL2P System *** This is an experimental implementation of the logic HOL2P [1] as an extension and modification of John Harrison's HOL-LIGHT (2.20) theorem prover [2]. From the user point of view, the HOL2P system is essentially a variation of HOL-LIGHT with additional type and term constructs as well as accompanying syntax, rules and tactics. *** Warnings The HOL2P system is made available with the aim of furthering research into higher order theorem proving. The system is currently of beta-version quality - it has not yet been widely tested and it might still contain significant bugs. Prospective users need to have a sound working knowledge of HOL-LIGHT, and this is assumed in the instructions below. *** Installation This implementation of HOL2P depends on OCAML 3.09 (tried with 3.09.3). Installation should consist simply of unpacking the zip-file, changing to the distribution directory and starting ocaml. Then type #use "hol2p.ml";; for running HOL2P. This will load the HOL2P logical core, as well as a minimal set of HOL-LIGHT developments about booleans, classical reasoning, inductive types, pairs, integers, and lists. Please modify file Hol_light_lib/basic_lib.ml if you want to load further HOL-LIGHT material. *** Examples Please see the Example directory type_quantification.ml (* simple type quantifier examples *) functor.ml (* Functors and natural transformations *) aop.ml (* "Algebra of Programming" [3] examples" *) In order to run all included examples, load hol2p into OCaml, and type: #use "hol2p_examples.ml";; *** HOL2P Syntax: Types and Terms The syntax of HOL2P types and terms is that of HOL-LIGHT with some extensions and restrictions. Universal types: (% 'A. T) e.g. (% 'A. 'A list) for (/\ 'A. 'A list) Type abstraction terms: (\\ 'A. t) e.g. (\\ 'A. (ID : 'A -> 'A)) for (/\ 'A. (ID : 'A -> 'A)) Type application terms: (t:T1)[:T2] e.g. (f : (% 'A. 'A))[:num] for (f:(/\ 'A. 'A)) [num]) The indication of the type of the argument term t in a type application term can be omitted if t is a constant, or if it is a variable whose type has already been inferred by parsing of preceding occurrences. In this case, the type application syntax becomes simply t[:T] In HOL2P, there is a smallness restriction on the bound type variables in universal types and type abstraction terms, as well as the type arguments of type application terms. Small type variables are distinguished by a leading apostrophe, such as 'A. Type variables that do not start with a leading apostrophe are taken to be unrestricted, they are therefore not permissible in those places where a small type is mandatory. Type operator variables are distinguished by a leading underscore character such as _T. Other type variables are not allowed to start with that character. Like normal type variable, type operator variables can be auto-generated by the system during parsing. Such variables are numbered and have the form "_?n", for example "_?12345". Theorems should normally not contain auto-generated system type operator variables. The reason is explained below in the section about explicit instantiation of theorems containing type operator variables. Type inference in HOL2P is incomplete, and users sometimes need to add explicit type (operator) variable instantations or type annotations. *** Type quantification Type quantification notation is implemented as syntactic sugar that is only relevant for parsing and printing. Within the system, HOL2P terms as described above are used. The translations are: (!! A. t) <=> ((\\ 'A. t) = (\\ 'A. T)) (?? A. t) <=> (~((\\ 'A. t) = (\\ 'A. F))) *** Explicit Type (Operator) Instantiation for Parsing When entering terms that involve (possibly implicit) type operator variables, it is often neccessary to add explicit type (operator) variable instantations or type annotations. This is so because the automatic type inference and term instantiation will match a type operator variable only with a type constructor or another type operator variable. To make this clearer, consider constant FUNCTOR (see file example/functor.ml): FUNCTOR: (% 'A 'B. ('A -> 'B) -> 'A _T -> 'B _T) -> bool and the following three inputs: (I1) FUNCTOR (\\ 'A 'B. (ID: ('A -> 'B) -> 'A -> 'B)) (I2) FUNCTOR (\\ 'A 'B. (MAP: ('A -> 'B) -> 'A list -> 'B list)) (I3) FUNCTOR (\\ 'A 'B. ((\f.MAP(MAP f)) :('A -> 'B) -> ('A list)list -> ('B list)list)) In the HOL2P system, only input (I2) will be parsed successfully to a term, and that term will include an instance of FUNCTOR where the type operator variable _T is replaced by the type constructor "list". Parsing (I1) and (I3) will lead to a unification failure. In order to overcome the problem with inputs (I1) and (I3), it is necessary to inform the parser of the required replacement of _T in the instantiation of FUNCTOR. For this purpose, an auxiliary construct TYINST was introduced into the HOL2P system. It associates type (operator) variables in constants with types resp. type operators. In the example, we have: (I1') TYINST (_T: (% 'A. 'A)) FUNCTOR (\\ 'A 'B. ID) (I3') TYINST (_T: (% 'A. ('A list) list)) FUNCTOR (\\ 'A 'B. \f.MAP(MAP f)) Please note that similar to normal HOL type annotations, TYINST is purely an auxiliary device that guides type inference. It is not contained in the term obtained from the parsing, and is also not visible when terms are printed. The TYINST directive always applies to a single argument which must be a constant containing the type (operator) variable in question. Please see file functor.ml for more examples, including cases of constants that require the instantiation of more than one type operator variable. *** Explicit Instantiation of Theorems containing Type Operator Variables When instantiating a theorem containing a type operator variable, the HOL2P system has the same limitation as in the case of parsing, e.g. the system will automatically only find those instantiations where a type operator variable _T is replaced by a type constructor such as "list" or another type operator variable. In cases where this is insufficient, the HOL_LIGHT function INST_TYPE can be used to explicitly instantiate both type operator variables as well as normal type variables. For example, in the proofs that ID resp (MAP (MAP F)) are functors, the following explicit instantiations are necessary: ... SIMP_TAC[INST_TYPE [`: % 'A. 'A`,`:_T`] FUNCTOR] ... ... SIMP_TAC[INST_TYPE [`: % 'A. ('A list)list`, `:_T`] FUNCTOR] ... *** Avoiding Auto-generated Type Operator Variables in Theorems It is usually a bad idea to let the system automatically invent type operator variables in a theorem, and the user will be warned when such a goal if formulated. The problem is caused by the fact that automatically generated system type operator variables such as "_?12345" can not be explicitly instantiated by the user, and hence the INST_TYPE function can not be used to create custom instances of such a theorem. Instead, when formulating a goal, users should explicitly give a name (such as _T) to all occurring type operator variables, either by adding suitable type annotations or by TYINST directives, see files functor.ml and aop.ml for examples. *** Implicit Type Applications in Terms HOL2P terms often contain type applications that appear redundant, just as they do in System F. In order to improve the readability of theorems, and to shorten the input, the HOL2P system allows to omit certain type applications. When the parser encounters a universally typed constant c that occurs in a context that does not have universal type, type applications will be added to c until it is no longer of universal type. As an example, here is the homomorphism composition theorem from file aop.ml first stated with explicit type applications: (? f2. HOMO (phi: % 'A 'B. ('A -> 'B) -> 'A _T -> 'B _T) [:'A] [:'B]) f1 f2 h1 /\ HOMO (phi [:'B] [:'C] f2 f3 h2) /\ FUNCTOR phi ==> HOMO (phi[:'A][:'C]) f1 f3 (h2 o h1) and here is the goal statement when type applications are omitted: (? f2. HOMO (phi: % 'A 'B. ('A -> 'B) -> 'A _T -> 'B _T) f1 f2 h1 /\ HOMO phi f2 f3 h2) /\ FUNCTOR phi ==> HOMO phi f1 f3 (h2 o h1) The implicit addition of type applications also works for variables provided the parser has already inferred that they belong to a universal type. Users might prefer to input all type applications in terms themselves. This can be enforced with the setting: add_tyapps_automatically := false;; This flag only effects the parsing of terms. Terms are always shown with full type applications in output. *** Rules and Tactics The normal HOL-LIGHT rules and tactics also apply in HOL2P. Some HOL2P specific tactics are described in hol2p_tactics.ml. HOL2P theorems and proofs can be found in the example files. *** Hints and Caveats When entering terms including universally quantified types such as (f: %'A.'A), do not omit the blank before the "%" sign as the character sequence ":%" will be parsed as a single token. When explicitly instantiating a type operator variable using TYINST or INST_TYPE, the replacement has to be written using the universal type syntax such as `: % 'A. 'A list`, see the examples above. The type of a constant can be identified with the HOL-LIGHT function get_generic_type. *** Credits The HOL2P system is essentially an extension and modification of the HOL-LIGHT theorem prover. HOL-LIGHT was written by John Harrison, and he deserves the credit for all the HOL-LIGHT code included or modified in HOL2P. Of course, any errors made during the construction of HOL2P are the sole responsibility of the HOL2P author. Please see the accompanying HOL2P and HOL-LIGHT LICENSE files for copyright declarations and conditions of use. *** Finally Please contact me if you have comments or questions about HOL2P. Norbert Voelker (norbert@essex.ac.uk) ****************** [1] Norbert Voelker. HOL2P - A System of Classical Higher Order Logic with Second Order Polymorphism, Proceedings of TPHOLs'07, Kaiserslautern, Germany, LNCS 4732, 2007. [2] John Harrison: The HOL Light theorem prover. See http://www.cl.cam.ac.uk/users/jrh13/hol-light/index.html. [3] Richard Bird and Oege de Moor: Algebra of Programming, Prentice Hall, 1996.