The study of the concept of Monad, at first glance, may seem a daunting task for those who are beginning to study the functional paradigm. In this article we demystify some points around this theme to make it more accessible and practical.

### Pipeline and Mathematics

Let's see**Listing 1**program.

**Listing
1**. Method calls

package example01; public class Example01 { public static double multiplyBy2(double n) { return n * 2; } public static double divideBy3(double n) { return n/3; } public static double round(double n) { return Math.round(n); } public static double applyOperation(double n1) { final double n2 = multiplyBy2(n1); final double n3 = divideBy3(n2); final double n4 = round(n3); return n4; } public static void main(String[] args) { System.out.println("Output = " + applyOperation(12)); } }

Note that from an input data *n1*, we apply various transformations
(multiplication, division and rounding) to obtain the final result. Note that
within the *applyOperation* function
(use the term function and method without distinctions in this article), the
output of a function is the input of the next.

We can say that *applyOperation*
is purely a composite function, as it was assembled exclusively from the
chaining of other functions. This is very common in imperative languages and
is one of the key schemes for Functional Programming.

This means that a pipeline in mathematical terms?

Let us generalize the
example of **Listing 1**: given three
functions *f(x),* *g(x)* and *h(x)* can
represent the pipeline as follows:

a = f (x); b = g (a); c = H (B); or just h (g (f (x)))

The notation h*(g(f(x)))* is the mathematical representation
of a pipeline of three functions. Let's rewrite the applyOperation function in
terms of this expression, as shown in **Listing
2**.

**Listing 2.**Mathematical Pipeline

package example02; public class Example02 { public static double multiplyBy2(double n) { return n * 2; } public static double divideBy3(double n) { return n/3; } public static double round(double n) { return Math.round(n); } public static double applyOperation(double n1) { return round(divideBy3(multiplyBy2(n1))); } public static void main(String[] args) { System.out.println("Output = " + applyOperation(12)); } }

Semantically
speaking, the functions of *applyOperation*
**Listings 1 **and **2** are identical, and the code in **Listing 2** makes clear the "signature" math pipeline and
removes the use of temporary variables. However, use this type of notation
greatly impairs the readability of the program, just imagine a pipeline with
ten functions.

Functional
Programming in the basic building blocks are the functions and composition that
we saw in the *applyOperation* function
is a very common technique that helps promote code reuse.

So we have the
following quandary: how to represent compositions method in an elegant way and
easy to read without getting using temporary variables, as in the example in **Listing 1**? This is where the concept of
Monad.

### Monads and Pipeline

Note the code in **Listing 3.**

**Listing 3.** Using
the Optional Monad

package example03; import java.util.Optional; public class Example03 { public static Optional<Double> multiplyBy2(double n) { return Optional.of(n * 2); } public static Optional<Double> divideBy3(double n) { return Optional.of(n/3); } public static Optional<Double> round(double n) { return Optional.of(Double.valueOf(Math.round(n))); } public static Optional<Double> applyOperation(double n1) { return multiplyBy2(n1) .flatMap(n -> divideBy3(n)) .flatMap(n -> round(n)); } public static void main(String[] args) { System.out.println("Output = " + applyOperation(12).get()); } }

The code in **Listing 3** is exactly the same as the
one in **Listing 2**, but using
Optional. Realize that graphically in **Figure
1** remains valid to represent the pipeline of *applyOperation* function operations, because the role of a Monad is
exactly this: apply the composition through a flat threaded writing (flat) a
level, being much more readable than the mathematical notation nested multiple
levels *h(g(f(x))).*

Then, instead of
h(g(f(x))), we have: *f(x).flapMap(y
=>g(y)).flapMap(z=>h(z)),* or make monads more readable and natural
reading sequence of steps (from left to right) applied to the original input
data.

This is the biggest reason for their presence is so remarkable in functional languages, as to be considered a standard of functional design and be the support base of all the declarative programming of Java 8 (Optional, Stream and CompletableFuture) along with support the Lambdas and Functional Interfaces.

### Map and flatMap

According to the definition of Martin Ordersky, creator of Scala, Monad is a parameterized type that must have at least two major operations:

- unit: put the value into the monad (container);
- flatMap: allows nested calls;
- ** Map: although not part of the definition,
this method usually appears in conjunction with
*flatMap*is highly recommend it available when you create a Monad (we shall see the reason).

The *unit *method is represented by the method
of the Optional, which puts the parameter into the monad (container). Note that
some monads can not have *unit*
methods, but use others to do the same thing (of) or own builder to include the
value directly in the container.

Already *flatMap* allows calls chained and gets a
lambda expression as a parameter, and the following code to your signature:

public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

What is the purpose
of a *flatMap* function of a Monad?
Consider the following example in **Listing
4**, which we will use to explain the map *flatMap*.

**Listing 4.** Using
map

package example04; import java.util.Optional; public class Example04 { public static void main(String[] args) { Optional<Integer> optionInt = Optional.of(10); Optional<String> optionStr = optionInt.map(i -> i + ""); System.out.println("Output = " + optionStr.get()); } }

See map we use to
apply a transformation from Integer to String. Every function map can be
plotted in the same manner as shown in **Figure
1**.

**Figure 1.**
Graphical representation of map

As a monad of n
elements, we can map set as a transformation applied to the set *X*, generating the corresponding elements
*Y*, from the use of a function (*lambda*) transforming *F(x),* while maintaining the same number
of elements.

Notice an important
detail: when applying map on a monad, the transformation of the input data is
made, and the result is encapsulated again in Monad. In **Listing 4** it is clear since map was applied to the Monad *Optional,* and, as the* lambda* function converts an Integer to
String,* map* returns the result in the
same Monad *Optional*, only changing
the type to *Optional.*

**Figure 2**. Map

**Figure 2**graphically depicts the map
behavior. It is this characteristic of preserving the monad allowing
successively applying *map* operations
(and *flatMap)* concatenating the
output of a lambda as the next entry. Let's rewrite the example in **Listing 3** using *map*, as shown in **Listing 5**.

**Listing 5**.
Pipeline with map

package example04; import java.util.Optional; public class Example04 { public static Double multiplyBy2(double n) { return n * 2; } public static Double divideBy3(double n) { return n/3; } public static Double round(double n) { return (double) Math.round(n); } public static Optional<Double> applyOperation(double n1) { return Optional.of(n1) .map(n -> multiplyBy2(n1)) .map(n -> divideBy3(n)) .map(n -> round(n)); } public static void main(String[] args) { System.out.println("Output = " + applyOperation(12).get()); } }

The program of **Listing 3** and **6** preserve the pipeline of **Figure
1**, and uses a *flatMap* and the
other *map*, so both are used to create
fluent composition lambda expressions.

Now let's look at the
following example in **Listing 6**.

**Listing 6**. Map
nestled

package example05; import java.util.Optional; public class Example05 { public static Optional<Double> multiplyBy2(double n) { return Optional.of(n * 2); } public static Optional<Double> divideBy3(double n) { return Optional.of(n/3); } public static Optional<Double> round(double n) { return Optional.of((double) Math.round(n)); } public static void main(String[] args) { Optional<Optional<Double>> optMap = multiplyBy2(12).map(n -> divideBy3(n)); Optional<Double> optFlatMap = multiplyBy2(12).flatMap(n -> divideBy3(n)); } }

Notice that the line:

Optional<Optional<Double>> optMap = multiplyBy2(12).map(n -> divideBy3(n));

The *map* function applies a transformation
preserving the Monad of origin, as shown in **Figure 3**.

**Figure 3**. Map the
Monad source

However, as the
return *divideBy3(12)* is *Optional,* we have an
Optional nesting, as **Figure 4**shows.

**Figure 4**.
Optional nesting

The figure presented
makes clear the problem to use map with lambda expressions that return monads.
To solve this we must use *flatMap *because
it applies the operation "*map*"
and then "*flatten*"
(flatten, level), removing the nesting of the two monads, as shown in **Figure 5.**

**Figure 5**.
"Flatten"

An important fact to note is that only accepts *flatMap* receive lambdas expressions that
return the same Monad source (the parameterized type can be different), while *map* accepts lambdas returning anything,
including other monads, as the example in **Listing
7**.

**Listing 7**. Map
and flatMap

package example06; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; public class Example06 { public static void testMap() { Optional<Integer> optInt = Optional.of(1); Optional<Stream<Integer>> optStreamInt = optInt.map(n -> Stream.of(n)); Optional<CompletableFuture<Stream<Integer>>> optStreamComplInt = optStreamInt.map(x -> CompletableFuture.supplyAsync(() -> { return x; })); } public static void testFlatMapOk() { Optional<Integer> optInt1 = Optional.of(1); Optional<Integer> optInt2 = optInt1.flatMap(n -> Optional.of(n+1)); Optional<String> optInt3 = optInt2.flatMap(n -> Optional.of(String.valueOf(n+1))); } public static void testFlatMapError() { Optional<Integer> optInt = Optional.of(1); Optional<Stream<Integer>> optStreamInt = optInt.flatMap(n -> Stream.of(n)); Optional<CompletableFuture<Stream<Integer>>> optStreamComplInt = optStreamInt.flatMap(x -> CompletableFuture.supplyAsync(() -> { return x; })); } }

When working with
composition lambdas expressions, the correct is to always use the same Monad to
avoid strangers nesting of these, as we saw in **Listing 7**, and enable the use of *flatMap*.

### Monads and "happy path"

Monads can be used to
implement the concept of "happy path", as we can see in the example
with Optional **Listing 8**.

**Listing 8.**
Avoiding NullPointer

package example07; import java.util.Optional; import java.util.Random; public class Example07 { public static Optional<Double> randomOptional(Double value) { return Optional.ofNullable((new Random()).nextBoolean() ? value : null); } public static Optional<Double> multiplyBy2(double n) { return randomOptional(n * 2); } public static Optional<Double> divideBy3(double n) { return randomOptional(n/3); } public static Optional<Double> round(double n) { return randomOptional((double) Math.round(n)); } public static Optional<Double> applyOperation(double n1) { return Optional.of(n1) .flatMap(n -> multiplyBy2(n1)) .flatMap(n -> divideBy3(n)) .flatMap(n -> round(n)); } public static void main(String[] args) { Optional opt = applyOperation(12); if(opt.isPresent()) { System.out.println("Output = " + opt.get()); } } }

In **Listing 8**
code, any of the functions can return *Optional.ofNullable(null),*
and when this happens, both *map* as *flatMap* continue chaining, but without
processing the following lambdas expressions to the expression that generated
the null result. To facilitate understanding, let's put prints in the code as
shown in **Listing 9**.

**Listing 9**. Using
prints

package example08; import java.util.Optional; import java.util.Random; public class Example08 { public static Optional<Double> randomOptional(Double value) { Optional<Double> opt = Optional.ofNullable((new Random()).nextBoolean() ? value : null); if(!opt.isPresent()) { System.out.print(" - Null"); } return opt; } public static Optional<Double> multiplyBy2(double n) { System.out.print("\nmultiplyBy2"); return randomOptional(n * 2); } public static Optional<Double> divideBy3(double n) { System.out.print("\ndivideBy3"); return randomOptional(n/3); } public static Optional<Double> round(double n) { System.out.print("\nround"); return randomOptional((double) Math.round(n)); } public static Optional<Double> applyOperation(double n1) { return Optional.of(n1) .flatMap(n -> multiplyBy2(n1)) .flatMap(n -> divideBy3(n)) .flatMap(n -> round(n)); } public static void main(String[] args) { Optional opt = applyOperation(12); if(opt.isPresent()) { System.out.print("\nOutput = " + opt.get()); } System.out.println(); } }

Let's look at the possible ways in **Listing 9**.

// Output 1 multiplyBy2 divideBy3 round – Null // Output 2 multiplyBy2 – Null // Output 3 multiplyBy2 divideBy3 – Null // Output 4 multiplyBy2 divideBy3 round Output = 8.0

Note that the lambda
expressions are executed until the first *null*
to appear, and the subsequent expressions are not processed (similar to the
resource if). But notice that the thread always comes to an end, regardless of *null* or not appear (hence the happy path
name). Then just test the final result of the pipeline to see if it failed or
not (fail here if means if any of the composition of functions had to deal with
null).

This property of Monad
*Optional* allows you to write a much
more compact code and elegant than the option of staying testing all returns to
see if they are null or not. But not only *Optional*
that has this feature. We will see in **Listing
10** to rewrite the previous application using *Stream*.

**Listing 10.** Using
Stream

package example09; import java.util.Random; import java.util.stream.Stream; public class Example09 { public static Stream<Double> randomStream(Double value) { if(new Random().nextBoolean()) { return Stream.of(value); } else { System.out.print(" - Empty"); return Stream.empty(); } } public static Stream<Double> multiplyBy2(double n) { System.out.print("\nmultiplyBy2"); return randomStream(n * 2); } public static Stream<Double> divideBy3(double n) { System.out.print("\ndivideBy3"); return randomStream(n/3); } public static Stream<Double> round(double n) { System.out.print("\nround"); return randomStream((double) Math.round(n)); } public static Stream<Double> applyOperation(double n1) { return Stream.of(n1) .flatMap(n -> multiplyBy2(n1)) .flatMap(n -> divideBy3(n)) .flatMap(n -> round(n)); } public static void main(String[] args) { Stream stream = applyOperation(12); stream.forEach(n -> System.out.print("\nOutput = " + n)); System.out.println(); } }

In the code shown,
the concept of "happy path" and short circuit still present, only
instead of *null*, use *Stream.empty* (both concepts represent no
value). The most interesting aspect is that we exchange *Optional* for *Stream*
without changing the program semantics, because any monad can be used to provide
pipelines.

The short circuit occurs when the subsequent concept lambda expressions are not processed when there is an empty occurrence in any one of lambda expressions.

Of course, to prove
this statement, could not miss the example with CompletableFuture, as shown in **Listing 11.**

**Listing 11**.
CompletableFuture

package example09; import java.util.Random; import java.util.concurrent.CompletableFuture; public class Example09 { public static CompletableFuture<Double> randomCompletableFuture(Double value) { if(new Random().nextBoolean()) { return CompletableFuture.completedFuture(value); } else { System.out.print(" - Empty"); CompletableFuture future = new CompletableFuture(); return new CompletableFuture(); } } public static CompletableFuture<Double> multiplyBy2(double n) { System.out.print("\nmultiplyBy2"); return randomCompletableFuture(n * 2); } public static CompletableFuture<Double> divideBy3(double n) { System.out.print("\ndivideBy3"); return randomCompletableFuture(n/3); } public static CompletableFuture<Double> round(double n) { System.out.print("\nround"); return randomCompletableFuture((double) Math.round(n)); } public static CompletableFuture<Double> applyOperation(double n1) { return CompletableFuture.completedFuture(n1) .thenCompose(n -> multiplyBy2(n1)) .thenCompose(n -> divideBy3(n)) .thenCompose(n -> round(n)); } public static void main(String[] args) { CompletableFuture<Double> future = applyOperation(12); future.handle((content, ex) -> { if (ex == null) { System.out.print("\nOutput = " + content); } else { ex.printStackTrace(); } return null; }); System.out.println(); } }

### Monads and Context

In the previous examples we use the three monads to provide pipeline, however, each is used to solve problems in a certain context:

- Optional: it's the null point (NullPointerException) and value of absences in general;
- CompletableFuture: Used in the context of asynchronous computations;
- Stream: the basis of declarative programming with collections, providing a cleaner coding style and features such as parallelization and lazy evaluation.

Use *Optional* gives programs a more defensive
and self-explanatory style to formalize the concept of zero return. For
example, any method that does not void or early return may or may not return
null, depending on your implementation. That is, seeing only his signature is
impossible to determine whether the function is "telling the truth"
because it could return something other than what we are expecting (null
instead of a valid object indicated in the return type).

But what about the
non-checked exceptions? Note that again a function/method might not be totally
honest, if we stick in your signature because it may return an unchecked exception,
and if we do not have access to the source, we have to use *try/catch *to develop a "safe" software.

In Scala there is the
Monad Try, which has the same paper *Optional*,
but applied to the context of the non-checked exceptions (there are no checked
exceptions in Scala), as shown in **Listing
12.**

**Listing 12.** Using
Try Scala

import scala.util.{Failure, Success, Random, Try} object TryTest extends App { def sum(a: Int, b: Int): Try[Int] = Try { val result = a + b if(Random.nextInt(2) % 2 == 0) { throw new RuntimeException("Error") } result } sum(2, 3) match { case Success(result) => println("Sum = " + result) case Failure(ex) => println(ex.getMessage) } }

Note that, instead of
returning int, the sum function returns a *Try[Int],*
because the function may return an exception, as we indicate by return type.

A *Try* Monad only has two subclasses,
Failure and Success, and use pattern matching to determine which type generated
(*Success(result:Int) *if no exception
occurs, and Failure (eg Exception) otherwise).

Github Jason Goodwin
(see Links section) there is a version of Monad *Try* done for Java 8. The implementation uses four files, and *Try* the principal and the remaining
three interfaces only support, as shown in **Listing
13** (list only *Try.java *in the
article, removing the *JavaDoc* to
reduce the code block size).

**Listing 13**. Try
Java

package example10; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Optional; import java.util.function.Function; import java.util.function.Predicate; public abstract class Try<T> { protected Try() { } public static <U> Try<U> ofFailable(TrySupplier<U> f) { Objects.requireNonNull(f); try { return Try.successful(f.get()); } catch (Throwable t) { return Try.failure(t); } } public abstract <U> Try<U> map(TryMapFunction<? super T, ? extends U> f); public abstract <U> Try<U> flatMap(TryMapFunction<? super T, Try<U>> f); public abstract T recover(Function<? super Throwable, T> f); public abstract Try<T> recoverWith(TryMapFunction<? super Throwable, Try<T>> f); public abstract T orElse(T value); public abstract Try<T> orElseTry(TrySupplier<T> f); public abstract T get() throws Throwable; public abstract boolean isSuccess(); public abstract <E extends Throwable> Try<T> onSuccess(TryConsumer<T, E> action) throws E; public abstract <E extends Throwable> Try<T> onFailure(TryConsumer<Throwable, E> action) throws E; public abstract Try<T> filter(Predicate<T> pred); public abstract Optional<T> toOptional(); public static <U> Try<U> failure(Throwable e) { return new Failure<>(e); } public static <U> Try<U> successful(U x) { return new Success<>(x); } } class Success<T> extends Try<T> { private final T value; public Success(T value) { this.value = value; } @Override public <U> Try<U> flatMap(TryMapFunction<? super T, Try<U>> f) { Objects.requireNonNull(f); try { return f.apply(value); } catch (Throwable t) { return Try.failure(t); } } @Override public T recover(Function<? super Throwable, T> f) { Objects.requireNonNull(f); return value; } @Override public Try<T> recoverWith(TryMapFunction<? super Throwable, Try<T>> f) { Objects.requireNonNull(f); return this; } @Override public T orElse(T value) { return this.value; } @Override public Try<T> orElseTry(TrySupplier<T> f) { Objects.requireNonNull(f); return this; } @Override public T get() throws Throwable { return value; } @Override public <U> Try<U> map(TryMapFunction<? super T, ? extends U> f) { Objects.requireNonNull(f); try { return new Success<>(f.apply(value)); } catch (Throwable t) { return Try.failure(t); } } @Override public boolean isSuccess() { return true; } @Override public <E extends Throwable> Try<T> onSuccess(TryConsumer<T, E> action) throws E { action.accept(value); return this; } @Override public Try<T> filter(Predicate<T> p) { Objects.requireNonNull(p); if (p.test(value)) { return this; } else { return Try.failure(new NoSuchElementException("Predicate does not match for " + value)); } } @Override public Optional<T> toOptional() { return Optional.ofNullable(value); } @Override public <E extends Throwable> Try<T> onFailure(TryConsumer<Throwable, E> action) { return this; } } class Failure<T> extends Try<T> { private final Throwable e; Failure(Throwable e) { this.e = e; } @Override public <U> Try<U> map(TryMapFunction<? super T, ? extends U> f) { Objects.requireNonNull(f); return Try.failure(e); } @Override public <U> Try<U> flatMap(TryMapFunction<? super T, Try<U>> f) { Objects.requireNonNull(f); return Try.<U>failure(e); } @Override public T recover(Function<? super Throwable, T> f) { Objects.requireNonNull(f); return f.apply(e); } @Override public Try<T> recoverWith(TryMapFunction<? super Throwable, Try<T>> f) { Objects.requireNonNull(f); try { return f.apply(e); } catch (Throwable t) { return Try.failure(t); } } @Override public T orElse(T value) { return value; } @Override public Try<T> orElseTry(TrySupplier<T> f) { Objects.requireNonNull(f); return Try.ofFailable(f); } @Override public T get() throws Throwable { throw e; } @Override public boolean isSuccess() { return false; } @Override public <E extends Throwable> Try<T> onSuccess(TryConsumer<T, E> action) { return this; } @Override public Try<T> filter(Predicate<T> pred) { return this; } @Override public Optional<T> toOptional() { return Optional.empty(); } @Override public <E extends Throwable> Try<T> onFailure(TryConsumer<Throwable, E> action) throws E { action.accept(e); return this; } }

Now let's refactor
the example in **Listing 3** in terms of
this new Monad, as shown in **Listing 14**.

**Listing 14**. Using
Try.

package example11; import example10.Try; public class Example11 { public static Try<Double> multiplyBy2(double n) { return Try.successful(n * 2); } public static Try<Double> divideBy3(double n) { return Try.successful(n/3); } public static Try<Double> round(double n) { return Try.successful(Double.valueOf(Math.round(n))); } public static Try<Double> applyOperation(double n1) { return multiplyBy2(n1) .flatMap(n -> divideBy3(n)) .flatMap(n -> round(n)); } public static void main(String[] args) throws Throwable { System.out.println("Output = " + applyOperation(12).get()); } }

Note that even using *Try* this code, the composition of
semantics has been preserved (as it was with Optional, Stream and
CompletableFuture). Finally, we have the Java version of **Listing 12** (Scala), the code in **Listing 15**.

**Listing 15.** Java
Version

package example12; import example10.Try; import java.util.Random; public class Example12 { public static Try<Integer> sum(int a, int b) { int result = a + b; if(new Random().nextInt(2) % 2 == 0) { return Try.failure(new RuntimeException("Error")); } return Try.successful(result); } public static void main(String[] args) { Try<Integer> result = sum(2, 3); if(result.isSuccess()) { result.onSuccess(r -> System.out.println("Sum = " + r)); } else { result.onFailure(ex -> System.out.println(ex.getMessage())); } } }

### Conclusion

We explored in this article some properties of monads and how they help to promote a better viewing functions compositions/methods in Java 8, in addition to providing semantics that help make safer programming day to day.

Despite its mathematical origin (category theory, which is a branch of mathematics that deals with categories/sets and their relationships), the concept of Monad is relatively simple to understand and apply, and therefore, a design pattern (functional) that It will become increasingly familiar and present to Java programmers.

**Links**

**What's Wrong in Java 8:
Monads**

https://dzone.com/articles/whats-wrong-java-8-part-iv

**Jason Goodwin**

https://github.com/jasongoodwin/better-java-monads/blob/master/src/main/java/com/jasongoodwin/monads/Try.java