Skip to content

Commit 5ee01bf

Browse files
authored
Merge pull request #400 from drewctaylor/functionaljava-400
Add fj.data.Option.sequence(Validation<E, Option<A>>).
2 parents 39896f5 + e98db34 commit 5ee01bf

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

core/src/main/java/fj/data/Option.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,11 +372,11 @@ public final <B> Option<P2<A,B>> bindProduct(final Option<B> ob) {
372372
public final <B, C> Option<P3<A,B,C>> bindProduct(final Option<B> ob, final Option<C> oc) {
373373
return bind(ob, oc, P.p3());
374374
}
375-
375+
376376
public final <B, C, D> Option<P4<A,B,C,D>> bindProduct(final Option<B> ob, final Option<C> oc, final Option<D> od) {
377377
return bind(ob, oc, od, P.p4());
378378
}
379-
379+
380380
public final <B,C,D,E> Option<P5<A,B,C,D,E>> bindProduct(final Option<B> ob, final Option<C> oc, final Option<D> od,
381381
final Option<E> oe) {
382382
return bind(ob, oc, od, oe, P.p5());
@@ -712,7 +712,7 @@ public static <A> Option<A> join(final Option<Option<A>> o) {
712712
}
713713

714714
/**
715-
* Sequence through the option monad.
715+
* Sequence a list through the option monad.
716716
*
717717
* @param a The list of option to sequence.
718718
* @return The option of list after sequencing.
@@ -723,6 +723,16 @@ public static <A> Option<List<A>> sequence(final List<Option<A>> a) {
723723
a.head().bind(aa -> sequence(a.tail()).map(cons_(aa)));
724724
}
725725

726+
/**
727+
* Sequence a validation through the option monad.
728+
*
729+
* @param a The validation of option to sequence.
730+
* @return The option of validation after sequencing.
731+
*/
732+
public static <E, A> Option<Validation<E, A>> sequence(final Validation<E, Option<A>> a) {
733+
return a.traverseOption(identity());
734+
}
735+
726736
/**
727737
* Returns an optional value that has a value of the given argument, if the given predicate holds
728738
* on that argument, otherwise, returns no value.

core/src/test/java/fj/data/OptionTest.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package fj.data;
22

3-
import org.junit.Assert;
43
import org.junit.Test;
54

5+
import static fj.data.List.arrayList;
6+
import static fj.data.List.nil;
7+
import static fj.data.Option.none;
8+
import static fj.data.Option.sequence;
69
import static fj.data.Option.some;
10+
import static fj.data.Validation.fail;
11+
import static fj.data.Validation.success;
12+
import static org.junit.Assert.assertEquals;
713
import static org.junit.Assert.assertTrue;
814

915
/**
@@ -26,4 +32,21 @@ public void traverseList() {
2632
assertTrue(actual.equals(expected));
2733
}
2834

35+
@Test
36+
public void sequenceListTest() {
37+
assertEquals(some(nil()), sequence(nil()));
38+
assertEquals(none(), sequence(arrayList(none())));
39+
assertEquals(some(arrayList(1)), sequence(arrayList(some(1))));
40+
assertEquals(none(), sequence(arrayList(none(), none())));
41+
assertEquals(none(), sequence(arrayList(some(1), none())));
42+
assertEquals(none(), sequence(arrayList(none(), some(2))));
43+
assertEquals(some(arrayList(1, 2)), sequence(arrayList(some(1), some(2))));
44+
}
45+
46+
@Test
47+
public void sequenceValidationTest() {
48+
assertEquals(some(fail(1)), sequence(Validation.<Integer, Option<String>>fail(1)));
49+
assertEquals(none(), sequence(Validation.<Integer, Option<String>>success(none())));
50+
assertEquals(some(success("string")), sequence(Validation.<Integer, Option<String>>success(some("string"))));
51+
}
2952
}

0 commit comments

Comments
 (0)