SeededGen

final class SeededGen[S, T <: Tag, V](genFn: S @@ T => Gen[V])(implicit extractor: SeedExtractor[S])

Used instead of a Gen to require the caller to provide a rallyId that is used to deterministically alter the underlying seed of the resulting generator.

If you use a SeededGen, the resulting generator will always generate the same results for the same seed.

Type parameters:
S

the seed type, must have an implicit SeedExtractor to mix in with the starting seed

T

the type of org.scalacheck.ops.SeededGen.Tag used to avoid exposing implicit type arguments on primitive values

V

the type of value produced by the generator

Value parameters:
genFn

a function from seed (typically implicit) to a generator

Note:

You only need to use this if you want to require the caller to pass a seed OR your generator depends on the value of the seed provided (passed along implicitly). Using a plain Gen will work as expected in all other contexts.

 trait ID extends SeededGen.Tag
 val genNamespacedID = SeededGen[String, ID, String] { implicit id =>
   for {
     inner <- Gen.identifier // doesn't need to be a SeededGen
   } yield s"thing-$id-$inner"
 }
 assert(gen.instance("1") startsWith "thing-1-")

You can treat a SeededGen as a Gen when inside the definition of a SeededGen if you make the given seed implicit.

 val gen = SeededGen[String, ID, Map[String, String]] { implicit id =>
   for {
     namespacedID <- genNamespacedID // implicitly converted from SeededGen to Gen because of the implicit id
     rank <- Gen.choose(1, 10)
   } yield Map(
     "id" -> namespacedID,
     "rank" -> rank.toString
   )
 }

Typically, it is most convenient to define a SeededGen alias so that you can benefit from type inference and hide the often repeated seed and tag types. For this, you should define an object that extends SeededGen#Companion. Instead of defining map and flatMap methods, this pattern opts to implicitly convert your SeededGen into a Gen where these methods are defined. This makes it easier to interlace Gen with SeededGen in the same for-yield comprehension. In order to access the seed, you can call your SeededGen builder and pass a block of code that takes an implicit seed and produces a Gen. In places where you don't want to define a full SeededGen, but you need access to the seed, you can use andThenWithSeed. If you don't need access to the seed, you can call andThen which will allow you to alter the underlying generator while keeping everything inside of a SeededGen.

Companion:
object
class Object
trait Matchable
class Any

Value members

Concrete methods

def andThen[X](fn: Gen[V] => Gen[X]): SeededGen[S, T, X]

Produce a new seeded gen maps over the underlying generator without accessing the seed.

Produce a new seeded gen maps over the underlying generator without accessing the seed.

def andThenWithSeed[X](fn: S @@ T => Gen[V] => Gen[X]): SeededGen[S, T, X]

Produce a new seeded gen maps over the underlying generator with access to the seed.

Produce a new seeded gen maps over the underlying generator with access to the seed.

def gen(seed: S): Gen[V]

Stateless function that generates an identical Gen of V instances for a given seed and GenConfig.

Stateless function that generates an identical Gen of V instances for a given seed and GenConfig.

def instance(seed: S)(implicit c: GenConfig): V

Stateless function that generates an identical instance value V for a given seed and GenConfig.

Stateless function that generates an identical instance value V for a given seed and GenConfig.