Skip to the content.

Coproduct to product monoidal functor

In the previous two posts, we’ve seen monoidal functors that preserve product and coproduct. Then, what does it look like if we define a functor that preserves monidal structure in different forms?

Let’s say we have coproduct monoidal structure in a source category, and product monoidal structure in a target category. To make a functor from the source category to the target category a monoidal functor, we need a morphism epsilon converting a unit in the target category to a mapped unit in the source category, and a natural transformation mu converting a monoidal product of mapped objects in the target category to a mapped monoidal product in the source category.

{-# LANGUAGE FlexibleInstances,
             InstanceSigs,
             ScopedTypeVariables,
             UndecidableInstances
#-}

import Control.Applicative (Alternative(..))
import Data.Void (Void, absurd)

class Functor f => Monoidal f where
    mu :: (f a, f b) -> f (Either a b)
    epsilon :: () -> f Void

For example, you can implement this type class for Maybe.

instance Monoidal Maybe where
    mu :: (Maybe a, Maybe b) -> Maybe (Either a b)
    mu (Just a, _) = Just (Left a)
    mu (_, Just b) = Just (Right b)
    mu (_, _) = Nothing

    epsilon :: () -> Maybe Void
    epsilon () = Nothing

It turns out that this monoidal functor is equivalent to Alternative functor. So you can implement Alternative in terms of Monoidal.

instance (Functor f, Monoidal f, Applicative f) => Alternative f where
instance (Functor f, Monoidal f, Applicative f) => Alternative f where
    (<|>) :: f a -> f a -> f a
    x <|> y = either id id <$> mu (x, y)

    empty :: f a
    empty = absurd <$> epsilon ()