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:
[20h..7Eh]
for ASCII printable characters[80h..FFh]
for ASCII extended charactersOperators.char<^T>
to the above)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'