I can't seem to figure out how to achieve strictness in the context of the State monad.  Consider:

> import Control.Monad.State
> try count = print final
>  where (_,final) = runState prog 0
>        prog = sequence_ (replicate count tick)

> tick :: State Int Int
> tick = do n <- get
>           put (n+1)
>           return n
(try 1000000) overflows the stack.

It doesn't help to use:

>           put $! (n+1)

The only way I've been able to get the necessary strictness is to add use of ($!) in the definition of (>>=):

> data SState s a = SState (s -> (a,s))
> instance Monad (SState s) where
>   return x = SState (\s -> (x,s))
>   m >>= f = SState (\s -> let SState m' = m
>                               (x,s1) = m' s
>                               SState f' = f x
>                               (y,s2) = f' $! s1
>                           in  (y,s2))
> runSState (SState m) s = m s
> sget = SState (\s -> (s,s))
> sput s' = SState (\s -> ((),s'))

> stry count = print final
>  where (_,final) = runSState prog 0
>        prog = sequence_ (replicate count stick)

> stick :: SState Int Int
> stick = do n <- sget
>            sput (n+1)
>            return n

Is there no way to get strictness using the standard State monad?

Dean