Haskell can derive the instance for MonadState s
in T1
below but not in T2
which is however a very similar type. In which way should I modify the code for T2
so that the instance for MonadState s
can be automatically derived?
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Monad.Reader
import Control.Monad.State
newtype T1 r s a =
T1 { runT1 :: ReaderT r (State s) a }
deriving (Monad, MonadReader r, MonadState s)
newtype T2 r s a =
T2 { runT2 :: StateT r (State s) a }
deriving (Monad, MonadState r, MonadState s)
You can't have a type have two instances for
MonadState
. This is becauseMonadState
is defined asThe key part is the
| m -> s
. This requires the extensionFunctionalDependencies
, and states that for anym
, we automatically know the associateds
. This means that for any givenm
, there can only be one choice fors
that is valid. So you can't have it work for bothMonadState r m
andMonadState s m
unlessr ~ s
. Ifr ~ s
, then how would the compiler know which underlying monad for it to apply to? In this case, I think you'll also find that it'll be much easier to understand and work with the code if you createget
andput
functions that have suffixes to indicate which, likegetInner
,setInner
andgetOuter
,setOuter
.