# Functors: map as a Pattern — Functional Programming Concepts

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

> Apply a function inside a container.

## One idea, many containers

A **functor** is a container or context with a `map` operation that applies a function to the value(s) inside and returns the same kind of container. Arrays map over every element; an Option maps over the value if present and leaves `None` alone; a Result maps the success value and passes errors through. Lawful functors obey two laws: mapping the identity function changes nothing, and mapping `f` then `g` equals mapping their composition. A `Promise`'s `then` behaves like `map` when the callback returns a plain value, but it is only an **analogy**: promises run eagerly and automatically flatten nested promises, so they do not satisfy the laws strictly.

## Patterns behind map and chaining

Functors and monads name patterns you already use, and the functional core / imperative shell architecture applies them at system scale.

![Three ideas: functors, monads in practice, effects at the edges.](assets/figures/functional-programming/section-7-map.svg) — Figure 7.1 — Mapping inside a context, chaining contexts, effects at the boundary.

## map for Option

The function runs only when a value exists.

```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 mapOption = <A, B>(o: Option<A>, f: (a: A) => B): Option<B> =>
  o.tag === 'some' ? some(f(o.value)) : none;

const len = (s: string) => s.length;
mapOption(some('hello'), len);  // { tag: 'some', value: 5 }
mapOption(none, len);           // { tag: 'none' }; len is never called

[1, 2, 3].map(n => n * 2);      // arrays: same idea over many values
```

## Gift wrapping

map lets you change the gift without unwrapping it yourself: the box (array, Option, Result) handles opening and rewrapping, and an empty box stays empty.

**Quiz:** Why is Promise only an analogy for a functor?

- [ ] Promises are synchronous
- [ ] Promises have no then method
- [ ] Promises cannot hold values
- [x] It runs eagerly and auto-flattens nested promises, so it does not follow the laws strictly

*Answer:* It runs eagerly and auto-flattens nested promises, so it does not follow the laws strictly. then mixes map and flatMap behaviour.
