Control.Monad.State.Class.modify' is defined as follows.
modify' :: MonadState s m => (s -> s) -> m ()
modify' f = state (\s -> let s' = f s in s' `seq` ((), s'))
According to the instance of MonadState s (StateT s m) , this is equivalent to:
modify' f = state (\s -> let s' = f s in s' `seq` ((), s'))
= StateT (return . (\s -> let s' = f s in s' `seq` ((), s')))
= StateT (\s -> return (let s' = f s in s' `seq` ((), s')))
Because (let s' = f s in s' `seq` ((), s')) is encapsulated by return,
f s does not evaluated when modify f is evaluated.
I think this behavior is NOT desired.
In the transformers package, modify' is defined as follows.
modify' :: (Monad m) => (s -> s) -> StateT s m ()
modify' f = do
s <- get
put $! f s
With this definition, modify' f evaluates f s, as expected.
It seems that pull request #13 fixes this issue, but it haven't been merged for a few years.
Control.Monad.State.Class.modify'
is defined as follows.According to the instance of
MonadState s (StateT s m)
, this is equivalent to:Because
(let s' = f s in s' `seq` ((), s'))
is encapsulated byreturn
,f s
does not evaluated whenmodify f
is evaluated.I think this behavior is NOT desired. In the
transformers
package,modify'
is defined as follows.With this definition,
modify' f
evaluatesf s
, as expected.It seems that pull request #13 fixes this issue, but it haven't been merged for a few years.