1
1
package com .jnape .palatable .lambda .adt ;
2
2
3
+ import com .jnape .palatable .lambda .adt .choice .Choice2 ;
4
+ import com .jnape .palatable .lambda .adt .choice .Choice3 ;
5
+ import com .jnape .palatable .lambda .adt .coproduct .CoProduct2 ;
6
+ import com .jnape .palatable .lambda .adt .hlist .HList ;
7
+ import com .jnape .palatable .lambda .adt .hlist .Tuple2 ;
3
8
import com .jnape .palatable .lambda .functions .builtin .fn2 .Peek ;
4
9
import com .jnape .palatable .lambda .functions .specialized .checked .CheckedSupplier ;
5
10
import com .jnape .palatable .lambda .functor .Applicative ;
14
19
import java .util .function .Supplier ;
15
20
16
21
import static com .jnape .palatable .lambda .adt .Either .left ;
22
+ import static com .jnape .palatable .lambda .adt .Unit .UNIT ;
23
+ import static com .jnape .palatable .lambda .functions .builtin .fn1 .Constantly .constantly ;
24
+ import static com .jnape .palatable .lambda .functions .builtin .fn1 .Id .id ;
17
25
18
26
/**
19
27
* The optional type, representing a potentially absent value. This is lambda's analog of {@link Optional}, supporting
22
30
* @param <A> the optional parameter type
23
31
* @see Optional
24
32
*/
25
- public abstract class Maybe <A > implements Monad <A , Maybe >, Traversable <A , Maybe > {
33
+ public abstract class Maybe <A > implements CoProduct2 <Unit , A , Maybe <A >>, Monad <A , Maybe >, Traversable <A , Maybe > {
34
+
26
35
private Maybe () {
27
36
}
28
37
@@ -32,7 +41,9 @@ private Maybe() {
32
41
* @param otherSupplier the supplier for the other value
33
42
* @return this value, or the supplied other value
34
43
*/
35
- public abstract A orElseGet (Supplier <A > otherSupplier );
44
+ public final A orElseGet (Supplier <A > otherSupplier ) {
45
+ return match (__ -> otherSupplier .get (), id ());
46
+ }
36
47
37
48
/**
38
49
* If the value is present, return it; otherwise, return <code>other</code>.
@@ -130,7 +141,24 @@ public final <B> Maybe<A> discardR(Applicative<B, Maybe> appB) {
130
141
}
131
142
132
143
@ Override
133
- public abstract <B > Maybe <B > flatMap (Function <? super A , ? extends Monad <B , Maybe >> f );
144
+ public final <B > Maybe <B > flatMap (Function <? super A , ? extends Monad <B , Maybe >> f ) {
145
+ return match (constantly (nothing ()), f .andThen (Applicative ::coerce ));
146
+ }
147
+
148
+ @ Override
149
+ public <B > Choice3 <Unit , A , B > diverge () {
150
+ return match (Choice3 ::a , Choice3 ::b );
151
+ }
152
+
153
+ @ Override
154
+ public Tuple2 <Maybe <Unit >, Maybe <A >> project () {
155
+ return CoProduct2 .super .project ().into (HList ::tuple );
156
+ }
157
+
158
+ @ Override
159
+ public Choice2 <A , Unit > invert () {
160
+ return match (Choice2 ::b , Choice2 ::a );
161
+ }
134
162
135
163
/**
136
164
* If this value is present, accept it by <code>consumer</code>; otherwise, do nothing.
@@ -142,6 +170,14 @@ public final Maybe<A> peek(Consumer<A> consumer) {
142
170
return Peek .peek (consumer , this );
143
171
}
144
172
173
+ @ Override
174
+ @ SuppressWarnings ("unchecked" )
175
+ public final <B , App extends Applicative , TravB extends Traversable <B , Maybe >, AppB extends Applicative <B , App >, AppTrav extends Applicative <TravB , App >> AppTrav traverse (
176
+ Function <? super A , ? extends AppB > fn ,
177
+ Function <? super TravB , ? extends AppTrav > pure ) {
178
+ return match (__ -> pure .apply ((TravB ) Maybe .<B >nothing ()), a -> (AppTrav ) fn .apply (a ).fmap (Maybe ::just ));
179
+ }
180
+
145
181
/**
146
182
* Convenience static factory method for creating a {@link Maybe} from an {@link Either}. If <code>either</code> is
147
183
* a right value, wrap the value in a <code>just</code> and return it; otherwise, return {@link #nothing()}.
@@ -192,80 +228,60 @@ public static <A> Maybe<A> just(A a) {
192
228
return new Just <>(a );
193
229
}
194
230
231
+ /**
232
+ * Return nothing.
233
+ *
234
+ * @param <A> the type of the value, if there was one
235
+ * @return nothing
236
+ */
195
237
@ SuppressWarnings ("unchecked" )
196
238
public static <A > Maybe <A > nothing () {
197
239
return Nothing .INSTANCE ;
198
240
}
199
241
200
- private static final class Just <A > extends Maybe <A > {
201
-
202
- private final A a ;
203
-
204
- private Just (A a ) {
205
- this .a = a ;
206
- }
207
-
208
- @ Override
209
- public A orElseGet (Supplier <A > otherSupplier ) {
210
- return a ;
211
- }
212
-
213
- @ Override
214
- public <B > Maybe <B > flatMap (Function <? super A , ? extends Monad <B , Maybe >> f ) {
215
- return f .apply (a ).coerce ();
216
- }
217
-
218
- @ Override
219
- @ SuppressWarnings ("unchecked" )
220
- public <B , App extends Applicative , TravB extends Traversable <B , Maybe >,
221
- AppB extends Applicative <B , App >, AppTrav extends Applicative <TravB , App >> AppTrav traverse (
222
- Function <? super A , ? extends AppB > fn , Function <? super TravB , ? extends AppTrav > pure ) {
223
- return fn .apply (a ).fmap (Just ::new ).<TravB >fmap (Applicative ::coerce ).coerce ();
224
- }
242
+ private static final class Nothing <A > extends Maybe <A > {
243
+ private static final Nothing INSTANCE = new Nothing ();
225
244
226
- @ Override
227
- public boolean equals (Object other ) {
228
- return other instanceof Just && Objects .equals (this .a , ((Just ) other ).a );
245
+ private Nothing () {
229
246
}
230
247
231
248
@ Override
232
- public int hashCode ( ) {
233
- return Objects . hash ( a );
249
+ public < R > R match ( Function <? super Unit , ? extends R > aFn , Function <? super A , ? extends R > bFn ) {
250
+ return aFn . apply ( UNIT );
234
251
}
235
252
236
253
@ Override
237
254
public String toString () {
238
- return "Just " + a ;
255
+ return "Nothing" ;
239
256
}
240
257
}
241
258
242
- private static final class Nothing <A > extends Maybe <A > {
243
- private static final Nothing INSTANCE = new Nothing ();
259
+ private static final class Just <A > extends Maybe <A > {
244
260
245
- private Nothing () {
261
+ private final A a ;
262
+
263
+ private Just (A a ) {
264
+ this .a = a ;
246
265
}
247
266
248
267
@ Override
249
- @ SuppressWarnings ("unchecked" )
250
- public <B > Maybe <B > flatMap (Function <? super A , ? extends Monad <B , Maybe >> f ) {
251
- return nothing ();
268
+ public <R > R match (Function <? super Unit , ? extends R > aFn , Function <? super A , ? extends R > bFn ) {
269
+ return bFn .apply (a );
252
270
}
253
271
254
272
@ Override
255
- @ SuppressWarnings ("unchecked" )
256
- public <B , App extends Applicative , TravB extends Traversable <B , Maybe >, AppB extends Applicative <B , App >, AppTrav extends Applicative <TravB , App >> AppTrav traverse (
257
- Function <? super A , ? extends AppB > fn , Function <? super TravB , ? extends AppTrav > pure ) {
258
- return pure .apply ((TravB ) nothing ());
273
+ public boolean equals (Object other ) {
274
+ return other instanceof Just && Objects .equals (this .a , ((Just ) other ).a );
259
275
}
260
276
261
277
@ Override
262
- public A orElseGet ( Supplier < A > otherSupplier ) {
263
- return otherSupplier . get ( );
278
+ public int hashCode ( ) {
279
+ return Objects . hash ( a );
264
280
}
265
281
266
282
@ Override
267
283
public String toString () {
268
- return "Nothing" ;
284
+ return "Just " + a ;
269
285
}
270
286
}
271
287
}
0 commit comments