Skip to content

Commit cd0de7e

Browse files
committed
Documentation
1 parent 2380a87 commit cd0de7e

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

core/src/main/java/fj/control/Trampoline.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@
66
import fj.P1;
77
import fj.data.Either;
88

9-
import static fj.Function.andThen;
109
import static fj.Function.curry;
1110
import static fj.data.Either.left;
1211
import static fj.data.Either.right;
1312

1413
/**
1514
* A Trampoline is a potentially branching computation that can be stepped through and executed in constant stack.
15+
* It represent suspendable coroutines with subroutine calls, reified as a data structure.
1616
*/
1717
public abstract class Trampoline<A> {
18+
19+
// A Normal Trampoline is either done or suspended, and is allowed to be a subcomputation of a Codense.
20+
// This is the pointed functor part of the Trampoline monad.
1821
private static abstract class Normal<A> extends Trampoline<A> {
1922
public abstract <R> R foldNormal(final F<A, R> pure, final F<P1<Trampoline<A>>, R> k);
2023

@@ -23,8 +26,14 @@ public <B> Trampoline<B> bind(final F<A, Trampoline<B>> f) {
2326
}
2427
}
2528

29+
// A Codense Trampoline delimits a subcomputation and tracks its current continuation. Subcomputations are only
30+
// allowed to be Normal, so all of the continuations accumulate on the right.
2631
private static final class Codense<A> extends Trampoline<A> {
32+
33+
// The Normal subcomputation
2734
private final Normal<Object> sub;
35+
36+
// The current continuation
2837
private final F<Object, Trampoline<A>> cont;
2938

3039
private Codense(final Normal<Object> t, final F<Object, Trampoline<A>> k) {
@@ -37,6 +46,8 @@ public <R> R fold(final F<Normal<A>, R> n,
3746
return gs.f(this);
3847
}
3948

49+
// The monadic bind constructs a new Codense whose subcomputation is still `sub`, and Kleisli-composes the
50+
// continuations.
4051
public <B> Trampoline<B> bind(final F<A, Trampoline<B>> f) {
4152
return codense(sub, new F<Object, Trampoline<B>>() {
4253
public Trampoline<B> f(final Object o) {
@@ -49,6 +60,8 @@ public Trampoline<B> _1() {
4960
});
5061
}
5162

63+
// The resumption of a Codense is the resumption of its subcomputation. If that computation is done, its result
64+
// gets shifted into the continuation.
5265
public Either<P1<Trampoline<A>>, A> resume() {
5366
return left(sub.resume().either(new F<P1<Trampoline<Object>>, P1<Trampoline<A>>>() {
5467
public P1<Trampoline<A>> f(final P1<Trampoline<Object>> p) {
@@ -93,7 +106,9 @@ public Trampoline<A> _1() {
93106
}
94107
}
95108

109+
// A suspended computation that can be resumed.
96110
private static final class Suspend<A> extends Normal<A> {
111+
97112
private final P1<Trampoline<A>> suspension;
98113

99114
private Suspend(final P1<Trampoline<A>> s) {
@@ -113,6 +128,7 @@ public Either<P1<Trampoline<A>>, A> resume() {
113128
}
114129
}
115130

131+
// A pure value at the leaf of a computation.
116132
private static final class Pure<A> extends Normal<A> {
117133
private final A value;
118134

@@ -150,7 +166,7 @@ public Trampoline<A> f(final A a) {
150166
}
151167

152168
/**
153-
* Constructs a leaf computation that results in the given value.
169+
* Constructs a pure computation that results in the given value.
154170
*
155171
* @param a The value of the result.
156172
* @return A trampoline that results in the given value.
@@ -307,13 +323,20 @@ public Trampoline<C> f(final Trampoline<A> as, final Trampoline<B> bs) {
307323
});
308324
}
309325

326+
/**
327+
* Combines two trampolines so they run cooperatively. The results are combined with the given function.
328+
*
329+
* @param b Another trampoline to combine with this trampoline.
330+
* @param f A function to combine the results of the two trampolines.
331+
* @return A new trampoline that runs this trampoline and the given trampoline simultaneously.
332+
*/
310333
@SuppressWarnings("LoopStatementThatDoesntLoop")
311334
public <B, C> Trampoline<C> zipWith(final Trampoline<B> b, final F2<A, B, C> f) {
312335
final Either<P1<Trampoline<A>>, A> ea = resume();
313336
final Either<P1<Trampoline<B>>, B> eb = b.resume();
314337
Trampoline<C> r;
315338
for (final P1<Trampoline<A>> x : ea.left()) {
316-
for (final P1<Trampoline<B>> y: eb.left()) {
339+
for (final P1<Trampoline<B>> y : eb.left()) {
317340
return suspend(P1.bind(x, y, new F2<Trampoline<A>, Trampoline<B>, Trampoline<C>>() {
318341
public Trampoline<C> f(final Trampoline<A> ta, final Trampoline<B> tb) {
319342
return ta.bind(tb, new F2<A, B, C>() {
@@ -324,23 +347,23 @@ public C f(final A a, final B b) {
324347
}
325348
}.curry()));
326349
}
327-
for (final B y: eb.right()) {
350+
for (final B y : eb.right()) {
328351
return suspend(x.map(new F<Trampoline<A>, Trampoline<C>>() {
329352
public Trampoline<C> f(final Trampoline<A> ta) {
330353
return ta.map(f.flip().f(y));
331354
}
332355
}));
333356
}
334357
}
335-
for (final A x: ea.right()) {
336-
for (final B y: eb.right()) {
358+
for (final A x : ea.right()) {
359+
for (final B y : eb.right()) {
337360
return suspend(new P1<Trampoline<C>>() {
338361
public Trampoline<C> _1() {
339362
return pure(f.f(x, y));
340363
}
341364
});
342365
}
343-
for (final P1<Trampoline<B>> y: eb.left()) {
366+
for (final P1<Trampoline<B>> y : eb.left()) {
344367
return suspend(y.map(liftM2(f.curry()).f(pure(x))));
345368
}
346369
}

0 commit comments

Comments
 (0)