Skip to content

Commit 0fc97a9

Browse files
committed
Adding Maybe treatment to README
1 parent b3b99ef commit 0fc97a9

1 file changed

Lines changed: 52 additions & 1 deletion

File tree

README.md

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ Functional patterns for Java 8
1919
- [Monads](#monads)
2020
- [Traversables](#traversables)
2121
- [ADTs](#adts)
22-
- [HLists](#hlists)
22+
- [Maybe](#maybe)
23+
- [HList](#hlist)
2324
- [Tuples](#tuples)
2425
- [HMaps](#hmaps)
2526
- [CoProducts](#coproducts)
@@ -455,6 +456,56 @@ As always, there are [some laws](https://hackage.haskell.org/package/base-4.9.1.
455456

456457
Lambda also supports a few first-class [algebraic data types](https://www.wikiwand.com/en/Algebraic_data_type).
457458

459+
### <a name="maybe">Maybe</a>
460+
461+
`Maybe` is the _lambda_ analog to `java.util.Optional`. It behaves in much of the same way as `j.u.Optional`, except that it quite intentionally does not support the inherently unsafe `j.u.Optional#get`.
462+
463+
```Java
464+
Maybe<Integer> maybeInt = Maybe.just(1); // Just 1
465+
Maybe<String> maybeString = Maybe.nothing(); // Nothing
466+
```
467+
468+
Also, because it's a _lambda_ type, it takes advantage of the full functor hierarchy, as well as some helpful conversion functions:
469+
470+
```Java
471+
Maybe<String> just = Maybe.maybe("string"); // Just "string"
472+
Maybe<String> nothing = Maybe.maybe(null); // Nothing
473+
474+
Maybe<Integer> maybeX = Maybe.just(1);
475+
Maybe<Integer> maybeY = Maybe.just(2);
476+
477+
maybeY.zip(maybeX.fmap(x -> y -> x + y)); // Just 3
478+
maybeY.zip(nothing()); // Nothing
479+
Maybe.<Integer>nothing().zip(maybeX.fmap(x -> y -> x + y)); // Nothing
480+
481+
Either<String, Integer> right = maybeX.toEither(() -> "was empty"); // Right 1
482+
Either<String, Integer> left = Maybe.<Integer>nothing().toEither(() -> "was empty"); // Left "was empty"
483+
484+
Maybe.fromEither(right); // Just 1
485+
Maybe.fromEither(left); // Nothing
486+
```
487+
488+
Finally, for compatibility purposes, `Maybe` and `j.u.Optional` can be trivially converted back and forth:
489+
490+
```Java
491+
Maybe<Integer> just1 = Maybe.just(1); // Just 1
492+
Optional<Integer> present1 = just1.toOptional(); // Optional.of(1)
493+
494+
Optional<String> empty = Optional.empty(); // Optional.empty()
495+
Maybe<String> nothing = Maybe.fromOptional(empty); // Nothing
496+
```
497+
498+
***Note***: One compatibility difference between `j.u.Optional` and `Maybe` is how `map`/`fmap` behave regarding functions that return `null`: `j.u.Optional` re-wraps `null` results from `map` operations in another `j.u.Optional`, whereas `Maybe` considers this to be an error, and throws an exception. The reason `Maybe` throws in this case is because `fmap` is not an operation to be called speculatively, and so any function that returns `null` in the context of an `fmap` operation is considered to be erroneous. Instead of calling `fmap` with a function that might return `null`, the function result should be wrapped in a `Maybe` and `flatMap` should be used, as illustrated in the following example:
499+
500+
```Java
501+
Function<Integer, Object> nullResultFn = __ -> null;
502+
503+
Optional.of(1).map(nullResultFn); // Optional.empty()
504+
Maybe.just(1).fmap(nullResultFn); // throws NullPointerException
505+
506+
Maybe.just(1).flatMap(nullResultFn.andThen(Maybe::maybe)); // Nothing
507+
```
508+
458509
### <a name="hlists">Heterogeneous Lists (HLists)</a>
459510
460511
HLists are type-safe heterogeneous lists, meaning they can store elements of different types in the same list while facilitating certain type-safe interactions.

0 commit comments

Comments
 (0)