### Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

### Introduction

On this series we’ve done a number of “deep dives” to really analyze a topic. Things like exploring the `map`

function to see that it’s a very universal idea and we should be comfortable defining it on our own types. And things like “contravariance”, which is kind of unintuitive at first but is really quite handy.

This often helps us see something we think we’re familiar with in a new light, or helps us see something that is very unintuitive but become comfortable with it because we develop ways to concisely manage it and transform it.

We’re doing another one of those today, and this time it’s the `zip`

function. You’ve probably used `zip`

a few times in your every day coding, and you probably thought it was pretty handy. But what we want to show people is that it’s a generalization of something you are already familiar with, but you may have never thought of it like this before. And once you see this generalization it really helps unify a bunch of disparate ideas.

Let’s begin by exploring the `zip`

that comes with Swift’s standard library.

### Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

Already a subscriber? Log in

### Exercises

In this episode we came across closures of the form

`{ ($0, $1.0, $1.1) }`

a few times in order to unpack a tuple of the form`(A, (B, C))`

to`(A, B, C)`

. Create a few overloaded functions named`unpack`

to automate this.Define

`zip4`

,`zip5`

,`zip4(with:)`

and`zip5(with:)`

on arrays and optionals. Bonus: learn how to use Apple’s`gyb`

tool to generate higher-arity overloads.Do you think

`zip2`

can be seen as a kind of associative infix operator? For example, is it true that`zip(xs, zip(ys, zs)) == zip(zip(xs, ys), zs)`

? If it’s not strictly true, can you define an equivalence between them?Define

`unzip2`

on arrays, which does the opposite of`zip2: ([(A, B)]) -> ([A], [B])`

. Can you think of any applications of this function?It turns out, that unlike the

`map`

function,`zip2`

is not uniquely defined. A single type can have multiple, completely different`zip2`

functions. Can you find another`zip2`

on arrays that is different from the one we defined? How does it differ from our`zip2`

and how could it be useful?Define

`zip2`

on the result type:`(Result<A, E>, Result<B, E>) -> Result<(A, B), E>`

. Is there more than one possible implementation? Also define`zip3`

,`zip2(with:)`

and`zip3(with:)`

.Is there anything that seems wrong or “off” about your implementation? If so, it will be improved in the next episode 😃.

In previous episodes we’ve considered the type that simply wraps a function, and let’s define it as

`struct Func<R, A> { let apply: (R) -> A }`

. Show that this type supports a`zip2`

function on the`A`

type parameter. Also define`zip3`

,`zip2(with:)`

and`zip3(with:)`

.The nested type

`[A]? = Optional<Array<A>>`

is composed of two containers, each of which has their own`zip2`

function. Can you define`zip2`

on this nested container that somehow involves each of the`zip2`

’s on the container types?