I have trouble even explaining what I'm trying to do, please bear with me. I haven't really grasped type theory, or how to use forall so that is probably the reason why wording (and implementing) this is difficult for me. So basically I'm trying to replicate the behaviour of MonadIO with a MonadTransformer. MonadIO is defined as
class (Monad m) => MonadIO m where
-- | Lift a computation from the 'IO' monad.
liftIO :: IO a -> m a
-- | @since 4.9.0.0
instance MonadIO IO where
liftIO = id
This code compiles (I haven't included the Applicative and Functor instances here though, but I can):
newtype Debugable m r = Debugable { runDebugable :: (DebugState -> m (DebugState, r)) }
instance MonadTrans (Debugable) where
lift action = Debugable $ \d -> do
r <- action
return (d, r)
class (Monad i, Monad m) => MonadDebug i m where
liftDebug :: Debugable i a -> m a
instance (Monad m) => MonadDebug m (Debugable m) where
liftDebug = id
I want to write a method like this, that should work in any MonadTransformer above MonadDebug in the transformer stack:
debug :: (MonadDebug i m) => String -> m ()
debug msg = liftDebug $ doDebug msg
(doDebug operates in the Debugable monad)
Of course this does not compile because the type variable i cannot be deduced (or something like that)... I tried a few things, but I don't really understand what the debug messages mean either. I don't even know if a generalized lifting of a MonadTransformer similar to liftIO is possible... Is it?