# Pairs as Functors

27 Apr 2017Two-ish weeks ago, we talked about the wonderful flexibility of `Function`

when you start treating it as a `Functor`

. We started off with **composition**, then **branching** composition, and then finally **environment-aware** composition. We also gave our humble function a new name: `Reader`

. Today, we’re going to walk the same path for `Pair`

, and build up a closely-related idea.

`Functor`

It’s pretty simple to write an implementation of `Functor`

for a `Pair a b`

structure:

```
const Pair = daggy.tagged('_1', '_2')
// We just transform the second value!
// map :: Pair a b ~> (b -> c) -> Pair a c
Pair.prototype.map = function (f) {
return Pair(this._1, f(this._2))
}
```

We transform the second half, but leave the first alone. I’m going to suggest that we treat the `Pair`

functor as a way of modelling **values with metadata** - some **extra information** about the value. I’ll admit that this, in isolation, is not particularly useful. However, we’ll see that, with some extra functionality provided by `ap`

and `chain`

, it’ll start to make sense.

`Applicative`

Now, let’s make something *interesting*. Turns out that one useful `Applicative`

implementation requires the left-hand side to be a `Monoid`

. We can implement this like so:

```
const Pair = T => {
const Pair_ = daggy.tagged('_1', '_2')
Pair_.prototype.map = function (f) {
return Pair_(this._1, f(this._2))
}
Pair_.prototype.ap = function (fs) {
return Pair_(fs._1.concat(this._1),
fs._2(this._2))
}
Pair_.of = x => Pair_(T.empty(), x)
return Pair_
}
```

As usual, note that only a.`Semigroup`

is required for`Apply`

, but`of`

needs`empty`

to produce a valid left-hand value

Turns out this is a pretty useful implementation, which is definitely made more readable with some help from `lift2`

. *Readers of the Fantasy Land series will remember the post on Apply, where we discussed lift2 as a way of “combining contexts” with a given function.* Let’s imagine we have a set of actions that have “costs”. We can write them as a

`Pair`

with `Sum`

as the left-side monoid:```
const CostPair = Pair(Sum)
//- Database lookups are pretty costly...
//+ userFromDB :: Int
//+ -> Pair (Sum Int) String
const nameFromDB = id => CostPair(
Sum(100), getUserById(id))
//- ... but ordering/counting is harder.
//+ rankFromDB :: Int
//+ -> Pair (Sum Int) Int
const rankFromDB = id => CostPair(
Sum(500), getUserRankById(id))
//- Do both jobs, end up with Sum(600)!
//+ getUserData :: Int
//+ -> Pair (Sum Int) User
const getUserData = id => lift2(
x => y => ({ name: x, rank: y }),
nameFromDB(id), rankFromDB(id))
// ===================== //
//- By the way, we can use `Function` as an
//- `Applicative` as we did last time, and
//- that lets us write this with a couple
//- of `lift2` calls! Beautiful point-free!
//+ getUserData_ :: Int
//+ -> Pair (Sum Int) User
const getUserData_ = lift2(
lift2(x => y => ({ name: x, rank: y }),
nameFromDB, rankFromDB)
```

So, we can collect the “cost” of our computation as we go, which we could then analyse at the end. As we said with `Functor`

, the `Pair`

allows for **metadata**, which, in this case, is cost of computation. We could also swap out `Sum`

for `Max`

to find the most expensive operation in our app, or `Average`

to… well, find the average!

`Monad`

```
const Pair = T => {
...
Pair_.prototype.chain = function (f) {
const that = f(this._2)
return Pair_(this._1.concat(that._1),
that._2)
}
...
}
```

Again,

`Monad`

requires`of`

(`Applicative`

) and thus needs a`Monoid`

for the left side.`Chain`

doesn’t require`of`

, and so we can get away with a`Semigroup`

.

This `chain`

function allows us to string actions together, while also collecting a value in the monoid, as we did before. Of course, this will work with the `CostPair`

we defined above, but let’s try something a bit different. Let’s instead use `[String]`

as our monoid, and play some Guess Who?

```
// Sneaky monkey patch!
Array.empty = () => []
LogPair = Pair(Array)
// Lift the users into the LogPair type.
// (The left side at this point is [])
LogPair.of(users)
// Keep only the users with brown hair
.chain(users => LogPair(
['Brown hair'],
users.filter(user =>
user.hair === 'brown')))
// Keep only the users over 180cm tall
.chain(users => LogPair(
['Tall'],
users.filter(user =>
user.height > 180)))
// Count the remaining users
.map(users => users.length)
// e.g.: Pair(['Brown Hair', 'Tall'], 36)
```

We can see that our final result is another `Pair`

, whose right side holds the number of remaining users, as we’d expect. However, the left side is now a list of all the actions that got us to that number! If you built your whole app inside the `Pair`

monad, you would have a purely-functional **logger**, to which you could write any number of messages at any time. On top of that, `Array`

’s `Monoid`

implementation doesn’t care about the *inner* type, so you can log any data structure you want!

This nifty little pattern - writing something to a log (or really just appending to a monoid) while transforming the other value - is what gives this type the common name `Writer`

. It is, in essence, the opposite of `Reader`

: `Reader`

can *read* from some “global” state, `Writer`

can *write* to some “global” state.

So, we’ve seen that, through a different lens, `s -> a`

is a `Reader`

, and `(s, a)`

is a `Writer`

. We have **readable or writable state**, and they’re purely functional! There’s only one downside, though: what if we want *both*?

Think about what state *is* in stateful languages. It’s a thing that can change as a result of **any instruction**. This means, really, our stateful languages execute functions kinda like this:

```
execute :: (State, Action) -> State
```

We take an **instruction** (`Action`

) and the **current state**, and we get back a potentially **new state**. Maybe something has been written the console, maybe a variable has been updated, etc. That’s really the most abstract that we can make it, and will look familiar to users of packages like Redux. Now, take a closer look at `execute`

:

```
-- FUNCTION v
execute :: (State, Action) -> State
-- ^ PAIR
```

**OMGWTF**. Turns out that `execute`

is a combination of `Reader`

and `Writer`

! Well, if we can make **read-only** state purely functional, and **write-only** state purely functional, and we can see that `State`

is really just a combination of the two… there has to be a way to build purely functional **read and write** state, right?

**Right**. Next time, we’ll look at the `State`

type, and see how we can combine these two principles to give us everything we need to combat those **pesky naysayers** who think functional programming is impractical. **Get excited**!

♥

*PS: if you want to play with the code in this post, I’ve put all the code in a Gist, so why not mess around with it?*