Ad hoc way to get a random number in a range
See original GitHub issueDoes FsCheck define an ad hoc way to get a random number in a range? Particularly, a way that works with FsCheck.Xunit?
Let’s say that I want a randomly generated number in the range 1-100, or 1-8. While I could use a custom Arbitrary, this is sometimes too heavy-handed. Besides, a custom arbitrary affects all values of a particular type (int
, byte
, float
, etc.), and that’s sometimes undesirable, because I want most numbers to be unconstrained, except for one or two. A motivating example is described below.
If there’s no current way to do this, I’d like to suggest a solution:
We could add a function that would take any number, and map it to the corresponding number in the required range.
It might look like this:
let y = Range.map Int32.MinValue Int32.MaxValue 1 100 x
This would take the 32-bit integer x
and map it to a value in the range 1-100. This could be useful when FsCheck provides an unbounded int
value.
The first two arguments are the original range from which x
was drawn, in this case all 32-bit integers. The function can be partially applied so that it can be used in a more readable manner:
let y = x |> between 1 100
If there’s no existing feature to address this requirement, and this suggestion sounds like an appropriate solution, I’ll be happy to make a pull request.
Motivating example
I often need to get a number in a predetermined range. One recent example that came up was that I was doing Conway’s Game of Life, and I wanted to express the property that Any live cell with more than three live neighbours dies.
I already have a function that gives me all (8 of) the neighbouring cells of a cell, so in order to express this test case, I want to pick a number of neighbours from 4 to 8, and then select that number of neighbouring cells as live cells.
It’d be nice to be able to express that like this:
[<Property>]
let ``Any live cell with more than three live neighbours dies``
(cell : int * int)
(neighborCount : int) =
let neighborCount = neighborCount |> between 4 8
// The rest of the property goes here...
In this example, a custom Arbitrary is undesirable, because I want the integers in cell
to be unconstrained.
Issue Analytics
- State:
- Created 8 years ago
- Comments:9 (9 by maintainers)
Top GitHub Comments
@mausch, thank you, I didn’t know about
Prop.forAll
. That turns out to address the issue elegantly and flexibly, even with FsCheck.Xuni:This almost deserves a blog post, unless you think there’s a good fit for it in the documentation somewhere!(?)
The only thing I’m not 100 % happy with is the extra indentation caused by the multi-line lambda function, but I am 95 % happy 😄
For my sake we can close the issue again.
Ok. I guess it is in the documentation, though if anything should be clarified, feel free to PR for that.