Skip to content

Commit 5dd1fad

Browse files
committed
RecursiveResult is now MonadRec
1 parent 1f33cc3 commit 5dd1fad

File tree

2 files changed

+72
-10
lines changed

2 files changed

+72
-10
lines changed

src/main/java/com/jnape/palatable/lambda/functions/recursion/RecursiveResult.java

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
import com.jnape.palatable.lambda.functor.Applicative;
77
import com.jnape.palatable.lambda.functor.Bifunctor;
88
import com.jnape.palatable.lambda.monad.Monad;
9+
import com.jnape.palatable.lambda.monad.MonadRec;
910
import com.jnape.palatable.lambda.traversable.Traversable;
1011

1112
import java.util.Objects;
1213

14+
import static com.jnape.palatable.lambda.functions.builtin.fn2.Sequence.sequence;
15+
1316
/**
1417
* Specialized {@link CoProduct2} representing the possible results of a primitive recursive function.
1518
* Used by {@link Trampoline} to cheat around {@link CoProduct2#match} and quickly unpack values via
@@ -22,65 +25,107 @@
2225
public abstract class RecursiveResult<A, B> implements
2326
CoProduct2<A, B, RecursiveResult<A, B>>,
2427
Bifunctor<A, B, RecursiveResult<?, ?>>,
25-
Monad<B, RecursiveResult<A, ?>>,
28+
MonadRec<B, RecursiveResult<A, ?>>,
2629
Traversable<B, RecursiveResult<A, ?>> {
2730

2831
private RecursiveResult() {
2932
}
3033

34+
/**
35+
* {@inheritDoc}
36+
*/
3137
@Override
3238
public RecursiveResult<B, A> invert() {
3339
return match(RecursiveResult::terminate, RecursiveResult::recurse);
3440
}
3541

42+
/**
43+
* {@inheritDoc}
44+
*/
3645
@Override
37-
@SuppressWarnings("unchecked")
3846
public <C> RecursiveResult<C, B> biMapL(Fn1<? super A, ? extends C> fn) {
39-
return (RecursiveResult<C, B>) Bifunctor.super.biMapL(fn);
47+
return (RecursiveResult<C, B>) Bifunctor.super.<C>biMapL(fn);
4048
}
4149

50+
/**
51+
* {@inheritDoc}
52+
*/
4253
@Override
43-
@SuppressWarnings("unchecked")
4454
public <C> RecursiveResult<A, C> biMapR(Fn1<? super B, ? extends C> fn) {
45-
return (RecursiveResult<A, C>) Bifunctor.super.biMapR(fn);
55+
return (RecursiveResult<A, C>) Bifunctor.super.<C>biMapR(fn);
4656
}
4757

58+
/**
59+
* {@inheritDoc}
60+
*/
4861
@Override
4962
public <C, D> RecursiveResult<C, D> biMap(Fn1<? super A, ? extends C> lFn,
5063
Fn1<? super B, ? extends D> rFn) {
5164
return match(a -> recurse(lFn.apply(a)), b -> terminate(rFn.apply(b)));
5265
}
5366

67+
/**
68+
* {@inheritDoc}
69+
*/
5470
@Override
5571
public <C> RecursiveResult<A, C> flatMap(Fn1<? super B, ? extends Monad<C, RecursiveResult<A, ?>>> f) {
5672
return match(RecursiveResult::recurse, b -> f.apply(b).coerce());
5773
}
5874

75+
/**
76+
* {@inheritDoc}
77+
*/
5978
@Override
6079
public <C> RecursiveResult<A, C> pure(C c) {
6180
return terminate(c);
6281
}
6382

83+
/**
84+
* {@inheritDoc}
85+
*/
6486
@Override
6587
public <C> RecursiveResult<A, C> fmap(Fn1<? super B, ? extends C> fn) {
66-
return Monad.super.<C>fmap(fn).coerce();
88+
return MonadRec.super.<C>fmap(fn).coerce();
6789
}
6890

91+
/**
92+
* {@inheritDoc}
93+
*/
6994
@Override
7095
public <C> RecursiveResult<A, C> zip(Applicative<Fn1<? super B, ? extends C>, RecursiveResult<A, ?>> appFn) {
71-
return Monad.super.zip(appFn).coerce();
96+
return MonadRec.super.zip(appFn).coerce();
7297
}
7398

99+
/**
100+
* {@inheritDoc}
101+
*/
74102
@Override
75103
public <C> RecursiveResult<A, C> discardL(Applicative<C, RecursiveResult<A, ?>> appB) {
76-
return Monad.super.discardL(appB).coerce();
104+
return MonadRec.super.discardL(appB).coerce();
77105
}
78106

107+
/**
108+
* {@inheritDoc}
109+
*/
79110
@Override
80111
public <C> RecursiveResult<A, B> discardR(Applicative<C, RecursiveResult<A, ?>> appB) {
81-
return Monad.super.discardR(appB).coerce();
112+
return MonadRec.super.discardR(appB).coerce();
82113
}
83114

115+
/**
116+
* {@inheritDoc}
117+
*/
118+
@Override
119+
public <C> RecursiveResult<A, C> trampolineM(
120+
Fn1<? super B, ? extends MonadRec<RecursiveResult<B, C>, RecursiveResult<A, ?>>> fn) {
121+
return flatMap(Trampoline.<B, RecursiveResult<A, C>>trampoline(
122+
b -> sequence(fn.apply(b).<RecursiveResult<A, RecursiveResult<B, C>>>coerce(),
123+
RecursiveResult::terminate)));
124+
}
125+
126+
/**
127+
* {@inheritDoc}
128+
*/
84129
@Override
85130
public <C, App extends Applicative<?, App>, TravB extends Traversable<C, RecursiveResult<A, ?>>,
86131
AppTrav extends Applicative<TravB, App>> AppTrav traverse(Fn1<? super B, ? extends Applicative<C, App>> fn,
@@ -89,10 +134,26 @@ AppTrav extends Applicative<TravB, App>> AppTrav traverse(Fn1<? super B, ? exten
89134
b -> fn.apply(b).fmap(this::pure).<TravB>fmap(RecursiveResult::coerce).coerce());
90135
}
91136

137+
/**
138+
* Static factory method for creating a "recurse" value.
139+
*
140+
* @param a the value
141+
* @param <A> the recurse type
142+
* @param <B> the terminate type
143+
* @return the {@link RecursiveResult}
144+
*/
92145
public static <A, B> RecursiveResult<A, B> recurse(A a) {
93146
return new Recurse<>(a);
94147
}
95148

149+
/**
150+
* Static factory method for creating a "terminate" value.
151+
*
152+
* @param b the value
153+
* @param <A> the recurse type
154+
* @param <B> the terminate type
155+
* @return the {@link RecursiveResult}
156+
*/
96157
public static <A, B> RecursiveResult<A, B> terminate(B b) {
97158
return new Terminate<>(b);
98159
}

src/test/java/com/jnape/palatable/lambda/functions/recursion/RecursiveResultTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import testsupport.traits.ApplicativeLaws;
99
import testsupport.traits.FunctorLaws;
1010
import testsupport.traits.MonadLaws;
11+
import testsupport.traits.MonadRecLaws;
1112
import testsupport.traits.TraversableLaws;
1213

1314
import static com.jnape.palatable.lambda.functions.recursion.RecursiveResult.recurse;
@@ -18,7 +19,7 @@
1819
@RunWith(Traits.class)
1920
public class RecursiveResultTest {
2021

21-
@TestTraits({FunctorLaws.class, ApplicativeLaws.class, MonadLaws.class, TraversableLaws.class})
22+
@TestTraits({FunctorLaws.class, ApplicativeLaws.class, MonadLaws.class, TraversableLaws.class, MonadRecLaws.class})
2223
public Subjects<RecursiveResult<String, Integer>> testSubject() {
2324
return subjects(recurse("foo"), terminate(1));
2425
}

0 commit comments

Comments
 (0)