6
6
import com .jnape .palatable .lambda .functor .Applicative ;
7
7
import com .jnape .palatable .lambda .functor .Bifunctor ;
8
8
import com .jnape .palatable .lambda .monad .Monad ;
9
+ import com .jnape .palatable .lambda .monad .MonadRec ;
9
10
import com .jnape .palatable .lambda .traversable .Traversable ;
10
11
11
12
import java .util .Objects ;
12
13
14
+ import static com .jnape .palatable .lambda .functions .builtin .fn2 .Sequence .sequence ;
15
+
13
16
/**
14
17
* Specialized {@link CoProduct2} representing the possible results of a primitive recursive function.
15
18
* Used by {@link Trampoline} to cheat around {@link CoProduct2#match} and quickly unpack values via
22
25
public abstract class RecursiveResult <A , B > implements
23
26
CoProduct2 <A , B , RecursiveResult <A , B >>,
24
27
Bifunctor <A , B , RecursiveResult <?, ?>>,
25
- Monad <B , RecursiveResult <A , ?>>,
28
+ MonadRec <B , RecursiveResult <A , ?>>,
26
29
Traversable <B , RecursiveResult <A , ?>> {
27
30
28
31
private RecursiveResult () {
29
32
}
30
33
34
+ /**
35
+ * {@inheritDoc}
36
+ */
31
37
@ Override
32
38
public RecursiveResult <B , A > invert () {
33
39
return match (RecursiveResult ::terminate , RecursiveResult ::recurse );
34
40
}
35
41
42
+ /**
43
+ * {@inheritDoc}
44
+ */
36
45
@ Override
37
- @ SuppressWarnings ("unchecked" )
38
46
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 );
40
48
}
41
49
50
+ /**
51
+ * {@inheritDoc}
52
+ */
42
53
@ Override
43
- @ SuppressWarnings ("unchecked" )
44
54
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 );
46
56
}
47
57
58
+ /**
59
+ * {@inheritDoc}
60
+ */
48
61
@ Override
49
62
public <C , D > RecursiveResult <C , D > biMap (Fn1 <? super A , ? extends C > lFn ,
50
63
Fn1 <? super B , ? extends D > rFn ) {
51
64
return match (a -> recurse (lFn .apply (a )), b -> terminate (rFn .apply (b )));
52
65
}
53
66
67
+ /**
68
+ * {@inheritDoc}
69
+ */
54
70
@ Override
55
71
public <C > RecursiveResult <A , C > flatMap (Fn1 <? super B , ? extends Monad <C , RecursiveResult <A , ?>>> f ) {
56
72
return match (RecursiveResult ::recurse , b -> f .apply (b ).coerce ());
57
73
}
58
74
75
+ /**
76
+ * {@inheritDoc}
77
+ */
59
78
@ Override
60
79
public <C > RecursiveResult <A , C > pure (C c ) {
61
80
return terminate (c );
62
81
}
63
82
83
+ /**
84
+ * {@inheritDoc}
85
+ */
64
86
@ Override
65
87
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 ();
67
89
}
68
90
91
+ /**
92
+ * {@inheritDoc}
93
+ */
69
94
@ Override
70
95
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 ();
72
97
}
73
98
99
+ /**
100
+ * {@inheritDoc}
101
+ */
74
102
@ Override
75
103
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 ();
77
105
}
78
106
107
+ /**
108
+ * {@inheritDoc}
109
+ */
79
110
@ Override
80
111
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 ();
82
113
}
83
114
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
+ */
84
129
@ Override
85
130
public <C , App extends Applicative <?, App >, TravB extends Traversable <C , RecursiveResult <A , ?>>,
86
131
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
89
134
b -> fn .apply (b ).fmap (this ::pure ).<TravB >fmap (RecursiveResult ::coerce ).coerce ());
90
135
}
91
136
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
+ */
92
145
public static <A , B > RecursiveResult <A , B > recurse (A a ) {
93
146
return new Recurse <>(a );
94
147
}
95
148
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
+ */
96
157
public static <A , B > RecursiveResult <A , B > terminate (B b ) {
97
158
return new Terminate <>(b );
98
159
}
0 commit comments