Published 21st of March, 2015, by Nikos Baxevanis. Tagged as fscheck, haskell, quickcheck, f#.

# Observing the size of generated test data

QuickCheck has a function called `sample` which, given a generator, prints some examples values to the standard output (stdout).

It’s signature is:

``````sample :: Show a => Gen a -> IO ()
``````

### Example

Using the `choose` generator we can use `sample` to generate random integers in the inclusive range [0, 9] and print them:

``````λ sample \$ choose (0, 9 :: Int)
``````

Output:

``````1
5
0
2
3
4
6
5
5
4
1
``````

## The sample function defined in FsCheck

FsCheck also defines a `sample` function, though it behaves in a slightly different way, as it takes two additional arguments `size` and `n`:

``````val sample : size:int -> n:int -> gn:Gen<'a> -> 'a list

// `size` is the size of generated test data
// `n` is the number of samples (defaults to 11 in QuickCheck)
``````

Let’s pause here and run `sample` by supplying different values for `size`.

### Using 0 for size

``````
open FsCheck.Gen

let sample'  = sample 0 11 // Size = 0, Number of samples = 11
let sample'' = sample' <| choose (0, 9)
``````

Output:

``````Length = 11
: 4
: 0
: 4
: 0
: 3
: 9
: 3
: 9
: 2
: 8
: 2
``````

However, since size is `0` the result should be:

``````Length = 11
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
``````

### Using 1000 for size

``````open FsCheck.Gen

let sample'  = sample 1000 11 // Size = 1000, Number of samples = 11
let sample'' = sample' <| choose (0, 9)
``````

Output:

``````Length = 11
: 8
: 6
: 2
: 3
: 7
: 3
: 1
: 2
: 6
: 2
: 0
``````

The above result looks incorrect, in fact it looks the same as the first result, where size was 0.

Since size is `1000` the result should look like:

``````Length = 11
: -78
: 347
: 242
: 707
: 414
: 49
: 551
: 45
: 897
: -99
: 77
``````

At this point, we observed that if a generator ignores size (e.g. as `choose` does) then `sample` ignores it’s `size` parameter.

## Just sample with a different generator, then.

Instead of the `choose` generator, the following example uses `generate<int>`.

### Using 0 for size

``````open FsCheck.Arb
open FsCheck.Gen

let sample'  = sample 0 11 // Size = 0, Number of samples = 11
let sample'' = sample' <| generate<int>
``````

The results are now looking good:

``````Length = 11
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
``````

That’s because `generate<int>` takes `size` into account.

### Using 1000 for size

``````open FsCheck.Arb
open FsCheck.Gen

let sample'  = sample 1000 11 // Size = 1000, Number of samples = 11
let sample'' = sample' <| generate<int>
``````

The results are now looking good:

``````Length = 11
: -98
: 307
: 142
: 507
: 414
: 39
: 501
: 4
: 807
: -81
: 31
``````

## How to always control the size of test data, then?

That seems to be the purpose of the `sized` function.

For the sake of completeness, here’s the original example with `choose` rewritten to use `sized`:

### sample and choose, using 0 for size

``````open FsCheck.Gen

let sample'  = sample 0 11 // Size = 0, Number of samples = 11
let sample'' = sample' <| (sized <| fun s -> choose (0, s))
``````

Results to the following, which is now correct:

``````Length = 11
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
``````

### sample and choose, using 1000 for size

``````open FsCheck.Gen

let sample'  = sample 1000 11 // Size = 1000, Number of samples = 11
let sample'' = sample' <| (sized <| fun s -> choose (-s, s))
``````

Results to the following, which now looks correct:

``````Length = 11
: 105
: 682
: -239
: 658
: -6
: 9
: 203
: -43
: 304
: -125
: -423
``````
• QuickCheck
• FsCheck

## Appendix

The above F# examples use the backward pipe `<|` operator to look similar to the Haskell examples. In F#, it’s idiomatic to use the forward pipe operator instead.

Using the forward pipe operator, the previous example would be:

``````let result =
(fun s -> Gen.choose (-s, s))
|> Gen.sized
|> Gen.sample 1000 11
``````

## Wish to comment?

You can comment on this post on GitHub. Alternatively, you can discuss this post on Twitter or elsewhere with a permalink. Ping me with the link, and I may respond.