|
1 | 1 | package fj.control;
|
2 | 2 |
|
| 3 | +import fj.Bottom; |
3 | 4 | import fj.F;
|
4 | 5 | import fj.F2;
|
5 | 6 | import fj.P1;
|
6 | 7 | import fj.data.Either;
|
7 | 8 |
|
| 9 | +import static fj.Function.andThen; |
8 | 10 | import static fj.Function.curry;
|
9 | 11 | import static fj.data.Either.left;
|
10 | 12 | import static fj.data.Either.right;
|
@@ -305,5 +307,43 @@ public Trampoline<C> f(final Trampoline<A> as, final Trampoline<B> bs) {
|
305 | 307 | });
|
306 | 308 | }
|
307 | 309 |
|
308 |
| - |
| 310 | + @SuppressWarnings("LoopStatementThatDoesntLoop") |
| 311 | + public <B, C> Trampoline<C> zipWith(final Trampoline<B> b, final F2<A, B, C> f) { |
| 312 | + final Either<P1<Trampoline<A>>, A> ea = resume(); |
| 313 | + final Either<P1<Trampoline<B>>, B> eb = b.resume(); |
| 314 | + Trampoline<C> r; |
| 315 | + for (final P1<Trampoline<A>> x : ea.left()) { |
| 316 | + for (final P1<Trampoline<B>> y: eb.left()) { |
| 317 | + return suspend(P1.bind(x, y, new F2<Trampoline<A>, Trampoline<B>, Trampoline<C>>() { |
| 318 | + public Trampoline<C> f(final Trampoline<A> ta, final Trampoline<B> tb) { |
| 319 | + return ta.bind(tb, new F2<A, B, C>() { |
| 320 | + public C f(final A a, final B b) { |
| 321 | + return f.f(a, b); |
| 322 | + } |
| 323 | + }.curry()); |
| 324 | + } |
| 325 | + }.curry())); |
| 326 | + } |
| 327 | + for (final B y: eb.right()) { |
| 328 | + return suspend(x.map(new F<Trampoline<A>, Trampoline<C>>() { |
| 329 | + public Trampoline<C> f(final Trampoline<A> ta) { |
| 330 | + return ta.map(f.flip().f(y)); |
| 331 | + } |
| 332 | + })); |
| 333 | + } |
| 334 | + } |
| 335 | + for (final A x: ea.right()) { |
| 336 | + for (final B y: eb.right()) { |
| 337 | + return suspend(new P1<Trampoline<C>>() { |
| 338 | + public Trampoline<C> _1() { |
| 339 | + return pure(f.f(x, y)); |
| 340 | + } |
| 341 | + }); |
| 342 | + } |
| 343 | + for (final P1<Trampoline<B>> y: eb.left()) { |
| 344 | + return suspend(y.map(liftM2(f.curry()).f(pure(x)))); |
| 345 | + } |
| 346 | + } |
| 347 | + throw Bottom.error("Match error: Trampoline is neither done nor suspended."); |
| 348 | + } |
309 | 349 | }
|
0 commit comments