<br>I (think)  I understand the problem.  What I don&#39;t have any intuition about is how much  space would &quot;Expensive Structure&quot; take if it was basically an IO Char computation fed into a simple function (say checks for char being equal to &quot;a&quot;).   Is there any way to guess, know the size of the buffer that is kept in the heap?<br>
<br>thanks,<br><br>Daryoush<br><div class="gmail_quote">On Wed, May 27, 2009 at 3:12 PM, Ryan Ingram <span dir="ltr">&lt;<a href="mailto:ryani.spam@gmail.com">ryani.spam@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;">
There&#39;s still the space used by the closure &quot;b&quot;.<br>
<br>
An example:<br>
<br>
expensiveParser :: Parser Char ExpensiveStructure<br>
<br>
simple :: Parser Char Int<br>
<br>
withExpensive :: ExpensiveStructure -&gt; Parser Char Int<br>
withExpensive _ = mzero  -- actually always fails, not using its argument.<br>
<br>
example = do<br>
    e &lt;- expensiveParser<br>
    simple `mplus` withExpensive e<br>
<br>
The expensive structure constructed by expensiveParser needs to be<br>
kept in memory throughout the entire parsing of &quot;simple&quot;, even though<br>
withExpensive doesn&#39;t actually use it and would immediately fail.  A<br>
smarter parser could realize that e couldn&#39;t actually ever be used and<br>
allow the GC to free it much more quickly.<br>
<br>
This example can be made arbitrarily more complicated; withExpensive<br>
could run different things based on the value of &quot;e&quot; that could be<br>
determined to fail quickly, simple might actually do a lot of work,<br>
etc.  But during the &quot;mplus&quot; in the monadic parser, we can&#39;t free e.<br>
<font color="#888888"><br>
  -- ryan<br>
</font><div><div></div><div class="h5"><br>
On Wed, May 27, 2009 at 12:49 PM, Daryoush Mehrtash &lt;<a href="mailto:dmehrtash@gmail.com">dmehrtash@gmail.com</a>&gt; wrote:<br>
&gt; So long as the [s] is a fixed list (say [1,2,3,4]) there is no space<br>
&gt; leak.    My understanding was that the space leak only happens if there is<br>
&gt; computation involved in building the list of s.      Am I correct?<br>
&gt;<br>
&gt; If so, I still don&#39;t have any feeling for what needs to be saved on the heap<br>
&gt; to be able to back track on computation that needs and  IO computation<br>
&gt; data.    What would be approximate  space that an IO (Char) computation<br>
&gt; take  on the heap, is it few bytes, 100, 1k,  ....?<br>
&gt;<br>
&gt; Daryoush<br>
&gt;<br>
&gt;<br>
&gt; On Tue, May 26, 2009 at 6:11 PM, Ryan Ingram &lt;<a href="mailto:ryani.spam@gmail.com">ryani.spam@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; On Tue, May 26, 2009 at 5:03 PM, Daryoush Mehrtash &lt;<a href="mailto:dmehrtash@gmail.com">dmehrtash@gmail.com</a>&gt;<br>
&gt;&gt; wrote:<br>
&gt;&gt; &gt; newtype Parser s a = P( [s] -&gt; Maybe (a, [s]))<br>
&gt;&gt; (fixed typo)<br>
&gt;&gt;<br>
&gt;&gt; &gt; instance MonadPlus  Parser where<br>
&gt;&gt; &gt;       P a mplus P b = P (\s -&gt; case a s of<br>
&gt;&gt; &gt;                             Just (x, s&#39;) -&gt; Just (x, s&#39;)<br>
&gt;&gt; &gt;                             Nothing -&gt; b s)<br>
&gt;&gt;<br>
&gt;&gt; &gt; a)what exactly gets saved on the heap between the mplus calls?<br>
&gt;&gt;<br>
&gt;&gt; Two things:<br>
&gt;&gt;<br>
&gt;&gt; (1) Values in the input stream that &quot;a&quot; parses before failing.<br>
&gt;&gt; Beforehand, it might just be a thunk that generates the list lazily in<br>
&gt;&gt; some fashion.<br>
&gt;&gt;<br>
&gt;&gt; (2) The state of the closure &quot;b&quot;; if parser &quot;a&quot; fails, we need to be<br>
&gt;&gt; able to run &quot;b&quot;; that could use an arbitrary amount of space depending<br>
&gt;&gt; on what data it keeps alive.<br>
&gt;&gt;<br>
&gt;&gt; &gt; b)I am assuming the computation to get the next character for parsing to<br>
&gt;&gt; &gt; be<br>
&gt;&gt; &gt; an &quot;IO Char&quot; type computation,  in that case, what would be the size of<br>
&gt;&gt; &gt; the<br>
&gt;&gt; &gt; heap buffer that is kept around in case the computation result needs to<br>
&gt;&gt; &gt; be<br>
&gt;&gt; &gt; reused?<br>
&gt;&gt;<br>
&gt;&gt; Nope, no IO involved; just look at the types:<br>
&gt;&gt;<br>
&gt;&gt; P :: ([s] -&gt; Maybe (a,[s])) -&gt; Parser s a<br>
&gt;&gt;<br>
&gt;&gt; (Parser s a) is just a function that takes a list of &quot;s&quot;, and possibly<br>
&gt;&gt; returns a value of type &quot;a&quot; and another list [s] (of the remaining<br>
&gt;&gt; tokens, one hopes)<br>
&gt;&gt;<br>
&gt;&gt; It&#39;s up to the caller of the parsing function to provide the token<br>
&gt;&gt; stream [s] somehow.<br>
&gt;&gt;<br>
&gt;&gt; &gt; c) Assuming Pa in the above code reads n tokens from the input stream<br>
&gt;&gt; &gt; then<br>
&gt;&gt; &gt; fails, how does the run time returns the same token to the P b?<br>
&gt;&gt;<br>
&gt;&gt; It just passes the same stream to both.  No mutability means no danger :)<br>
&gt;&gt;<br>
&gt;&gt;  -- ryan<br>
&gt;<br>
&gt;<br>
&gt;<br>
</div></div></blockquote></div><br>