# Monads Explained Practically — Functional Programming Concepts

Source: https://www.geekswithgeeks.com/en/functional-programming/ab-monad

> flatMap and chaining.

## Chaining steps that return wrapped values

Problem: you have steps that each return a wrapped value, such as a function returning `Option<User>` and another taking a `User` and returning `Option<Address>`. Using `map` would give `Option<Option<Address>>`. A **monad** adds an operation usually called `flatMap`, `chain`, `bind` or `>>=` that runs the next step and **flattens** the result, so a sequence of fallible steps reads as a straight line and stops at the first `None` or `Err`. You already use the pattern: `Array.prototype.flatMap`, `Promise.then` returning a promise (and `async`/`await`), and optional chaining `a?.b?.c` for nullable values. Monads also need a way to wrap a plain value (`of`/`return`/`Promise.resolve`) and obey laws that make chaining predictable.

## flatMap for Option and Result-like chains

Each step can fail; the chain short-circuits.

```typescript
type Option<T> = { tag: 'some'; value: T } | { tag: 'none' };
const some = <T>(value: T): Option<T> => ({ tag: 'some', value });
const none: Option<never> = { tag: 'none' };
const flatMap = <A, B>(o: Option<A>, f: (a: A) => Option<B>): Option<B> =>
  o.tag === 'some' ? f(o.value) : none;

type User = { id: string; addressId?: string };
type Address = { city: string };
declare function findUser(id: string): Option<User>;
declare function findAddress(id: string): Option<Address>;

const cityOf = (userId: string): Option<string> =>
  flatMap(findUser(userId), u =>
    flatMap(u.addressId ? some(u.addressId) : none, aid =>
      flatMap(findAddress(aid), a => some(a.city))));

// The same shape you already know from promises:
// fetchUser(id).then(u => fetchAddress(u.addressId)).then(a => a.city)

// And from arrays:
[[1, 2], [3]].flatMap(xs => xs);   // [1, 2, 3]
```

## do-notation and async/await

Haskell's `do` blocks and JavaScript's `async`/`await` both exist to hide nested chaining: they let monadic code read like ordinary sequential statements.

**Quiz:** What does flatMap add compared with map?

- [ ] It sorts the values
- [x] It flattens the result when the function itself returns a wrapped value
- [ ] It runs the function twice
- [ ] It removes the need for a container

*Answer:* It flattens the result when the function itself returns a wrapped value. map would nest: Option<Option<T>>.
