|
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