# What Is Applicative? Basic Theory for Java Developers

### Are you a Java developer who wants to know the theory behind Applicatives? Here you will find a step-by-step tutorial that will help you understand them.

Join the DZone community and get the full member experience.

Join For FreeApplicative is just another concept similar in meaning and history to Functors and Monads. I have covered these two in my previous articles, and I think it is finally time to start closing this little series about the most commonly known functional abstractions. Besides explaining some details and theory, I will implement a simple Applicative. I will also use Optional, hopefully one last time, to show what advantages Applicatives give us.

The source code for this article is available in GitHub repository.

**Why Should We Care About Applicatives?**

First of all, Applicatives are the intermediate construct between Functors and Monads. They are more powerful than Functors but less powerful than Monads. Applicatives are also great for performing various context-free computations like parsers or traversable instances.

Additionally, all Applicatives are Functors, which may make implementing Applicatives easier if you have some experience with Functors. Thanks to this relation, Applicatives can make the whole journey from Functors to Monads easier, playing the role of a bridge between both concepts.

Moreover, they are usually easier to write than Monads. In more functional languages like Scala or Haskell, Applicatives tend to have more instances than Monads.

**What Is An Applicative?**

An Applicative Functor, or Applicative in short, is a mostly functional programming concept. It was introduced in 2008 by Conor McBride and Ross Paterson in their paper Applicative programming with effects. Their indirect counterpart in category theory is known as lax monoidal functors. Additionally, please keep in mind that **all Applicatives are Functors**. Such a relation will have significant implications when we start discussing **Applicative Laws** and methods — it mostly implies that all Laws required by Functors have to be also met by Applicatives.

In the world of software, the main focus of Applicatives is, similarly to Monads, to wrap values in a particular context and then perform operations - to be exact, operations wrapped in the same context as the value. Contrary to Monads, Applicatives do not allow chain operations in the same ways as Monads do, with the output of one operation being the input of the other. Unfortunately, it is not so easily implementable in Java, so we basically end up with such an ability anyway. Furthermore, unlike Functors, Applicatives allow us to sequence our computations.

**Applicative Laws**

As both previously described data types, Applicatives also have laws to fulfill. In fact, Applicatives have the highest number of such laws, namely: **Identity,** **Homomorphism**, **Interchange**, **Composition**. In my opinion, Applicative Laws are also the hardest to understand at first sight, especially **Homomorphism** and **Interchange**, among all the three data types I described.

Classically, a few assumptions before we start:

**f**is a function mapping from type**T**to type**R****g**is a function mapping from type**R**to type**U**

**Identity**

Applying the identity function to a value wrapped with pure should always return an unchanged value.Java`Applicative<Integer> identity = Applicative.pure(x).apply(Applicative.pure(Function.identity())); boolean identityLawFulfilled = identity.valueEquals(Applicative.pure(x));`

**Homomorphism**

Applying a wrapped function to a wrapped value should give the same result as applying the function to the value and then wrapping the result with the usage of pure.Java`Applicative<String> leftSide = Applicative.pure(x).apply(Applicative.pure(f)); Applicative<String> rightSide = Applicative.pure(f.apply(x)); boolean homomorphismLawFulfilled = leftSide.valueEquals(rightSide);`

**Interchange**

Applying the wrapped function f to a wrapped value should be the same as applying the wrapped function which supplies the value as an argument to another function, to the wrapped function fJava`// As far as I can tell it is as close, to original meaning of this Law, as possible in Java Applicative<String> interchangeLeftSide = Applicative.pure(x).apply(Applicative.pure(f)); Supplier<Integer> supplier = () -> x; Function<Supplier<Integer>, String> tmp = i -> f.apply(i.get()); Applicative<String> interchangeRightSide = Applicative.pure(supplier).apply(Applicative.pure(tmp)); boolean interchangeLawFulfilled = interchangeLeftSide.valueEquals(interchangeRightSide);`

**Composition**

Applying the wrapped function f and then the wrapped function g should give the same results as applying wrapped functions composition of f and g togetherJava`// As far as I can tell it should be in line with what is expected from this Law Applicative<Long> compositionLeftSide = Applicative.pure(x).apply(Applicative.pure(f)).apply(Applicative.pure(g)); Applicative<Long> compositionRightSide = Applicative.pure(x).apply(Applicative.pure(f.andThen(g))); boolean compositionLawFulfilled = compositionLeftSide.valueEquals(compositionRightSide);`

Additionally, because the Applicative is an extension of a Functor, your instance should fulfill both laws from the Functor: **Identity** and **Composition**. Fortunately, both laws imposed by the definition of Functor are already among four laws of Applicative, so they should be fulfilled by the Applicative definition itself.

Now that you know what laws you have to fulfill, I can start talking about what exactly you need to implement your Applicative.

**Creating an Applicative**

**What We Need To Implement The Applicative**The first thing you will need is parameterized type

**A<T>.**The parameterized type is the cornerstone of all data types similar in structure to Applicatives, Monads and Functors. Moreover, you will need two methods:**apply**(or**ap**) responsible for performing operations. Here you pass a function already wrapped in our context and that operates on the value in our context. This method should have the following signature**M<U> (M<T -> U>)**.**pure**which is used to wrap your value and has the following signature**M<T>(T)**.

Additionally, because all Applicatives are Functors, you get a

**map**method with signature**M<R> (T -> R)**by definition.**Be Aware:**There is a second, probably more common, equivalent for Applicative in such a case. Instead of the apply method, we have a product method with signature

**M<(T, U)>(M<T>, M<U>)**. Such Applicatives must obey different Laws, namely:**Associativity**,**Left Identity**and**Right Identity.**Their descriptions and examples are included in the GitHub repository.Knowing what one needs to make an Applicative, I can start implementing one.

**Implementing an Applicative**Java`public final class OptionalApplicative<T> implements Functor<T> { private final Optional<T> value; private OptionalApplicative(T value) { this.value = Optional.of(value); } private OptionalApplicative() { this.value = Optional.empty(); } <U> OptionalApplicative<U> apply(OptionalApplicative<Function<T, U>> functionApplicative) { Optional<U> apply = functionApplicative.value.flatMap(value::map); return apply.map(OptionalApplicative::new).orElseGet(OptionalApplicative::new); } static <T> OptionalApplicative<T> pure(T value) { return new OptionalApplicative<>(value); } @Override public <R> Functor<R> map(Function<T, R> f) { return apply(pure(f)); } // For sake of asserting in Example and LawsValidator public boolean valueEquals(Optional<T> s) { return value.equals(s); } public boolean valueEquals(OptionalApplicative<T> s) { return this.valueEquals(s.value); } }`

### Describing Applicative Implementation

The base of this implementation is the parameterized class with the immutable field named "value", which is responsible for storing the value. Then, you can see private constructors that make it impossible to create an object in any other way than through a wrapping method –

**pure**.Next come two methods unique for Applicatives -

**pure**used for wrapping values in Applicative context and**apply**for using wrapped functions to wrapped values. Both are implemented using Optional and its methods, so they are fully null safe.Then you have a method

**map**coming from the Functor, it is an “additional” method that may become useful if you are interested in performing some operation over the value inside the Applicative.**Applicative Usage Example**Let’s move on to presenting a simple example of Applicative usage along with a short description why it may be better than a non-applicative approach.

Java`public class Example { public static void main(String[] args) { int x = 2; Function<Integer, String> f = Object::toString; // Task: applying function wrapped in context to value inside that context. // Non-applicative Optional<Integer> ox = Optional.of(x); Optional<Function<Integer, String>> of = Optional.of(f); Optional<String> ofx = ox.flatMap(d -> of.map(h -> h.apply(d))); // One liner -> Optional.of(x).flatMap(d -> Optional.of(f).map(h -> h.apply(d))); // Applicative OptionalApplicative<Integer> ax = OptionalApplicative.pure(x); OptionalApplicative<Function<Integer, String>> af = OptionalApplicative.pure(f); OptionalApplicative<String> afx = ax.apply(af); // One liner -> OptionalApplicative.pure(x).apply(OptionalApplicative.pure(f)); if (afx.valueEquals(ofx)) { System.out.println("Values inside wrappers are equal"); } else { throw new RuntimeException("Values inside wrappers are not equal"); } } }`

Above you can see for yourself the possible benefits given by Applicative abstraction over plain Optional-based approach. First of all, Applicative-based code is simpler and easier to understand than the Optional one, it does not require any complex things like embedded map calls. In fact, the user does not even know that they are using Applicative with Optional features, so I was able to provide better encapsulation. In my opinion, the pros of using such abstraction outbalance the cost of writing one.

**Summing up**

Despite being a concept of less power than Monads, Applicatives can be a great solution especially when you need to handle context-free computations. They are very useful when you have to write parsers or traversables. Additionally, being the intermediate concept between Functors and Monads, they can make your journey through category theory data types easier. Thank you for your time.

### Category Theory Data Types** in Java**

If this piece of text was interesting, you may also be interested in other articles from my series about category theory data types in Java:

### Applicatives FAQ

#### What Is an Applicative?

An Applicative Functor, or Applicative, is a functional programming concept, all Applicatives are instances of Functors.

#### What Are Applicative Laws?

Every Applicative instance has to satisfy four laws:

**Identity**,**Homomorphism**,**Interchange**, and**Composition**#### What Do I Need to Implement an Applicative?

To implement an Applicative, you need a parameterized type

**M<T>**and two methods:**pure**and**apply**, the method ‘**map**’ is inherited from the Functor, so we get it by definition.

Opinions expressed by DZone contributors are their own.

Comments