The functor–applicative–monad hierarchy is a layered abstraction for sequencing computations on wrapped values. A functor is any type that implements a map operation, letting you apply a function to its wrapped value without unwrapping it; arrays, \( \text{Maybe} \), and \( \text{Either} \) are all functors. Functors must satisfy the identity law \( \text{map}(\text{id}) \equiv \text{id} \) and the composition law \( \text{map}(f \circ g) \equiv \text{map}(f) \circ \text{map}(g) \). An applicative functor extends a functor by allowing the application of a wrapped function to a wrapped value through the ap operator, with operations \( \text{pure} \) and \( \text{ap} \); its laws include the homomorphism, interchange, identity, and composition laws. Every monad is an applicative, and every applicative is a functor, so power increases as one moves up the chain. The key distinction is that in an applicative the choice of function cannot depend on previous values, while in a monad it can.
A monad is a design pattern for composing functions that return wrapped values. It consists of a type constructor, a unit operation that wraps a value, and a bind operation, also called flatMap or \( \gg= \), that chains operations while flattening one level. The three monad laws — left identity \( \text{return}\,a \gg= f \equiv f\,a \), right identity \( m \gg= \text{return} \equiv m \), and associativity \( (m \gg= f) \gg= g \equiv m \gg= (\lambda x.\, f\,x \gg= g) \) — ensure that monadic computations behave consistently across refactorings. Specific monads address recurring patterns: the Maybe monad, called Optional in Java and Swift, handles possibly absent values with a Just/Some branch and a Nothing/None branch that short-circuits subsequent operations so that \( \text{Maybe.map}(f, \text{Nothing}) \) returns \( \text{Nothing} \) without ever applying \( f \). The Either monad represents success with Right and failure with Left, providing a functional alternative to exceptions where errors propagate through the chain. The IO monad encapsulates side effects in Haskell, keeping the type system honest so that a function's type alone reveals whether it performs effects, and the State, Reader, Writer, List, and Continuation monads respectively thread pure state, read from a shared environment, accumulate logs, represent non-deterministic computation, and encode the rest of a computation as a callback.
Monad transformers stack monadic effects. \( \text{MaybeT}\,m\,a \) adds Maybe short-circuiting to an underlying monad \( m \); \( \text{EitherT}\,e\,m\,a \) lifts error handling into effectful code; and \( \text{ReaderT}\,r\,m\,a \) combines a read-only environment with any monad, forming the basis of mtl-style effects such as \( \text{AppM} = \text{ReaderT Config IO} \). Free monads separate the description of a computation from its interpretation: \( \text{Free}\,f\,a = \text{Pure}\,a \mid \text{Free}(f(\text{Free}\,f\,a)) \) lifts any functor into a monad, allowing the same program to be given different interpreters for testing and production. The Coyoneda lemma ensures that any functor can be made a Functor automatically, which simplifies Free monad construction, while join flattens one level of monadic structure and is the primitive from which bind is derived. Bifunctors are functorial in two arguments, contravariant functors apply functions in the opposite direction, and contravariant applicatives use contramap in place of \( \text{ap} \) for structures like predicates and comparisons. The ApplicativeDo extension in Haskell lets do-notation desugar through \( \text{ap} \) instead of bind when bound names are not reused, enabling concurrent rather than sequential execution of independent effects.