logo

Write you some QuickCheck - Generating random characters

This post is part of a series of posts on implementing a minimal version of QuickCheck from scratch. The source code is available on GitHub.

In the previous post I’ve generated random bytes. In this post, I’ll be generating random characters.

I’m going to need a couple of generators for this:

Porting Gen’s oneof

/// <summary>
/// Randomly uses one of the given generators.
/// </summary>
/// <param name="gens">The input list of generators to use.</param>
/// <remarks>
/// The input list must be non-empty.
/// </remarks>
let oneof gens =
    let join x = Gen.bind x id
    join (Gen.elements gens)

Porting Gen’s elements since oneof depends on it

/// <summary>
/// Generates one of the given values.
/// </summary>
/// <param name="xs">The input list.</param>
/// <remarks>
/// The input list must be non-empty.
/// </remarks>
let elements xs =
    // http://stackoverflow.com/a/1817654/467754
    let flip f x y = f y x
    Gen.choose (0, (Seq.length xs) - 1) |> Gen.map (flip Seq.item xs)

All the pieces are now in place, and so a char generator can be written as:

let char =
    Gen.oneof [ Gen.choose ( 32, 126)
                Gen.choose (127, 255) ]
    |> Gen.map Operators.char

val char : Gen<char>

Finally, here are some sample characters:

> Gen.char |> Gen.generate;;
val it : char = 'æ'

> Gen.char |> Gen.generate;;
val it : char = 'W'

> Gen.char |> Gen.generate;;
val it : char = 'h'

> Gen.char |> Gen.generate;;
val it : char = 'à'

> Gen.char |> Gen.generate;;
val it : char = 'ì'

> Gen.char |> Gen.generate;;
val it : char = '&'

> Gen.char |> Gen.generate;;
val it : char = ' '

> Gen.char |> Gen.generate;;
val it : char = 'o'

> Gen.char |> Gen.generate;;
val it : char = 'X'


  1. I used the ASCII codes from this table.