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.