## FreeAp is a Comonad

by Phil Freeman on 2017/07/01

While thinking about comonads as spaces and Day convolution, I realized an interesting thing. The free applicative functor generated by a comonad `f`

is also a comonad.

The free applicative can be defined in a few different ways, but I like to define it like this:

```
data FreeApplicative f a = Pure a | Free (Day f (FreeApplicative f) a)
```

Here, `Day`

is taken from my `purescript-day`

package. I think this presentation makes it easy to understand the free applicative, since it is just a Day convolution of a finite number of copies of `f`

. It also makes it simple to define various operations like `hoistFreeAp`

.

If we refactor this slightly to use a `Coproduct`

, then a `Comonad`

instance can even be derived:

```
newtype FreeApplicative f a = FreeApplicative (Coproduct Identity (Day f (FreeApplicative f)) a)
derive newtype instance functorFreeApplicative :: Functor f => Functor (FreeApplicative f)
derive newtype instance extendFreeApplicative :: Extend f => Extend (FreeApplicative f)
derive newtype instance comonadFreeApplicative :: Comonad f => Comonad (FreeApplicative f)
```

This works since `Identity`

is a comonad, and `Coproduct`

and `Day`

both preserve comonads.

In the comonads as spaces approach to user interfaces, the free applicative gives a way to build a UI for a finite list of subcomponents, just like `Day`

gives us a way to compose two subcomponents.

Unfortunately, `FreeAp`

isn't a `Comonad`

transformer. The problem is that we would not be able to handle the `Pure`

case if we tried to `lower`

a `FreeAp w`

to a `w`

.

However, we can construct a `ComonadTrans`

instance if we restrict ourselves to a Day convolution of a non-zero number of copies of `f`

. Instead of the free `Applicative`

, this gives us the free `Apply`

:

```
newtype FreeApplicative f a = FreeApplicative (Coproduct Identity (FreeApply f) a)
derive newtype instance functorFreeApplicative :: Functor f => Functor (FreeApplicative f)
derive newtype instance extendFreeApplicative :: Extend f => Extend (FreeApplicative f)
derive newtype instance comonadFreeApplicative :: Comonad f => Comonad (FreeApplicative f)
newtype FreeApply f a = FreeApply (Day f (FreeApplicative f) a)
derive newtype instance functorFreeApply :: Functor f => Functor (FreeApply f)
derive newtype instance extendFreeApply :: Extend f => Extend (FreeApply f)
derive newtype instance comonadFreeApply :: Comonad f => Comonad (FreeApply f)
```

Now, we can write a `ComonadTrans`

instance for `FreeApply`

which keeps the first `w`

in a non-empty collection of `w`

s, and `extract`

s the focus from the rest.

```
instance comonadTransFreeApply :: ComonadTrans FreeApply where
lower (FreeApply d) = runDay (\f w fa -> map (\x -> f x (extract fa)) w) d
```