Heh. Actually, there is no more rewrite. But I muffed the second definition: it should, of course be:<br><br>type Programmable a = State2 [a-&gt;a] a<br><br><div class="gmail_quote">On Sat, Feb 28, 2009 at 10:35 AM, Andrew Wagner <span dir="ltr">&lt;<a href="mailto:wagner.andrew@gmail.com" target="_blank">wagner.andrew@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Thanks for helping clean up my dirty little hacking. This could actually be made nicer by defining the following, and rewriting the original code in terms of it:<br>


<br>
type State2 a b = StateT a (State b)<br>
type Programmable a = State2 a (a-&gt;a)<br>
<br>
I&#39;ll leave the rewrite as an exercise for the reader, since I&#39;m standing in the store writing this on my iPhone :)<div><div></div><div><br>
<br>
<br>
On Feb 28, 2009, at 10:08 AM, Daniel Fischer &lt;<a href="mailto:daniel.is.fischer@web.de" target="_blank">daniel.is.fischer@web.de</a>&gt; wrote:<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Am Samstag, 28. Februar 2009 15:36 schrieb Andrew Wagner:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Ok, so this question of stacking state on top of state has come up several<br>
times lately. So I decided to whip up a small example. So here&#39;s a goofy<br>
little example of an abstract representation of a computer that can compute<br>
a value of type &#39;a&#39;. The two states here are a value of type &#39;a&#39;, and a<br>
stack of functions of type (a-&gt;a) which can be applied to that value.<br>
</blockquote>
<br>
Nice.<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Disclaimer: this code is only type-checked, not tested!<br>
<br>
import Control.Monad.State<br>
</blockquote>
<br>
import Control.Moand (unless)<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
-- first, we&#39;ll rename the type, for convenience<br>
type Programmable a = StateT [a-&gt;a] (State a)<br>
<br>
-- add a function to the stack of functions that can be applied<br>
-- notice that we just use the normal State functions when dealing<br>
-- with the first type of state<br>
add :: (a -&gt; a) -&gt; Programmable a ()<br>
add f = modify (f:)<br>
<br>
-- add a bunch of functions to the stack<br>
-- this time, notice that Programmable a is just a monad<br>
addAll :: [a -&gt; a] -&gt; Programmable a ()<br>
addAll = mapM_ add<br>
</blockquote>
<br>
Be aware that this adds the functions in reverse order, an alternative is<br>
<br>
addAll = modify . (++)<br>
<br>
(addAll fs = modify (fs ++))<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
-- this applies a function directly to the stored state, bypassing the<br>
function stack<br>
-- notice that, to use State functions on the second type of state, we must<br>
use<br>
-- lift to get to that layer<br>
modify&#39; :: (a -&gt; a) -&gt; Programmable a ()<br>
modify&#39; f = lift (modify f)<br>
<br>
-- pop one function off the stack and apply it<br>
-- notice again the difference between modify&#39; and modify. we use modify&#39;<br>
to modify the value<br>
-- and modify to modify the function stack. This is again because of the<br>
order in which we wrapped<br>
-- the two states. If we were dealing with StateT a (State [a-&gt;a]), it<br>
would be the opposite.<br>
step :: Programmable a ()<br>
step = do<br>
 fs &lt;- get<br>
 let f = if (null fs) then id else (head fs)<br>
 modify&#39; f<br>
 modify $ if (null fs) then id else (const (tail fs))<br>
</blockquote>
<br>
Last line could be<br>
<br>
modify (drop 1)<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
-- run the whole &#39;program&#39;<br>
runAll :: Programmable a ()<br>
runAll = do<br>
 fs &lt;- get<br>
 if (null fs) then (return ()) else (step &gt;&gt; runAll)<br>
</blockquote>
<br>
runAll = do<br>
   stop &lt;- gets null<br>
   unless stop (step &gt;&gt; runAll)<br>
<br>
<br>
</blockquote>
</div></div></blockquote></div><br>