### An intuition

Monad is like a …

There is no good analogy to explain what is monad to new person (monad tutorial fallacy). The best way to get it right is just to do some coding. So lets explore simple design pattern – one-way wrapper. Such wrapper can wrap value but can’t unwrap it back.

In Java it can look like simple immutable object

@ToString @EqualsAndHashCode class Wrap<T> { private final T value; private Wrap(T value) { this.value = value; } public static <T> Wrap<T> of(T value) { return new Wrap<>(value); } }

This class is just going to wrap a value using factory method `of`

. There are no getters and setters, but present `toString`

, `equals`

and `hashCode`

for convenience (see lombok).

To do something with value we need a method that will apply mapping function and then return new wrapped value. It is important to keep value wrapped so it never escapes.

class Wrap<T> { // ... public <R> Wrap<R> map(Function<T, R> mapper) { return Wrap.of(mapper.apply(value)); } }

Wrap<Integer> a = Wrap.of(1); // Wrap(value=1) Wrap<Integer> b = a.map(i -> i + 9); // Wrap(value=10) Wrap<Integer> c = b.map(i -> i * 11); // Wrap(value=110) a.map(i -> i * 10).map(i -> i + 11); // Wrap(value=21)

OK, now we can do something with this, but usually things are more interesting. After starting using wrapped values here and there we eventually create method like this

Wrap<Integer> inc(Integer x) { return Wrap.of(x + 1); }

`inc`

gets a number and then returns a wrapped result. It is very useful business logic and we want to apply it even to wrapped values.

Wrap<Integer> a = Wrap.of(1); // Wrap(value=1) a.map(this::inc); // Wrap(value=Wrap(value=2)) a.map(this::inc).map(this::inc); // !!! COMPILATION ERROR

First problem we face is that it wraps already wrapped result. And then we cannot continue applying it – `inc`

accepts only `Integer`

but not `Wrap<Integer>`

instance.

There should be some way to `inc`

value and not wrap it again.

class Wrap<T> { // ... public <R> Wrap<R> flatMap(Function<T, Wrap<R>> mapper) { return mapper.apply(value); } }

`flatMap`

is still safe – it doesn’t give user a plain value but provides it to the mapper.

Now we can apply `inc`

several times in chains

Wrap<Integer> a = Wrap.of(1); // Wrap(value=1) a.flatMap(this::inc); // Wrap(value=2) a.flatMap(this::inc).flatMap(this::inc); // Wrap(value=3)

Actually `flatMap`

is more generic then `map`

and we can implement `map`

using it

class Wrap<T> { // ... <R> Wrap<R> map(Function<T, R> mapper) { return flatMap(mapper.andThen(Wrap::of)); } }

`andThen`

composes function with another, passing result of first as argument to the second Function#andThen

Now we have all tools to work with our wrapper type. `of`

wraps a value and `flatMap`

gives a way to modify it without need to unwrap anything. And we can chain multiple transformations without worry how to unwrap layers of results.

Basically, this is a monad – type that provides APIs to enclose some value and modify it without exiting enclosed context

interface Monad<T> { Monad<T> of(T value); <R> Monad<R> flatMap(Function<T, Monad<R>> mapper); }

### Real world problems

In Java there are several monadic types and even more with growing number of libraries. I will use Optional next, but these examples can be similarly applied to others.

#### Operations on Optionals

Assume we need to add two optional values. And we don’t know how to unwrap them, I mean don’t know what to do with empty values. All what we want is only add values together and leave that decision for later

Optional<Integer> a = ... Optional<Integer> b = ... return add(a, b);

Such function `add`

should return new Optional with the result of adding values

Optional<Integer> add(Optional<Integer> oa, Optional<Integer> ob) { return oa.flatMap(a -> ob.map(b -> a + b)); }

Lambda inside `flatMap`

has access to value of `oa`

and uses it to increment value of `ob`

similarly to previous `inc`

function.

Optional<Integer> a = Optional.of(13); Optional<Integer> b = Optional.of(42); add(a, b); // Optional[55] add(a, Optional.empty()); // Optional.empty add(Optional.empty(), b); // Optional.empty

What if we need to perform other operations? Lets create another method that additionally accepts an operation

<A, B, R> Optional<R> compute(BiFunction<A, B, R> operation, Optional<A> oa, Optional<B> ob) { return oa.flatMap(a -> ob.map(b -> operation.apply(a, b))); }

It is little bit to verbose but basically `compute`

applies `operation`

on values from optionals and returns optional result

Optional<Integer> a = Optional.of(13); Optional<Integer> b = Optional.of(42); BiFunction<Integer, Integer, Integer> plus = (x, y) -> x + y; BiFunction<Integer, Integer, Integer> times = (x, y) -> x * y; compute(plus, a, b); // Optional[55] compute(times, a, b); // Optional[546]

#### Streams of Optionals

So far so good. But with Java 8 we usually deal with a lot of streams. It is a common case when during pipeline we end up with stream of optional values. Now as we know how to perform operations on optionals lets find a product of all optional values in stream

Optional<Integer> one = Optional.of(1); Stream<Optional<Integer>> stream = Stream.of(1, 2, 3, 4).map(Optional::of); stream.reduce(one, (acc, elem) -> compute(times, acc, elem)); // Optional[24] stream = Stream.of(Optional.of(10), Optional.empty()); stream.reduce(one, (acc, elem) -> compute(times, acc, elem)); // Optional.empty

We provide initial value `one`

and then compute product of accumulator and each value in stream.

APIs are not always so friendly. Lets look at the reduce but without initial value

stream.reduce((acc, elem) -> compute(times, acc, elem)); // Optional[Optional[24]]

It wraps result into optional, because stream can be empty and we didn’t provide any initial value.

#### Flattening

How can we deal with optional of optional without unwrapping it? We can flatten it with `flatMap`

Optional<Optional<Integer>> ooa = Optional.of(Optional.of(24)); Optional<Integer> oa = ooa.flatMap(o -> o); // Optional[24]

Function `o -> o`

is called identity and actually it is so useful that you can find it in standard library Function#identity

### Wrap-up

Sometimes it is better to operate on monads and leave decision how to unwrap them for later. Consider this next time when you will try to get value from Optional, CompletableFuture or some other monadic type. I hope you’ve learned here one or two methods how to simplify your design using operations on Monads.

Code is available on Gist – feel free to play with it.

`Have a nice hack ;)`