On Tue, Jan 13, 2009 at 3:29 PM, Phil <span dir="ltr">&lt;<a href="mailto:pbeadling@mail2web.com">pbeadling@mail2web.com</a>&gt;</span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
My only concern with using this method is - Will &#39;iterate&#39; not create a full<br>
list of type [Double] and then take the final position once the list has<br>
been fully realized? &nbsp;For my application this would be undesirable as the<br>
list may be millions of items long, and you only ever care about the last<br>
iteration (It&#39;s a crude Monte Carlo simulator to give it some context). &nbsp;If<br>
Haskell is smart enough to look ahead and see as we only need the last<br>
element as it is creating the list, therefore garbage collecting earlier<br>
items then this would work fine - by I&#39;m guessing that is a step to far for<br>
the compiler?</blockquote><div><br>No, doing this type of thing is very typical Haskell, and the garbage collector <i>will</i> incrementally throw away early elements of the list. <br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

<br>
I had originally implemented this similar to the above (although I didn&#39;t<br>
know about the &#39;iterate&#39; keyword</blockquote><div><br>FWIW, iterate is just a function, not a keyword.&nbsp; Could just be terminology mismatch.<br>&nbsp;<br>So, while the garbage collector will do the right thing, for a list millions of elements long, I suspect you will get stack overflows and/or bad memory performance because the computation is too lazy.&nbsp; One solution is to use a stricter version of !!, which evaluates elements of the list as it whizzes by them.&nbsp; Because the function you&#39;re iterating is strict to begin with, you do not lose performance by doing this:<br>
<br><font face="courier new,monospace">strictIdx :: Int -&gt; [a] -&gt; a<br>strictIdx _ []&nbsp;&nbsp;&nbsp;&nbsp; = error &quot;empty list&quot;<br>strictIdx 0 (x:xs) = x<br>strictIdx n (x:xs) = x `seq` strictIdx (n-1) xs<br></font><br>(Note that I flipped the arguments, to an order that is nicer for currying)<br>
<br>The reason is that iterate f x0 constructs a list like this:<br><br>[ x0, f x0, f (f x0), f (f (f x0)), ... ]<br><br>But shares the intermediate elements, so if we were to evaluate the first f x0 to, say, 42, then the thunks are overwritten and become:<br>
<br>[ x0, 42, f 42, f (f 42), ... ]<br><br>So iterate f x0 !! 1000000 is f (f (f (f ( ... a million times ... f x0)))), which will be a stack overflow because of each of the calls.&nbsp; What strictIdx does is to evaluate each element as it traverses it, so that each call is only one function deep, then we move on to the next one.<br>
<br>This is the laziness abstraction leaking.&nbsp; Intuition about it develops with time and experience.&nbsp; It would be great if this leak could be patched by some brilliant theorist somewhere.<br><br>Luke<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
 - which makes things tidier - a useful<br>
tip!), I moved to using the state monad and replicateM_ for the first<br>
truncate(endTime/timeStep)-1 elements so that everything but the last result<br>
is thrown away, and a final bind to getEvolution would return the result.<br>
<br>
Now that the code has been modified so that no result is passed back, using<br>
modify and execState, this can be simplified to &quot;replicateM_<br>
truncate(endTime/timeStep)&quot; with no final bind needed. &nbsp;I&#39;ve tried this and<br>
it works fine.<br>
<br>
The key reason for using the Monad was to tell Haskell to discard all but<br>
the current state. &nbsp;If I&#39;m wrong about please let me know, as I don&#39;t want<br>
to be guilty of overcomplicating my algorithm, and more importantly it means<br>
I&#39;m not yet totally grasping the power of Haskell!<br>
<br>
Thanks again,<br>
<font color="#888888"><br>
Phil.<br>
</font><div><div></div><div class="Wj3C7c"><br>
<br>
<br>
<br>
On 13/01/2009 03:13, &quot;David Menendez&quot; &lt;<a href="mailto:dave@zednenem.com">dave@zednenem.com</a>&gt; wrote:<br>
<br>
&gt; On Mon, Jan 12, 2009 at 8:34 PM, Phil &lt;<a href="mailto:pbeadling@mail2web.com">pbeadling@mail2web.com</a>&gt; wrote:<br>
&gt;&gt; Thanks Minh - I&#39;ve updated my code as you suggested. &nbsp;This looks better than<br>
&gt;&gt; my first attempt!<br>
&gt;&gt;<br>
&gt;&gt; Is it possible to clean this up any more? &nbsp;I find:<br>
&gt;&gt;<br>
&gt;&gt; ( (), (Double, Word64) )<br>
&gt;&gt;<br>
&gt;&gt; a bit odd syntactically, although I understand this is just to fit the type<br>
&gt;&gt; to the State c&#39;tor so that we don&#39;t have to write our own Monad longhand.<br>
&gt;<br>
&gt; If you have a function which transforms the state, you can lift it<br>
&gt; into the state monad using &quot;modify&quot;.<br>
&gt;<br>
&gt;&gt; evolveUnderlying :: (Double, Word64) -&gt; (Double, Word64)<br>
&gt;&gt; evolveUnderlying (stock, state) = ( newStock, newState )<br>
&gt;&gt; &nbsp;where<br>
&gt;&gt; &nbsp; &nbsp;newState = ranq1Increment state<br>
&gt;&gt; &nbsp; &nbsp;newStock = stock * exp ( ( ir - (0.5*(vol*vol)) )*timeStep + (<br>
&gt;&gt; vol*sqrt(timeStep)*normalFromRngState(state) ) )<br>
&gt;&gt;<br>
&gt;&gt; getEvolution :: State (Double, Word64) ()<br>
&gt;&gt; getEvolution = modify evolveUnderlying<br>
&gt;<br>
&gt; Now, I don&#39;t know the full context of what you&#39;re doing, but the<br>
&gt; example you posted isn&#39;t really gaining anything from the state monad.<br>
&gt; Specifically,<br>
&gt;<br>
&gt; &nbsp; execState (replicateM_ n (modify f))<br>
&gt; = execState (modify f &gt;&gt; modify f &gt;&gt; ... &gt;&gt; modify f)<br>
&gt; = execState (modify (f . f . ... . f))<br>
&gt; = f . f . ... . f<br>
&gt;<br>
&gt; So you could just write something along these lines,<br>
&gt;<br>
&gt;&gt; mcSimulate :: Double -&gt; Double -&gt; Word64 -&gt; [Double]<br>
&gt;&gt; mcSimulate startStock endTime seedForSeed = fst expiryStock : mcSimulate<br>
&gt;&gt; startStock endTime newSeedForSeed<br>
&gt;&gt; &nbsp;where<br>
&gt;&gt; &nbsp; &nbsp;expiryStock = iterate evolveUnderlying (startStock, ranq1Init seedForSeed)<br>
&gt;&gt; !! truncate (endTime/timeStep)<br>
&gt;&gt; &nbsp; &nbsp;newSeedForSeed = seedForSeed + 246524<br>
&gt;<br>
&gt;<br>
&gt; Coming back to your original question, it is possible to work with<br>
&gt; nested state monad transformers. The trick is to use &quot;lift&quot; to make<br>
&gt; sure you are working with the appropriate state.<br>
&gt;<br>
&gt; get :: StateT s1 (State s2) s1<br>
&gt; put :: s1 -&gt; StateT s1 (State s2) ()<br>
&gt;<br>
&gt; lift get :: StateT s1 (State s2) s2<br>
&gt; lift put :: s2 -&gt; StateT s1 (State s2) ()<br>
&gt;<br>
&gt; A more general piece of advice is to try breaking things into smaller<br>
&gt; pieces. For example:<br>
&gt;<br>
&gt; getRanq1 :: MonadState Word64 m =&gt; m Word64<br>
&gt; getRanq1 = do<br>
&gt; &nbsp; &nbsp; seed &lt;- get<br>
&gt; &nbsp; &nbsp; put (ranq1Increment seed)<br>
&gt; &nbsp; &nbsp; return seed<br>
&gt;<br>
&gt; getEvolution :: StateT Double (State Word64) ()<br>
&gt; getEvolution = do<br>
&gt; &nbsp; &nbsp; seed &lt;- lift getRanq1<br>
&gt; &nbsp; &nbsp; modify $ \stock -&gt; stock * exp ( ( ir - (0.5*(vol*vol)) )*timeStep<br>
&gt; + ( vol*sqrt(timeStep)*normalFromRngState(seed) ) )<br>
&gt;<br>
<br>
</div></div><div><div></div><div class="Wj3C7c">_______________________________________________<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" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br>