
David Menendez wrote:
I think replacing "put s" with "put $! s" should guarantee that the state is evaluated.
If you're using get and put in many place in the code, you could try something along these lines:
newtype SStateT s m a = S { unS :: StateT s m a } deriving (Monad, etc.)
instance (Monad m) => MonadState s (SStateT s m) where get = S get put s = S (put $! s)
Interestingly, this is different from Control.Monad.State.Strict . The latter never forces the state itself, just the pair constructor of the (result,state) pair. Here the different cases: evalLazy m = Control.Monad.State.Lazy.evalState m 0 evalStrict m = Control.Monad.State.Strict.evalState m 0 -- Pair constructor non-bottom GHCi> evalLazy $ put undefined () GHCi> evalStrict $ put undefined () -- Pair constructor bottom GHCi> evalLazy $ put $! undefined *** Exception: Prelude.undefined GHCi> evalStrict $ put $! undefined *** Exception: Prelude.undefined -- Last pair constructor non-bottom GHCi> evalLazy $ (put $! undefined) >> put 1 () -- Everything bottom GHCi> evalStrict $ (put $! undefined) >> put 1 *** Exception: Prelude.undefined Regards, apfelmus -- http://apfelmus.nfshost.com