frontend = comonad, backend = monad
Tags: webdev, functional
Published: 2021-03-25 14:04:16

---
title: frontend = comonad, backend = monad
published: true
description: A quick note about two different roles and a categorical dual
tags: webdev, functional
cover_image: http://www.ouarzy.com/wp-content/uploads/2017/09/monad-eye.gif
---

I'm writing this short article based on two observations:

1. The internet is filled with many "what is a monad" articles but comparatively few "what is a comonad" articles.
2. These "what is a monad" articles are often written for frontend developers.

I'd like to set the record straight in this article by claiming, in the most hand-wavey and unscientific of ways, that **frontend = comonad, backend = monad**. So, if you are frontend engineer, learning about comonads is IMO the way to go.

This observation is not at all new. Phil Freeman's article [The Future is Comonadic](https://speakerdeck.com/paf31/the-future-is-comonadic) makes the point that working with UIs is tantamount to working with a comonad.  So I'm writing this article mostly to amalgamate different strands of thought, clear up confusion, and put a name on certain industry trends.

# Monad vs comonad

A monad `m` providing a context for type `a` is equipped with two operations:

```haskell
pure :: a -> m a
join :: m (m a) -> m a
```

A comonad `w` providing a context for type `a` is equipped with two operations:

```haskell
extract :: w a -> a
duplicate :: w a -> w (w a)
```

The only difference between the two is what's on the left and right of the arrow.

# An example of a monad and a comonad

Let's take a quick gander at a monad and a comonad in the wild.

## Our monad - Maybe

`Maybe` is a monad that provides a context of existing _or_ not existing to a value of type `a`.

```haskell
data Maybe a = Just a | Nothing
```

`pure` for `Maybe` is defined like this:

```haskell
pure :: a -> Maybe a
pure = Just
```

We _could_ have defined it like this:

```haskell
pure :: a -> Maybe a
pure _ = Nothing
```

But that wouldn't be very nice, as it would destroy all the input values. While perfectly legal, the community has rallied around the first `pure` with `Just` because it is closer to our intuition about how `pure` for `Maybe` should behave.

`join` is defined like this:

```haskell
join :: Maybe (Maybe a) -> Maybe a
join (Just x) = x
join Nothing = Nothing
```

As maybes pile up, join gives us a way to squish them back down to a single level of `Maybe`-ness.

## Our comonad - Stream

`Stream` is a comonad that provides an infinite list of values.

```haskell
data Stream a = Stream a (Stream a)
```

In that context, `extract` gets the head of the stream

```haskell
extract :: Stream a -> a
extract (Stream head rest) = head
```

`duplicate` gets the tail of the stream.

```haskell
duplicate :: Stream a -> Stream (Stream a)
duplicate (Stream head rest) = Stream rest
```

You can then call `extract` on the result of duplicate to get a `Stream` and get its head with `extract`.

# Backend vs frontend

## Backend

In backend development, there are two main tasks:

1. Reigning in the chaos (API calls, flaky hardware, working with the filesystem, GPUs, blech...)
2. Inserting our business logic, the only thing we "know", into this madness to produce value for someone somewhere.

These correspond to:

1. `join` : Reigning in the chaos.
2. `pure` : Bringing our business logic to the party.

## Frontend

In frontend development, there are two main tasks:

1. Managing and anticipating possible future scenarios so that when a user does thing _x_ or _y_ it "just works".
2. Rendering a UI for a user.

These correspond to:

1. `duplicate` : Projecting into the future (the tail of our stream).
2. `extract` : Rendering a UI.

# Community trends

Massive community trends can be boiled down to the comonad vs monad divide.

## Backend: Kubernetes is a monad

Kubernetes is a monad. You call `pure` on bits of your stack to get it into a pod, and you call `join` on pods so that you never have kubernetes-in-kubernetes: there's always just one level.

## Frontend: Nextjs is a comonad

Nextjs is a comonad. You call `extract` to take JavaScript and make it a static webpage via its SSR, and React hooks are essentially `duplicate`: they project a value into the future by returning a callback.

# Ask for a comonad tutorial

So, if you're a frontend dev and rolling your eyes at "not another monad tutorial", ask for a comonad tutorial. Chances are it will be much more relevant to your day-to-day work!