gen Monad #
This monad is used to formulate randomized computations with a parameter to specify the desired size of the result.
This is a port of the Haskell QuickCheck library.
Main definitions #
genmonad
Local notation #
i .. j:Icc i j, the set of values betweeniandjinclusively;
Tags #
random testing
References #
Monad to generate random examples to test properties with.
It has a nat parameter so that the caller can decide on the
size of the examples.
Execute a gen inside the io monad using i as the example
size and with a fresh random number generator.
Equations
- slim_check.io.run_gen x i = io.run_rand (x.run {down := i})
Lift random.random to the gen monad.
Equations
- slim_check.gen.choose_any α = ⟨λ (_x : ulift ℕ), rand.random α⟩
Lift random.random_r to the gen monad.
Equations
- slim_check.gen.choose x y p = ⟨λ (_x : ulift ℕ), rand.random_r x y p⟩
Generate a nat example between x and y.
Equations
- slim_check.gen.choose_nat x y p = slim_check.gen.choose x y p
Generate a nat example between x and y.
Equations
- slim_check.gen.choose_nat' x y p = have this : ∀ (i : ℕ), x < i → i ≤ y → i.pred < y, from _, subtype.map nat.pred _ <$> slim_check.gen.choose (x + 1) y p
Equations
- slim_check.gen.has_orelse = {orelse := λ (α : Type u) (x y : slim_check.gen α), uliftable.up (slim_check.gen.choose_any bool) >>= λ (b : ulift bool), ite ↥(b.down) x y}
Get access to the size parameter of the gen monad. For
reasons of universe polymorphism, it is specified in
continuation passing style.
Apply a function to the size parameter.
Create n examples using cmd.
Equations
- slim_check.gen.vector_of n.succ cmd = vector.cons <$> cmd <*> slim_check.gen.vector_of n cmd
- slim_check.gen.vector_of 0 _x = return vector.nil
Create a list of examples using cmd. The size is controlled
by the size parameter of gen.
Equations
- cmd.list_of = slim_check.gen.sized (λ (sz : ℕ), uliftable.up (slim_check.gen.choose_nat 0 (sz + 1) _) >>= λ (_p : ulift ↥(set.Icc 0 (sz + 1))), slim_check.gen.list_of._match_1 cmd sz _p)
- slim_check.gen.list_of._match_1 cmd sz {down := n} = slim_check.gen.vector_of n.val cmd >>= λ (v : vector α n.val), return v.to_list
Given a list of example generators, choose one to create an example.
Equations
- slim_check.gen.one_of xs pos = uliftable.up (slim_check.gen.choose_nat' 0 xs.length pos) >>= λ (_p : ulift ↥(set.Ico 0 xs.length)), slim_check.gen.one_of._match_1 xs _p
- slim_check.gen.one_of._match_1 xs {down := ⟨n, _⟩} = xs.nth_le n h'
Given a list of example generators, choose one to create an example.
Equations
- slim_check.gen.elements xs pos = uliftable.up (slim_check.gen.choose_nat' 0 xs.length pos) >>= λ (_p : ulift ↥(set.Ico 0 xs.length)), slim_check.gen.elements._match_1 xs _p
- slim_check.gen.elements._match_1 xs {down := ⟨n, _⟩} = has_pure.pure (xs.nth_le n h₁)
freq_aux xs i _ takes a weighted list of generator and a number meant to select one of the
generators.
If we consider freq_aux [(1, gena), (3, genb), (5, genc)] 4 _, we choose a generator by splitting
the interval 1-9 into 1-1, 2-4, 5-9 so that the width of each interval corresponds to one of the
number in the list of generators. Then, we check which interval 4 falls into: it selects genb.
freq [(1, gena), (3, genb), (5, genc)] _ will choose one of gena, genb, genc with
probabilities proportional to the number accompanying them. In this example, the sum of
those numbers is 9, gena will be chosen with probability ~1/9, genb with ~3/9 (i.e. 1/3)
and genc with probability 5/9.
Equations
- slim_check.gen.freq xs pos = let s : ℕ := (list.map (subtype.val ∘ prod.fst) xs).sum in have ha : 1 ≤ s, from _, have this : 0 ≤ s - 1, from _, uliftable.adapt_up slim_check.gen slim_check.gen (slim_check.gen.choose_nat 0 (s - 1) this) (λ (i : ↥(set.Icc 0 (s - 1))), slim_check.gen.freq_aux xs i.val _)
Generate a random permutation of a given list.
Equations
- slim_check.gen.permutation_of (x :: xs) = slim_check.gen.permutation_of xs >>= λ (_p : subtype xs.perm), slim_check.gen.permutation_of._match_2 x xs _p
- slim_check.gen.permutation_of list.nil = has_pure.pure ⟨list.nil α, _⟩
- slim_check.gen.permutation_of._match_2 x xs ⟨xs', h⟩ = uliftable.up (slim_check.gen.choose_nat 0 xs'.length _) >>= λ (_p : ulift ↥(set.Icc 0 xs'.length)), slim_check.gen.permutation_of._match_1 x xs xs' h _p
- slim_check.gen.permutation_of._match_1 x xs xs' h {down := ⟨n, _⟩} = has_pure.pure ⟨list.insert_nth n x xs', _⟩