src/HOL/ex/Random.thy
author haftmann
Mon Feb 04 10:52:40 2008 +0100 (2008-02-04)
changeset 26038 55a02586776d
parent 24994 c385c4eabb3b
child 26042 e7a421d1f5c1
permissions -rw-r--r--
towards quickcheck
haftmann@22528
     1
(*  ID:         $Id$
haftmann@22528
     2
    Author:     Florian Haftmann, TU Muenchen
haftmann@22528
     3
*)
haftmann@22528
     4
haftmann@26038
     5
header {* A simple term generator *}
haftmann@22528
     6
haftmann@22528
     7
theory Random
haftmann@26038
     8
imports State_Monad Code_Index List Eval
haftmann@22528
     9
begin
haftmann@22528
    10
haftmann@26038
    11
subsection {* The random engine *}
haftmann@26038
    12
haftmann@26038
    13
types seed = "index \<times> index"
haftmann@22528
    14
haftmann@26038
    15
definition
haftmann@26038
    16
  "next" :: "seed \<Rightarrow> index \<times> seed"
haftmann@26038
    17
where
haftmann@26038
    18
  "next s = (let
haftmann@26038
    19
     (v, w) = s;
haftmann@26038
    20
     k = v div 53668;
haftmann@26038
    21
     v' = 40014 * (v - k * 53668) - k * 12211;
haftmann@26038
    22
     v'' = (if v' < 0 then v' + 2147483563 else v');
haftmann@26038
    23
     l = w div 52774;
haftmann@26038
    24
     w' = 40692 * (w - l * 52774) - l * 3791;
haftmann@26038
    25
     w'' = (if w' < 0 then w' + 2147483399 else w');
haftmann@26038
    26
     z = v'' - w'';
haftmann@26038
    27
     z' = (if z < 1 then z + 2147483562 else z)
haftmann@26038
    28
   in (z',  (v'', w'')))"
haftmann@22528
    29
haftmann@22528
    30
definition
haftmann@26038
    31
  split_seed :: "seed \<Rightarrow> seed \<times> seed"
haftmann@26038
    32
where
haftmann@26038
    33
  "split_seed s = (let
haftmann@26038
    34
     (v, w) = s;
haftmann@26038
    35
     (v', w') = snd (next s);
haftmann@26038
    36
     v'' = (if v = 2147483562 then 1 else v + 1);
haftmann@26038
    37
     s'' = (v'', w');
haftmann@26038
    38
     w'' = (if w = 2147483398 then 1 else w + 1);
haftmann@26038
    39
     s''' = (v', w'')
haftmann@26038
    40
   in (s'', s'''))"
haftmann@26038
    41
haftmann@26038
    42
text {* Base selectors *}
haftmann@26038
    43
haftmann@26038
    44
primrec
haftmann@26038
    45
  pick :: "(nat \<times> 'a) list \<Rightarrow> nat \<Rightarrow> 'a"
haftmann@26038
    46
where
haftmann@26038
    47
  "pick (x#xs) n = (if n < fst x then snd x else pick xs (n - fst x))"
haftmann@22528
    48
haftmann@26038
    49
function
haftmann@26038
    50
  iLogBase :: "index \<Rightarrow> index \<Rightarrow> index"
haftmann@26038
    51
where
haftmann@26038
    52
  "iLogBase b i = (if b \<le> 1 \<or> i < b then 1 else 1 + iLogBase b (i div b))"
haftmann@26038
    53
by pat_completeness auto
haftmann@26038
    54
termination
haftmann@26038
    55
  by (relation "measure (nat_of_index o snd)")
haftmann@26038
    56
    (auto simp add: index)
haftmann@22528
    57
haftmann@26038
    58
function
haftmann@26038
    59
  range_aux :: "index \<Rightarrow> index \<Rightarrow> seed \<Rightarrow> index \<times> seed"
haftmann@26038
    60
where
haftmann@26038
    61
  "range_aux k l s = (if k = 0 then (l, s) else
haftmann@26038
    62
    let (v, s') = next s
haftmann@26038
    63
  in range_aux (k - 1) (v + l * 2147483561) s')"
haftmann@26038
    64
by pat_completeness auto
haftmann@26038
    65
termination
haftmann@26038
    66
  by (relation "measure (nat_of_index o fst)")
haftmann@26038
    67
    (auto simp add: index)
haftmann@22528
    68
haftmann@22528
    69
definition
haftmann@26038
    70
  range :: "index \<Rightarrow> seed \<Rightarrow> index \<times> seed"
haftmann@26038
    71
where
haftmann@26038
    72
  "range k s = (let
haftmann@26038
    73
    b = 2147483561;
haftmann@26038
    74
    n = iLogBase b k;
haftmann@26038
    75
    (v, s') = range_aux n 1 s
haftmann@26038
    76
  in (v mod k, s'))"
haftmann@26038
    77
haftmann@22528
    78
definition
haftmann@26038
    79
  select :: "'a list \<Rightarrow> seed \<Rightarrow> 'a \<times> seed"
haftmann@26038
    80
where
haftmann@26038
    81
  [simp]: "select xs s = (let
haftmann@26038
    82
    (k, s') = range (index_of_nat (length xs)) s
haftmann@26038
    83
  in (nth xs (nat_of_index k), s'))"
haftmann@22528
    84
haftmann@26038
    85
definition
haftmann@26038
    86
  select_weight :: "(nat \<times> 'a) list \<Rightarrow> seed \<Rightarrow> 'a \<times> seed"
haftmann@26038
    87
where
haftmann@26038
    88
  [simp]: "select_weight xs s = (let
haftmann@26038
    89
    (k, s') = range (foldr (op + \<circ> index_of_nat \<circ> fst) xs 0) s
haftmann@26038
    90
  in (pick xs (nat_of_index k), s'))"
haftmann@26038
    91
haftmann@26038
    92
(*lemma
haftmann@22528
    93
  "select (x#xs) s = select_weight (map (Pair 1) (x#xs)) s"
haftmann@22528
    94
proof (induct xs)
haftmann@26038
    95
  case Nil show ?case apply (auto simp add: Let_def split_def) 
haftmann@22528
    96
next
haftmann@22528
    97
  have map_fst_Pair: "!!xs y. map fst (map (Pair y) xs) = replicate (length xs) y"
haftmann@22528
    98
  proof -
haftmann@22528
    99
    fix xs
haftmann@22528
   100
    fix y
haftmann@22528
   101
    show "map fst (map (Pair y) xs) = replicate (length xs) y"
haftmann@22528
   102
      by (induct xs) simp_all
haftmann@22528
   103
  qed
haftmann@22528
   104
  have pick_nth: "!!xs n. n < length xs \<Longrightarrow> pick (map (Pair 1) xs) n = nth xs n"
haftmann@22528
   105
  proof -
haftmann@22528
   106
    fix xs
haftmann@22528
   107
    fix n
haftmann@22528
   108
    assume "n < length xs"
haftmann@22528
   109
    then show "pick (map (Pair 1) xs) n = nth xs n"
haftmann@22528
   110
    proof (induct xs arbitrary: n)
haftmann@22528
   111
      case Nil then show ?case by simp
haftmann@22528
   112
    next
haftmann@22528
   113
      case (Cons x xs) show ?case
haftmann@22528
   114
      proof (cases n)
haftmann@22528
   115
        case 0 then show ?thesis by simp
haftmann@22528
   116
      next
haftmann@22528
   117
        case (Suc _)
haftmann@22528
   118
    from Cons have "n < length (x # xs)" by auto
haftmann@22528
   119
        then have "n < Suc (length xs)" by simp
haftmann@22528
   120
        with Suc have "n - 1 < Suc (length xs) - 1" by auto
haftmann@22528
   121
        with Cons have "pick (map (Pair (1\<Colon>nat)) xs) (n - 1) = xs ! (n - 1)" by auto
haftmann@22528
   122
        with Suc show ?thesis by auto
haftmann@22528
   123
      qed
haftmann@22528
   124
    qed
haftmann@22528
   125
  qed
haftmann@22528
   126
  have sum_length: "!!xs. foldl (op +) 0 (map fst (map (Pair 1) xs)) = length xs"
haftmann@22528
   127
  proof -
haftmann@22528
   128
    have replicate_append:
haftmann@22528
   129
      "!!x xs y. replicate (length (x # xs)) y = replicate (length xs) y @ [y]"
haftmann@22528
   130
      by (simp add: replicate_app_Cons_same)
haftmann@22528
   131
    fix xs
haftmann@22528
   132
    show "foldl (op +) 0 (map fst (map (Pair 1) xs)) = length xs"
haftmann@22528
   133
    unfolding map_fst_Pair proof (induct xs)
haftmann@22528
   134
      case Nil show ?case by simp
haftmann@22528
   135
    next
haftmann@22528
   136
      case (Cons x xs) then show ?case unfolding replicate_append by simp
haftmann@22528
   137
    qed
haftmann@22528
   138
  qed
haftmann@22528
   139
  have pick_nth_random:
haftmann@22528
   140
    "!!x xs s. pick (map (Pair 1) (x#xs)) (fst (random (length (x#xs)) s)) = nth (x#xs) (fst (random (length (x#xs)) s))"
haftmann@22528
   141
  proof -
haftmann@22528
   142
    fix s
haftmann@22528
   143
    fix x
haftmann@22528
   144
    fix xs
haftmann@22528
   145
    have bound: "fst (random (length (x#xs)) s) < length (x#xs)" by (rule random_bound) simp
haftmann@22528
   146
    from pick_nth [OF bound] show
haftmann@22528
   147
      "pick (map (Pair 1) (x#xs)) (fst (random (length (x#xs)) s)) = nth (x#xs) (fst (random (length (x#xs)) s))" .
haftmann@22528
   148
  qed
haftmann@22528
   149
  have pick_nth_random_do:
haftmann@22528
   150
    "!!x xs s. (do n \<leftarrow> random (length (x#xs)); return (pick (map (Pair 1) (x#xs)) n) done) s =
haftmann@22528
   151
      (do n \<leftarrow> random (length (x#xs)); return (nth (x#xs) n) done) s"
haftmann@22528
   152
  unfolding monad_collapse split_def unfolding pick_nth_random ..
haftmann@22528
   153
  case (Cons x xs) then show ?case
haftmann@22528
   154
    unfolding select_weight_def sum_length pick_nth_random_do
haftmann@22528
   155
    by simp
haftmann@26038
   156
qed*)
haftmann@22528
   157
haftmann@26038
   158
text {* The @{text ML} interface *}
haftmann@22528
   159
haftmann@22528
   160
ML {*
haftmann@26038
   161
structure Quickcheck =
haftmann@22528
   162
struct
haftmann@22528
   163
haftmann@26038
   164
type seed = int * int;
haftmann@22528
   165
haftmann@22528
   166
local
haftmann@26038
   167
haftmann@26038
   168
val seed = ref (0, 0);
haftmann@26038
   169
haftmann@26038
   170
fun init () =
haftmann@26038
   171
  let
haftmann@26038
   172
    val now = Time.toNanoseconds (Time.now ());
haftmann@26038
   173
    val (q, s1) = IntInf.divMod (now, 2147483562);
haftmann@26038
   174
    val s2 = q mod 2147483398;
haftmann@26038
   175
  in seed := (s1 + 1, s2 + 1) end;
haftmann@26038
   176
  
haftmann@22528
   177
in
haftmann@26038
   178
haftmann@26038
   179
val seed = seed; (* FIXME *)
haftmann@26038
   180
haftmann@26038
   181
fun run f =
haftmann@26038
   182
  let
haftmann@26038
   183
    val (x, seed') = f (!seed);
haftmann@26038
   184
    val _ = seed := seed'
haftmann@26038
   185
    val _ = if fst (! seed) = 0 orelse snd (! seed) = 0 then
haftmann@26038
   186
      (warning "broken random seed"; init ())
haftmann@26038
   187
      else ()
haftmann@26038
   188
  in x end;
haftmann@26038
   189
haftmann@22528
   190
end;
haftmann@22528
   191
haftmann@22528
   192
end;
haftmann@22528
   193
*}
haftmann@22528
   194
haftmann@26038
   195
haftmann@26038
   196
subsection {* The @{text random} class *}
haftmann@26038
   197
haftmann@26038
   198
class random = type +
haftmann@26038
   199
  fixes random :: "index \<Rightarrow> seed \<Rightarrow> 'a \<times> seed"
haftmann@26038
   200
haftmann@26038
   201
-- {* FIXME dummy implementations *}
haftmann@26038
   202
haftmann@26038
   203
instantiation nat :: random
haftmann@26038
   204
begin
haftmann@26038
   205
haftmann@26038
   206
definition
haftmann@26038
   207
  "random k = apfst nat_of_index \<circ> range k"
haftmann@26038
   208
haftmann@26038
   209
instance ..
haftmann@26038
   210
haftmann@26038
   211
end
haftmann@26038
   212
haftmann@26038
   213
instantiation bool :: random
haftmann@26038
   214
begin
haftmann@26038
   215
haftmann@26038
   216
definition
haftmann@26038
   217
  "random _ = apfst (op = 0) \<circ> range 2"
haftmann@26038
   218
haftmann@26038
   219
instance ..
haftmann@26038
   220
haftmann@26038
   221
end
haftmann@24226
   222
haftmann@26038
   223
instantiation unit :: random
haftmann@26038
   224
begin
haftmann@26038
   225
haftmann@26038
   226
definition
haftmann@26038
   227
  "random _ = Pair ()"
haftmann@26038
   228
haftmann@26038
   229
instance ..
haftmann@26038
   230
haftmann@26038
   231
end
haftmann@26038
   232
haftmann@26038
   233
instantiation "+" :: (random, random) random
haftmann@26038
   234
begin
haftmann@26038
   235
haftmann@26038
   236
definition
haftmann@26038
   237
  "random n = (do
haftmann@26038
   238
     k \<leftarrow> next;
haftmann@26038
   239
     let l = k div 2;
haftmann@26038
   240
     (if k mod 2 = 0 then do 
haftmann@26038
   241
       x \<leftarrow> random l;
haftmann@26038
   242
       return (Inl x)
haftmann@26038
   243
     done else do
haftmann@26038
   244
       x \<leftarrow> random l;
haftmann@26038
   245
       return (Inr x)
haftmann@26038
   246
     done)
haftmann@26038
   247
   done)"
haftmann@26038
   248
haftmann@26038
   249
instance ..
haftmann@26038
   250
haftmann@26038
   251
end
haftmann@22528
   252
haftmann@26038
   253
instantiation "*" :: (random, random) random
haftmann@26038
   254
begin
haftmann@26038
   255
haftmann@26038
   256
definition
haftmann@26038
   257
  "random n = (do
haftmann@26038
   258
     x \<leftarrow> random n;
haftmann@26038
   259
     y \<leftarrow> random n;
haftmann@26038
   260
     return (x, y)
haftmann@26038
   261
   done)"
haftmann@26038
   262
haftmann@26038
   263
instance ..
haftmann@26038
   264
haftmann@26038
   265
end
haftmann@26038
   266
haftmann@26038
   267
instantiation int :: random
haftmann@26038
   268
begin
haftmann@26038
   269
haftmann@26038
   270
definition
haftmann@26038
   271
  "random n = (do
haftmann@26038
   272
     (b, m) \<leftarrow> random n;
haftmann@26038
   273
     return (if b then int m else - int m)
haftmann@26038
   274
   done)"
haftmann@26038
   275
haftmann@26038
   276
instance ..
haftmann@26038
   277
haftmann@26038
   278
end
haftmann@26038
   279
haftmann@26038
   280
instantiation list :: (random) random
haftmann@26038
   281
begin
haftmann@22528
   282
haftmann@26038
   283
primrec
haftmann@26038
   284
  random_list_aux
haftmann@26038
   285
where
haftmann@26038
   286
  "random_list_aux 0 = Pair []"
haftmann@26038
   287
  | "random_list_aux (Suc n) = (do
haftmann@26038
   288
       x \<leftarrow> random (index_of_nat (Suc n));
haftmann@26038
   289
       xs \<leftarrow> random_list_aux n;
haftmann@26038
   290
       return (x#xs)
haftmann@26038
   291
     done)"
haftmann@26038
   292
haftmann@26038
   293
definition
haftmann@26038
   294
  [code func del]: "random n = random_list_aux (nat_of_index n)"
haftmann@26038
   295
haftmann@26038
   296
lemma [code func]:
haftmann@26038
   297
  "random n = (if n = 0 then return ([]::'a list)
haftmann@26038
   298
    else do
haftmann@26038
   299
       x \<leftarrow> random n;
haftmann@26038
   300
       xs \<leftarrow> random (n - 1);
haftmann@26038
   301
       return (x#xs)
haftmann@26038
   302
     done)"
haftmann@26038
   303
unfolding random_list_def
haftmann@26038
   304
by (cases "nat_of_index n", auto)
haftmann@26038
   305
  (cases n, auto)+
haftmann@26038
   306
haftmann@26038
   307
(*fun
haftmann@26038
   308
  random_list
haftmann@26038
   309
where
haftmann@26038
   310
  "random_list n = (if n = 0 then (\<lambda>_. ([]::'a list)) 
haftmann@26038
   311
    else random n \<guillemotright>=\<^isub>R (\<lambda>x::'a. random_list (n - 1) \<guillemotright>=\<^isub>R (\<lambda>(xs::'a list) _. x#xs)))"*)
haftmann@26038
   312
haftmann@26038
   313
instance ..
haftmann@22528
   314
haftmann@22528
   315
end
haftmann@26038
   316
haftmann@26038
   317
code_reserved SML Quickcheck
haftmann@26038
   318
haftmann@26038
   319
haftmann@26038
   320
subsection {* Quickcheck generator *}
haftmann@26038
   321
haftmann@26038
   322
ML {*
haftmann@26038
   323
structure Quickcheck =
haftmann@26038
   324
struct
haftmann@26038
   325
haftmann@26038
   326
open Quickcheck;
haftmann@26038
   327
haftmann@26038
   328
val eval_ref : (unit -> int -> int * int -> term list option * (int * int)) option ref = ref NONE;
haftmann@26038
   329
haftmann@26038
   330
fun mk_generator_expr prop tys =
haftmann@26038
   331
  let
haftmann@26038
   332
    val bounds = map_index (fn (i, ty) => (i, ty)) tys;
haftmann@26038
   333
    val result = list_comb (prop, map (fn (i, _) => Bound (length tys - i - 1)) bounds);
haftmann@26038
   334
    val terms = map (fn (i, ty) => Const (@{const_name Eval.term_of}, ty --> @{typ term}) $ Bound (length tys - i - 1)) bounds;
haftmann@26038
   335
    val check = @{term "If \<Colon> bool \<Rightarrow> term list option \<Rightarrow> term list option \<Rightarrow> term list option"}
haftmann@26038
   336
      $ result $ @{term "None \<Colon> term list option"} $ (@{term "Some \<Colon> term list \<Rightarrow> term list option "} $ HOLogic.mk_list @{typ term} terms);
haftmann@26038
   337
    val return = @{term "Pair \<Colon> term list option \<Rightarrow> seed \<Rightarrow> term list option \<times> seed"};
haftmann@26038
   338
    fun mk_bindtyp ty = @{typ seed} --> HOLogic.mk_prodT (ty, @{typ seed});
haftmann@26038
   339
    fun mk_bindclause (i, ty) t = Const (@{const_name mbind}, mk_bindtyp ty
haftmann@26038
   340
      --> (ty --> mk_bindtyp @{typ "term list option"}) --> mk_bindtyp @{typ "term list option"})
haftmann@26038
   341
      $ (Const (@{const_name random}, @{typ index} --> mk_bindtyp ty)
haftmann@26038
   342
        $ Bound i) $ Abs ("a", ty, t);
haftmann@26038
   343
    val t = fold_rev mk_bindclause bounds (return $ check);
haftmann@26038
   344
  in Abs ("n", @{typ index}, t) end;
haftmann@26038
   345
haftmann@26038
   346
fun compile_generator_expr thy prop tys =
haftmann@26038
   347
  let
haftmann@26038
   348
    val f = CodePackage.eval_term ("Quickcheck.eval_ref", eval_ref) thy
haftmann@26038
   349
      (mk_generator_expr prop tys) [];
haftmann@26038
   350
  in f #> run #> (Option.map o map) (Code.postprocess_term thy) end;
haftmann@26038
   351
haftmann@26038
   352
end
haftmann@26038
   353
*}
haftmann@26038
   354
haftmann@26038
   355
ML {* val f = Quickcheck.compile_generator_expr @{theory}
haftmann@26038
   356
  @{term "\<lambda>(n::nat) (m::nat) (q::nat). n = m + q + 1"} [@{typ nat}, @{typ nat}, @{typ nat}] *}
haftmann@26038
   357
haftmann@26038
   358
ML {* f 5 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   359
ML {* f 5 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   360
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   361
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   362
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   363
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   364
ML {* f 25 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   365
ML {* f 1 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   366
ML {* f 1 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   367
ML {* f 2 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   368
ML {* f 2 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   369
haftmann@26038
   370
ML {* val f = Quickcheck.compile_generator_expr @{theory}
haftmann@26038
   371
  @{term "\<lambda>(n::int) (m::int) (q::int). n = m + q + 1"} [@{typ int}, @{typ int}, @{typ int}] *}
haftmann@26038
   372
haftmann@26038
   373
ML {* f 5 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   374
ML {* f 5 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   375
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   376
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   377
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   378
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   379
ML {* f 25 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   380
ML {* f 1 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   381
ML {* f 1 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   382
ML {* f 2 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   383
ML {* f 2 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   384
haftmann@26038
   385
haftmann@26038
   386
subsection {* Incremental function generator *}
haftmann@26038
   387
haftmann@26038
   388
ML {*
haftmann@26038
   389
structure Quickcheck =
haftmann@26038
   390
struct
haftmann@26038
   391
haftmann@26038
   392
open Quickcheck;
haftmann@26038
   393
haftmann@26038
   394
fun random_fun (eq : 'a -> 'a -> bool)
haftmann@26038
   395
    (random : seed -> 'b * seed)
haftmann@26038
   396
    (random_split : seed -> seed * seed)
haftmann@26038
   397
    (seed : seed) =
haftmann@26038
   398
  let
haftmann@26038
   399
    val (seed', seed'') = random_split seed;
haftmann@26038
   400
    val state = ref (seed', []);
haftmann@26038
   401
    fun random_fun' x =
haftmann@26038
   402
      let
haftmann@26038
   403
        val (seed, fun_map) = ! state;
haftmann@26038
   404
      in case AList.lookup (uncurry eq) fun_map x
haftmann@26038
   405
       of SOME y => y
haftmann@26038
   406
        | NONE => let
haftmann@26038
   407
              val (y, seed') = random seed;
haftmann@26038
   408
              val _ = state := (seed', (x, y) :: fun_map);
haftmann@26038
   409
            in y end
haftmann@26038
   410
      end;
haftmann@26038
   411
  in (random_fun', seed'') end;
haftmann@26038
   412
haftmann@26038
   413
end
haftmann@26038
   414
*}
haftmann@26038
   415
haftmann@26038
   416
axiomatization
haftmann@26038
   417
  random_fun_aux :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> (seed \<Rightarrow> 'b \<times> seed)
haftmann@26038
   418
    \<Rightarrow> (seed \<Rightarrow> seed \<times> seed) \<Rightarrow> seed \<Rightarrow> ('a \<Rightarrow> 'b) \<times> seed"
haftmann@26038
   419
haftmann@26038
   420
code_const random_fun_aux (SML "Quickcheck.random'_fun")
haftmann@26038
   421
haftmann@26038
   422
instantiation "fun" :: (term_of, term_of) term_of
haftmann@26038
   423
begin
haftmann@26038
   424
haftmann@26038
   425
instance ..
haftmann@26038
   426
haftmann@26038
   427
end
haftmann@26038
   428
haftmann@26038
   429
code_const "Eval.term_of :: ('a\<Colon>term_of \<Rightarrow> 'b\<Colon>term_of) \<Rightarrow> _"
haftmann@26038
   430
  (SML "(fn '_ => Const (\"arbitrary\", dummyT))")
haftmann@26038
   431
haftmann@26038
   432
instantiation "fun" :: (eq, random) random
haftmann@26038
   433
begin
haftmann@26038
   434
haftmann@26038
   435
definition
haftmann@26038
   436
  "random n = random_fun_aux (op =) (random n) split_seed"
haftmann@26038
   437
haftmann@26038
   438
instance ..
haftmann@26038
   439
haftmann@26038
   440
end
haftmann@26038
   441
haftmann@26038
   442
ML {* val f = Quickcheck.compile_generator_expr @{theory}
haftmann@26038
   443
  @{term "\<lambda>f k. int (f k) = k"} [@{typ "int \<Rightarrow> nat"}, @{typ int}] *}
haftmann@26038
   444
haftmann@26038
   445
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   446
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   447
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   448
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   449
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   450
ML {* f 20 |> (Option.map o map) (Sign.string_of_term @{theory}) *}
haftmann@26038
   451
haftmann@26038
   452
end