This is a limitation, but one with good reason: if it did not work that way what would the expected semantics of
runState :: State t s a -> s -> (s,a)
runState (State f) s = f s
example :: s -> a
example = snd $ runState ((State undefined) >> return 1) ()
well, it could be
example = snd $ runState ((State undefined) >>= \_ -> return 1) ()
= snd $ runState (State $ \s -> case undefined s of (s',_) -> (s',1)) ()
= snd $ case undefined () of (s',_) -> (s',1)
= snd $ case undefined of (s',_) -> (s',1)
= snd undefined
= undefined
or it could be
example = snd $ runState ((State undefined) >>= \_ -> return 1) ()
= snd $ runState (State $ \s -> case undefined s of ~(s',_) -> (s',1)) ()
= snd $ case undefined () of ~(s',_) -> (s',1)
= snd $ (undefined,1)
= 1
these are not the same. One option would be to define a function an extra class, like
class IsStrictness t where
bindState :: State t s a -> (a -> State t s b) -> State t s b
and then then define
instance IsStrictness t => Monad (State t s) where
return = returnState
(>>=) = bindState
and instead of defining bindState
as part of IsStrictness
, you can use a singleton
data SingStrictness (t :: Strictness) where
SingStrict :: SingStrictness Strict
SingLazy :: SingStrictness Lazy
class IsStrictness t where
singStrictness :: SingStrictness t
bindState :: IsStrictness t => State t s a -> (a -> State t s b) -> State t s b
bindState ma' amb' = go singStrictness ma' amb' where
go :: SingStrictness t -> State t s a -> (a -> State t s b) -> State t s b
go SingStrict ma amb = ...
go SingLazy ma amb = ...
which can be enhanced even further using the singelton infrastructures from GHC 7.6 instead of the custom class and singleton type. You will end up with
instance SingI t => Monad (State t s)
which is really not so scary. Get used to having lots of SingI _
in your constraint sets. This is how it is going to work for at least a while, and isn't that ugly.
As to why State t [Bool]
is not deducible from State t s
: the problem is that State t s
is in your top level context, which means that s
is quantified at the outermost level. You are defining a function which says "for any t and s such that Monad (State t s) I will give you ...". But, this doesn't say "for any t such that Monad (State t [Bool]) I will give you ...". Sadly, these universally quantified constraints are not so easy in Haskell.