
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