[Haskell-cafe] How to define a common return and bind?

Bas van Dijk v.dijk.bas at gmail.com
Thu Apr 9 06:40:53 EDT 2009


Hello,

Suppose you have defined a monad transformer such as:

> newtype T1 m a = T1 { unT1 :: A1 m a }

Where 'A1 m' is an arbitrary monad of your choosing.
For this discussion we just take the identity:

> type A1 m a = m a   -- (can be any monad)

If you want to define a Monad instance for 'T1 m' you generally do this:

instance Monad m => Monad (T1 m) where
    return  = T1 . return
    m >>= f = T1 $ unT1 m >>= unT1 . f

(I know I can use the 'GeneralizedNewtypeDeriving' language extension
to automatically derive a Monad but suppose that isn't available)

Now when I define a new monad transformer:

> newtype T2 m a = T2 { unT2 :: A2 m a }

Where 'A2 m' is again an arbitrary monad of your choosing but for now
just the identity:

> type A2 m a = m a   -- (can be any monad)

The Monad instance for it is almost completely identical to the former:

instance Monad m => Monad (T2 m) where
    return  = T2 . return
    m >>= f = T2 $ unT2 m >>= unT2 . f

Note that the only differences are:

 * a function to convert
   from the outer monad _to_ the inner monad:
   'unT1' and 'unT2'

 * a function to convert
   _from_ the inner monad to the outer monad:
   'T1' and 'T2'

The common parts seem to be:

liftReturn from = from . return
liftBind   from to m f = from $ to m >>= to . f

My question is: can these be given suitable and general enough types
so that they can be used to define Monad instances for monad
transformers?

In other words can I use them to write:

instance Monad m => Monad (T1 m) where
    return = liftReturn T1
    (>>=)  = liftBind   T1 unT1

and:

instance Monad m => Monad (T2 m) where
    return = liftReturn T2
    (>>=)  = liftBind   T2 unT2

Thanks,

Bas


More information about the Haskell-Cafe mailing list