[Haskell-cafe] Switching monadic encapsulations

Ross Paterson ross at soi.city.ac.uk
Mon Jun 28 18:44:37 EDT 2004

On Mon, Jun 28, 2004 at 02:59:39PM +0100, Graham Klyne wrote:
> Is there a function that switches monadic layering?
>     f :: (Monad m1,Monad m2) => m1 (m2 a) -> m2 (m1 a)
> Does this even make sense in the general case?  I'm thinking along the 
> lines of a generalization of sequence to non-list monads.

Such a function is called a distributive law of m1 over m2 if it satisfies
the following equations (subscripts added for readability):

	f . return_1 = liftM_2 return_1
	f . liftM_1 return_2 = return_2
	f . join_1 = liftM_2 join_1 . f . liftM_1 f
	f . liftM_1 join_2 = join_2 . liftM_2 f . f

The composition m2.m1 can be made a monad in a standard way:

	return = return_2 . return_1
	join = liftM_2 join_1 . join_2 . liftM_2 f

if and only if such a distributive law exists.  See section 9.2 of
"Toposes, Triples and Theories", by Michael Barr and Charles Wells,
online at


("triple" is another name for a monad)

> [...], and sequence does 
> for the List monad what I am seeking to generalize:
>    sequence :: [m a] -> m [a]

Yes, it's a distributive law of [] over m, but only if m is a
commutative monad (lists are so sequential).

Some more distributive laws:

* the exception monad distributes over any other monad:

	either (return . Left) (liftM Right)
		:: Monad m => Either x (m a) -> m (Either x a)

* so does the writer monad:

	uncurry (liftM . (,)) :: (Monoid w, Monad m) => (w, m a) -> m (w,a)

* any monad distributes over the reader monad:

	flip (liftM . flip ($)) :: Monad m => m (r -> a) -> r -> m a

More information about the Haskell-Cafe mailing list