
Hi,
You can do things like that for "new" monads that are isomorphic to
existing ones. Take a look at the MonadLib.Derive package from
MonadLib (http://hackage.haskell.org/packages/archive/monadLib/3.5.2/doc/html/MonadLib...).
More specifically, the functions "derive_return" and "derive_bind"
might be of interest. A more general property for monad transformers
is that you can always define the "return" of the new monad in terms
of the "return" of the underlying monad and "lift":
return_new x = lift (return x)
This works because, in general, "lift" should be a "monad morphism".
Hope that this helps,
Iavor
On Thu, Apr 9, 2009 at 3:40 AM, Bas van Dijk
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 _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe