Monoidal Functor is Applicative but where is the Monoid typeclass in the definition of Applicative?

The monoid that’s referred to with “monoidal functor” is not a Monoid monoid, i.e. a value-level monoid. It’s a type-level monoid instead. Namely, the boring product monoid

type Mempty = ()
type a <> b = (a,b)

(You may notice that this is not strictly speaking a monoid; it’s only if you consider ((a,b),c) and (a,(b,c)) as the same type. They are sure enough isomorphic.)

To see what this has to do with Applicative, resp. monoidal functors, we need to write the class in other terms.

class Functor f => Monoidal f where
  pureUnit :: f Mempty
  fzip :: f a -> f b -> f (a<>b)

-- an even more “general nonsense”, equivalent formulation is
-- upure :: Mempty -> f Mempty
-- fzipt :: (f a<>f b) -> f (a<>b)
-- i.e. the functor maps a monoid to a monoid (in this case the same monoid).
-- That's really the mathematical idea behind this all.

IOW

class Functor f => Monoidal f where
  pureUnit :: f ()
  fzip :: f a -> f b -> f (a,b)

It’s a simple exercise to define a generic instance of the standard Applicative class in terms of Monoidal, vice versa.


Regarding ("ab",(+1)) <*> ("cd", 5): that doesn’t have much to do with Applicative in general, but only with the writer applicative specifically. The instance is

instance Monoid a => Monoidal ((,) a) where
  pureUnit = (mempty, ())
  fzip (p,a) (q,b) = (p<>q, (a,b))

Leave a Comment