src/HOL/Tools/Quickcheck/quickcheck_common.ML
changeset 41927 8759e9d043f9
child 41935 d786a8a3dc47
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/Quickcheck/quickcheck_common.ML	Fri Mar 11 15:21:13 2011 +0100
@@ -0,0 +1,54 @@
+(*  Title:      HOL/Tools/Quickcheck/quickcheck_common.ML
+    Author:     Florian Haftmann, Lukas Bulwahn, TU Muenchen
+
+Common functions for quickcheck's generators
+
+*)
+
+signature QUICKCHECK_COMMON =
+sig
+  val perhaps_constrain: theory -> (typ * sort) list -> (string * sort) list
+    -> (string * sort -> string * sort) option
+  val ensure_sort_datatype:
+    sort * (Datatype.config -> Datatype.descr -> (string * sort) list -> string list -> string ->
+      string list * string list -> typ list * typ list -> theory -> theory)
+    -> Datatype.config -> string list -> theory -> theory
+end;
+
+structure Quickcheck_Common : QUICKCHECK_COMMON =
+struct
+
+fun perhaps_constrain thy insts raw_vs =
+  let
+    fun meet (T, sort) = Sorts.meet_sort (Sign.classes_of thy) 
+      (Logic.varifyT_global T, sort);
+    val vtab = Vartab.empty
+      |> fold (fn (v, sort) => Vartab.update ((v, 0), sort)) raw_vs
+      |> fold meet insts;
+  in SOME (fn (v, _) => (v, (the o Vartab.lookup vtab) (v, 0)))
+  end handle Sorts.CLASS_ERROR _ => NONE;
+
+fun ensure_sort_datatype (sort, instantiate_datatype) config raw_tycos thy =
+  let
+    val algebra = Sign.classes_of thy;
+    val (descr, raw_vs, tycos, prfx, (names, auxnames), raw_TUs) =
+      Datatype.the_descr thy raw_tycos;
+    val typerep_vs = (map o apsnd)
+      (curry (Sorts.inter_sort algebra) @{sort typerep}) raw_vs;
+    val sort_insts = (map (rpair sort) o flat o maps snd o maps snd)
+      (Datatype_Aux.interpret_construction descr typerep_vs
+        { atyp = single, dtyp = (K o K o K) [] });
+    val term_of_insts = (map (rpair @{sort term_of}) o flat o maps snd o maps snd)
+      (Datatype_Aux.interpret_construction descr typerep_vs
+        { atyp = K [], dtyp = K o K });
+    val has_inst = exists (fn tyco =>
+      can (Sorts.mg_domain algebra tyco) sort) tycos;
+  in if has_inst then thy
+    else case perhaps_constrain thy (sort_insts @ term_of_insts) typerep_vs
+     of SOME constrain => instantiate_datatype config descr
+          (map constrain typerep_vs) tycos prfx (names, auxnames)
+            ((pairself o map o map_atyps) (fn TFree v => TFree (constrain v)) raw_TUs) thy
+      | NONE => thy
+  end;
+
+end;