Skip to content

Commit 2269c74

Browse files
committed
Merged #80: Added traverse method family
1 parent 57fa068 commit 2269c74

7 files changed

Lines changed: 396 additions & 190 deletions

File tree

core/src/main/java/fj/P1.java

Lines changed: 68 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
import fj.data.Array;
66
import fj.data.List;
77
import fj.data.Stream;
8+
import fj.data.Either;
9+
import fj.data.Option;
10+
import fj.data.Validation;
11+
//import fj.data.*;
12+
import fj.function.Try0;
813

914
public abstract class P1<A> implements F0<A> {
1015

@@ -26,11 +31,7 @@ public A f() {
2631
* @return A function that returns the first element of a product.
2732
*/
2833
public static <A> F<P1<A>, A> __1() {
29-
return new F<P1<A>, A>() {
30-
public A f(final P1<A> p) {
31-
return p._1();
32-
}
33-
};
34+
return p -> p._1();
3435
}
3536

3637
/**
@@ -40,11 +41,7 @@ public A f(final P1<A> p) {
4041
* @return A function promoted to operate on P1s.
4142
*/
4243
public static <A, B> F<P1<A>, P1<B>> fmap(final F<A, B> f) {
43-
return new F<P1<A>, P1<B>>() {
44-
public P1<B> f(final P1<A> a) {
45-
return a.map(f);
46-
}
47-
};
44+
return a -> a.map(f);
4845
}
4946

5047
/**
@@ -55,11 +52,7 @@ public P1<B> f(final P1<A> a) {
5552
*/
5653
public <B> P1<B> bind(final F<A, P1<B>> f) {
5754
P1<A> self = this;
58-
return new P1<B>() {
59-
public B _1() {
60-
return f.f(self._1())._1();
61-
}
62-
};
55+
return P.lazy(u -> f.f(self._1())._1());
6356
}
6457

6558
/**
@@ -69,15 +62,7 @@ public B _1() {
6962
* @return A function whose result is wrapped in a P1.
7063
*/
7164
public static <A, B> F<A, P1<B>> curry(final F<A, B> f) {
72-
return new F<A, P1<B>>() {
73-
public P1<B> f(final A a) {
74-
return new P1<B>() {
75-
public B _1() {
76-
return f.f(a);
77-
}
78-
};
79-
}
80-
};
65+
return a -> P.lazy(u -> f.f(a));
8166
}
8267

8368
/**
@@ -88,11 +73,7 @@ public B _1() {
8873
*/
8974
public <B> P1<B> apply(final P1<F<A, B>> cf) {
9075
P1<A> self = this;
91-
return cf.bind(new F<F<A, B>, P1<B>>() {
92-
public P1<B> f(final F<A, B> f) {
93-
return fmap(f).f(self);
94-
}
95-
});
76+
return cf.bind(f -> fmap(f).f(self));
9677
}
9778

9879
/**
@@ -123,11 +104,7 @@ public static <A> P1<A> join(final P1<P1<A>> a) {
123104
* @return A function of arity-2 promoted to map over P1s.
124105
*/
125106
public static <A, B, C> F<P1<A>, F<P1<B>, P1<C>>> liftM2(final F<A, F<B, C>> f) {
126-
return Function.curry(new F2<P1<A>, P1<B>, P1<C>>() {
127-
public P1<C> f(final P1<A> pa, final P1<B> pb) {
128-
return pa.bind(pb, f);
129-
}
130-
});
107+
return Function.curry((pa, pb) -> pa.bind(pb, f));
131108
}
132109

133110
/**
@@ -146,11 +123,7 @@ public static <A> P1<List<A>> sequence(final List<P1<A>> as) {
146123
* @return A function from a List of P1s to a single P1 of a List.
147124
*/
148125
public static <A> F<List<P1<A>>, P1<List<A>>> sequenceList() {
149-
return new F<List<P1<A>>, P1<List<A>>>() {
150-
public P1<List<A>> f(final List<P1<A>> as) {
151-
return sequence(as);
152-
}
153-
};
126+
return as -> sequence(as);
154127
}
155128

156129
/**
@@ -170,11 +143,57 @@ public static <A> P1<Stream<A>> sequence(final Stream<P1<A>> as) {
170143
* @return A single P1 for the given array.
171144
*/
172145
public static <A> P1<Array<A>> sequence(final Array<P1<A>> as) {
173-
return new P1<Array<A>>() {
174-
public Array<A> _1() {
175-
return as.map(P1.<A>__1());
176-
}
177-
};
146+
return P.lazy(u -> as.map(P1.<A>__1()));
147+
}
148+
149+
/**
150+
* Traversable instance of P1 for List
151+
*
152+
* @param f The function that takes A and produces a List<B> (non-deterministic result)
153+
* @return A List of P1<B>
154+
*/
155+
public <B> List<P1<B>> traverseList(final F<A, List<B>> f){
156+
return f.f(_1()).map(b -> P.p(b));
157+
}
158+
159+
/**
160+
* Traversable instance of P1 for Either
161+
*
162+
* @param f The function produces Either
163+
* @return An Either of P1<B>
164+
*/
165+
public <B, X> Either<X, P1<B>> traverseEither(final F<A, Either<X, B>> f){
166+
return f.f(_1()).right().map(b -> P.p(b));
167+
}
168+
169+
/**
170+
* Traversable instance of P1 for Option
171+
*
172+
* @param f The function that produces Option
173+
* @return An Option of P1<B>
174+
*/
175+
public <B> Option<P1<B>> traverseOption(final F<A, Option<B>> f){
176+
return f.f(_1()).map(b -> P.p(b));
177+
}
178+
179+
/**
180+
* Traversable instance of P1 for Validation
181+
*
182+
* @param f The function might produces Validation
183+
* @return An Validation of P1<B>
184+
*/
185+
public <B, E> Validation<E, P1<B>> traverseValidation(final F<A, Validation<E, B>> f){
186+
return f.f(_1()).map(b -> P.p(b));
187+
}
188+
189+
/**
190+
* Traversable instance of P1 for Stream
191+
*
192+
* @param f The function that produces Stream
193+
* @return An Stream of P1<B>
194+
*/
195+
public <B> Stream<P1<B>> traverseStream(final F<A, Stream<B>> f){
196+
return f.f(_1()).map(b -> P.p(b));
178197
}
179198

180199
/**
@@ -185,11 +204,7 @@ public Array<A> _1() {
185204
*/
186205
public <X> P1<X> map(final F<A, X> f) {
187206
final P1<A> self = this;
188-
return new P1<X>() {
189-
public X _1() {
190-
return f.f(self._1());
191-
}
192-
};
207+
return P.lazy(u -> f.f(self._1()));
193208
}
194209

195210
/**
@@ -198,12 +213,12 @@ public X _1() {
198213
* @return A P1 that calls this P1 once and remembers the value for subsequent calls.
199214
*/
200215
public P1<A> memo() {
201-
final P1<A> self = this;
216+
final P1<A> self = this;
202217
return new P1<A>() {
203218
private final Object latch = new Object();
204219
@SuppressWarnings({"InstanceVariableMayNotBeInitialized"})
205220
private volatile SoftReference<A> v;
206-
221+
207222
public A _1() {
208223
A a = v != null ? v.get() : null;
209224
if (a == null)
@@ -228,18 +243,15 @@ static <A> P1<A> memo(F<Unit, A> f) {
228243
*/
229244
public <B> F<B, A> constant() {
230245

231-
return new F<B, A>() {
232-
public A f(final B b) {
233-
return P1.this._1();
234-
}
235-
};
246+
return b -> P1.this._1();
236247
}
237248

238249
@Override
239250
public String toString() {
240251
return Show.p1Show(Show.<A>anyShow()).showS(this);
241252
}
242253

254+
@SuppressWarnings("unchecked")
243255
@Override
244256
public boolean equals(Object other) {
245257
return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p1Equal(Equal.<A>anyEqual()).eq(this, (P1<A>) other)));

core/src/main/java/fj/P2.java

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package fj;
22

33
import static fj.Function.*;
4-
import fj.data.List;
5-
import fj.data.Stream;
4+
5+
import fj.data.*;
66

77
/**
88
* A product-2.
@@ -156,6 +156,26 @@ public final <C> List<C> sequenceW(final List<F<P2<A, B>, C>> fs) {
156156
return cs.toList();
157157
}
158158

159+
public final <C> List<P2<A, C>> traverseList(final F<B, List<C>> f) {
160+
return f.f(_2()).map(x -> P.p(_1(), x));
161+
}
162+
163+
public final <C> Stream<P2<A, C>> traverseStream(final F<B, Stream<C>> f) {
164+
return f.f(_2()).map(x -> P.p(_1(), x));
165+
}
166+
167+
public final <C> IO<P2<A, C>> traverseIO(final F<B, IO<C>> f) {
168+
return IOFunctions.map(f.f(_2()), x -> P.p(_1(), x));
169+
}
170+
171+
public final <C> Option<P2<A, C>> traverseOption(final F<B, Option<C>> f) {
172+
return f.f(_2()).map(x -> P.p(_1(), x));
173+
}
174+
175+
public final <C, X> Either<X, P2<A, C>> traverseEither(final F<B, Either<X, C>> f) {
176+
return f.f(_2()).right().map(x -> P.p(_1(), x));
177+
}
178+
159179
/**
160180
* Applies a stream of comonadic functions to this product, returning a stream of values.
161181
*
@@ -219,11 +239,7 @@ public B _2() {
219239
* @return A function that splits a given product between the two given functions and combines their output.
220240
*/
221241
public static <A, B, C, D> F<P2<A, B>, P2<C, D>> split_(final F<A, C> f, final F<B, D> g) {
222-
return new F<P2<A, B>, P2<C, D>>() {
223-
public P2<C, D> f(final P2<A, B> p) {
224-
return p.split(f, g);
225-
}
226-
};
242+
return p -> p.split(f, g);
227243
}
228244

229245
/**
@@ -233,11 +249,7 @@ public P2<C, D> f(final P2<A, B> p) {
233249
* @return The given function, promoted to map the first element of products.
234250
*/
235251
public static <A, B, X> F<P2<A, B>, P2<X, B>> map1_(final F<A, X> f) {
236-
return new F<P2<A, B>, P2<X, B>>() {
237-
public P2<X, B> f(final P2<A, B> p) {
238-
return p.map1(f);
239-
}
240-
};
252+
return p -> p.map1(f);
241253
}
242254

243255
/**
@@ -247,11 +259,7 @@ public P2<X, B> f(final P2<A, B> p) {
247259
* @return The given function, promoted to map the second element of products.
248260
*/
249261
public static <A, B, X> F<P2<A, B>, P2<A, X>> map2_(final F<B, X> f) {
250-
return new F<P2<A, B>, P2<A, X>>() {
251-
public P2<A, X> f(final P2<A, B> p) {
252-
return p.map2(f);
253-
}
254-
};
262+
return p -> p.map2(f);
255263
}
256264

257265
/**
@@ -283,11 +291,7 @@ public static <A, B> P2<B, B> map(final F<A, B> f, final P2<A, A> p) {
283291
* @return A curried form of {@link #swap()}.
284292
*/
285293
public static <A, B> F<P2<A, B>, P2<B, A>> swap_() {
286-
return new F<P2<A, B>, P2<B, A>>() {
287-
public P2<B, A> f(final P2<A, B> p) {
288-
return p.swap();
289-
}
290-
};
294+
return p -> p.swap();
291295
}
292296

293297
/**
@@ -296,11 +300,7 @@ public P2<B, A> f(final P2<A, B> p) {
296300
* @return A function that returns the first element of a product.
297301
*/
298302
public static <A, B> F<P2<A, B>, A> __1() {
299-
return new F<P2<A, B>, A>() {
300-
public A f(final P2<A, B> p) {
301-
return p._1();
302-
}
303-
};
303+
return p -> p._1();
304304
}
305305

306306
/**
@@ -309,11 +309,7 @@ public A f(final P2<A, B> p) {
309309
* @return A function that returns the second element of a product.
310310
*/
311311
public static <A, B> F<P2<A, B>, B> __2() {
312-
return new F<P2<A, B>, B>() {
313-
public B f(final P2<A, B> p) {
314-
return p._2();
315-
}
316-
};
312+
return p -> p._2();
317313
}
318314

319315
/**
@@ -323,11 +319,7 @@ public B f(final P2<A, B> p) {
323319
* @return The function, transformed to operate on on a product-2
324320
*/
325321
public static <A, B, C> F<P2<A, B>, C> tuple(final F<A, F<B, C>> f) {
326-
return new F<P2<A, B>, C>() {
327-
public C f(final P2<A, B> p) {
328-
return f.f(p._1()).f(p._2());
329-
}
330-
};
322+
return p -> f.f(p._1()).f(p._2());
331323
}
332324

333325
/**
@@ -347,11 +339,7 @@ public static <A, B, C> F<P2<A, B>, C> tuple(final F2<A, B, C> f) {
347339
* @return The function, transformed to an uncurried function of arity-2.
348340
*/
349341
public static <A, B, C> F2<A, B, C> untuple(final F<P2<A, B>, C> f) {
350-
return new F2<A, B, C>() {
351-
public C f(final A a, final B b) {
352-
return f.f(P.p(a, b));
353-
}
354-
};
342+
return (a, b) -> f.f(P.p(a, b));
355343
}
356344

357345
@Override

0 commit comments

Comments
 (0)