# Fantas, Eel, and Specification 17: Comonad

19 Jun 2017**‘Ello ‘ello**! Remember that `Monad`

thing we used to be afraid of, and how it just boiled down to a way for us to **sequence** our ideas? How `Extend`

was really just `Chain`

backwards? Well, today, we’ll answer the question that I’m sure has plagued you *all* week: **what is a backwards Monad**?

First up, we should talk about the **name**. *No*, not the `monad`

bit - the `co`

bit. When we talk about structures like `Monad`

, we sometimes talk about the idea of the **dual structure**. Now, for our purposes, we can just think of this as, “*The same, but with all the arrows backwards*”.

This is a

surprisinglygood intuition for dual structures. Seriously.

Hey, that was our **first hint**! `Comonad`

is `Monad`

with “the arrows backwards”. When we **boil it down**, there are really only two **interesting** things that a `Monad`

can do:

```
-- For any monad `m`:
of :: a -> m a
chain :: m a -> (a -> m b) -> m b
```

From this, we can derive all the other fun stuff like `join`

, `map`

, `ap`

, and whatnot. So, let’s write this all **backwards**, turning our entire types the **wrong way round**:

```
-- Turn the arrows around...
coOf :: a <- m a
coChain :: m a <- (a <- m b) <- m b
-- Or, more familiarly...
-- For any COmonad `w`:
coOf :: w a -> a
coChain :: w a -> (w a -> b) -> w b
```

Well, here’s the **good news**: we already know `coChain`

, and we call it `extend`

! That leaves us with that `coOf`

function, which the glorious Fantasy Land spec calls ** extract**.

When I first looked at `extract`

, I got a bit confused. Couldn’t we do that with `Monad`

? If not, what’s the *point* in a `Monad`

if we can’t get a value back *out*? What helped me was looking **a little closer** at `extract`

:

```
extract :: w a -> a
```

That function takes **any** `Comonad`

and returns the value **inside**. We couldn’t do that for `Maybe`

, because some of our values - `Nothing`

- don’t have a value to return! We couldn’t do it for `Array`

; what if it’s **empty**? We couldn’t do it for `Promise`

; we don’t know what the value *is* yet! It turns out that, for a *lot* of `Monad`

types, this function **isn’t as easy** to write as we might think at first glance.

Let’s think about `Maybe`

for a second, though. Would it be a `Comonad`

if we removed the `Nothing`

option? Well, yes, but then it wouldn’t be a `Maybe`

- it would be `Identity`

with a funny name!

What about `Array`

? What if we made a type like this:

```
//- An array with AT LEAST ONE element.
//+ data NonEmpty = NonEmpty a (Array a)
const NonEmpty = daggy.tagged(
'head', 'tail'
)
// Extend would function the same way as it
// did for Array in the last article...
NonEmpty.prototype.extract = function () {
return this.head
}
// e.g.
NonEmpty(1, [2, 3, 4]).extract() // 1
```

Now we have a **type** for non-empty lists, we can **guarantee** a value to extract! This type, it transpires, forms a beautiful `Comonad`

.

A piece of good advice is to

make illegal states unrepresentable. If we need an array somewhere in our code thatmusthave at least one element, using the`NonEmpty`

type gives us an API with thatguarantee!

So, `chain`

gave us sequencing with **write** access to the **output**, and `of`

let us **lift** a value into the computation whenever we liked. `extend`

gives us sequencing with **read** access to the **input**, and `extract`

lets us **extract** a value out of the computation whenever we like!

If you’ve followed the blog series up until now, the

`Comonad`

laws are going to be what you’ve come to expect.No new ideas!

Now, before we start to assume that all `Comonad`

types are just **bastardised Monad types**, let’s look at something

**very**comonadic:

`Store`

.```
//+ data Store p s = Store (p -> s) p
const Store = daggy.tagged(
'lookup', 'pointer'
)
```

The intuition here is that `lookup`

represents a function to get things *out* of a “store” of `s`

-values, indexed by `p`

-values. So, if we pass a `p`

to the `lookup`

function, we’ll get out its corresponding `s`

. The `pointer`

value represents the “current” value. Think of this like the **read head** on an old **hard disk**.

Now, to make this type more useful, we can stick a couple of functions onto this:

```
//- "Move" the current pointer.
//+ seek :: Store p s ~> p -> Store p s
Store.prototype.seek = function (p) {
return Store(this.lookup, p)
}
//- Have a look at a particular cell.
//+ peek :: Store p s ~> s
Store.prototype.peek = function (p) {
return this.lookup(p)
}
```

And, wouldn’t you know it, we can also make this a functor by mapping over the **function**!

```
//- Compose the functions! Yay!
Store.prototype.map = function (f) {
const { lookup, pointer } = this
return Store(lookup.map(f), pointer)
// Store(p => f(lookup(p)), pointer)
}
```

Now, if we’re going to make a `Comonad`

of our `Store`

, we first need to make it an `Extend`

instance. Remember: `extend`

should behave like `map`

, but with **read-access to the input**. Here’s where `Store`

gets *really* sneaky.

```
//+ extend :: Store p s ~> (Store p s -> t)
//+ -> Store p t
Store.prototype.extend = function (f) {
return Store(
p => f(Store(this.lookup, p)),
this.pointer)
}
```

Our `lookup`

function now applies `f`

to a `Store`

**identical** to the original, but with the focus on the **given index**! Can you see the magic yet? Let’s **build something exciting**: Conway’s **Game of Life**.

For this, we’re going to use a “board” of `[[Bool]]`

type to represent our “live” and “dead” cells. Something like this, perhaps:

```
let start = [
[ true, true, false, false ],
[ true, false, true, false ],
[ true, false, false, true ],
[ true, false, true, false ]
]
```

If we want to look up a value in this store, we’re going to need an `x`

and `y`

coordinate. What better choice of structure to hold two numbers than a `Pair`

?

```
const Game = Store(
({ _1: x, _2: y }) =>
// Return the cell OR false.
y in start && x in start[y]
? start[y][x]
: false,
// We don't care about `pointer` yet.
Pair(0, 0))
```

Now, we need to write out some logic! The rule for the Game of Life is that, if a `false`

cell has **exactly three** `true`

neighbours, make it true. If a `true`

cell has **two or three** `true`

neighbours, keep it as true. If **neither** apply, make it `false`

. We can work this out for any cell with eight sneaky `peek`

s!

```
// What will the current cell be next time?
//+ isSurvivor :: Store (Pair Int Int) Bool
//+ -> Bool
const isSurvivor = store => {
const { _1: x, _2: y } = store.pointer
// The number of `true` neighbours.
const neighbours =
[ Pair(x - 1, y - 1) // NW
, Pair(x, y - 1) // N
, Pair(x + 1, y - 1) // NE
, Pair(x - 1, y) // W
, Pair(x + 1, y) // E
, Pair(x - 1, y + 1) // SW
, Pair(x, y + 1) // S
, Pair(x + 1, y + 1) // SE
]
.map(x => store.peek(x)) // Look up!
.filter(x => x) // Ignore false cells
.length
// Exercise: simplify this.
return store.extract() // Is it true?
? neighbours === 2 || neighbours === 3
: neighbours === 2
}
```

Now, *why* did we go to all this trouble? Well, we now have a `Store (Int, Int) Bool`

to `Bool`

function, which is the exact shape that `extend`

needs… and `extend`

will (lazily!) apply this function to **every cell on the board!** By using `extend`

, we now get to see the **entire board** one step into **the future**. Isn’t that *magical*?

I

stronglyrecommend you look at the Gist for this article and be sure that this makes sense.`Store`

is anunfamiliar beast.

Now, there are plenty of other `Comonad`

types, but they’re not quite as popular as `Monad`

types, probably because their use isn’t so **obvious**. After all, we can write our applications just using `Monad`

types, so this (*unfairly*) ends up in the *advanced* box. How **rude**!

For now, however, we’ll stop here. I will come back to `Comonad`

in other posts - they’re my latest **obsession** - but `Store`

gives a really clear idea about why these are useful. Incidentally, if you want to play the Game of Life, the article’s Gist has a working demo!

Next time, we’ll be looking at `Bifunctor`

and `Profunctor`

: so simple, we’re going to do both at the same time! I promise: these last two are going to be a bit of a **cool-down session**. Until then!

♥