new_recursive_definition : {name:string, def:term, rec_axiom:thm} -> thm
A theorem th of the form returned by define_type is a primitive recursion theorem for an automatically-defined concrete type ty. Let C1, ..., Cn be the constructors of this type, and let ‘(Ci vs)’ represent a (curried) application of the ith constructor to a sequence of variables. Then a curried primitive recursive function fn over ty can be specified by a conjunction of (optionally universally-quantified) clauses of the form:
fn v1 ... (C1 vs1) ... vm = body1 /\ fn v1 ... (C2 vs2) ... vm = body2 /\ . . fn v1 ... (Cn vsn) ... vm = bodyn
fn t1 ... v ... tm
If tm is a conjunction of clauses, as described above, then evaluating:
new_recursive_definition{name=name, rec_axiom=th, def=tm}
new_recursive_definition also allows the supplied definition to omit clauses for any number of constructors. If a defining equation for the ith constructor is omitted, then the value of fn at that constructor:
fn v1 ... (Ci vsi) ... vn
|- !f0 f1. ?! fn. (!x. fn(LEAF x) = f0 x) /\ (!b1 b2. fn(NODE b1 b2) = f1(fn b1)(fn b2)b1 b2)
- val Leaves = new_recursive_definition {name = "Leaves", rec_axiom = th, def= “(Leaves (LEAF (x:'a)) = 1) /\ (Leaves (NODE t1 t2) = (Leaves t1) + (Leaves t2))”}; > val Leaves = |- (!x. Leaves (LEAF x) = 1) /\ !t1 t2. Leaves (NODE t1 t2) = Leaves t1 + Leaves t2 : thm
The function defined using new_recursive_definition need not, in fact, be recursive. Here is the definition of a predicate IsLeaf, which is true of binary trees which are leaves, but is false of the internal nodes in a binary tree:
- val IsLeaf = new_recursive_definition {name = "IsLeaf", rec_axiom = th, def = “(IsLeaf (NODE t1 t2) = F) /\ (IsLeaf (LEAF (x:'a)) = T)”}; > val IsLeaf = |- (!t1 t2. IsLeaf (NODE t1 t2) = F) /\ !x. IsLeaf (LEAF x) = T : thm
new_recursive_definition also allows the user to partially specify the value of a function defined on a concrete type, by allowing defining equations for some of the constructors to be omitted. Here, for example, is the definition of a function Label which extracts the label from a leaf node. The value of Label applied to an internal node is left unspecified:
- val Label = new_recursive_definition {name = "Label", rec_axiom = th, def = “Label (LEAF (x:'a)) = x”}; > val Label = |- !x. Label (LEAF x) = x : thm
- val _ = set_fixity ("<<", Infixl 231); - val Subtree = new_recursive_definition {name = "Subtree", rec_axiom = th, def = “($<< (t:'a bintree) (LEAF (x:'a)) = F) /\ ($<< t (NODE t1 t2) = (t = t1) \/ (t = t2) \/ ($<< t t1) \/ ($<< t t2))”}; > val Subtree = |- (!t x. t << LEAF x = F) /\ !t t1 t2. t << NODE t1 t2 = (t = t1) \/ (t = t2) \/ (t << t1) \/ (t << t2) : thm