from the Random package, and so it’ll be easier to start by porting those in F#:

/// <summary>/// This module deals with the common task of pseudo-random number generation./// It makes it possible to generate repeatable results, by starting with a/// specified initial random number generator, or to get different results on/// echch run by using the system-initialised generator or by supplying a seed/// from some other source./// </summary>/// <remarks>/// This implementation uses the Portable Combined Generator of L'Ecuyer for/// 32-bit computers, transliterated by Lennart Augustsson. It has a period of/// roughly 2.30584e18./// </remarks>[<AutoOpen>]moduleinternalLightCheck.RandomtypeStdGen=private|StdGenofint*int/// <summary>/// The next operation returns an Int that is uniformly distributed in the/// rangge of at least 30 bits, and a new generator. The result of repeatedly/// using next should be at least as statistically robust as the Minimal/// Standard Random Number Generator. Until more is known about implementations/// of split, all we require is that split deliver generators that are (a) not/// identical and (b) independently robust in the sense just given./// </summary>letprivatenext(StdGen(s1,s2))=letk=s1/53668letk'=s2/52774lets1'=40014*(s1-k*53668)-k*12211lets2'=40692*(s2-k'*52774)-k'*3791lets1''=ifs1'<0thens1'+2147483563elses1'lets2''=ifs2'<0thens2'+2147483399elses2'letz=s1''-s2''letz'=ifz<1thenz+2147483562elsez(z',StdGen(s1'',s2''))/// <summary>/// The split operation allows one to obtain two distinct random number/// generators. This is very useful in functional programs (for example, when/// passing a random number generator down to recursive calls), but very little/// work has been done on statistically robust implementations of split./// </summary>letsplit(StdGen(s1,s2)asstd)=lets1'=ifs1=2147483562then1elses1+1lets2'=ifs2=1then2147483398elses2-1let(StdGen(t1,t2))=nextstd|>snd(StdGen(s1',t2),StdGen(t1,s2'))/// <summary>/// The range operation takes a range (lo,hi) and a random number generator g,/// and returns a random value, uniformly distributed, in the closed interval/// [lo,hi], together with a new generator./// </summary>/// <remarks>/// It is unspecified what happens if lo > hi. For continuous types there is no/// requirement that the values lo and hi are ever produced, although they very/// well may be, depending on the implementation and the interval./// </remarks>letrecrange(l,h)rng=ifl>hthenrange(h,l)rngelselet(l',h')=(32767,2147483647)letb=h'-l'+1letq=1000letk=h-l+1letmagnitude=k*qletrecfcvg=ifc>=magnitudethen(v,g)elselet(x,g')=nextgletv'=(v*b+(x-l'))f(c*b)v'g'let(v,rng')=f10rng(l+v%k),rng'letprivater=intSystem.DateTime.UtcNow.Ticks|>System.Random/// <summary>/// Provides a way of producing an initial generator using a random seed./// </summary>letcreateNew()=lets=r.Next()&&&2147483647let(q,s1)=(s/2147483562,s%2147483562)lets2=q%2147483398StdGen(s1+1,s2+1)

To port QuickCheck’s basic generators, and combinators for making custom ones, we need a type of Gen<'a>:

/// <summary>/// LightCheck exports some basic generators, and some combinators for making/// new ones. Gen of 'a is the type for generators of 'a's and essentially is/// a State Monad combining a pseudo-random generation seed, and a size value/// for data structures (i.e. list length)./// Using the type Gen of 'a, we can specify at the same time a set of values/// that can be generated and a probability distribution on that set.////// Read more about how it works here:/// http://www.dcc.fc.up.pt/~pbv/aulas/tapf/slides/quickcheck.html#the-gen-monad/// http://quviq.com/documentation/eqc/index.html/// </summary>moduleLightCheck.Gen/// <summary>/// A generator for values of type 'a./// </summary>typeGen<'a>=private|Genof(int->StdGen->'a)

Finally, we also need a function2 that runs a generator; taking a Gen<'a> and returning random test data of type 'a:

/// <summary>/// Runs a generator. The size passed to the generator is up to 30; if you want/// another size then you should explicitly use 'resize'./// </summary>letgenerate(Genm)=let(size,rand)=Random.createNew()|>Random.range(0,30)msizerandvalgenerate:Gen<'a>->'a

We’re all set! Let’s generate some random test data in the next post(s).

The other thing to notice about QuickCheck 1.2.0.1, is that it’s the last version before version 2 came out. In version 2 there’s added support for shrinking, which is a major advancement. The shrinking functions are going to be ported from QuickCheck 2.8.2. ↩

The implementation of the generate function is based on both QuickCheck 1.2.0.1 and QuickCheck 2.8.2. ↩