From: Eric Rasmussen &lt;<a href="mailto:ericrasmussen@gmail.com" target="_blank">ericrasmussen@gmail.com</a>&gt;<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
Hi,<br>
<br>
Examples are very helpful to me too -- thank you for sharing. I&#39;m especially<br>
curious to see if there are any examples that allow you to use or convert<br>
non-iteratee-based functions. I have only just begun reading about iteratees<br>
and might be missing the point, but it seems like many of the examples so<br>
far rely on explicit recursion or special functions from one of the iteratee<br>
modules.<br></blockquote><div><br>You might be interested in the attoparsec-enumerator and attoparsec-iteratee packages, which adapt attoparsec parsers to work with iteratees.  They&#39;re small, self-contained, and quite readable.  Since attoparsec works with partial parses, it&#39;s a natural fit for iteratees.<br>

<br>Honestly I&#39;m quite dis-satisfied with the current state of code which depends on iteratee/enumerator.  It&#39;s nearly all written in a very low-level style, i.e. directly writing &#39;liftI step&#39;, or &#39;case x of Yield -&gt; ...&#39;.  This is exactly what I would hope users could avoid, by using the functions in e.g. Data.Iteratee.ListLike.<br>

<br>I&#39;ve recently added more functions to iteratee which greatly reduce the need for this type of code.  I don&#39;t know about enumerator, but I expect it isn&#39;t rich enough since most user code I&#39;ve seen is pretty low-level.<br>
<br>For some other iteratee examples, you can &#39;darcs get <a href="http://www.tiresiaspress.us/haskell/sndfile-enumerators/" target="_blank">http://www.tiresiaspress.us/haskell/sndfile-enumerators/</a>&#39; and look at the examples directory (or browse online, of course).<br>

 </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204, 204, 204);padding-left:1ex">
<br>
Is there a way to take a simple function (example below) and use an<br>
enumerator to feed it a ByteString from a file, or do you have to write<br>
functions explicitly to work with a given iteratee implementation?<br>
<br>
    import qualified Data.ByteString.Char8 as B<br>
    sortLines = B.unlines . sort . B.lines<br></blockquote><div><br>For this case, there&#39;s no point to using iteratees at all.  Just read the file in directly to a strict bytestring.  Since you&#39;re sorting, you&#39;ll need to see all the lines before results can be returned.  If the file is too big to fit into memory, you&#39;d need a more sophisticated algorithm for which you could use iteratees.<br>
<br>In the general case, you need to write for a given iteratee implementation, but in many specific cases it&#39;s not necessary.  If you want to transform each line of a file, for instance (with iteratee):<br><br>import Data.ByteString.Char8 as B<br>
import Data.Iteratee as I<br>import Data.Iteratee.Char<br>import System.IO<br>import Control.Monad.IO.Class<br><br>transform :: (ByteString -&gt; ByteString) -&gt; FilePath -&gt; Iteratee [ByteString] IO ()<br>transform tFunc oFile = do<br>
  h &lt;- liftIO $ openFile oFile WriteMode<br>  joinI $ rigidMapStream tFunc $ I.mapM_ (B.hPutStrLn h)<br>  liftIO $ hClose h<br><br>rewriteFile :: (ByteString -&gt; ByteString) -&gt; FilePath -&gt; FilePath -&gt; IO ()<br>
rewriteFile tFunc iFile oFile = fileDriver (joinI $ enumLinesBS (transform tFunc oFile)) iFile<br><br>An unfolding version would be possible too, which would take a parameter<br><br>tFunc :: (s -&gt; ByteString -&gt; (s, ByteString))<br>
<br>Maybe I&#39;ll add these as utilities in the next version of iteratee.<br><br>John<br></div></div>