66import com .jnape .palatable .lambda .functor .Applicative ;
77import com .jnape .palatable .lambda .functor .Bifunctor ;
88import com .jnape .palatable .lambda .monad .Monad ;
9+ import com .jnape .palatable .lambda .monad .MonadRec ;
910import com .jnape .palatable .lambda .traversable .Traversable ;
1011
1112import 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
2225public 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 }
0 commit comments