So I have this code
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import MonadA
data A = A
newtype MonadA a => MyStateT a b { runMyStateT :: StateT A a b }
deriving (Functor, Applicative, Monad, MonadIO, MonadState A)
instance MonadTrans MyStateT where
lift = MyStateT . lift
and I get the compiler complaining that it cannot prove the m
from signature of lift
is of type MonadA
or thats how I read these cryptic error messages.
Could not deduce (MonadA m) arising from a use of `MyStateT'
from the context (Monad m)
bound by the type signature for
lift :: Monad m => m a -> MyStateT m a
is there a way to deal with this? I think I need the constraint to be able to instantiate as follows:
instance MonadA a => MonadA (MyStateT a) where
f = MyStateT . lift . f
Also would such an implementation of f
work? (I did not get that far due to the above error). I hope f
on the right side to resolve to f
over the inner monad a
.
Edit: It indeed helped to drop the type constraint in newtype MonadA a => MyStateT ...
to avoid the exact error that I mentioned. However there was just another error which I previously attributed to the same thing, consider this continuation of the example code above (some parts are repeated, now without type constraints):
class MonadB m where
fB :: m ()
newtype MyStateT m a = MyStateT { runMyStateT :: StateT A m a}
deriving (... MonadState A ...)
instance MonadTrans MyStateT where
lift = MyStateT . lift
instance MonadA a => MonadA (MyStateT a) where
f = lift . f
instance MonadA a => MonadB (MyStateT a) where
fB = lift (modify (...))
the error is
Could not deduce (a ~ StateT A m0) from context (MonadA (MyStateT a), MonadA a)
in the implementation of fB
. Earlier I tried class MonadA m => MonadB m
to no avail. It doesn't even make sense to be matching a
with StateT A m
. Since MyStateT
is an instance of MonadState A
it should work, no?
Edit:
OK, got it working:
fB = MyStateT (modify ...)
stupid me.
The solution is dropping the constraint from the MyStateT
definition:
newtype MyStateT a b { runMyStateT :: StateT A a b }
deriving (Functor, Applicative, Monad, MonadIO, MonadState A)
Datatype constraints are essentially useless, as you need to put them in the function signatures anyway. For that reason, that feature is actually deprecated.
I think I need the constraint to be able to instantiate as follows:
Not really; instance MonadA a => MonadA (MyStateT a)
will work just fine without it.
Also would such an implementation of
f
work?
It will. Note that, as you provided a MonadTrans
instance for MyStateT
, you don't actually need to wrap with MyStateT
explicitly:
instance MonadA a => MonadA (MyStateT a) where
f = lift . f