I'm not sure this example really has anything to do with state.  Is there anything about your domain & examples that differs from standard functional programming (or math)?  To my eye, your example code below looks less like an imperative program than like an intermediate form that a compiler would generate from an expression built up from nested function applications and a few "let"s.
<br><br>Cheers, - Conal<br><br><div><span class="gmail_quote">On 12/24/06, <b class="gmail_sendername">Steve Schafer</b> &lt;<a href="mailto:steve@fenestra.com">steve@fenestra.com</a>&gt; wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
In my text/graphics formatting work, I find myself doing a lot of<br>&quot;pipeline&quot; processing, where a data structure will undergo a number of<br>step-by-step transformations from input to output. For example, I have a
<br>function that looks like this (the names have been changed to protect<br>the innocent--and to focus on the structure):<br><br> process :: a -&gt; b -&gt; c -&gt; d -&gt; e<br> process x1 x2 x3 x4 =<br>&nbsp;&nbsp; let y01&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f01 x1 x2 x3;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y02&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f02 x1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y03&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f03 y02;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y04&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f04 y03;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y05&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f05 x1 y01 y04;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y06&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f06 x2 y05;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (y07,y08) = f07 y01 y06;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y09&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f08 y07;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (y10,y11) = f09 x2 x4 y09 y08;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f10 y10;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f11 y12;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f12 x1 x2 x3 y01 y13;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f13 y14;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = f14 y15 y11<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in y16
<br><br>As you can see, the process is somewhat imperative in overall<br>appearance, with each intermediate function f01..f14 accepting some<br>combination of the original input values and/or intermediate values and<br>returning a new value (or, in some cases, a tuple of values).
<br><br>Obviously, not all of the steps need to be broken out this way. We can,<br>for example, skip the second and third steps and directly write:<br><br> y04 = f04 $ f03 $ f02 x1;<br><br>Laying it out this way has a couple of advantages. It makes the steps in
<br>the process transparently clear, and if I discover at some point that I<br>need to make a change (e.g., a new requirement causes f13 to need access<br>to x2), it&#39;s perfectly obvious where to make the modifications.
<br><br>Nevertheless, it also looks like something that would be amenable to<br>processing with a State monad, except for one thing: The &quot;shape&quot; of the<br>state isn&#39;t constant throughout the process. At any given step, new
<br>information may be added to the state, and old information may be thrown<br>away, if there is no further need for it. In principle, it could be<br>managed with a bunch of nested StateT monads, but my attempts to do so
<br>seem to get so caught up in the bookkeeping that I lose the advantages<br>mentioned above.<br><br>Alternatively, I can wrap all of the state up into a single universal<br>structure that holds everything I will ever need at every step, but
<br>doing so seems to me to fly in the face of strong typing; at the early<br>stages of processing, the structure will have &quot;holes&quot; in it that don&#39;t<br>contain useful values and shouldn&#39;t be accessed.<br>
<br>So here&#39;s the question: Is there a reasonable way to express this kind<br>of process (where I suppose that &quot;reasonable&quot; means &quot;in keeping with<br>Haskell-nature&quot;) that preserves the advantages mentioned above, but
<br>avoids having to explicitly pass all of the various bits of state<br>around? The (unattainable?) ideal would be something that looks like<br>this:<br><br> process = f14 . f13 . ... . f01<br><br>or<br><br> process = f01 &gt;&gt;= f02 &gt;&gt;= ... &gt;&gt;= f14
<br><br>Steve Schafer<br>Fenestra Technologies Corp.<br><a href="http://www.fenestra.com/">http://www.fenestra.com/</a><br>_______________________________________________<br>Haskell-Cafe mailing list<br><a href="mailto:Haskell-Cafe@haskell.org">
Haskell-Cafe@haskell.org</a><br><a href="http://www.haskell.org/mailman/listinfo/haskell-cafe">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br></blockquote></div><br>