I find ignoring the implementations and focus on the type signatures helpful. There are also several `map`

s and `flatMap`

s in the standard library and frameworks that may help your understanding. The type signature of most of them is similar and imply some commonalities.

**Note**: I'm will use `Optional<A>`

for `A?`

, `Array<A>`

for `[A]`

as (I find it) easier to see the similarities.

`map`

The type signature of `Optional<Wrapped>.map`

is

```
extension Optional {
func map<U>(
_ transform: (Wrapped) -> U
) -> Optional<U>
}
```

Similarly, the type signature of `Array<Element>.map`

is

```
extension Array {
func map<U>(
_ transform: (Element) -> U
) -> Array<A>
}
```

The type signature of `Result<Success, Failure>.map`

is

```
extension Result {
func map<U>(
_ transform: (Success) -> U
) -> Result<U, Failure>
}
```

All three of these methods have have the same structure. They take a function from a type parameter (`Wrapped`

, `Element`

, `Success`

) to a generic (`U`

), and they return a new value of type `Optional<U>`

, `Array<U>`

, `Result<U, Failure>`

. More succinctly

```
Optional<Wrapped>.map + ((Wrapped) -> U) -> Optional<U>
Array<Element>.map + ((Element) -> U) -> Array<U>
Result<Success, Failure>.map + ((Success) -> U) -> Result<U, Failure>
```

Each of these generic types that looks like `F<A>`

, where `F = Optional`

, `F = Array`

, or `F = Result<_, Failure>`

. And their `map`

s have the following type signature

```
F<A>.map + ((A) -> B) -> F<B>
```

That is, you can think of `map`

as preserving the structure of your generic while changing the values in the container.

```
let x: Optional<Int> = .some(2) // or 2
let y: Optional<Int> = nil
let xs: [1,2,3]
let success: Result<Int, Error> = .success(2)
let failure: Result<Int, Error> = .failure(anError)
x.map { $0 + 1 } == 3
y.map { $0 + 1 } == nil
xs.map { $0 + 1 } == [2,3,4]
success.map { $0 + 1 } == .success(3)
failure.map { $0 + 1 } == .failure(anError)
```

Notice that the structure didn't change. If I started with `.some`

, map kept the same structure but changed values by incrementing them by 1. Similarly for the other values.

`flatMap`

We have slightly different type signatures for `flatMap`

:

```
extension Optional {
func flatMap<T>(
_ transform: (Wrapped) -> Optional<T>
) -> Optional<T>
}
extension Array {
func flatMap<T>(
_ transform: (Element) -> Array<T>
) -> Array<T>
}
extension Result {
func flatMap<T>(
_ transform: (Success) -> Result<T, Failure>
) -> Result<T, Failure>
}
```

Notice difference in the type signatures. `map`

's closure has type `(A) -> B`

and `flatMap`

's closure has type `(A) -> F<B>`

where `F`

corresponds to `Optional`

, `Array`

or `Result<_, Failure>`

.

Before looking at what `flatMap`

does to particular values, let see what `map`

does

```
let f: (Int) -> Optional<Int> = {
$0.isMultiple(of: 2)
? .some($0 + 1)
: nil
}
let x: Optional<Int> = .some(2)
let y: Optional<Int> = .some(3)
let z: Optional<Int> = nil
x.map(f) == .some(.some(3))
y.map(f) == .some(.none)
z.map(f) == .none
let xs: Array<Int> = [1,2,3]
xs.map { Array(repeating: $0, count: $0) } == [[1],[2,2],[3,3,3]]
let g: (Int) -> Result<Int, Error> = {
$0.isMultiple(of: 2)
? .success($0 + 1)
: .failure(Error.evenNumbersOnly)
}
let success2: Result<Int, Error> = .success(2)
let success3: Result<Int, Error> = .success(3)
let failure: Result<Int, Error> = .failure(anError)
success2.map(g) == .success(.success(3))
success3.map(g) == .success(.failure(Error.evenNumbersOnly))
failure.map(g) == .failure(anError)
```

What about `flatMap`

?

```
x.flatMap(f) == .some(3)
y.flatMap(f) == nil
z.flatMap(f) == nil
let xs: Array<Int> = [1,2,3]
xs.flatMap { Array(repeating: $0, count: $0) } == [1,2,2,3,3,3]
success2.flatMap(g) == .success(3)
success3.flatMap(g) == .failure(Error.evenNumbersOnly)
failure.flatMap(g) == .failure(anError)
```

So `map`

yielded nested values of type `F<F<B>>`

and `flatMap`

yielded `F<B>`

. In fact, you can think of `flatMap`

as `map`

then `join`

, where `join`

is a function with the following type signatures

```
func join<U>(_ x: Optional<Optional<U>>) -> Optional<U>
func join<U>(_ x: Array<Array<U>>) -> Array<U>
func join<U>(_ x: Result<Result<U, Failure>, Failure>) -> Result<U, Failure>
```

That is,

```
join(optionalValue.map(f)) == optionalValue.flatMap(f)
join(array.map(f)) == array.flatMap(f)
join(result.map(f)) == array.flatMap(f)
```