Skip to content

Commit 48eaeec

Browse files
committed
Trampoline functions.
1 parent 09e65d4 commit 48eaeec

File tree

4 files changed

+95
-6
lines changed

4 files changed

+95
-6
lines changed

.idea/inspectionProfiles/Project_Default.xml

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/scopes/scope_settings.xml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package fj.control;
22

33
import fj.F;
4+
import fj.F2;
45
import fj.P1;
56
import fj.data.Either;
67

8+
import java.util.Iterator;
9+
10+
import static fj.Function.constant;
11+
import static fj.Function.curry;
712
import static fj.data.Either.left;
813
import static fj.data.Either.right;
914

@@ -256,4 +261,46 @@ public A run() {
256261
}
257262
}
258263
}
264+
265+
/**
266+
* Performs function application within a Trampoline (applicative functor pattern).
267+
*
268+
* @param lf A Trampoline resulting in the function to apply.
269+
* @return A new Trampoline after applying the given function through this Trampoline.
270+
*/
271+
public final <B> Trampoline<B> apply(final Trampoline<F<A, B>> lf) {
272+
return lf.bind(new F<F<A, B>, Trampoline<B>>() {
273+
public Trampoline<B> f(final F<A, B> f) {
274+
return map(f);
275+
}
276+
});
277+
}
278+
279+
/**
280+
* Binds the given function across the result of this Trampoline and the given Trampoline.
281+
*
282+
* @param lb A given Trampoline to bind the given function with.
283+
* @param f The function to combine the results of this Trampoline and the given Trampoline.
284+
* @return A new Trampoline combining the results of the two trampolines with the given function.
285+
*/
286+
public final <B, C> Trampoline<C> bind(final Trampoline<B> lb, final F<A, F<B, C>> f) {
287+
return lb.apply(map(f));
288+
}
289+
290+
291+
/**
292+
* Promotes the given function of arity-2 to a function on Trampolines.
293+
*
294+
* @param f The function to promote to a function on Trampolines.
295+
* @return The given function, promoted to operate on Trampolines.
296+
*/
297+
public static <A, B, C> F<Trampoline<A>, F<Trampoline<B>, Trampoline<C>>> liftM2(final F<A, F<B, C>> f) {
298+
return curry(new F2<Trampoline<A>, Trampoline<B>, Trampoline<C>>() {
299+
public Trampoline<C> f(final Trampoline<A> as, final Trampoline<B> bs) {
300+
return as.bind(bs, f);
301+
}
302+
});
303+
}
304+
305+
259306
}

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

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import static fj.P.p;
2121
import static fj.P.p2;
2222
import static fj.Unit.unit;
23-
import static fj.data.Array.array;
2423
import static fj.data.Array.mkArray;
2524
import static fj.data.List.Buffer.*;
2625
import static fj.data.Option.none;
@@ -30,6 +29,7 @@
3029
import static fj.Ord.intOrd;
3130

3231
import fj.Ordering;
32+
import fj.control.Trampoline;
3333

3434
import java.util.AbstractCollection;
3535
import java.util.Collection;
@@ -458,7 +458,7 @@ public final <B, C> List<C> bind(final List<B> lb, final F2<A, B, C> f) {
458458
/**
459459
* Promotes the given function of arity-2 to a function on lists.
460460
*
461-
* @param f The functio to promote to a function on lists.
461+
* @param f The function to promote to a function on lists.
462462
* @return The given function, promoted to operate on lists.
463463
*/
464464
public static <A, B, C> F<List<A>, F<List<B>, List<C>>> liftM2(final F<A, F<B, C>> f) {
@@ -626,6 +626,20 @@ public final <B> B foldRight(final F2<A, B, B> f, final B b) {
626626
return foldRight(curry(f), b);
627627
}
628628

629+
/**
630+
* Performs a right-fold reduction across this list in O(1) stack space.
631+
* @param f The function to apply on each element of the list.
632+
* @param b The beginning value to start the application from.
633+
* @return A Trampoline containing the final result after the right-fold reduction.
634+
*/
635+
public final <B> Trampoline<B> foldRightC(final F2<A, B, B> f, final B b) {
636+
return Trampoline.suspend(new P1<Trampoline<B>>() {
637+
public Trampoline<B> _1() {
638+
return isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(f.f(head()));
639+
}
640+
});
641+
}
642+
629643
/**
630644
* Performs a left-fold reduction across this list. This function runs in constant space.
631645
*
@@ -1080,7 +1094,7 @@ public final <B, C> F<B, List<C>> mapM(final F<A, F<B, C>> f) {
10801094
/**
10811095
* Maps the given function across this list by binding through the Option monad.
10821096
*
1083-
* @param f Thefunction to apply through the this list.
1097+
* @param f The function to apply through the this list.
10841098
* @return A possible list of values after binding through the Option monad.
10851099
*/
10861100
public final <B> Option<List<B>> mapMOption(final F<A, Option<B>> f) {
@@ -1099,6 +1113,28 @@ public List<B> f(final List<B> bbs) {
10991113
}, Option.<List<B>>some(List.<B>nil()));
11001114
}
11011115

1116+
/**
1117+
* Maps the given function across this list by binding through the Trampoline monad.
1118+
*
1119+
* @param f The function to apply through the this list.
1120+
* @return A list of values in the Trampoline monad.
1121+
*/
1122+
public final <B> Trampoline<List<B>> mapMTrampoline(final F<A, Trampoline<B>> f) {
1123+
return foldRight(new F2<A, Trampoline<List<B>>, Trampoline<List<B>>>() {
1124+
public Trampoline<List<B>> f(final A a, final Trampoline<List<B>> bs) {
1125+
return f.f(a).bind(new F<B, Trampoline<List<B>>>() {
1126+
public Trampoline<List<B>> f(final B b) {
1127+
return bs.map(new F<List<B>, List<B>>() {
1128+
public List<B> f(final List<B> bbs) {
1129+
return bbs.cons(b);
1130+
}
1131+
});
1132+
}
1133+
});
1134+
}
1135+
}, Trampoline.<List<B>>pure(List.<B>nil()));
1136+
}
1137+
11021138
/**
11031139
* Returns the index of the first element in this list which is equal (by the given equality) to the
11041140
* query element, or None if there is no such element.

0 commit comments

Comments
 (0)