Hol_datatype : type quotation -> unit
spec ::= [ <binding> ; ]* <binding>
binding ::= <ident> = [ <clause> | ]* <clause>
| <ident> = <| [ <ident> : <type> ; ]* <ident> : <type> |>
clause ::= <ident>
| <ident> of [<type> => ]* <type>
The notation used to declare datatypes is, unfortunately, not the same as that of ML. For example, an ML declaration
datatype ('a,'b) btree = Leaf of 'a
| Node of ('a,'b) btree * 'b * ('a,'b) btree
Hol_datatype `btree = Leaf of 'a
| Node of btree => 'b => btree`
When a record type is defined, the parser is adjusted to allow new syntax (appropriate for records), and a number of useful simplification theorems are also proved. The most useful of the latter are automatically stored in the TypeBase and can be inspected using the simpls_of function. For further details on record types, see the DESCRIPTION.
To start, enumerated types can be defined as in the following example:
Hol_datatype `enum = A1 | A2 | A3 | A4 | A5
| A6 | A7 | A8 | A9 | A10
| A11 | A12 | A13 | A14 | A15
| A16 | A17 | A18 | A19 | A20
| A21 | A22 | A23 | A24 | A25
| A26 | A27 | A28 | A29 | A30`
Hol_datatype `foo = N of num
| B of bool
| Fn of 'a -> 'b
| Pr of 'a # 'b`
- Hol_datatype `tree = Leaf of num
| Node of tree => tree`
Hol_datatype `tree = Leaf of 'a
| Node of tree # 'b # tree`
The basic syntax of the named lambda calculus is easy to describe:
- load "stringTheory";
> val it = () : unit
- Hol_datatype `lambda = Var of string
| Const of 'a
| Comb of lambda => lambda
| Abs of lambda => lambda`
Hol_datatype `dB = Var of string
| Const of 'a
| Bound of num
| Comb of dB => dB
| Abs of dB`
Hol_datatype `ntree = Node of 'a => ntree list`
Hol_datatype `term = Var of string
| Fnapp of string # term list`
Hol_datatype
`atexp = var_exp of string
| let_exp of dec => exp ;
exp = aexp of atexp
| app_exp of exp => atexp
| fn_exp of match ;
match = match of rule
| matchl of rule => match ;
rule = rule of pat => exp ;
dec = val_dec of valbind
| local_dec of dec => dec
| seq_dec of dec => dec ;
valbind = bind of pat => exp
| bindl of pat => exp => valbind
| rec_bind of valbind ;
pat = wild_pat
| var_pat of string`
Hol_datatype `state = <| Reg1 : num; Reg2 : num; Waiting : bool |>`
Hol_datatype
`file = Text of string
| Dir of directory
;
directory = <| owner : string ;
files : (string # file) list |>`
First, an empty type is not allowed in HOL, so the following attempt is doomed to fail.
Hol_datatype `foo = A of foo`
Hol_datatype `btree = Leaf of 'a
| Node of ('a # 'a) btree`
Hol_datatype `lazylist = Nil
| Cons of 'a # (one -> lazylist)`
Finally, for cardinality reasons, HOL does not allow the following attempt to model the untyped lambda calculus as a set (note the -> in the clause for the Abs constructor):
Hol_datatype `lambda = Var of string
| Const of 'a
| Comb of lambda => lambda
| Abs of lambda -> lambda`
For example, invoking
Hol_datatype `tree = Leaf of num
| Node of tree => tree`;
tree_case_def =
|- (!f f1 a. case f f1 (Leaf a) = f a) /\
!f f1 a0 a1. case f f1 (Node a0 a1) = f1 a0 a1
tree_size_def
|- (!a. tree_size (Leaf a) = 1 + a) /\
!a0 a1. tree_size (Node a0 a1) = 1 + (tree_size a0 + tree_size a1)
tree_Axiom
|- !f0 f1.
?fn. (!a. fn (Leaf a) = f0 a) /\
!a0 a1. fn (Node a0 a1) = f1 a0 a1 (fn a0) (fn a1)
tree_induction
|- !P. (!n. P (Leaf n)) /\
(!t t0. P t /\ P t0 ==> P (Node t t0))
==>
!t. P t
tree_nchotomy |- !t. (?n. t = Leaf n) \/ ?t' t0. t = Node t' t0
tree_11
|- (!a a'. (Leaf a = Leaf a') = (a = a')) /\
!a0 a1 a0' a1'. (Node a0 a1 = Node a0' a1') = (a0=a0') /\ (a1=a1')
tree_distinct |- !a1 a0 a. ~(Leaf a = Node a0 a1)
tree_case_cong
|- !M M' f f1.
(M = M') /\
(!a. (M' = Leaf a) ==> (f a = f' a)) /\
(!a0 a1. (M' = Node a0 a1) ==> (f1 a0 a1 = f1' a0 a1))
==>
(case f f1 M = case f' f1' M')
A definition of mutually recursives types results in the above theorems and definitions being added for each of the defined types.