Applicative Functor has the following two properties.

Pure: create a functor from value.

Apply: a function taking arguments which are a Functor having a function and a Pure. This function will return the Functor after applying the function inside the first Functor with a value from a Pure by unwrapping.

Example)

Optional<int> apply(Optional<function<int(std::string)>> f, Optional<std::string> v) { if (f & v) { return Optional<int>(*f (*v)); } return Optional(nullptr); }

Java example)

Optional<Integer> apply(Optional<Function<String, Integer>> f, Optional<String> v) { return f.flatMap(a -> v.map(a(v)) }

Monad is the Applicative Functor with joining to flat the returning Functor.

So Monad is Applicative Functor with a join.

Join: flattening the Functor

Join Example)

Optional<int> join(Optional<Optional<int>> v) { if (v) { return *v; } return Optional<int>(nullptr); }

Monad C++ definition:

template<typename T, typename U> Monad<U> bind(Monad<T> m, std::function<Monad<U>(T)> f) { return join(apply(pure(f), m)); }