# Zap as the Machinery of Program Reduction

Last time around, we discussed duality and cofree comonads towards our quest in generating rich stories. I promised that comonads were the abstraction and machinery behind interpreters, but I have yet to prove that. Let’s do it today.

## My Kingdom for a Functor🔗

Two posts ago, we created a “command functor” whose job it was to specify the specific commands possible in our DSL:

```
data StoryF a = Change Character ChangeType (ChangeResult -> a)
| Interrupt (Story ()) (Story ()) a
type Story a = Free StoryF a
```

Recall, this should be understood as “a story is built out of primitives where characters can change, or where one story interrupted by another.” The polymorphic `a`

is “the type of the next piece of the computation,” and so the conspicuous `(ChangeResult -> a)`

argument to the `Change`

data constructor is “the remainder of the computation will be given a `ChangeResult`

” or perhaps more naturally, “the `Change`

command returns a `ChangeResult`

.”

So that’s one half of the puzzle. We can create programs in our DSL, but we can’t yet interpret them. We’ve derived `Cofree`

from first principles, and I’ve promised you that once we have an appropriate cofree comonad, we can use it as an interpreter for our DSL. In the same way that we created `StoryF`

to exist as a `Functor`

over which `Free`

would give us a `Monad`

, we’re going to need to find a meaningful `CoStoryF`

to act as a carrier over `Cofree`

to give us a `Comonad`

.

It’s tempting to dive right in and try our same old tried-and-true approach: dualize everything and go from there. Unfortunately, that doesn’t work (I tried it), so instead of leading ourselves down a path of madness, let’s slow down and think about what we’re actually trying to accomplish.

The function we’re actually trying to write is this:

`interpret :: Story a -> CoStory b -> (a, b)`

which is to say, a function that runs `Story a`

programs through an interpreter with internal state `b`

. While the program itself computes an `a`

, in the case of our interpreter, it’s this internal state `b`

that we’re actually interested in. When we get closer to actually using this machinery to generate stories, this `b`

is going to be instantiated as necessary locations, interesting character quirks, and other things we’re trying to compute *about* our story.

While `a`

carries information between program segments (on the DSL side of things), `b`

carries information *about* program segments (on the interpretation side).

## When Zap’s in Charge, Every Mission’s a Suicide Mission🔗

Due to free theorems from parametricity, it’s often easier to find implementations of general functions than it is for more specific ones. In light of this, we can view this desired `interpret`

function as the special case of a more general one:

`zap :: (a -> b -> c) -> f a -> g b -> c`

Here, `zap`

is understood to be a function where somehow the functors `f`

and `g`

“annihilate” one another, and allow us to run pure functions over top of them. Obviously this depends on our choice of `f`

and `g`

, so we will make a typeclass:

```
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
class Zap f g | f -> g, g -> f where
zap :: (a -> b -> c) -> f a -> g b -> c
```

It’s safe to ignore the `LANGUAGE`

pragmas and the `| f -> g, g -> f`

syntax if you don’t know what’s going on with them; they’re just there to convince Haskell that the gnarly things we’re doing with the type are kosher. Things won’t compile without them, but the type signature of `zap`

is really what we care about here.

If you’ve forgotten what we’re trying to do by this point, we’re still looking for a meaningful `CoStoryF`

functor. Once we get that, we can make a `Cofree CoStoryF`

, which will necessarily form a `Comonad`

and we’ll *finally* be able to evaluate our programs. Carrying on.

As is usually the case with typeclasses, we can probably derive `Zap f g`

inductively, by which I mean this: if we have a `Zap StoryF CoStoryF`

, we can likely use it to derive `Zap (Free StoryF) (Cofree CoStoryF)`

. Following this line of reasoning, we’ll try to work backwards to see what `CoStoryF`

might look like.

But where do we start? Well, in the same line of reasoning, we can probably get a `Zap StoryF CoStoryF`

from a `Zap`

over the constituent functors of `StoryF`

. Recall its definition:

```
data StoryF a = Change Character ChangeType (ChangeResult -> a)
| Interrupt (Story ()) (Story ()) a
```

The constituent functors here are kind of hidden, but if you stare at it, you’ll see we have a sum (between `Change`

and `Interrupt`

), a product (the parameters in each branch), and a function.

In functor form, we know these as `Either x`

, `(,) x`

and `(->) x`

. This suggests we should start looking for instances of `Zap`

between these functors. Since pairs make up most of `StoryF`

, we’ll start there. With the wisdom of having done it already, I’ll suggest we look for a `Zap ((,) x) ((->) x)`

instance^{1}.

If we expand this out, it means we’re looking for a function of type `(a -> b -> c) -> (x, a) -> (x -> b) -> c`

. Given the signature, it’s actually pretty easy to work out:

```
instance Zap ((,) x) ((->) x) where
-- zap :: (a -> b -> c) -> (x, a) -> (x -> b) -> c
= f a (xtob x) zap f (x, a) xtob
```

It’s worth noticing that `Zap f g`

is symmetric about `f`

and `g`

. We had to pick one to go first, but there is no semantic distinction between the positions. We can exploit this fact to derive `Zap g f`

automatically: we can just `flip`

our incoming function:

```
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
instance {-# OVERLAPPABLE #-} Zap f g => Zap g f where
= zap (flip f) b a zap f a b
```

Again, more magic syntax to convince Haskell that this is kosher. `UndecidableInstances`

certainly sounds scary, but I promise that this is an OK use of it.

## Searching for a Functor Clarity🔗

The construction of this `Zap`

instance between pairs and functions is promising. If you’re curious about what sorcery is actually going on here, this magic comes directly from the adjunction between curry and uncurry. Since every term in our sum-type `StoryF`

is made up of nothing but pairs and functions, and functions and pairs can annihilate one another, this suggests our `CoStoryF`

should be a product-type where we swap all of our products with functions and vice-versa:

```
data CoStoryF b = CoStoryF
changeH :: Character -> ChangeType -> (ChangeResult, b)
{ interruptH :: Story () -> Story () -> b
,
}type CoStory b = Cofree CoStoryF b
```

This actually makes a great deal of sense if you look at it for a minute or two. If a `StoryF`

is one of any possible commands, a `CoStoryF`

should be a collection of functions to handle any action that a `StoryF`

is capable of throwing at it. A `StoryF`

is a sum of arguments, while a `CoStoryF`

is a product of functions taking those arguments.

Convinced that we’ve found the right data structure, we’ll write a `Functor`

instance for it:

```
instance Functor CoStoryF where
fmap f (CoStoryF c i) = CoStoryF
fmap (fmap (fmap f)) c)
(fmap (fmap f) i) (
```

Your first thought might be “what a disgusting mess of `fmap`

”. And you’d be right. You can convince yourself that it’s right by remembering that each application of `fmap`

moves you inside a function, or into the second piece of a pair. Alternatively, you can try compiling it, see that it type-checks, and move on with your life thinking no more about it.

Armed with the right data structure and a `Functor`

instance it, we’ll go on to build our `Zap StoryF CoStoryF`

. Remember that the pieces of our `CoStoryF`

product are “handlers” of particular actions from our `StoryF`

, and thus we’ll call these pieces `h`

in the following snippet:

```
instance Zap StoryF CoStoryF where
Change c ct k) (CoStoryF h _) =
zap f (let (cr, b) = h c ct
= k cr
a in f a b
Interrupt x x' a) (CoStoryF _ h) = f a (h x x') zap f (
```

Gross and ugly, I know. What are we writing here, C? Instead, we can exploit our `Zap`

instance from earlier to perform the computation in that `let`

block for us:

```
-- much nicer version of our previous snippet
instance Zap StoryF CoStoryF where
Change c ct k) (CoStoryF h _) = zap f k (h c ct)
zap f (Interrupt x x' k) (CoStoryF _ h) = f k (h x x') zap f (
```

Much better.

I claim that this does what we want. But why does this work? Well we’re using the sum constructor from our `StoryF`

type as an *index* into the related handler from the product of our `CoStoryF`

.

To interpret a `Change`

, for example, we compute a `ChangeResult`

from our handler given the arguments from `Change`

. We then take this resulting `ChangeResult`

and pass it into the continuation `(ChangeResult -> a)`

returned by `Change`

. In effect, this instance of `Zap`

has performed a single stage of reduction between our DSL and our interpreter.

## The Cogs in the Machine🔗

Maybe you’re starting to see now why this `Zap`

machinery is useful for running our program: it automatically interleaves the results from our interpretation into the bound values in our DSL. What we’ve built so far automatically connects a single step of the program with a single step of the interpretation; as you might expect, the `Zap`

over `Free`

and `Cofree`

will take care of running the individual reductions sequentially until we’ve fully evaluated our program.

And so we need to find a derivation of `Zap (Free f) (Cofree g)`

. If you followed the last derivation, this one should be a piece of cake. If not, it’s worth staring at for a little while – grokking it definitely helped solidify in my mind how `Free`

and `Cofree`

are related.

```
instance Zap f g => Zap (Cofree f) (Free g) where
Pure a) (Cofree b _ ) = f a b
zap f (Bind as) (Cofree _ bs) = zap (zap f) as bs zap f (
```

Notice that we’re doing the same trick here: using the sum constructor of our `Free`

type to pick a particular piece out of the product of our `Cofree`

type.

All that’s left now is to construct a particular `interpreter : CoStory b`

, which we can `zap`

against any `story : Story a`

. That will be our focus for the next post, but in the meantime, we’ll convince ourselves that we’ve done something worthwhile here by implementing our desired `interpret`

function from earlier:

```
interpret :: Story a -> CoStory b -> (a, b)
= zap (,) interpret
```

Oh. That was easy. Definitely a sign that we’re onto something here.

Until next time.

Deriving the other two instances is informative for how this machinery actually works, and is left as an exercise to the reader.↩︎