Functors, Applicatives and Monads in Java

Ismail S

September 2018

Intro

  • Abstraction of common design patterns
  • Underlying ideas are very general, but lots of practical applications

Warning

This stuff is hard to learn, especially for the first time. If it doesn’t make sense, ask.

Functors

Motivating examples

Optional

Sequencing operations and treating all failures in the same way

Streams

Lazy lists

CompletableFuture

Representation of a value or error that will be available at some future time

Function

Representation of a value that will be available once this function is called (it’s weird)

Generic implementation

Haskell

Elevate a function (with one input) to operate on Functor objects

Rules

An example helper function

<$ is equivalent to:

Applicatives

Motivating examples

Optional

No library support. If there was, could look like:

Or:

Streams

No library support. If there was, could look like:

Or:

This can work in one of 2 ways:

  • For all combinations of elements of both streams, apply function and return a Stream with all results. With this definition, we can make Stream be an instance of Monad.
  • Apply the function to the first 2 elements of both streams, then the 2nd elements, etc, until the shortest length Stream is consumed. With this definition, Stream can’t be an instance of Monad.

CompletableFuture

Very limited library support (Only 2 arguments)

Function

No library support. If there was, could look like:

Or:

where we have:

Essentially, Function.map2 would have a type signature:

Generic implementation

Haskell

Sequential application means we can do things like:

where all the arguments are Applicative objects thingies

Rules

Some helper functions

Monads

Some examples

Optional

Another example:

Streams

No library support. If there was, could look like:

CompletableFuture

Function

No library support. If there was, could look like:

Generic implementation

Haskell

Rules

Example implementations

Optional

List

ZipList