summaryrefslogtreecommitdiff
path: root/pbt/ts/src/property.ts
diff options
context:
space:
mode:
Diffstat (limited to 'pbt/ts/src/property.ts')
-rw-r--r--pbt/ts/src/property.ts27
1 files changed, 27 insertions, 0 deletions
diff --git a/pbt/ts/src/property.ts b/pbt/ts/src/property.ts
index 500c423..04f2a62 100644
--- a/pbt/ts/src/property.ts
+++ b/pbt/ts/src/property.ts
@@ -1,3 +1,5 @@
+import {Option, getOrElse, isSome, none, some} from 'fp-ts/lib/Option';
+import {LazyArg, pipe} from 'fp-ts/lib/function';
import Prando from 'prando';
type Result = 'OK' | 'Falsified' | 'Exception';
@@ -125,6 +127,31 @@ export function elements<A>(arr: A[]): Gen<A> {
};
}
+export function frequency<A>(distribution: [number, Gen<A>][]): Gen<A> {
+ const total: number = distribution.reduce((acc, [freq, _]) => acc + freq, 0);
+
+ return (rng: Prando) => (size: number) => {
+ const idx = rng.next(0, total);
+ let selectedGen: Option<Gen<A>> = none;
+ selectedGen = distribution.reduce((found, [freq, gen]) => {
+ if (isSome(found)) {
+ return found;
+ } else if (idx <= freq) {
+ return some(gen);
+ } else {
+ return none;
+ }
+ }, selectedGen);
+ const generator: Gen<A> = pipe(
+ selectedGen,
+ getOrElse((() => {
+ throw new Error(`invalid frequency distribution ${distribution}`);
+ }) as LazyArg<Gen<A>>),
+ );
+ return generator(rng)(size);
+ };
+}
+
/// Select one key-value pair from given map
export function keyValueOf<K, V>(map: Map<K, V>): Gen<[K, V]> {
let keys = Array.from(map.keys());