[Haskell-cafe] Monads that are Comonads and the role of Adjunction

Jules Bean jules at jellybean.co.uk
Fri Dec 14 05:14:56 EST 2007

Dan Weston wrote:
> apfelmus wrote:
>> Luke Palmer wrote:
>>> Isn't a type which is both a Monad and a Comonad just Identity?
>>> (I'm actually not sure, I'm just conjecting)
>> Good idea, but it's not the case.
>>   data L a = One a | Cons a (L a)   -- non-empty list
> Maybe I can entice you to elaborate slightly. From
> http://www.eyrie.org/~zednenem/2004/hsce/Control.Functor.html and 
> Control.Comonad.html there is
> ----------------------------------------------------------
> newtype O f g a   -- Functor composition:  f `O` g
> instance (Functor f, Functor g) => Functor (O f g) where ...
> instance Adjunction f g         => Monad   (O g f) where ...
> instance Adjunction f g         => Comonad (O f g) where ...
> -- I assume Haskell can infer Functor (O g f) from Monad (O g f), which
> -- is why that is missing here?

No. But it can infer Functor (O g f) from instance (Functor f, Functor 
g) => Functor (O f g), (using 'g' for 'f' and 'f' for 'g').

> class (Functor f, Functor g) => Adjunction f g | f -> g, g -> f where
>   leftAdjunct  :: (f a -> b) -> a -> g b
>   rightAdjunct :: (a -> g b) -> f a -> b
> ----------------------------------------------------------
> Functors are associative but not generally commutative. Apparently a 
> Monad is also a Comonad if there exist left (f) and right (g) adjuncts 
> that commute. [and only if also??? Is there a contrary example of a 
> Monad/Comonad for which no such f and g exist?]
> In the case of
>  >   data L a = One a | Cons a (L a)   -- non-empty list
> what are the appropriate definitions of leftAdjunct and rightAdjunct? 
> Are they Monad.return and Comonad.extract respectively? That seems to 
> unify a and b unnecessarily. Do they wrap bind and cobind? Are they of 
> any practical utility?

I think you're asking the wrong question!

The first question needs to be :

What is "f" and what is "g" ? What are the two Functors in this case?

We know that we want g `O` f to be L, because we know that the unit is 
return, i.e. One, and

unit :: a -> O g f a
otherwise known as eta :: a -> O g f a

We also know there is a co-unit epsilon :: O f g a -> a, but we don't 
know much about that until we work out how to decompose L into two Functors.

There are two standard ways to decompose a monad into two adjoint 
functors: the Kleisli decomposition and the Eilenberg-Moore decomposition.

However, neither of these categories is a subcategory of Hask in an 
obvious way, so I don't immediately see how to write "f" and "g" as 
haskell functors.

Maybe someone else can show the way :)


More information about the Haskell-Cafe mailing list