|
28 | 28 | import static com.jnape.palatable.lambda.adt.choice.Choice2.a;
|
29 | 29 | import static com.jnape.palatable.lambda.adt.choice.Choice2.b;
|
30 | 30 | import static com.jnape.palatable.lambda.adt.hlist.HList.tuple;
|
31 |
| -import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly; |
32 | 31 | import static com.jnape.palatable.lambda.functions.builtin.fn2.Into.into;
|
33 | 32 | import static com.jnape.palatable.lambda.functions.builtin.fn2.Tupler2.tupler;
|
34 | 33 | import static com.jnape.palatable.lambda.functions.builtin.fn3.FoldLeft.foldLeft;
|
@@ -138,11 +137,30 @@ public IterateT<M, A> concat(IterateT<M, A> other) {
|
138 | 137 | */
|
139 | 138 | public <B, MB extends MonadRec<B, M>> MB fold(Fn2<? super B, ? super A, ? extends MonadRec<B, M>> fn,
|
140 | 139 | MonadRec<B, M> acc) {
|
| 140 | + return foldCut((b, a) -> fn.apply(b, a).fmap(RecursiveResult::recurse), acc); |
| 141 | + } |
| 142 | + |
| 143 | + /** |
| 144 | + * Monolithically fold the spine of this {@link IterateT} (with the possibility of early termination) by |
| 145 | + * {@link MonadRec#trampolineM(Fn1) trampolining} the underlying effects (for iterative folding, use |
| 146 | + * {@link IterateT#trampolineM(Fn1) trampolineM} directly). |
| 147 | + * |
| 148 | + * @param fn the folding function |
| 149 | + * @param acc the starting accumulation effect |
| 150 | + * @param <B> the accumulation type |
| 151 | + * @param <MB> the witnessed target result type |
| 152 | + * @return the folded effect result |
| 153 | + */ |
| 154 | + public <B, MB extends MonadRec<B, M>> MB foldCut( |
| 155 | + Fn2<? super B, ? super A, ? extends MonadRec<RecursiveResult<B, B>, M>> fn, |
| 156 | + MonadRec<B, M> acc) { |
141 | 157 | return acc.fmap(tupler(this))
|
142 | 158 | .trampolineM(into((as, b) -> maybeT(as.runIterateT())
|
143 |
| - .flatMap(into((a, aas) -> maybeT(fn.apply(b, a).fmap(tupler(aas)).fmap(Maybe::just)))) |
| 159 | + .flatMap(into((a, aas) -> maybeT(fn.apply(b, a).fmap(Maybe::just)).fmap(tupler(aas)))) |
144 | 160 | .runMaybeT()
|
145 |
| - .fmap(maybeRecur -> maybeRecur.match(constantly(terminate(b)), RecursiveResult::recurse)))) |
| 161 | + .fmap(maybeR -> maybeR.match( |
| 162 | + __ -> terminate(b), |
| 163 | + into((rest, rr) -> rr.biMapL(tupler(rest))))))) |
146 | 164 | .coerce();
|
147 | 165 | }
|
148 | 166 |
|
|
0 commit comments