First thanks for the reply,<br><br><div class="gmail_quote">On Wed, Mar 31, 2010 at 11:15 AM, Valery V. Vorotyntsev <span dir="ltr">&lt;<a href="mailto:valery.vv@gmail.com">valery.vv@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;">
&gt; I&#39;m looking at iteratee as a way to replace my erroneous and really<br>
&gt; inefficient lazy-IO-based backend for an expect like Monad DSL I&#39;ve<br>
&gt; been working for about 6 months or so now on and off.<br>
&gt;<br>
&gt; The problem is I want something like:<br>
&gt;<br>
&gt; expect &quot;some String&quot;<br>
&gt; send &quot;some response&quot;<br>
&gt;<br>
&gt; to block or perhaps timeout, depending on the environment, looking for<br>
&gt; &quot;some String&quot; on an input Handle, and it appears that iteratee works<br>
&gt; in a very fixed block size.<br>
<br>
Actually, it doesn&#39;t. It works with what enumerator gives him.<br>
In case of `enum_fd&#39;[1] this is a fixed block, but generally this is<br>
a ``value&#39;&#39; of some ``collection&#39;&#39;[2].  And it is up to programmer to<br>
decide of what should become a value.<br>
<br>
  [1] <a href="http://okmij.org/ftp/Haskell/Iteratee/IterateeM.hs" target="_blank">http://okmij.org/ftp/Haskell/Iteratee/IterateeM.hs</a><br>
  [2] <a href="http://okmij.org/ftp/papers/LL3-collections-enumerators.txt" target="_blank">http://okmij.org/ftp/papers/LL3-collections-enumerators.txt</a></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
<br>
&gt; While a fixed block size is ok, if I can put back unused bytes into<br>
&gt; the enumerator somehow (I may need to put a LOT back in some cases,<br>
&gt; but in the common case I will not need to put any back as most<br>
&gt; expect-like scripts typically catch the last few bytes of data sent<br>
&gt; before the peer is blocked waiting for a response...)<br>
<br>
I don&#39;t quite get this ``last few bytes&#39;&#39; thing. Could you explain?<br></blockquote><div><br></div><div>What I mean is let&#39;s say the stream has</div><div><br></div><div>&quot;abcd efg abcd efg&quot;</div>
<div><br></div><div>and then I run some kind of iteratee computation looking for &quot;abcd&quot;</div><div><br></div><div>and the block size was fixed to cause a read 1024 bytes, but returns as much as it can providing it to the iteratee to deal with.  The iteratee, which I want to implement Expect like behavior, would really only want to read up to &quot;abcd&quot; consuming that from the input stream.  Does the iteratee get the whole stream that was read by the enumerator, or is it supplied a single atomic unit at a time, such as a character, in which I can halt the consumption of the streamed data?</div>
<div><br></div><div>What I don&#39;t want to have happen is my consuming bytes from the input Handle, only to have them ignored, as the second instance of &quot;abcd&quot; could be important.</div><div><br></div><div>I&#39;m actually not sure that was very clear :-).   I don&#39;t want to throw out bytes by accident if that&#39;s even possible.  </div>
<div><br></div><div>My discomfort with Iteratee is that most Haskell texts really want you to go the way of lazy IO, which has led me to a good bit of trouble, and I&#39;ve never seen a very comprehensive tutorial of Iteratee available anywhere.  I am reading the Examples that come with the hackage package though.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
I was about writing that there is no problem with putting data back to<br>
Stream, and referring to head/peek functions...  But then I thought,<br>
that the ``not consuming bytes from stream&#39;&#39; approach may not work<br>
well in cases, when the number of bytes needed (by your function to<br>
accept/reject some rule) exceeds the size of underlying memory buffer<br>
(4K in current version of `iteratee&#39; library[3]).<br>
<br>
  [3] <a href="http://hackage.haskell.org/packages/archive/iteratee/0.3.4/doc/html/src/Data-Iteratee-IO-Fd.html" target="_blank">http://hackage.haskell.org/packages/archive/iteratee/0.3.4/doc/html/src/Data-Iteratee-IO-Fd.html</a><br>

<br>
Do you think that abstracting to the level of _tokens_ - instead of<br>
bytes - could help here? (Think of flex and bison.)  You know, these<br>
enumerators/iteratees things can be layered into<br>
_enumeratees_[1][4]... It&#39;s just an idea.<br>
<br></blockquote><div><br></div><div>Now that&#39;s an interesting idea, and sort of where my previous confusing answer seemed to be heading.  I wasn&#39;t sure if the iteratee was provided a byte, a char, or a token.  If I can tell the enumerator to only send tokens to the iteratee, (which I&#39;d have to define), then perhaps I can ignore the amount consumed per read, and deal with let the enumerator deal with that buffering issue directly.  Perhaps that&#39;s how iteratee really works anyway!</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
  [4] <a href="http://ianen.org/articles/understanding-iteratees/" target="_blank">http://ianen.org/articles/understanding-iteratees/</a><br>
<br>
&gt; Otherwise, I&#39;m going to want to roll my own iteratee style library<br>
&gt; where I have to say &quot;NotDone howMuchMoreIThinkINeed&quot; so I don&#39;t over<br>
&gt; consume the input stream.<br>
<br>
What&#39;s the problem with over-consuming a stream? In your case?<br></blockquote><div><br></div><div>Well my concern is if it&#39;s read from the input stream, and then not used, the next time I access it, I&#39;m not certain what&#39;s happened to the buffer.  However I suppose it&#39;s really a 2-level situation where the enumerator pulls out some fixed chunk from a Handle or FD or what have you, and then folds the iteratee over the buffer in some sized chunk.</div>
<div><br></div><div>In C++ I&#39;ve used ideas like this example that a professor I had in college showed me from a newsgroup he helped to moderate.</div><div><br></div><div>int main () {</div><div>std::cout &lt;&lt; &quot;Word count on stdin: &quot; &lt;&lt; std::distance(std::istream_iterator&lt;std::string&gt;(std::cin), std::istream_iterator&lt;std::string&gt;()) &lt;&lt; std::endl;</div>
<div>}</div><div><br></div><div>If the code were changed to be:</div><div><br></div><div>int main () {</div><div>std::cout &lt;&lt; &quot;Character count on stdin: &quot; &lt;&lt; std::distance(std::istreambuf_iterator&lt;char&gt;(std::cin), std::istreambuf_iterator&lt;char&gt;()) &lt;&lt; std::endl;</div>
<div>}</div><div><br></div><div>We get different behavior out of the upper level distance algorithm due to the kind of iterator, while distance does a form of folding over the iterators, but it&#39;s actually doing the accumulation of a count at the enumerator level rather than having the iterator evaluate it.  Iteratee seems to be like this but with this inversion of control.</div>
<div><br></div><div>Note in the C++ example, changing the properties of each chunk being iterated over changes the result of the folding from  &quot;word counter&quot; to &quot;character counter&quot;.</div><div><br></div>
<div>I guess I need to just get familiar with Iteratee to understand what knobs I have available to turn.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

<br>
BTW, this `NotDone&#39; is just a ``control message&#39;&#39; to the chunk<br>
producer (an enumerator):<br>
<br>
    IE_cont k (Just (GimmeThatManyBytes n))<br></blockquote><div><br></div><div>Yes, I was thinking of something like that.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

<br>
&gt; Does that even make any sense?  I&#39;m kind of brainstorming in this<br>
&gt; email unfortunately :-)<br>
<br>
What&#39;s the problem with brainstorming? :)<br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>
Cheers.<br>
<br>
--<br>
<font color="#888888">vvv<br>
</font></blockquote></div><br>