From: Eric Rasmussen <ericrasmus...@gmail.com> > > Hi, > > Examples are very helpful to me too -- thank you for sharing. I'm > especially > curious to see if there are any examples that allow you to use or convert > non-iteratee-based functions. I have only just begun reading about > iteratees > and might be missing the point, but it seems like many of the examples so > far rely on explicit recursion or special functions from one of the > iteratee > modules. >
You might be interested in the attoparsec-enumerator and attoparsec-iteratee packages, which adapt attoparsec parsers to work with iteratees. They're small, self-contained, and quite readable. Since attoparsec works with partial parses, it's a natural fit for iteratees. Honestly I'm quite dis-satisfied with the current state of code which depends on iteratee/enumerator. It's nearly all written in a very low-level style, i.e. directly writing 'liftI step', or 'case x of Yield -> ...'. This is exactly what I would hope users could avoid, by using the functions in e.g. Data.Iteratee.ListLike. I've recently added more functions to iteratee which greatly reduce the need for this type of code. I don't know about enumerator, but I expect it isn't rich enough since most user code I've seen is pretty low-level. For some other iteratee examples, you can 'darcs get http://www.tiresiaspress.us/haskell/sndfile-enumerators/' and look at the examples directory (or browse online, of course). > > Is there a way to take a simple function (example below) and use an > enumerator to feed it a ByteString from a file, or do you have to write > functions explicitly to work with a given iteratee implementation? > > import qualified Data.ByteString.Char8 as B > sortLines = B.unlines . sort . B.lines > For this case, there's no point to using iteratees at all. Just read the file in directly to a strict bytestring. Since you're sorting, you'll need to see all the lines before results can be returned. If the file is too big to fit into memory, you'd need a more sophisticated algorithm for which you could use iteratees. In the general case, you need to write for a given iteratee implementation, but in many specific cases it's not necessary. If you want to transform each line of a file, for instance (with iteratee): import Data.ByteString.Char8 as B import Data.Iteratee as I import Data.Iteratee.Char import System.IO import Control.Monad.IO.Class transform :: (ByteString -> ByteString) -> FilePath -> Iteratee [ByteString] IO () transform tFunc oFile = do h <- liftIO $ openFile oFile WriteMode joinI $ rigidMapStream tFunc $ I.mapM_ (B.hPutStrLn h) liftIO $ hClose h rewriteFile :: (ByteString -> ByteString) -> FilePath -> FilePath -> IO () rewriteFile tFunc iFile oFile = fileDriver (joinI $ enumLinesBS (transform tFunc oFile)) iFile An unfolding version would be possible too, which would take a parameter tFunc :: (s -> ByteString -> (s, ByteString)) Maybe I'll add these as utilities in the next version of iteratee. John
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe