All it takes to be a Monad is to provide two functions which conform to three laws.
The two functions:
- Place a value into monadic context
- Haskell's Maybe: return / Just
- Scala's Option: Some
- Functional Java's Option: Option.some
- JDK8's Optional: Optional.of
- Apply a function in monadic context
- Haskell's Maybe: >>= (aka bind)
- Scala's Option: flatMap
- Functional Java's Option: flatMap
- JDK8's Optional: flatMap
NOTE: One of the key things to understand is the signature of the function to apply in monadic context: it takes the raw value type, and returns the monadic type.
In other words, if you have Optional<Integer>
, the functions you
can pass to flatMap
will have the signature (Integer) -> Optional<U>
,
where U
is a value type which does not have to be Integer, for example String
:
Optional<Integer> maybeInteger = Optional.of(1);
// Function that takes Integer and returns Optional<Integer>
Optional<Integer> maybePlusOne = maybeInteger.flatMap(n -> Optional.of(n + 1));
// Function that takes Integer and returns Optional<String>
Optional<String> maybeString = maybePlusOne.flatMap(n -> Optional.of(n.toString));
You don't need any sort of Monad Interface to code this way, or to think this way. In Scala, you don't code to a Monad Interface (unless you are using Scalaz library...). It appears that JDK8 will empower Java folks to use this style of chained monadic computations as well.