Skip to content

Commit 0a50e8b

Browse files
Fixes #401. Add fj.test.Gen.sequence(Validation<E, Gen<A>>).
1 parent 5ee01bf commit 0a50e8b

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

quickcheck/src/main/java/fj/test/Gen.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import fj.data.List;
1111
import fj.data.Option;
1212
import fj.data.Stream;
13+
import fj.data.Validation;
1314
import fj.function.Effect1;
1415

1516
import static fj.Bottom.error;
@@ -319,6 +320,19 @@ public static <A> Gen<List<A>> sequenceN(final int n, final Gen<A> g) {
319320
return sequence(replicate(n, g));
320321
}
321322

323+
/**
324+
* Transform a validation for a generator into a generator of validations: if the given validation is a failure, the
325+
* generator produces that failure value; if the given validation is a success, the generator produces success values.
326+
*
327+
* @param gv The validation for a generator.
328+
* @param <A> the type of the value
329+
* @param <E> the type of the failure
330+
* @return if the given validation is a failure, the generator produces that failure value; if the given validation is a success, the generator produces success values.
331+
*/
332+
public static <E, A> Gen<Validation<E, A>> sequence(final Validation<E, Gen<A>> gv) {
333+
return gen(i -> r -> gv.map(g -> g.gen(i, r)));
334+
}
335+
322336
/**
323337
* Constructs a generator that can access its construction arguments &mdash; size and random
324338
* generator.

quickcheck/src/test/java/fj/test/GenTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
package fj.test;
22

3+
import fj.Equal;
34
import fj.data.List;
5+
import fj.data.NonEmptyList;
6+
import fj.data.Option;
47
import fj.data.Stream;
8+
import fj.data.Validation;
59
import fj.function.Effect1;
610
import org.junit.Test;
711

812
import static fj.Ord.charOrd;
913
import static fj.data.List.list;
1014
import static fj.data.List.range;
15+
import static fj.data.NonEmptyList.nel;
16+
import static fj.data.Option.somes;
17+
import static fj.data.Validation.fail;
18+
import static fj.data.Validation.success;
1119
import static fj.test.Gen.combinationOf;
20+
import static fj.test.Gen.listOf;
1221
import static fj.test.Gen.permutationOf;
1322
import static fj.test.Gen.pickOne;
1423
import static fj.test.Gen.selectionOf;
24+
import static fj.test.Gen.sequence;
1525
import static fj.test.Gen.streamOf;
1626
import static fj.test.Gen.wordOf;
1727
import static fj.test.Rand.standard;
@@ -187,6 +197,15 @@ public void testStreamOf() {
187197
});
188198
}
189199

200+
@Test
201+
public void testSequenceValidation() {
202+
final Gen<List<Validation<NonEmptyList<Exception>, Character>>> success = listOf(sequence(success(pickOne(AS))), 4);
203+
testPick(100, success, list -> assertEquals(list.length(),somes(list.map(v -> Option.sequence(v.map(c -> AS.elementIndex(Equal.anyEqual(), c))))).length()));
204+
205+
final Gen<List<Validation<NonEmptyList<Exception>, Gen<Character>>>> failure = listOf(sequence(fail(nel(new Exception()))), 4);
206+
testPick(100, failure, list -> assertTrue(list.forall(a -> a.isFail())));
207+
}
208+
190209
private static <A> void testPick(int n, Gen<List<A>> instance, Effect1<List<A>> test) {
191210
range(0, n).map(ignore -> instance.gen(0, standard)).foreachDoEffect(test);
192211
}

0 commit comments

Comments
 (0)