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 generated random bytes. In this post, I’ll be generating random characters.
I’m going to need a couple of generators for this:
[20h..7Eh] for ASCII printable characters[80h..FFh] for ASCII extended charactersOperators.char<^T>) to
the abovePorting 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'