Monad
- Pronunciation
- MOH-nad
In short
A monad is a functional programming pattern for chaining steps that each return a wrapped value, such as an Optional, while the wrapper handles the plumbing.
What is a monad?
Monads have a reputation for being hard, but the everyday idea is simple. Some values come in a wrapper that adds a concern: an Optional might be empty, a promise isn't ready yet, a list holds many values, a result might be an error. A monad is such a wrapper type plus two operations: one that puts a plain value into the wrapper, and one, usually called flatMap, bind or then, that chains a next step which itself returns a wrapped value.
The chaining operation is where the work happens. It takes the value out of the wrapper, passes it to the next step and flattens the result, so you never end up with a box inside a box. In Java, findUser(id).flatMap(User::address) skips the remaining steps as soon as one comes back empty, so the null checks between them disappear. JavaScript promises feel the same: then accepts a function that returns another promise and waits for it, and a single catch at the end handles a failure in any step.
Think of an assembly line where every item travels on a tray: each station takes the item off, works on it and puts the result back on a tray, and the line can pull a faulty tray aside so the later stations skip it. Strictly speaking, the definition comes from category theory, a branch of mathematics, and Eugenio Moggi and Philip Wadler brought it into functional programming in the early 1990s. Haskell uses monads to keep its functions pure: input and output are described as IO values chained in order, and do notation lets such chains read like ordinary step-by-step code.
A true monad must also obey three monad laws, which in plain words say that wrapping a value adds nothing by itself and that grouping the steps differently doesn't change the result. Many everyday types are only monad-like: a JavaScript promise automatically flattens any promise you give it, so a promise of a promise can't exist, and that breaks the laws in edge cases. Monads are also confused with functors, which only need map: map transforms the value inside the box, while a monad's flatMap chains steps that return boxes of their own.
Key takeaways
- A monad is a wrapper type plus a way to chain steps that return wrapped values.
- The chaining operation, often
flatMap,bindorthen, unwraps, applies the next step and flattens. - The wrapper handles a concern between steps: missing values, errors, waiting or many results.
Optional,Result, lists and promises are familiar monads or close relatives.- Strictly, the term comes from category theory and requires three laws to hold.
Example
// Each lookup may find nothing, so each one returns an Optional
Optional<String> city = findUser(42) // Optional<User>
.flatMap(user -> user.address()) // Optional<Address>
.flatMap(address -> address.city()); // Optional<String>
// No null checks between steps: once one is empty, the rest are skipped
System.out.println(city.orElse("unknown"));
// map would nest the boxes; flatMap flattens them, the heart of a monad
Optional<Optional<Address>> nested = findUser(42).map(user -> user.address());Readers ask
Is a JavaScript Promise a monad?
Almost. then works much like a monad's chaining operation, which makes promises a good way to build intuition. But a promise automatically unwraps any promise-like value, so a promise of a promise can never exist, and that breaks the monad laws in some edge cases. Calling promises monad-like is accurate.
Do I need to understand monads to be a good developer?
No. You probably already use them through Optional, promises or the array method flatMap. The concept matters more in Haskell, Scala or libraries built on functional patterns, where one shared name lets the same tools work across many types.
What is the difference between map and flatMap?
map applies a function that returns a plain value, so the result stays in one box. flatMap applies a function that returns a box of its own and then flattens the two boxes into one, and that flattening step is what a monad adds.
See also
- Functional ProgrammingProgramming Fundamentals, p. 27Functional programming is a style of building software from pure functions that avoid changing shared data, making code more predictable and easier to test.
- PromiseProgramming Fundamentals, p. 52A promise is an object that represents the eventual result of an asynchronous operation, letting code react to success or failure once the work completes.
- HaskellProgramming Languages, p. 14Haskell is a purely functional, statically typed language with lazy evaluation, known for its expressive type system and mathematically precise code.
- Higher-Order FunctionProgramming Fundamentals, p. 30A higher-order function is a function that takes another function as an argument, returns a function, or both, so behavior can be passed around like data.
- NullProgramming Fundamentals, p. 44Null is a special value that means "no value here", used when a variable deliberately refers to no object or data at all instead of holding something real.
- CurryingProgramming Fundamentals, p. 18Currying turns a function that takes several arguments into a chain of functions that each take one argument, so the arguments can be supplied one at a time.
Sources
Spotted a mistake or something missing on this page?Suggest an edit