<!doctype html public "-//W3C//DTD W3 HTML//EN">
<html><head><style type="text/css"><!--
blockquote, dl, ul, ol, li { padding-top: 0 ; padding-bottom: 0 }
 --></style><title>State monad strictness - how?</title></head><body>
<div>I can't seem to figure out how to achieve strictness in the
context of the State monad.&nbsp; Consider:</div>
<div><br></div>
<div><font face="Courier">&gt; import Control.Monad.State</font><br>
<font face="Courier"></font></div>
<div><font face="Courier">&gt; try count = print final</font></div>
<div><font face="Courier">&gt;&nbsp; where (_,final) = runState prog
0<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prog = sequence_
(replicate count tick)<br>
<br>
&gt; tick :: State Int Int<br>
&gt; tick = do n &lt;- get</font></div>
<div><font
face="Courier"
>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; put
(n+1)</font></div>
<div><font
face="Courier"
>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
return n</font><br>
<font face="Courier"></font></div>
<div><font face="Courier">(try 1000000)</font> overflows the
stack.</div>
<div><font face="Courier"><br></font></div>
<div>It doesn't help to use:</div>
<div><br></div>
<div><font
face="Courier"
>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; put
$! (n+1)</font></div>
<div><font face="Courier"><br></font></div>
<div>The only way I've been able to get the necessary strictness is to
add use of ($!) in the definition of (&gt;&gt;=):</div>
<div><font face="Courier"><br>
&gt; data SState s a = SState (s -&gt; (a,s))<br>
&gt; instance Monad (SState s) where<br>
&gt;&nbsp;&nbsp; return x = SState (\s -&gt; (x,s))<br>
&gt;&nbsp;&nbsp; m &gt;&gt;= f = SState (\s -&gt; let SState m' =
m<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
></span
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (x,s1)
= m' s<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
></span
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SState
f' = f x<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
></span
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (y,s2)
= f' $! s1<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
></span
>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in&nbsp; (y,s2))<br>
&gt; runSState (SState m) s = m s<br>
&gt; sget = SState (\s -&gt; (s,s))<br>
&gt; sput s' = SState (\s -&gt; ((),s'))<br>
<br>
&gt; stry count = print final<br>
&gt;&nbsp; where (_,final) = runSState prog 0<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prog = sequence_
(replicate count stick)<br>
<br>
&gt; stick :: SState Int Int<br>
&gt; stick = do n &lt;- sget<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sput (n+1)</font></div>
<div><font
face="Courier"
>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
return n</font></div>
<div><font face="Courier"><br></font></div>
<div>Is there no way to get strictness using the standard State
monad?</div>
<div><br></div>
<div>Dean</div>
</body>
</html>