# Fantas, Eel, and Specification 17: Comonad

‘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 surprisingly good 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...
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(
)

// Extend would function the same way as it
// did for Array in the last article...

NonEmpty.prototype.extract = function () {
}

// 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 that must have at least one element, using the `NonEmpty` type gives us an API with that guarantee!

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(
'Store', ['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 ~> p -> 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 strongly recommend you look at the Gist for this article and be sure that this makes sense. `Store` is an unfamiliar 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!