summaryrefslogtreecommitdiff
path: root/src/main/java/au/id/zancanaro/Generator.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/au/id/zancanaro/Generator.java')
-rw-r--r--src/main/java/au/id/zancanaro/Generator.java51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/main/java/au/id/zancanaro/Generator.java b/src/main/java/au/id/zancanaro/Generator.java
new file mode 100644
index 0000000..4b80e51
--- /dev/null
+++ b/src/main/java/au/id/zancanaro/Generator.java
@@ -0,0 +1,51 @@
+package au.id.zancanaro;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.function.Function;
+
+public interface Generator<T> {
+ RoseTree<T> generate(Random random, int size);
+
+ static <T> Generator<T> pure(T value) {
+ return (random, size) -> RoseTree.pure(value);
+ }
+
+ default <R> Generator<R> genFlatmap(Function<RoseTree<T>, Generator<R>> f) {
+ return (random, size) -> {
+ RoseTree<T> inner = this.generate(random, size);
+ Generator<R> generator = f.apply(inner);
+ return generator.generate(random, size);
+ };
+ }
+
+ default <R> Generator<R> genFmap(Function<RoseTree<T>, RoseTree<R>> f) {
+ return (random, size) -> f.apply(this.generate(random, size));
+ }
+
+ @SafeVarargs
+ static <T> Generator<T[]> tuple(Generator<T>... generators) {
+ return (random, size) -> {
+ @SuppressWarnings("unchecked")
+ RoseTree<T>[] result = (RoseTree<T>[]) new RoseTree[generators.length];
+ int index = 0;
+ for (Generator<T> generator : generators) {
+ result[index++] = generator.generate(random, size);
+ }
+ return RoseTree.zip(Function.identity(), result);
+ };
+ }
+
+ default <R> Generator<R> fmap(Function<T, R> f) {
+ return (random, size) -> this.generate(random, size).fmap(f);
+ }
+
+ default <R> Generator<R> flatMap(Function<T, Generator<R>> action) {
+ return this.genFlatmap(rose -> {
+ Generator<RoseTree<R>> generator = (random, size) ->
+ rose.fmap(action).fmap(g -> g.generate(random, size));
+ return generator.<R>genFmap(RoseTree::join);
+ });
+ }
+}