Skip to content

Gen<A> final

final class Gen<A> with Functor<A>, Applicative<A>, Monad<A>

A random generator for values of type A, optionally paired with a Shrinker for counter-example minimisation.

Gen is a monad: use map and flatMap to build complex generators from simpler ones, and the static factory methods (e.g. chooseInt, ilistOf, option) for the most common cases.

Available Extensions

Constructors

Gen()

Gen(State<StatefulRandom, A> sample, {Shrinker<A>? shrinker})

Creates a Gen from a sample computation and an optional shrinker.

Implementation
dart
Gen(this.sample, {this.shrinker});

Properties

hashCode no setter inherited

int get hashCode

The hash code for this object.

A hash code is a single integer which represents the state of the object that affects operator == comparisons.

All objects have hash codes. The default hash code implemented by Object represents only the identity of the object, the same way as the default operator == implementation only considers objects equal if they are identical (see identityHashCode).

If operator == is overridden to use the object state instead, the hash code must also be changed to represent that state, otherwise the object cannot be used in hash based data structures like the default Set and Map implementations.

Hash codes must be the same for objects that are equal to each other according to operator ==. The hash code of an object should only change if the object changes in a way that affects equality. There are no further requirements for the hash codes. They need not be consistent between executions of the same program and there are no distribution guarantees.

Objects that are not equal are allowed to have the same hash code. It is even technically allowed that all instances have the same hash code, but if clashes happen too often, it may reduce the efficiency of hash-based data structures like HashSet or HashMap.

If a subclass overrides hashCode, it should override the operator == operator as well to maintain consistency.

Inherited from Object.

Implementation
dart
external int get hashCode;

runtimeType no setter inherited

Type get runtimeType

A representation of the runtime type of the object.

Inherited from Object.

Implementation
dart
external Type get runtimeType;

sample final

final State<StatefulRandom, A> sample

The underlying stateful computation that produces a value.

Implementation
dart
final State<StatefulRandom, A> sample;

shrinker final

final Shrinker<A>? shrinker

Optional shrinker used to minimise failing counter-examples.

Implementation
dart
final Shrinker<A>? shrinker;

tuple10 no setter

Gen<Record> get tuple10

Generates a 10-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A, A, A, A, A)> get tuple10 => tuple9.flatMap((t) => map(t.appended));

tuple11 no setter

Gen<Record> get tuple11

Generates a 11-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A, A, A, A, A, A)> get tuple11 => tuple10.flatMap((t) => map(t.appended));

tuple12 no setter

Gen<Record> get tuple12

Generates a 12-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A, A, A, A, A, A, A)> get tuple12 => tuple11.flatMap((t) => map(t.appended));

tuple13 no setter

Gen<Record> get tuple13

Generates a 13-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A, A, A, A, A, A, A, A)> get tuple13 =>
    tuple12.flatMap((t) => map(t.appended));

tuple14 no setter

Gen<Record> get tuple14

Generates a 14-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A, A, A, A, A, A, A, A, A)> get tuple14 =>
    tuple13.flatMap((t) => map(t.appended));

tuple15 no setter

Gen<Record> get tuple15

Generates a 15-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)> get tuple15 =>
    tuple14.flatMap((t) => map(t.appended));

tuple16 no setter

Gen<Record> get tuple16

Generates a 16-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A)> get tuple16 =>
    tuple15.flatMap((t) => map(t.appended));

tuple2 no setter

Gen<Record> get tuple2

Generates a pair of independent values from this generator.

Implementation
dart
Gen<(A, A)> get tuple2 => (this, this).tupled;

tuple3 no setter

Gen<Record> get tuple3

Generates a 3-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A)> get tuple3 => tuple2.flatMap((t) => map(t.appended));

tuple4 no setter

Gen<Record> get tuple4

Generates a 4-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A)> get tuple4 => tuple3.flatMap((t) => map(t.appended));

tuple5 no setter

Gen<Record> get tuple5

Generates a 5-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A)> get tuple5 => tuple4.flatMap((t) => map(t.appended));

tuple6 no setter

Gen<Record> get tuple6

Generates a 6-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A)> get tuple6 => tuple5.flatMap((t) => map(t.appended));

tuple7 no setter

Gen<Record> get tuple7

Generates a 7-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A, A)> get tuple7 => tuple6.flatMap((t) => map(t.appended));

tuple8 no setter

Gen<Record> get tuple8

Generates a 8-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A, A, A)> get tuple8 => tuple7.flatMap((t) => map(t.appended));

tuple9 no setter

Gen<Record> get tuple9

Generates a 9-tuple of independent values from this generator.

Implementation
dart
Gen<(A, A, A, A, A, A, A, A, A)> get tuple9 => tuple8.flatMap((t) => map(t.appended));

Methods

ap() inherited

Monad<B> ap<B>(Monad<B Function(A)> f)

Apply f to the value of this Applicative.

Inherited from Monad.

Implementation
dart
@override
Monad<B> ap<B>(covariant Monad<Function1<A, B>> f) => flatMap((a) => f.map((f) => f(a)));

flatMap() override

Gen<B> flatMap<B>(Gen<B> Function(A) f)

Applyf to the value in this monadic context, returning the result in the same context.

Implementation
dart
@override
Gen<B> flatMap<B>(Function1<A, Gen<B>> f) => Gen(sample.flatMap((t) => f(t).sample));

map() override

Gen<B> map<B>(B Function(A) f)

Applies f to the value of this Functor.

Implementation
dart
@override
Gen<B> map<B>(Function1<A, B> f) => flatMap((a) => Gen(sample.map(f)));

noSuchMethod() inherited

dynamic noSuchMethod(Invocation invocation)

Invoked when a nonexistent method or property is accessed.

A dynamic member invocation can attempt to call a member which doesn't exist on the receiving object. Example:

dart
dynamic object = 1;
object.add(42); // Statically allowed, run-time error

This invalid code will invoke the noSuchMethod method of the integer 1 with an Invocation representing the .add(42) call and arguments (which then throws).

Classes can override noSuchMethod to provide custom behavior for such invalid dynamic invocations.

A class with a non-default noSuchMethod invocation can also omit implementations for members of its interface. Example:

dart
class MockList<T> implements List<T> {
  noSuchMethod(Invocation invocation) {
    log(invocation);
    super.noSuchMethod(invocation); // Will throw.
  }
}
void main() {
  MockList().add(42);
}

This code has no compile-time warnings or errors even though the MockList class has no concrete implementation of any of the List interface methods. Calls to List methods are forwarded to noSuchMethod, so this code will log an invocation similar to Invocation.method(#add, [42]) and then throw.

If a value is returned from noSuchMethod, it becomes the result of the original invocation. If the value is not of a type that can be returned by the original invocation, a type error occurs at the invocation.

The default behavior is to throw a NoSuchMethodError.

Inherited from Object.

Implementation
dart
@pragma("vm:entry-point")
@pragma("wasm:entry-point")
external dynamic noSuchMethod(Invocation invocation);

retryUntil()

Gen<A> retryUntil(bool Function(A) p)

Returns a generator that retries until the predicate p holds.

Throws an Exception after 1000 consecutive rejections to prevent infinite loops when p is too restrictive.

Implementation
dart
Gen<A> retryUntil(Function1<A, bool> p) {
  Gen<A> go(int retriesSoFar) {
    if (retriesSoFar >= 1000) {
      throw Exception('Gen.retryUntil exceeded max retries: 1000');
    } else {
      return flatMap((a) => p(a) ? Gen.constant(a) : go(retriesSoFar + 1));
    }
  }

  return go(0);
}

shrink()

ILazyList<A> shrink(A a)

Returns shrink candidates for a using this generator's shrinker, or an empty list when no shrinker is attached.

Implementation
dart
ILazyList<A> shrink(A a) => shrinker?.shrink(a) ?? ILazyList.empty();

stream()

ILazyList<A> stream(StatefulRandom rand)

Returns an infinite lazy stream of sampled values using rand as the random source.

Implementation
dart
ILazyList<A> stream(StatefulRandom rand) => ILazyList.unfold(
  rand,
  (r) {
    final result = sample.run(r);
    return Some((result.$2, result.$1));
  },
);

toString() inherited

String toString()

A string representation of this object.

Some classes have a default textual representation, often paired with a static parse function (like int.parse). These classes will provide the textual representation as their string representation.

Other classes have no meaningful textual representation that a program will care about. Such classes will typically override toString to provide useful information when inspecting the object, mainly for debugging or logging.

Inherited from Object.

Implementation
dart
external String toString();

withShrinker()

Gen<A> withShrinker(Shrinker<A> shrinker)

Returns a copy of this generator with shrinker attached.

Implementation
dart
Gen<A> withShrinker(Shrinker<A> shrinker) => Gen(sample, shrinker: shrinker);

Extension Methods

forAll() extension

void forAll(
  String description,
  FutureOr<void> Function(A) testBody, {
  int? numTests,
  int? seed,
  String? testOn,
  Timeout? timeout,
  dynamic skip,
  dynamic tags,
  Map<String, dynamic>? onPlatform,
  int? retry,
})

Available on Gen<A>, provided by the PropOps<A> extension

Implementation
dart
@isTest
void forAll(
  String description,
  Function1<A, FutureOr<void>> testBody, {
  int? numTests,
  int? seed,
  String? testOn,
  Timeout? timeout,
  dynamic skip,
  dynamic tags,
  Map<String, dynamic>? onPlatform,
  int? retry,
}) => _forAll(
  description,
  this,
  testBody,
  numTests: numTests,
  seed: seed,
  testOn: testOn,
  timeout: timeout,
  skip: skip,
  tags: tags,
  onPlatform: onPlatform,
  retry: retry,
);

Operators

operator ==() inherited

bool operator ==(Object other)

The equality operator.

The default behavior for all Objects is to return true if and only if this object and other are the same object.

Override this method to specify a different equality relation on a class. The overriding method must still be an equivalence relation. That is, it must be:

  • Total: It must return a boolean for all arguments. It should never throw.

  • Reflexive: For all objects o, o == o must be true.

  • Symmetric: For all objects o1 and o2, o1 == o2 and o2 == o1 must either both be true, or both be false.

  • Transitive: For all objects o1, o2, and o3, if o1 == o2 and o2 == o3 are true, then o1 == o3 must be true.

The method should also be consistent over time, so whether two objects are equal should only change if at least one of the objects was modified.

If a subclass overrides the equality operator, it should override the hashCode method as well to maintain consistency.

Inherited from Object.

Implementation
dart
external bool operator ==(Object other);

Static Properties

alphaLowerChar final

final Gen<String> alphaLowerChar

Generator for lowercase ASCII letters (az).

Implementation
dart
static final Gen<String> alphaLowerChar = Choose.integer
    .choose('a'.codeUnitAt(0), 'z'.codeUnitAt(0) + 1)
    .map(String.fromCharCode);

alphaNumChar read / write

Gen<String> alphaNumChar

getter:

Generator for a single alphanumeric character (a–z, A–Z, 0–9).

setter:

Generator for a single alphanumeric character (a–z, A–Z, 0–9).

Implementation
dart
static Gen<String> alphaNumChar = frequency([
  (26, Gen.alphaLowerChar),
  (26, Gen.alphaUpperChar),
  (10, numChar),
]);

alphaUpperChar final

final Gen<String> alphaUpperChar

Generator for uppercase ASCII letters (AZ).

Implementation
dart
static final Gen<String> alphaUpperChar = alphaLowerChar.map((c) => c.toUpperCase());

asciiChar final

final Gen<String> asciiChar

Generator for a single ASCII character (code points 0–127).

Implementation
dart
static final Gen<String> asciiChar = chooseInt(0, 127).map(String.fromCharCode);

bigInt final

final Gen<BigInt> bigInt

Generator for positive BigInt values made up of 1–20 decimal digits.

Implementation
dart
static final Gen<BigInt> bigInt = Gen.listOf(
  Gen.chooseInt(1, 20),
  Gen.numChar,
).map((a) => BigInt.parse(a.join()));

binChar final

final Gen<String> binChar

Generator for a single binary digit character (0 or 1).

Implementation
dart
static final Gen<String> binChar = charSample('01');

boolean final

final Gen<bool> boolean

Generator for bool values.

Implementation
dart
static final Gen<bool> boolean = Gen(State((r) => r.nextBool()));

byte final

final Gen<int> byte

Generator for byte values in [0, 255].

Implementation
dart
static final Gen<int> byte = chooseInt(0, 255);

date final

final Gen<DateTime> date

Generator for DateTime values representing calendar dates from 1970 to 100 years in the future.

Implementation
dart
static final Gen<DateTime> date = (
  chooseInt(1970, DateTime.now().year + 100),
  chooseInt(DateTime.january, DateTime.december),
  chooseInt(0, 30),
).tupled.map((t) => DateTime(t.$1, t.$2, t.$3));

dateTime final

final Gen<DateTime> dateTime

Generator for DateTime values with full time-of-day precision from 1970 to 100 years in the future.

Implementation
dart
static final Gen<DateTime> dateTime = (
  chooseInt(1970, DateTime.now().year + 100),
  chooseInt(DateTime.january, DateTime.december),
  chooseInt(0, 30),
  chooseInt(0, 23),
  chooseInt(0, 59),
  chooseInt(0, 59),
  chooseInt(0, 9999),
  chooseInt(0, 999999),
).tupled.map((t) => DateTime(t.$1, t.$2, t.$3, t.$4, t.$5, t.$6, t.$7, t.$8));

duration read / write

Gen<Duration> duration

getter:

Generator for Duration values spanning roughly ±1 year with microsecond precision.

setter:

Generator for Duration values spanning roughly ±1 year with microsecond precision.

Implementation
dart
static Gen<Duration> duration = (
  chooseInt(-365, 365),
  chooseInt(-23, 23),
  chooseInt(-59, 59),
  chooseInt(-59, 59),
  chooseInt(-9999, 9999),
  chooseInt(-999999, 999999),
).tupled.map(
  (t) => Duration(
    days: t.$1,
    hours: t.$2,
    minutes: t.$3,
    seconds: t.$4,
    milliseconds: t.$5,
    microseconds: t.$6,
  ),
);

hexChar final

final Gen<String> hexChar

Generator for a single hexadecimal digit character (09, af, AF).

Implementation
dart
static final Gen<String> hexChar = charSample('01234567890abcdefABCDEF');

integer final

final Gen<int> integer

Generator for int values across the full 32-bit signed range.

Implementation
dart
static final Gen<int> integer = Gen.chooseInt(-2147483648, 2147483647);

nonNegativeInt final

final Gen<int> nonNegativeInt

Generator for non-negative int values up to Integer.maxValue.

Implementation
dart
static final Gen<int> nonNegativeInt = chooseInt(0, Integer.maxValue);

numChar final

final Gen<String> numChar

Generator for a single decimal digit character (09).

Implementation
dart
static final Gen<String> numChar = charSample('01234567890');

positiveInt final

final Gen<int> positiveInt

Generator for positive int values up to Integer.maxValue.

Implementation
dart
static final Gen<int> positiveInt = chooseInt(1, Integer.maxValue);

Static Methods

alphaLowerString()

Gen<String> alphaLowerString([int? size])

Generator for strings of lowercase ASCII letters with an optional maximum size (default 100).

Implementation
dart
static Gen<String> alphaLowerString([int? size]) => stringOf(alphaLowerChar, size);

alphaNumString()

Gen<String> alphaNumString([int? limit])

Generator for alphanumeric strings with an optional maximum limit (default 100).

Implementation
dart
static Gen<String> alphaNumString([int? limit]) => stringOf(alphaNumChar, limit);

alphaUpperString()

Gen<String> alphaUpperString([int? size])

Generator for strings of uppercase ASCII letters with an optional maximum size (default 100).

Implementation
dart
static Gen<String> alphaUpperString([int? size]) => stringOf(alphaUpperChar, size);

atLeastOne()

Gen<IList<A>> atLeastOne<A>(List<A> as)

Generator for a non-empty IList whose size is drawn from [1, as.length] and whose elements are drawn from as.

Implementation
dart
static Gen<IList<A>> atLeastOne<A>(List<A> as) =>
    chooseInt(1, as.length - 1).flatMap((size) => ilistOfN(size, oneOf(as)));

charSample()

Gen<String> charSample(String chars)

Generator for a single character drawn from chars.

Implementation
dart
static Gen<String> charSample(String chars) => oneOf(chars.split(''));

chooseDouble()

Gen<double> chooseDouble(
  double min,
  double max, {
  IList<double> specials = const Nil(),
})

Generator for double values in [min, max].

specials are extra boundary values that are sampled with higher probability. The built-in specials are min, max, 0.0, 1.0, and -1.0.

Implementation
dart
static Gen<double> chooseDouble(
  double min,
  double max, {
  IList<double> specials = const Nil(),
}) => chooseNum(
  min,
  max,
  ilist([min, max, 0.0, 1.0, -1.0]).concat(specials),
  Choose.dubble,
).withShrinker(Shrinker.dubble);

chooseEnum()

Gen<T> chooseEnum<T extends Enum>(List<T> enumeration)

Generator for a random value from enumeration.

Implementation
dart
static Gen<T> chooseEnum<T extends Enum>(List<T> enumeration) =>
    chooseInt(0, enumeration.length - 1).map((ix) => enumeration[ix]);

chooseInt()

Gen<int> chooseInt(int min, int max, {IList<int> specials = const Nil()})

Generator for int values in [min, max].

specials are extra boundary values that are sampled with higher probability. The built-in specials are min, max, 0, 1, and -1.

Implementation
dart
static Gen<int> chooseInt(
  int min,
  int max, {
  IList<int> specials = const Nil(),
}) => chooseNum(
  min,
  max,
  ilist([min, max, 0, 1, -1]).concat(specials),
  Choose.integer,
).withShrinker(Shrinker.integer);

chooseNum()

Gen<A> chooseNum<A extends num>(
  A min,
  A max,
  IList<A> specials,
  Choose<A> choose,
)

Generator for numeric values in [min, max] with weighted special cases.

Special values that fall within [min, max] are each given weight 1; the remaining range is covered by choose with a weight equal to the number of specials.

Implementation
dart
static Gen<A> chooseNum<A extends num>(
  A min,
  A max,
  IList<A> specials,
  Choose<A> choose,
) {
  final basicsAndSpecials = specials
      .filter((x) => min <= x && x <= max)
      .map((t) => (1, constant(t)));
  final others = (basicsAndSpecials.size, choose.choose(min, max));

  return frequency(basicsAndSpecials.appended(others).toList());
}

constant()

Gen<A> constant<A>(A a)

Generator that always produces a.

Implementation
dart
static Gen<A> constant<A>(A a) => Gen(State.pure(a));

either()

Gen<Either<A, B>> either<A, B>(Gen<A> genA, Gen<B> genB)

Generator for Either values.

Produces Left and Right with equal probability, shrinking via the shrinkers attached to genA and genB.

Implementation
dart
static Gen<Either<A, B>> either<A, B>(Gen<A> genA, Gen<B> genB) => boolean
    .flatMap(
      (a) => a ? genA.map((x) => Either.left<A, B>(x)) : genB.map((x) => Either.right<A, B>(x)),
    )
    .withShrinker(Shrinker.either(genA.shrinker, genB.shrinker));

frequency()

Gen<A> frequency<A>(Iterable<Record> gs)

Generator that picks from gs according to their integer weights.

Each element of gs is a (weight, gen) pair. Pairs with a weight ≤ 0 are ignored. Throws if no pair has a positive weight.

Implementation
dart
static Gen<A> frequency<A>(Iterable<(int, Gen<A>)> gs) {
  final filteredGens = ilist(gs).filter((t) => t.$1 > 0);

  return filteredGens.headOption.fold(
    () => throw Exception('No items with positive weights!'),
    (defaultGen) {
      var sum = 0;
      final tree = SplayTreeMap<int, Gen<A>>();

      for (final (x, gen) in filteredGens.toList()) {
        sum = x + sum;
        tree[sum] = gen;
      }

      return Choose.integer
          .choose(0, sum)
          .flatMap((n) => tree[tree.firstKeyAfter(n)] ?? defaultGen.$2);
    },
  );
}

hexString()

Gen<String> hexString([int? size])

Generator for hexadecimal strings with an optional maximum size (default 100).

Implementation
dart
static Gen<String> hexString([int? size]) => stringOf(hexChar, size);

ilistOf()

Gen<IList<A>> ilistOf<A>(Gen<int> sizeGen, Gen<A> gen)

Generator for IList values whose size is drawn from sizeGen.

Implementation
dart
static Gen<IList<A>> ilistOf<A>(Gen<int> sizeGen, Gen<A> gen) =>
    sizeGen.flatMap((size) => ilistOfN(size, gen)).withShrinker(Shrinker.ilist(gen.shrinker));

ilistOfN()

Gen<IList<A>> ilistOfN<A>(int size, Gen<A> gen)

Generator for IList values with exactly size elements.

Implementation
dart
static Gen<IList<A>> ilistOfN<A>(int size, Gen<A> gen) =>
    listOfN(size, gen).map(IList.fromDart).withShrinker(Shrinker.ilist(gen.shrinker));

imapOf()

Gen<IMap<A, B>> imapOf<A, B>(Gen<int> sizeGen, Gen<A> keyGen, Gen<B> valueGen)

Generator for IMap values whose size is drawn from sizeGen.

Implementation
dart
static Gen<IMap<A, B>> imapOf<A, B>(Gen<int> sizeGen, Gen<A> keyGen, Gen<B> valueGen) => sizeGen
    .flatMap((size) => imapOfN(size, keyGen, valueGen))
    .withShrinker(Shrinker.imap(keyGen.shrinker, valueGen.shrinker));

imapOfN()

Gen<IMap<A, B>> imapOfN<A, B>(int size, Gen<A> keyGen, Gen<B> valueGen)

Generator for IMap values with exactly size entries.

Implementation
dart
static Gen<IMap<A, B>> imapOfN<A, B>(int size, Gen<A> keyGen, Gen<B> valueGen) => mapOfN(
  size,
  keyGen,
  valueGen,
).map(IMap.fromDart).withShrinker(Shrinker.imap(keyGen.shrinker, valueGen.shrinker));

listOf()

Gen<List<A>> listOf<A>(Gen<int> sizeGen, Gen<A> gen)

Generator for List values whose size is drawn from sizeGen.

Implementation
dart
static Gen<List<A>> listOf<A>(Gen<int> sizeGen, Gen<A> gen) =>
    sizeGen.flatMap((size) => listOfN(size, gen)).withShrinker(Shrinker.list(gen.shrinker));

listOfN()

Gen<List<A>> listOfN<A>(int size, Gen<A> gen)

Generator for List values with exactly size elements.

Implementation
dart
static Gen<List<A>> listOfN<A>(int size, Gen<A> gen) => Gen(
  State((rand) {
    var currentRand = rand;
    final list = <A>[];
    for (var i = 0; i < size; i++) {
      final result = gen.sample.run(currentRand);
      currentRand = result.$1;
      list.add(result.$2);
    }
    return (currentRand, list);
  }),
  shrinker: Shrinker.list(gen.shrinker),
);

mapOf()

Gen<Map<A, B>> mapOf<A, B>(Gen<int> sizeGen, Gen<A> keyGen, Gen<B> valueGen)

Generator for Map values whose size is drawn from sizeGen.

Implementation
dart
static Gen<Map<A, B>> mapOf<A, B>(Gen<int> sizeGen, Gen<A> keyGen, Gen<B> valueGen) => sizeGen
    .flatMap((size) => mapOfN(size, keyGen, valueGen))
    .withShrinker(Shrinker.map(keyGen.shrinker, valueGen.shrinker));

mapOfN()

Gen<Map<A, B>> mapOfN<A, B>(int size, Gen<A> keyGen, Gen<B> valueGen)

Generator for Map values with exactly size entries.

Implementation
dart
static Gen<Map<A, B>> mapOfN<A, B>(int size, Gen<A> keyGen, Gen<B> valueGen) => Gen(
  State((rand) {
    var currentRand = rand;

    final map = <A, B>{};

    for (var i = 0; i < size; i++) {
      final keyResult = keyGen.sample.run(currentRand);
      currentRand = keyResult.$1;

      final valResult = valueGen.sample.run(currentRand);
      currentRand = valResult.$1;

      map[keyResult.$2] = valResult.$2;
    }

    return (currentRand, map);
  }),
  shrinker: Shrinker.map(keyGen.shrinker, valueGen.shrinker),
);

nonEmptyAlphaNumString()

Gen<String> nonEmptyAlphaNumString([int? limit])

Generator for non-empty alphanumeric strings with an optional maximum limit (default 100).

Implementation
dart
static Gen<String> nonEmptyAlphaNumString([int? limit]) => nonEmptyStringOf(alphaNumChar, limit);

nonEmptyHexString()

Gen<String> nonEmptyHexString([int? size])

Generator for non-empty hexadecimal strings with an optional maximum size (default 100).

Implementation
dart
static Gen<String> nonEmptyHexString([int? size]) => nonEmptyStringOf(hexChar, size);

nonEmptyIList()

Gen<NonEmptyIList<A>> nonEmptyIList<A>(Gen<A> gen, [int? limit])

Generator for non-empty IList values with sizes drawn from [1, limit] (default limit 1000).

Implementation
dart
static Gen<NonEmptyIList<A>> nonEmptyIList<A>(Gen<A> gen, [int? limit]) => Choose.integer
    .choose(1, limit ?? 1000)
    .flatMap((size) => Gen.ilistOfN(size, gen).map(NonEmptyIList.unsafe));

nonEmptyStringOf()

Gen<String> nonEmptyStringOf(Gen<String> char, [int? limit])

Generator for non-empty strings built from char with lengths in [1, limit] (default limit 100).

Implementation
dart
static Gen<String> nonEmptyStringOf(Gen<String> char, [int? limit]) => listOf(
  Gen.chooseInt(1, limit ?? 100),
  char,
).map((a) => a.join()).withShrinker(Shrinker.string);

oneOf()

Gen<A> oneOf<A>(Iterable<A> xs)

Generator that picks a random element from xs.

Throws if xs is empty.

Implementation
dart
static Gen<A> oneOf<A>(Iterable<A> xs) => Choose.integer
    .choose(0, xs.length)
    .map(
      (ix) => ilist(xs).lift(ix).getOrElse(() => throw Exception('oneOf called on empty list')),
    );

oneOfGen()

Gen<A> oneOfGen<A>(List<Gen<A>> xs)

Generator that picks a random generator from xs and samples from it.

Throws if xs is empty.

Implementation
dart
static Gen<A> oneOfGen<A>(List<Gen<A>> xs) => Choose.integer
    .choose(0, xs.length)
    .flatMap(
      (ix) =>
          ilist(xs).lift(ix).getOrElse(() => throw Exception('oneOfGen called on empty list')),
    );

option()

Gen<Option<A>> option<A>(Gen<A> a)

Generator for Option values.

Produces None with probability 1/10 and Some with probability 9/10.

Implementation
dart
static Gen<Option<A>> option<A>(Gen<A> a) =>
    frequency([(1, constant(none<A>())), (9, some(a))]).withShrinker(Shrinker.option(a.shrinker));

sequence()

Gen<IList<A>> sequence<A>(IList<Gen<A>> gs)

Runs each generator in gs in sequence and collects the results into an IList.

Implementation
dart
static Gen<IList<A>> sequence<A>(IList<Gen<A>> gs) => Gen(
  State((rand) {
    var currentRand = rand;
    final list = <A>[];
    for (final gen in gs.toList()) {
      final result = gen.sample.run(currentRand);
      currentRand = result.$1;
      list.add(result.$2);
    }
    return (currentRand, IList.fromDart(list));
  }),
);

some()

Gen<Option<A>> some<A>(Gen<A> a)

Generator that wraps every sampled value from a in Some.

Implementation
dart
static Gen<Option<A>> some<A>(Gen<A> a) => a.map((a) => Some(a));

stringOf()

Gen<String> stringOf(Gen<String> char, [int? limit])

Generator for strings built from char with lengths in [0, limit] (default limit 100).

Implementation
dart
static Gen<String> stringOf(Gen<String> char, [int? limit]) => listOf(
  Gen.chooseInt(0, limit ?? 100),
  char,
).map((a) => a.join()).withShrinker(Shrinker.string);