Monads in Java

Hello there!

In the company that I work for, we use a lot of functional code to solve business problems in a more natural and safe way. And mostly of that code are written in Java.

In purely functional programming languages such Haskell, there is monads as a native language structure, but in OOP/FP languages such as Java and Scala we also can create and work with monads in an almost natural way :P.

Just to contextualize, a monad is a kind of “wrapper” that can represent or perform computational sequences on a data structure wrapped by the monad, easy to understood, right? And also, a Monad  must follows a set of laws, simply called monad laws:

– Left Identity
– Right Identity
– Associativity

All it takes be a Monad is to provide two functions which conform to three laws:

The two functions in some langs examples:

Place a value into monadic context:
– Haskell’s Maybe: return / Just
– Scala’s Option: Some
– Java 8 Optional: Optional.of

Apply a function in monadic context:
– Haskell’s Maybe: >>= (aka bind)
– Scala’s Option: flatMap
– Java 8 Optional: flatMap

Well, talking about Java 8, we have a monad called Optional.

A lot of programmers just uses Optional to prevent NullPointerException, because with Optional, you can verify the object consistence before performing some computational operation. For example:

// The simplest world's example
  Optional.of(Arrays.asList(1,2,3,null,5,6))
     .map(i -> i.get(3))
     .orElse(4);

In this boring example, we just wrap a immutable List of Integer on a Optional and try to get the nullable value from 3 position. The Optional helped us allowed the T orElse(T t) operation ir order to prevent gets a null value. But the Optional class can be helpful for a lot of other complex computational sequences.

So, let’s se how JDK8 Optional apply the three monad laws:

Left Identity: If we put a value in the monadic context and bind a Java Function to it, its the same as just applying the Function to a value:

Function<Integer, Optional> addOne = x -> Optional.of(x + 1);
Optional.of(5).flatMap(addOne).equals(addOne.apply(5));

Right Identity: If we have a monad and bind that monad’s return method — it is the same as the original wrapped value:

Optional.of(5).flatMap(Optional::of).equals(Optional.of(5));

Associativity: If we have a sequence of functions applied to a monad it doesn’t matter how they’re nested:

Function<Integer, Optional> addOne = i -> Optional.of(i + 1);
Function<Integer, Optional> addTwo = i -> Optional.of(i + 2);
Function<Integer, Optional> addThree = i -> addOne.apply(i).
flatMap(addTwo);
Optional.of(5).flatMap(addOne).flatMap(addTwo).equals(Optional.of(5).
flatMap(addThree));

this is so fashion, is not it?

Advertisements

One thought on “Monads in Java

Comments are closed.