(* ========================================================================= *)
(* Abstract type of HOL types and functions for manipulating them. *)
(* *)
(* John Harrison, University of Cambridge Computer Laboratory *)
(* *)
(* (c) Copyright, University of Cambridge 1998 *)
(* (c) Copyright, John Harrison 1998-2007 *)
(* ========================================================================= *)
module type Hol_type_primitives =
sig type hol_type = private
Tyvar of string
| Tyapp of string * hol_type list
val types: unit -> (string*int)list
val get_type_arity : string -> int
val new_type : (string * int) -> unit
val mk_type: (string * hol_type list) -> hol_type
val mk_vartype : string -> hol_type
val dest_type : hol_type -> (string * hol_type list)
val dest_vartype : hol_type -> string
val is_type : hol_type -> bool
val is_vartype : hol_type -> bool
val tyvars : hol_type -> hol_type list
val type_subst : (hol_type * hol_type)list -> hol_type -> hol_type
end;;
(* ------------------------------------------------------------------------- *)
(* This is the implementation of those primitives. *)
(* ------------------------------------------------------------------------- *)
module Type : Hol_type_primitives = struct
type hol_type = Tyvar of string
| Tyapp of string * hol_type list
(* ------------------------------------------------------------------------- *)
(* List of current type constants with their arities. *)
(* *)
(* Initially we just have the boolean type and the function space *)
(* constructor. Later on we add as primitive the type of individuals. *)
(* All other new types result from definitional extension. *)
(* ------------------------------------------------------------------------- *)
let the_type_constants = ref ["bool",0; "fun",2]
(* ------------------------------------------------------------------------- *)
(* Return all the defined types. *)
(* ------------------------------------------------------------------------- *)
let types() = !the_type_constants
(* ------------------------------------------------------------------------- *)
(* Lookup function for type constants. Returns arity if it succeeds. *)
(* ------------------------------------------------------------------------- *)
let get_type_arity s = assoc s (!the_type_constants)
(* ------------------------------------------------------------------------- *)
(* Declare a new type. *)
(* ------------------------------------------------------------------------- *)
let new_type(name,arity) =
if can get_type_arity name then
failwith ("new_type: type "^name^" has already been declared")
else the_type_constants := (name,arity)::(!the_type_constants)
(* ------------------------------------------------------------------------- *)
(* Basic type constructors. *)
(* ------------------------------------------------------------------------- *)
let mk_type(tyop,args) =
let arity = try get_type_arity tyop with Failure _ ->
failwith ("mk_type: type "^tyop^" has not been defined") in
if arity = length args then
Tyapp(tyop,args)
else failwith ("mk_type: wrong number of arguments to "^tyop)
let mk_vartype v = Tyvar(v)
(* ------------------------------------------------------------------------- *)
(* Basic type destructors. *)
(* ------------------------------------------------------------------------- *)
let dest_type =
function
(Tyapp (s,ty)) -> s,ty
| (Tyvar _) -> failwith "dest_type: type variable not a constructor"
let dest_vartype =
function
(Tyapp(_,_)) -> failwith "dest_vartype: type constructor not a variable"
| (Tyvar s) -> s
(* ------------------------------------------------------------------------- *)
(* Basic type discriminators. *)
(* ------------------------------------------------------------------------- *)
let is_type = can dest_type
let is_vartype = can dest_vartype
(* ------------------------------------------------------------------------- *)
(* Return the type variables in a type and in a list of types. *)
(* ------------------------------------------------------------------------- *)
let rec tyvars =
function
(Tyapp(_,args)) -> itlist (union o tyvars) args []
| (Tyvar v as tv) -> [tv]
(* ------------------------------------------------------------------------- *)
(* Substitute types for type variables. *)
(* *)
(* NB: non-variables in subst list are just ignored (a check would be *)
(* repeated many times), as are repetitions (first possibility is taken). *)
(* ------------------------------------------------------------------------- *)
let rec type_subst i ty =
match ty with
Tyapp(tycon,args) ->
let args' = qmap (type_subst i) args in
if args' == args then ty else Tyapp(tycon,args')
| _ -> rev_assocd ty i ty
end;;
(* ------------------------------------------------------------------------- *)
(* Display all the externally visible functions. *)
(* ------------------------------------------------------------------------- *)
include Type;;
(* ------------------------------------------------------------------------- *)
(* The following are common enough to deserve their own bindings. *)
(* ------------------------------------------------------------------------- *)
let bool_ty = mk_type("bool",[]);;
let mk_fun_ty ty1 ty2 = mk_type("fun",[ty1; ty2]);;
let aty = mk_vartype "A";;
let bty = mk_vartype "B";;