It is often joked "a monad is a monoid in the category of endofunctors."
Little known fact, an Applicative functor is a monoid in the category of functors with day convolution as the product.
And day convolution unlike endofunctor composition can be defined over any strong monoidal category (basically just has tuples and functions.)
Hence
{-# LANGUAGE ExistentialQuantification, RankNTypes #-}
import Prelude hiding (Functor (..), Applicative (..))
class Functor f where
fmap :: Hom a b -> f a -> f b
class Functor f => Monoidal f where
pure :: Id a -> f a
join :: Day f f a -> f a
data Day f g a = forall x y. Day (f x) (g y) (Hom (PRODUCT x y) a)
instance Functor (Day f g) where
fmap f (Day h x y) = Day (f :.: h) x y
data Id a = Id (forall x. Hom x a)
instance Functor Id where
fmap f (Id x) = Id (f :.: x)
data Free f a = Pure (Id a) | Ap (Day f (Free f) a)
instance Functor (Free f) where
fmap f (Pure x) = Pure (fmap f x)
fmap f (Ap x) = Ap (fmap f x)
instance Monoidal (Free f) where
pure = Pure
join (Day h (Pure x) y) = Ap h x y
Where PRODUCT
and Hom
are up to you to define.
In order to have full applicative functors you need functions which your category might not have.
Top comments (0)