Skip to content

Commit ef3d99b

Browse files
committed
Merge pull request #85 from mperry/option-traverse
Add traverse family of methods to Option
2 parents 18ae251 + fd3951b commit ef3d99b

2 files changed

Lines changed: 73 additions & 0 deletions

File tree

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import fj.Unit;
1818
import fj.Show;
1919
import fj.function.Effect1;
20+
import fj.Equal;
21+
import fj.Ord;
2022

2123
import static fj.Function.*;
2224
import static fj.P.p;
@@ -415,6 +417,47 @@ public final <B> Option<B> sequence(final Option<B> o) {
415417
return bind(c);
416418
}
417419

420+
public <L, B> Either<L, Option<B>> traverseEither(F<A, Either<L, B>> f) {
421+
return map(a -> f.f(a).right().map(b -> some(b))).orSome(Either.right(none()));
422+
}
423+
424+
public <B> IO<Option<B>> traverseIO(F<A, IO<B>> f) {
425+
return map(a -> IOFunctions.map(f.f(a), b -> some(b))).orSome(IOFunctions.lazy(u -> none()));
426+
}
427+
428+
public <B> List<Option<B>> traverseList(F<A, List<B>> f) {
429+
return map(a -> f.f(a).map(b -> some(b))).orSome(List.list());
430+
}
431+
432+
public <B> Option<Option<B>> traverseOption(F<A, Option<B>> f) {
433+
return map(f);
434+
}
435+
436+
public <B> Stream<Option<B>> traverseStream(F<A, Stream<B>> f) {
437+
return map(a -> f.f(a).map(b -> some(b))).orSome(Stream.nil());
438+
}
439+
440+
public <B> P1<Option<B>> traverseP1(F<A, P1<B>> f) {
441+
return map(a -> f.f(a).map(b -> some(b))).orSome(P.p(none()));
442+
}
443+
444+
public <B> Seq<Option<B>> traverseSeq(F<A, Seq<B>> f) {
445+
return map(a -> f.f(a).map(b -> some(b))).orSome(Seq.empty());
446+
}
447+
448+
public <B> Set<Option<B>> traverseSet(Ord<B> ord, F<A, Set<B>> f) {
449+
Ord<Option<B>> optOrd = Ord.optionOrd(ord);
450+
return map(a -> f.f(a).map(optOrd, b -> some(b))).orSome(Set.empty(optOrd));
451+
}
452+
453+
public <B> F2<Ord<B>, F<A, Set<B>>, Set<Option<B>>> traverseSet() {
454+
return (o, f) -> traverseSet(o, f);
455+
}
456+
457+
public <E, B> Validation<E, Option<B>> traverseValidation(F<A, Validation<E, B>> f) {
458+
return map(a -> f.f(a).map(b -> some(b))).orSome(Validation.success(none()));
459+
}
460+
418461
/**
419462
* Performs function application within an optional value (applicative functor pattern).
420463
*
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package fj.data;
2+
3+
import org.junit.Assert;
4+
import org.junit.Test;
5+
6+
import static fj.data.Option.some;
7+
import static org.junit.Assert.assertTrue;
8+
9+
/**
10+
* Created by MarkPerry on 15/01/2015.
11+
*/
12+
public class OptionTest {
13+
14+
@Test
15+
public void equals() {
16+
int max = 4;
17+
assertTrue(some(1).equals(some(1)));
18+
assertTrue(some(List.range(1, max)).equals(some(List.range(1, max))));
19+
}
20+
21+
@Test
22+
public void traverseList() {
23+
int max = 3;
24+
List<Option<Integer>> actual = some(max).traverseList(a -> List.range(1, a + 1));
25+
List<Option<Integer>> expected = List.range(1, max + 1).map(i -> some(i));
26+
System.out.println(String.format("actual: %s, expected: %s", actual.toString(), expected.toString()));
27+
assertTrue(actual.equals(expected));
28+
}
29+
30+
}

0 commit comments

Comments
 (0)