Skip to content

Commit 35f8178

Browse files
committed
#163: Implemented Validation.sequence using a semigroup
1 parent bd3c4c6 commit 35f8178

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,18 @@ public <A> Validation<E, A> sequence(final Validation<E, A> v) {
200200
return bind(Function.<T, Validation<E, A>>constant(v));
201201
}
202202

203+
/**
204+
* If list contains a failure, returns a failure of the reduction of
205+
* all the failures using the semigroup, otherwise returns the successful list.
206+
*/
207+
public static <E, A> Validation<E, List<A>> sequence(final Semigroup<E> s, final List<Validation<E, A>> list) {
208+
if (list.exists(v -> v.isFail())) {
209+
return Validation.<E, List<A>>fail(list.filter(v -> v.isFail()).map(v -> v.fail()).foldLeft1((e1, e2) -> s.sum(e1, e2)));
210+
} else {
211+
return Validation.success(list.foldLeft((List<A> acc, Validation<E, A> v) -> acc.cons(v.success()), List.nil()).reverse());
212+
}
213+
}
214+
203215
/**
204216
* Returns <code>None</code> if this is a failure or if the given predicate <code>p</code> does not hold for the
205217
* success value, otherwise, returns a success in <code>Some</code>.

props-core/src/test/java/fj/data/properties/ValidationProperties.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fj.data.properties;
22

33
import fj.P2;
4+
import fj.Semigroup;
45
import fj.data.List;
56
import fj.data.Validation;
67
import fj.test.Arbitrary;
@@ -45,4 +46,18 @@ public Property sequenceReduce() {
4546
});
4647
}
4748

49+
public Property sequence() {
50+
return Property.property(arbList(arbValidation(arbString, arbInteger)), list -> {
51+
Validation<String, List<Integer>> v = Validation.sequence(Semigroup.stringSemigroup, list);
52+
Property p1 = implies(list.exists((Validation<String, Integer> v2) -> v2.isFail()), () -> prop(v.isFail()));
53+
boolean b = list.forall((Validation<String, Integer> v2) -> v2.isSuccess());
54+
Property p2 = implies(b, () -> {
55+
List<Integer> l2 = list.map((Validation<String, Integer> v2) -> v2.success());
56+
boolean b2 = v.success().equals(l2);
57+
return prop(b2);
58+
});
59+
return p1.and(p2);
60+
});
61+
}
62+
4863
}

0 commit comments

Comments
 (0)