|
5 | 5 | import com.jnape.palatable.lambda.functions.Fn0; |
6 | 6 | import com.jnape.palatable.lambda.functions.Fn1; |
7 | 7 | import com.jnape.palatable.lambda.functions.Fn2; |
| 8 | +import com.jnape.palatable.lambda.functions.recursion.RecursiveResult; |
8 | 9 | import com.jnape.palatable.lambda.functions.specialized.Pure; |
9 | 10 | import com.jnape.palatable.lambda.functions.specialized.SideEffect; |
10 | 11 | import com.jnape.palatable.lambda.functor.Applicative; |
|
13 | 14 | import com.jnape.palatable.lambda.io.IO; |
14 | 15 | import com.jnape.palatable.lambda.monad.Monad; |
15 | 16 | import com.jnape.palatable.lambda.monad.MonadError; |
| 17 | +import com.jnape.palatable.lambda.monad.MonadRec; |
16 | 18 | import com.jnape.palatable.lambda.traversable.Traversable; |
17 | 19 |
|
18 | 20 | import java.util.Objects; |
19 | 21 |
|
20 | 22 | import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly; |
21 | 23 | import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id; |
22 | 24 | import static com.jnape.palatable.lambda.functions.builtin.fn3.FoldLeft.foldLeft; |
| 25 | +import static com.jnape.palatable.lambda.functions.recursion.RecursiveResult.terminate; |
| 26 | +import static com.jnape.palatable.lambda.functions.recursion.Trampoline.trampoline; |
23 | 27 | import static com.jnape.palatable.lambda.functor.builtin.Lazy.lazy; |
24 | 28 | import static com.jnape.palatable.lambda.io.IO.io; |
25 | 29 | import static java.util.Arrays.asList; |
|
35 | 39 | public abstract class Either<L, R> implements |
36 | 40 | CoProduct2<L, R, Either<L, R>>, |
37 | 41 | MonadError<L, R, Either<L, ?>>, |
| 42 | + MonadRec<R, Either<L, ?>>, |
38 | 43 | Traversable<R, Either<L, ?>>, |
39 | 44 | Bifunctor<L, R, Either<?, ?>> { |
40 | 45 |
|
@@ -134,6 +139,16 @@ public <R2> Either<L, R2> flatMap(Fn1<? super R, ? extends Monad<R2, Either<L, ? |
134 | 139 | return match(Either::left, rightFn.fmap(Monad<R2, Either<L, ?>>::coerce)); |
135 | 140 | } |
136 | 141 |
|
| 142 | + /** |
| 143 | + * {@inheritDoc} |
| 144 | + */ |
| 145 | + @Override |
| 146 | + public <B> Either<L, B> trampolineM(Fn1<? super R, ? extends MonadRec<RecursiveResult<R, B>, Either<L, ?>>> fn) { |
| 147 | + return match(Either::left, trampoline(a -> fn.apply(a).<Either<L, RecursiveResult<R, B>>>coerce() |
| 148 | + .match(l -> terminate(left(l)), |
| 149 | + aOrB -> aOrB.fmap(Either::right)))); |
| 150 | + } |
| 151 | + |
137 | 152 | @Override |
138 | 153 | public final Either<R, L> invert() { |
139 | 154 | return match(Either::right, Either::left); |
|
0 commit comments