diff --git a/src/main/java/com/jnape/palatable/lambda/monad/transformer/builtin/IterateT.java b/src/main/java/com/jnape/palatable/lambda/monad/transformer/builtin/IterateT.java index cb719060..07ee9f29 100644 --- a/src/main/java/com/jnape/palatable/lambda/monad/transformer/builtin/IterateT.java +++ b/src/main/java/com/jnape/palatable/lambda/monad/transformer/builtin/IterateT.java @@ -67,11 +67,11 @@ */ public class IterateT, A> implements MonadT, IterateT> { - private final Pure pureM; - private final ImmutableQueue>>, M>>, MonadRec>> spine; + private final Pure pureM; + private final ImmutableQueue, IterateT>>, M>>, MonadRec, M>>> spine; private IterateT(Pure pureM, - ImmutableQueue>>, M>>, MonadRec>> spine) { + ImmutableQueue, IterateT>>, M>>, MonadRec, M>>> spine) { this.pureM = pureM; this.spine = spine; } @@ -108,10 +108,9 @@ public , IterateT>>, M>> MSte thunkOrReal -> thunkOrReal.match( thunk -> thunk.apply()., IterateT>>>fmap(m -> m.match( fn0(() -> just(tuple(nothing(), new IterateT<>(pureM, spine.tail())))), - t -> just(t.biMap(Maybe::just, - as -> new IterateT<>(pureM, as.spine.concat(spine.tail())))))) - .coerce(), - ma -> ma.fmap(a -> just(tuple(just(a), new IterateT<>(pureM, spine.tail())))).coerce())); + t -> just(t.fmap(as -> new IterateT<>(pureM, as.spine.concat(spine.tail())))))), + mMaybeA -> mMaybeA.fmap(maybeA -> just(tuple(maybeA, new IterateT<>(pureM, spine.tail())))))) + .coerce(); } /** @@ -121,9 +120,17 @@ public , IterateT>>, M>> MSte * @return the cons'ed {@link IterateT} */ public final IterateT cons(MonadRec head) { + return consStep(head.fmap(Maybe::just)); + } + + public final IterateT consStep(MonadRec, M> head) { return new IterateT<>(pureM, spine.pushFront(b(head))); } + public final IterateT snocStep(MonadRec, M> last) { + return new IterateT<>(pureM, spine.pushBack(b(last))); + } + /** * Add an element inside an effect to the back of this {@link IterateT}. * @@ -131,7 +138,7 @@ public final IterateT cons(MonadRec head) { * @return the snoc'ed {@link IterateT} */ public final IterateT snoc(MonadRec last) { - return new IterateT<>(pureM, spine.pushBack(b(last))); + return snocStep(last.fmap(Maybe::just)); } /** @@ -207,18 +214,16 @@ public > IterateT lift(MonadRec nb) { * {@inheritDoc} */ @Override - @SuppressWarnings("RedundantTypeArguments") public IterateT trampolineM( Fn1, IterateT>> fn) { - return $(withSelf( - (self, queued) -> suspended( - () -> pureM.>, MonadRec>, M>>apply(queued) - .trampolineM(q -> q.runIterateT().>, Maybe>>>>fmap(m -> m.match( - __ -> terminate(nothing()), - into((rr, tail) -> rr.biMap( - a -> fn.apply(a).>>coerce().concat(tail), - b -> just(tuple(b, self.apply(tail)))))))), - pureM)), + return $(withSelf((self, queued) -> suspendStep(() -> pureM.>, MonadRec>, M>>apply(queued) + .trampolineM(q -> q.runStep().fmap(m -> m.match( + __ -> terminate(nothing()), + t -> t.into((maybeRR, tail) -> maybeRR.match(__ -> recurse(tail), + rr -> rr.biMap( + a -> fn.apply(a).>>coerce().concat(tail), + b -> just(tuple(just(b), self.apply(tail)))))) + ))), pureM)), flatMap(fn)); } @@ -227,16 +232,17 @@ public IterateT trampolineM( */ @Override public IterateT flatMap(Fn1>> f) { - return suspended(() -> maybeT(runIterateT()) - .trampolineM(into((a, as) -> maybeT( - f.apply(a).>coerce().runIterateT() - .flatMap(maybePair -> maybePair.match( - fn0(() -> as.runIterateT() - .fmap(maybeResult -> maybeResult.fmap(RecursiveResult::recurse))), - t -> pureM.apply(just(terminate(t.fmap(mb -> mb.concat(as.flatMap(f)))))) - ))))) - .runMaybeT(), - pureM); + return suspendStep(() -> { + MonadRec, IterateT>>, M> runStep = runStep(); + return maybeT(runStep) + .trampolineM(into((maybeA, as) -> maybeT(maybeA.match( + fn0(() -> runStep.pure(just(terminate(tuple(Maybe.nothing(), as.flatMap(f)))))), + a -> f.apply(a).>coerce().runStep() + .flatMap(maybePair -> maybePair.match( + fn0(() -> as.runStep().fmap(maybeResult -> maybeResult.fmap(RecursiveResult::recurse))), + t -> runStep.pure(just(terminate(t.fmap(mb -> mb.concat(as.flatMap(f)))))))))))) + .runMaybeT(); + }, pureM); } /** @@ -281,15 +287,18 @@ public , MAS extends MonadRec> MAS toCollection(Fn */ @Override public IterateT zip(Applicative, IterateT> appFn) { - return suspended(() -> { - MonadRec>>, M> mmta = runIterateT(); + return suspendStep(() -> { + MonadRec, IterateT>>, M> mmta = runStep(); return join(maybeT(mmta).zip( - maybeT(appFn.>>coerce().runIterateT()) - .fmap(into((f, fs) -> into((a, as) -> maybeT( - as.fmap(f) - .cons(mmta.pure(f.apply(a))) - .concat(as.cons(mmta.pure(a)).zip(fs)) - .runIterateT())))))) + maybeT(appFn.>>coerce().runStep()) + .fmap(into((maybeF, fs) -> into((maybeA, as) -> maybeF.match( + fn0(() -> maybeT(mmta.pure(just(tuple(nothing(), as.consStep(mmta.pure(maybeA)).zip(fs)))))), + f -> maybeA.match( + fn0(() -> maybeT(mmta.pure(just(tuple(nothing(), as.zip(fs.cons(mmta.pure(f)))))))), + a -> maybeT(as.fmap(f) + .cons(mmta.pure(f.apply(a))) + .concat(as.cons(mmta.pure(a)).zip(fs)) + .runStep())))))))) .runMaybeT(); }, pureM); } @@ -356,6 +365,11 @@ public static , A> IterateT iterateT( return suspended(() -> unwrapped, Pure.of(unwrapped)); } + public static , A> IterateT fromSteps( + MonadRec, IterateT>>, M> unwrapped) { + return new IterateT<>(Pure.of(unwrapped), ImmutableQueue.singleton(a(() -> unwrapped))); + } + /** * Static factory method for creating an {@link IterateT} from a spine represented by one or more elements. * @@ -405,6 +419,11 @@ public static , A, B> IterateT unfold( */ public static , A> IterateT suspended( Fn0>>, M>> thunk, Pure pureM) { + return suspendStep(thunk.fmap(m -> m.fmap(mt -> mt.fmap(t -> t.biMapL(Maybe::just)))), pureM); + } + + public static , A> IterateT suspendStep( + Fn0, IterateT>>, M>> thunk, Pure pureM) { return new IterateT<>(pureM, ImmutableQueue.singleton(a(thunk))); }