I have a Monad of named TaskMonad
, defined as follows:
data TaskMonad a = TaskMonad (Environment -> (TaskResult a, Environment))
where Environment
is a record type and TaskResult
is an ADT; but they are not important for the problem.
I have defed Functor
, Applicative
and Monad
instances for TaskMonad
, and I now want to be able to combine this monad with other Monads (e.g. IO
), So I defined a new type as follows:
newtype Task m a = Task { runTask :: m (TaskMonad a) }
I have defined Functor
and Applicative
as follows:
instance Monad m => Functor (Task m) where
fmap f ta = Task $ do tma <- runTask ta
return (fmap f tma)
instance Monad m => Applicative (Task m) where
pure = Task . return . return
(<*>) prod tx = Task $ do tmprod <- runTask prod
tmtx <- runTask tx
return (tmprod <*> tmtx)
And I also made Task
member of the MonadTrans
class:
instance MonadTrans Task where
lift = Task . (liftM return)
So far so good (or atleast it compiles..), but now I want to define the instance for Monad
, but I am running into problems here:
instance Monad m => Monad (Task m) where
return = pure
(>>=) ta tb = ...
I attempted multiple things, most attempts starting out like this:
(>>=) ta tb = Task $ do tma <- runTask ta
Now we have tma :: TaskMonad a
inside the do
block for the m
monad. Now what I would like to do, is somehow calling the >>=
instance for TaskMonad
so I can get the result of tma
, a value of type a
so I can parameterize tb
with it to obtain a value of Task b
. But I am within the context of the m
monad and I'm running into all kinds of problems.
How could I obtain tma
's result to provide it to tb
?