You seem to ignore garbage collection.<br><br><div class="gmail_quote">On Sat, Sep 24, 2011 at 6:40 AM, Arseniy Alekseyev <span dir="ltr">&lt;<a href="mailto:arseniy.alekseyev@gmail.com">arseniy.alekseyev@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="im">&gt; Apparently it doesn&#39;t, and it seems to be fixed now.<br>
<br>
</div>Does anyone know what exactly the bug was? Because this seems like a<br>
serious bug to me. I&#39;ve run into it myself today and wasn&#39;t happy.<br>
Linear algorithms should work in linear time however much memory they<br>
allocate (modulo cache thrashing of course). Existence of people<br>
claiming otherwise surprises me!<br>
<div><div></div><div class="h5"><br>
<br>
On 22 September 2011 01:05, John Lato &lt;<a href="mailto:jwlato@gmail.com">jwlato@gmail.com</a>&gt; wrote:<br>
&gt; On Wed, Sep 21, 2011 at 1:57 PM, Tim Docker &lt;<a href="mailto:tim@dockerz.net">tim@dockerz.net</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; On 09/09/2011, at 8:19 PM, John Lato wrote:<br>
&gt;&gt;<br>
&gt;&gt;&gt; Agreed.  Whenever I&#39;d like to use mapM (or any other function for<br>
&gt;&gt;&gt; which a *M_ is available), I&#39;ve found the following rules helpful:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; 1.  If I can guarantee the list is short (~ n&lt;=20), go ahead and use mapM<br>
&gt;&gt;&gt; 2.  Otherwise use mapM_, foldM_, or foldM if a real reduction is<br>
&gt;&gt;&gt; possible (i.e. not &quot;foldM snocM []&quot;).<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Step 2 sometimes requires changing my design, but it&#39;s always been for<br>
&gt;&gt;&gt; the better.  `mapM_` tends to require more pipeline composition, so<br>
&gt;&gt;&gt; it&#39;s leveraging the language&#39;s strengths.<br>
&gt;&gt;<br>
&gt;&gt; This thread is really interesting - it relates directly to problems I am<br>
&gt;&gt; currently<br>
&gt;&gt; having with mapM over large lists (see the thread &quot;stack overflow pain&quot;).<br>
&gt;&gt;<br>
&gt;&gt; Can you explain what you mean by &quot;mapM_ tends to require more pipeline<br>
&gt;&gt; composition&quot;?<br>
&gt;&gt; In what way is it leveraging the language strengths?<br>
&gt;<br>
&gt; Hmm, that is suitably cryptic.  One way to think of it is an inversion<br>
&gt; of control.  Instead of operating on whole collections of things in a<br>
&gt; monad, you specify monadic actions (pipelines) which are applied<br>
&gt; sequentially to each input.<br>
&gt;<br>
&gt; Here&#39;s a simple example.  Suppose you have a bunch of data serialized<br>
&gt; to files, and you want to read each file into a data structure, apply<br>
&gt; some process based upon the last file&#39;s data, and write out the output<br>
&gt; to new files.  One way to do that would look like:<br>
&gt;<br>
&gt; do<br>
&gt;    dats &lt;- mapM readMyData files<br>
&gt;    let pairs = zip (mempty:dats) dats<br>
&gt;    zipWithM_ (\(last, this) fname -&gt; writeMyData (update last this)<br>
&gt; fname) pairs newFiles<br>
&gt;<br>
&gt; However, you could also put everything into a single monadic<br>
&gt; operation, like this<br>
&gt;<br>
&gt; do<br>
&gt;    foldM_ (\last (infile, outfile) -&gt; do<br>
&gt;                                                    this &lt;- readMyData infile<br>
&gt;                                                    writeMyData<br>
&gt; (update last this) outfile<br>
&gt;                                                    return this<br>
&gt;               )<br>
&gt;               mempty<br>
&gt;               (zip files newFiles)<br>
&gt;<br>
&gt; The first interleaves control (mapM, zipWIthM_) with monadic actions<br>
&gt; (file IO), whereas the second only has one control function (foldM_)<br>
&gt; which completely processes one input.  I say this is more pipeline<br>
&gt; composition because you have to create an entire pipeline from input<br>
&gt; to output, which is then sequentially fed inputs by the control<br>
&gt; function.<br>
&gt;<br>
&gt; I say this leverages Haskell&#39;s strengths because it&#39;s quite easy to<br>
&gt; compose functions and monadic actions in Haskell.  It also tends to be<br>
&gt; garbage-collector friendly.  I also find it much easier to reason<br>
&gt; about space usage.  You don&#39;t need to worry if part of a list is being<br>
&gt; retained, because the full list of data doesn&#39;t appear anywhere.  If<br>
&gt; you need to access prior elements they&#39;re specified explicitly so you<br>
&gt; know exactly how much data you&#39;re holding on to.<br>
&gt;<br>
&gt; My perspective might be warped by my work on iteratees, but I find<br>
&gt; this a very natural approach.<br>
&gt;<br>
&gt; John L.<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; Haskell-Cafe mailing list<br>
&gt; <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
&gt; <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
&gt;<br>
<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" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br>