packages feed

iteratee 0.8.1.2 → 0.8.2.0

raw patch · 8 files changed

+398/−105 lines, 8 filesdep +mtlPVP ok

version bump matches the API change (PVP)

Dependencies added: mtl

API changes (from Hackage documentation)

+ Data.Iteratee.IO: defaultBufSize :: Int
+ Data.Iteratee.IO: enumFile :: (NullPoint s, MonadCatchIO m, ReadableChunk s el) => Int -> FilePath -> Enumerator s m a
+ Data.Iteratee.IO: enumFileRandom :: (NullPoint s, MonadCatchIO m, ReadableChunk s el) => Int -> FilePath -> Enumerator s m a
+ Data.Iteratee.IO.Handle: enumFile :: (NullPoint s, MonadCatchIO m, ReadableChunk s el) => Int -> FilePath -> Enumerator s m a
+ Data.Iteratee.IO.Handle: enumFileRandom :: (NullPoint s, MonadCatchIO m, ReadableChunk s el) => Int -> FilePath -> Enumerator s m a
+ Data.Iteratee.Iteratee: (<><) :: (Nullable s1, Monad m) => Enumeratee s2 s3 m a -> (forall x. Enumeratee s1 s2 m x) -> Enumeratee s1 s3 m a
+ Data.Iteratee.Iteratee: (><>) :: (Nullable s1, Monad m) => (forall x. Enumeratee s1 s2 m x) -> Enumeratee s2 s3 m a -> Enumeratee s1 s3 m a
+ Data.Iteratee.ListLike: enumWith :: (Monad m, Nullable s, ListLike s el) => Iteratee s m a -> Iteratee s m b -> Iteratee s m (a, b)
+ Data.Iteratee.ListLike: sequence_ :: (Monad m, ListLike s el, Nullable s) => [Iteratee s m a] -> Iteratee s m ()
+ Data.Iteratee.ListLike: zip :: (Monad m, Nullable s, ListLike s el) => Iteratee s m a -> Iteratee s m b -> Iteratee s m (a, b)
+ Data.Iteratee.ListLike: zip3 :: (Monad m, Nullable s, ListLike s el) => Iteratee s m a -> Iteratee s m b -> Iteratee s m c -> Iteratee s m (a, b, c)
+ Data.Iteratee.ListLike: zip4 :: (Monad m, Nullable s, ListLike s el) => Iteratee s m a -> Iteratee s m b -> Iteratee s m c -> Iteratee s m d -> Iteratee s m (a, b, c, d)
+ Data.Iteratee.ListLike: zip5 :: (Monad m, Nullable s, ListLike s el) => Iteratee s m a -> Iteratee s m b -> Iteratee s m c -> Iteratee s m d -> Iteratee s m e -> Iteratee s m (a, b, c, d, e)

Files

iteratee.cabal view
@@ -1,5 +1,5 @@ name:          iteratee-version:       0.8.1.2+version:       0.8.2.0 synopsis:      Iteratee-based I/O description:   The Iteratee monad provides strict, safe, and functional I/O. In addition@@ -10,7 +10,7 @@ license:       BSD3 license-file:  LICENSE homepage:      http://www.tiresiaspress.us/haskell/iteratee-tested-with:   GHC == 7.0.1, GHC == 6.12.3+tested-with:   GHC == 7.0.3, GHC == 6.12.3 stability:     experimental  cabal-version: >= 1.6@@ -96,6 +96,7 @@    if flag(buildTests)     build-depends:+      mtl                        >= 2   && < 3,       QuickCheck                 >= 2   && < 3,       test-framework             >= 0.3 && < 0.4,       test-framework-quickcheck2 >= 0.2 && < 0.3
src/Data/Iteratee/IO.hs view
@@ -3,10 +3,14 @@ -- |Random and Binary IO with generic Iteratees.  module Data.Iteratee.IO(+  -- * Data+  defaultBufSize,   -- * File enumerators   -- ** Handle-based enumerators   enumHandle,   enumHandleRandom,+  enumFile,+  enumFileRandom, #if defined(USE_POSIX)   -- ** FileDescriptor based enumerators   enumFd,@@ -35,6 +39,7 @@  import Control.Monad.CatchIO +-- | The default buffer size. defaultBufSize :: Int defaultBufSize = 1024 
src/Data/Iteratee/IO/Fd.hs view
@@ -25,6 +25,7 @@ import Data.Iteratee.Binary() import Data.Iteratee.IO.Base +import Control.Concurrent (yield) import Control.Exception import Control.Monad import Control.Monad.CatchIO as CIO@@ -37,7 +38,6 @@ import System.IO (SeekMode(..))  import System.Posix hiding (FileOffset)-import GHC.Conc  -- ------------------------------------------------------------------------ -- Binary Random IO enumerators@@ -50,11 +50,10 @@   -> st   -> m (Either SomeException ((Bool, st), s)) makefdCallback p bufsize fd st = do-  liftIO $ GHC.Conc.threadWaitRead fd   n <- liftIO $ myfdRead fd (castPtr p) bufsize   case n of-    Left _   -> return $ Left undefined-    Right 0  -> return $ Right ((False, st), empty)+    Left  _  -> return $ Left (error "myfdRead failed")+    Right 0  -> liftIO yield >> return (Right ((False, st), empty))     Right n' -> liftM (\s -> Right ((True, st), s)) $                   readFromPtr p (fromIntegral n') 
src/Data/Iteratee/IO/Handle.hs view
@@ -10,6 +10,8 @@   enumHandle   ,enumHandleCatch   ,enumHandleRandom+  ,enumFile+  ,enumFileRandom   -- * Iteratee drivers   ,fileDriverHandle   ,fileDriverRandomHandle@@ -105,33 +107,48 @@ -- ---------------------------------------------- -- File Driver wrapper functions. -fileDriver :: (NullPoint s, MonadCatchIO m, ReadableChunk s el) =>+enumFile' :: (NullPoint s, MonadCatchIO m, ReadableChunk s el) =>   (Int -> Handle -> Enumerator s m a)   -> Int -- ^Buffer size-  -> Iteratee s m a   -> FilePath-  -> m a-fileDriver enumf bufsize iter filepath = CIO.bracket+  -> Enumerator s m a+enumFile' enumf bufsize filepath iter = CIO.bracket   (liftIO $ openBinaryFile filepath ReadMode)   (liftIO . hClose)-  (run <=< flip (enumf bufsize) iter)+  (flip (enumf bufsize) iter) +enumFile ::+  (NullPoint s, MonadCatchIO m, ReadableChunk s el)+  => Int                 -- ^Buffer size+  -> FilePath+  -> Enumerator s m a+enumFile = enumFile' enumHandle++enumFileRandom ::+  (NullPoint s, MonadCatchIO m, ReadableChunk s el)+  => Int                 -- ^Buffer size+  -> FilePath+  -> Enumerator s m a+enumFileRandom = enumFile' enumHandleRandom+ -- |Process a file using the given @Iteratee@.  This function wraps -- @enumHandle@ as a convenience. fileDriverHandle   :: (NullPoint s, MonadCatchIO m, ReadableChunk s el) =>-     Int -- ^Buffer size (number of elements)+     Int                      -- ^Buffer size (number of elements)      -> Iteratee s m a      -> FilePath      -> m a-fileDriverHandle = fileDriver enumHandle+fileDriverHandle bufsize iter filepath =+  enumFile bufsize filepath iter >>= run  -- |A version of @fileDriverHandle@ that supports seeking. fileDriverRandomHandle   :: (NullPoint s, MonadCatchIO m, ReadableChunk s el) =>-     Int+     Int                      -- ^ Buffer size (number of elements)      -> Iteratee s m a      -> FilePath      -> m a-fileDriverRandomHandle = fileDriver enumHandleRandom+fileDriverRandomHandle bufsize iter filepath =+  enumFileRandom bufsize filepath iter >>= run 
src/Data/Iteratee/Iteratee.hs view
@@ -1,4 +1,8 @@-{-# LANGUAGE KindSignatures, FlexibleContexts, ScopedTypeVariables, DeriveDataTypeable #-}+{-# LANGUAGE KindSignatures+            ,RankNTypes+            ,FlexibleContexts+            ,ScopedTypeVariables+            ,DeriveDataTypeable #-}  -- |Monadic and General Iteratees: -- incremental input parsers, processors and transformers@@ -34,6 +38,9 @@   -- ** Enumerator Combinators   ,(>>>)   ,eneeCheckIfDone+  -- ** Enumeratee Combinators+  ,(><>)+  ,(<><)   -- * Misc.   ,seek   ,FileOffset@@ -133,7 +140,6 @@     step (Chunk xs)       | nullC xs = liftI step       | True     = lift (f xs) >> liftI step-    step (Chunk xs) = lift (f xs) >> liftI step     step s@(EOF _)  = idone () s {-# INLINE mapChunksM_ #-} @@ -256,6 +262,32 @@  (>>>) :: (Monad m) => Enumerator s m a -> Enumerator s m a -> Enumerator s m a (e1 >>> e2) i =  e1 i >>= e2+  -- I think (>>>) is identical to (>=>)...+++-- | Enumeratee composition+-- Run the second enumeratee within the first.  In this example, stream2list+-- is run within the 'take 10', which is itself run within 'take 15', resulting+-- in 15 elements being consumed+--+-- > run =<< enumPure1Chunk [1..1000 :: Int]+-- >   (joinI $ (I.take 15 ><> I.take 10) I.stream2list)+-- > [1,2,3,4,5,6,7,8,9,10]+-- +(><>) ::+ (Nullable s1, Monad m)+  => (forall x . Enumeratee s1 s2 m x)+  -> Enumeratee s2 s3 m a+  -> Enumeratee s1 s3 m a+f ><> g = joinI . f . g++-- | enumeratee composition with the arguments flipped, see '><>'+(<><) ::+ (Nullable s1, Monad m)+  => Enumeratee s2 s3 m a+  -> (forall x. Enumeratee s1 s2 m x)+  -> Enumeratee s1 s3 m a+f <>< g = joinI . g . f  -- |The pure 1-chunk enumerator -- It passes a given list of elements to the iteratee in one chunk
src/Data/Iteratee/ListLike.hs view
@@ -45,6 +45,12 @@   ,enumPureNChunk   -- ** Enumerator Combinators   ,enumPair+  ,enumWith+  ,zip+  ,zip3+  ,zip4+  ,zip5+  ,sequence_   -- ** Monadic functions   ,mapM_   ,foldM@@ -53,19 +59,22 @@ ) where -import Prelude hiding (mapM_, null, head, last, drop, dropWhile, take, break, foldl, foldl1, length, filter, sum, product)+import Prelude hiding (mapM_, null, head, last, drop, dropWhile, take, break, foldl, foldl1, length, filter, sum, product, zip, zip3, sequence_) +import qualified Prelude as Prelude+ import qualified Data.ListLike as LL import qualified Data.ListLike.FoldableLL as FLL import Data.Iteratee.Iteratee import Data.Monoid+import Data.Maybe (catMaybes) import Control.Applicative+import Control.Monad (liftM, liftM2, mplus, (<=<)) import Control.Monad.Trans.Class import Data.Word (Word8) import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC - -- Useful combinators for implementing iteratees and enumerators  -- | Check if a stream has received 'EOF'.@@ -199,8 +208,9 @@  -- | Return a chunk of `t' elements length, while consuming `d' elements --   from the stream.  Useful for creating a "rolling average" with convStream.-roll :: (Monad m, Functor m, Nullable s, LL.ListLike s el, LL.ListLike s' s) =>-  Int+roll+  :: (Monad m, Functor m, Nullable s, LL.ListLike s el, LL.ListLike s' s)+  => Int   -> Int   -> Iteratee s m s' roll t d | t > d  = liftI step@@ -271,7 +281,10 @@ -- @break@ pred === @joinI@ (@breakE@ pred stream2stream) -- -- @breakE@ should be used in preference to @break@ whenever possible.-breakE :: (Monad m, LL.ListLike s el, NullPoint s) => (el -> Bool) -> Enumeratee s s m a+breakE+  :: (Monad m, LL.ListLike s el, NullPoint s)+  => (el -> Bool)+  -> Enumeratee s s m a breakE cpred = eneeCheckIfDone (liftI . step)  where   step k (Chunk s)@@ -342,14 +355,14 @@ -- given iteratee to it. -- -- The analog of @List.map@-mapStream ::- (Monad m,-  LL.ListLike (s el) el,-  LL.ListLike (s el') el',-  NullPoint (s el),-  LooseMap s el el') =>- (el -> el')- -> Enumeratee (s el) (s el') m a+mapStream+  :: (Monad m+     ,LL.ListLike (s el) el+     ,LL.ListLike (s el') el'+     ,NullPoint (s el)+     ,LooseMap s el el')+  => (el -> el')+  -> Enumeratee (s el) (s el') m a mapStream f = eneeCheckIfDone (liftI . step)   where     step k (Chunk xs)@@ -363,9 +376,9 @@ -- Like 'mapStream', but the element type cannot change. -- This function is necessary for @ByteString@ and similar types -- that cannot have 'LooseMap' instances, and may be more efficient.-rigidMapStream ::- (Monad m, LL.ListLike s el, NullPoint s) =>-  (el -> el)+rigidMapStream+  :: (Monad m, LL.ListLike s el, NullPoint s)+  => (el -> el)   -> Enumeratee s s m a rigidMapStream f = eneeCheckIfDone (liftI . step)   where@@ -381,9 +394,9 @@ -- satisfy the predicate function.  The outer stream is completely consumed. -- -- The analogue of @List.filter@-filter ::- (Monad m, Nullable s, LL.ListLike s el) =>-  (el -> Bool)+filter+  :: (Monad m, Nullable s, LL.ListLike s el)+  => (el -> Bool)   -> Enumeratee s s m a filter p = convStream f'   where@@ -397,8 +410,10 @@ -- |Creates an 'enumeratee' in which elements from the stream are -- grouped into \sz\-sized blocks.  The outer stream is completely -- consumed and the final block may be smaller than \sz\.-group :: (LL.ListLike s el, Monad m, Nullable s) => -             Int -> Enumeratee s [s] m a+group+  :: (LL.ListLike s el, Monad m, Nullable s)+  => Int+  -> Enumeratee s [s] m a group sz iinit = liftI $ go iinit LL.empty   where go icurr pfx (Chunk s) = case gsplit (pfx `LL.append` s) of            (full, partial) | LL.null full -> liftI $ go icurr partial@@ -422,8 +437,10 @@ --  -- The analogue of @List.groupBy#           -groupBy :: (LL.ListLike s el, Monad m, Nullable s) =>-               (el -> el -> Bool) -> Enumeratee s [s] m a+groupBy+  :: (LL.ListLike s el, Monad m, Nullable s)+  => (el -> el -> Bool)+  -> Enumeratee s [s] m a groupBy same iinit = liftI $ go iinit LL.empty     where go icurr pfx (Chunk s) = case gsplit (pfx `LL.append` s) of                                           (full, partial)@@ -453,9 +470,9 @@ -- | Left-associative fold. -- -- The analogue of @List.foldl@-foldl ::- (Monad m, LL.ListLike s el, FLL.FoldableLL s el) =>-  (a -> el -> a)+foldl+  :: (Monad m, LL.ListLike s el, FLL.FoldableLL s el)+  => (a -> el -> a)   -> a   -> Iteratee s m a foldl f i = liftI (step i)@@ -471,9 +488,9 @@ -- This function should be used in preference to 'foldl' whenever possible. -- -- The analogue of @List.foldl'@.-foldl' ::- (Monad m, LL.ListLike s el, FLL.FoldableLL s el) =>-  (a -> el -> a)+foldl'+  :: (Monad m, LL.ListLike s el, FLL.FoldableLL s el)+  => (a -> el -> a)   -> a   -> Iteratee s m a foldl' f i = liftI (step i)@@ -488,9 +505,9 @@ --   in the stream. -- -- The analogue of @List.foldl1@.-foldl1 ::- (Monad m, LL.ListLike s el, FLL.FoldableLL s el) =>-  (el -> el -> el)+foldl1+  :: (Monad m, LL.ListLike s el, FLL.FoldableLL s el)+  => (el -> el -> el)   -> Iteratee s m el foldl1 f = liftI step   where@@ -503,9 +520,9 @@   -- | Strict variant of 'foldl1'.-foldl1' ::- (Monad m, LL.ListLike s el, FLL.FoldableLL s el) =>-  (el -> el -> el)+foldl1'+  :: (Monad m, LL.ListLike s el, FLL.FoldableLL s el)+  => (el -> el -> el)   -> Iteratee s m el foldl1' f = liftI step   where@@ -543,42 +560,176 @@ -- Zips  -- |Enumerate two iteratees over a single stream simultaneously.+--  Deprecated, use `Data.Iteratee.ListLike.zip` instead. -- -- Compare to @zip@.-enumPair ::- (Monad m, Nullable s, LL.ListLike s el) =>-  Iteratee s m a+{-# DEPRECATED enumPair "use Data.Iteratee.ListLike.zip" #-}+enumPair+  :: (Monad m, Nullable s, LL.ListLike s el)+  => Iteratee s m a   -> Iteratee s m b-  -> Iteratee s m (a,b)-enumPair i1 i2 = Iteratee $ \od oc -> runIter i1 (onDone od oc) (onCont od oc)+  -> Iteratee s m (a, b)+enumPair = zip+++-- |Enumerate two iteratees over a single stream simultaneously.+--+-- Compare to @zip@.+zip+  :: (Monad m, Nullable s, LL.ListLike s el)+  => Iteratee s m a+  -> Iteratee s m b+  -> Iteratee s m (a, b)+zip x y = liftI step   where-    onDone od oc x s        = runIter i2 (oD12 od oc x s) (onCont' od oc x)-    oD12 od oc x1 s1 x2 s2  = runIter (idone (x1,x2) (longest s1 s2)) od oc-    onCont od oc k mErr     = runIter (icont (step k) mErr) od oc+    step (Chunk xs) | nullC xs = liftI step+    step (Chunk xs) = do+      (a', x') <- lift $ (\i -> runIter i od oc) =<< enumPure1Chunk xs x+      (b', y') <- lift $ (\i -> runIter i od oc) =<< enumPure1Chunk xs y+      case checkDone a' b' of+        Just (a, b, s) -> idone (a, b) s+        Nothing        -> zip x' y'+    step (EOF err) = joinIM $ case err of+      Nothing -> (liftM2.liftM2) (,) (enumEof   x) (enumEof   y)+      Just e  -> (liftM2.liftM2) (,) (enumErr e x) (enumErr e y)++    od a s = return (Just (a, s), idone a s)+    oc k e = return (Nothing    , icont k e)++    checkDone r1 r2 =+      r1 >>= \(a, s1) -> r2 >>= \(b, s2) ->+      return (a, b, shorter s1 s2)++    shorter c1@(Chunk xs) c2@(Chunk ys)+      | LL.length xs < LL.length ys = c1+      | otherwise                   = c2+    shorter e@(EOF _)  _         = e+    shorter _          e@(EOF _) = e+{-# INLINE zip #-}++zip3+  :: (Monad m, Nullable s, LL.ListLike s el)+  => Iteratee s m a -> Iteratee s m b+  -> Iteratee s m c -> Iteratee s m (a, b, c)+zip3 a b c = zip a (zip b c) >>=+  \(r1, (r2, r3)) -> return (r1, r2, r3)+{-# INLINE zip3 #-}++zip4+  :: (Monad m, Nullable s, LL.ListLike s el)+  => Iteratee s m a -> Iteratee s m b+  -> Iteratee s m c -> Iteratee s m d+  -> Iteratee s m (a, b, c, d)+zip4 a b c d = zip a (zip3 b c d) >>=+  \(r1, (r2, r3, r4)) -> return (r1, r2, r3, r4)+{-# INLINE zip4 #-}++zip5+  :: (Monad m, Nullable s, LL.ListLike s el)+  => Iteratee s m a -> Iteratee s m b+  -> Iteratee s m c -> Iteratee s m d+  -> Iteratee s m e -> Iteratee s m (a, b, c, d, e)+zip5 a b c d e = zip a (zip4 b c d e) >>=+  \(r1, (r2, r3, r4, r5)) -> return (r1, r2, r3, r4, r5)+{-# INLINE zip5 #-}++-- | Enumerate over two iteratees in parallel as long as the first iteratee+-- is still consuming input.  The second iteratee will be terminated with EOF+-- when the first iteratee has completed.  An example use is to determine+-- how many elements an iteratee has consumed:+--+-- > snd <$> enumWith (dropWhile (<5)) length+--+-- Compare to @zip@+enumWith+  :: (Monad m, Nullable s, LL.ListLike s el)+  => Iteratee s m a+  -> Iteratee s m b+  -> Iteratee s m (a, b)+enumWith i1 i2 = go i1 i2+  where+    od a s = return (Just (a, s), idone a s)+    oc k e = return (Nothing    , icont k e)++    getUsed xs (Chunk ys) = LL.take (LL.length xs - LL.length ys) xs+    getUsed xs (EOF _)    = xs++    go x y = liftI step       where-    onCont' od oc x1 k mErr = runIter (icont (step2 x1 k) mErr) od oc-    step k c@(Chunk str)-      | nullC str            = liftI (step k)-      | True                = lift (enumPure1Chunk str i2) >>= enumPair (k c)-    step k s@(EOF Nothing)  = lift (enumEof i2) >>= enumPair (k s)-    step k s@(EOF (Just e)) = lift (enumErr e i2) >>= enumPair (k s)-    step2 x1 k (Chunk str)-      | nullC str            = liftI (step2 x1 k)-    step2 x1 k str          = enumPair (return x1) (k str)-    longest c1@(Chunk xs) c2@(Chunk ys) = if LL.length xs > LL.length ys-                                          then c1 else c2-    longest e@(EOF _)  _         = e-    longest _          e@(EOF _) = e-{-# INLINE enumPair #-}+        step (Chunk xs) | nullC xs = liftI step+        step (Chunk xs) = do+          (a', x') <- lift $ (\i -> runIter i od oc) =<< enumPure1Chunk xs x+          case a' of+            Just (a, s) -> do+              b <- lift $ run =<< enumPure1Chunk (getUsed xs s) y+              idone (a, b) s+            Nothing        -> lift (enumPure1Chunk xs y) >>= go x'+        step (EOF err) = joinIM $ case err of+          Nothing -> (liftM2.liftM2) (,) (enumEof   x) (enumEof   y)+          Just e  -> (liftM2.liftM2) (,) (enumErr e x) (enumErr e y)+{-# INLINE enumWith #-} +-- |Enumerate a list of iteratees over a single stream simultaneously+-- and discard the results. This is a different behavior than Prelude's+-- sequence_ which runs iteratees in the list one after the other.+--+-- Compare to @sequence_@.+sequence_+  :: (Monad m, LL.ListLike s el, Nullable s)+  => [Iteratee s m a]+  -> Iteratee s m ()+sequence_ = self+  where+    self is = liftI step+      where+        step (Chunk xs) | LL.null xs = liftI step+        step s@(Chunk _) = do+          -- give a chunk to each iteratee+          is'  <- lift $ mapM (enumChunk s) is+          -- filter done iteratees+          is'' <- lift $ catMaybes `liftM` mapM checkIfDone is'+          if Prelude.null is''+            then idone () <=< remainingStream $ is'+            else self is''+        step s@(EOF _) = do+          s' <- remainingStream <=< lift $ mapM (enumChunk s) $ is+          case s' of+            EOF (Just e) -> throwErr e+            _            -> idone () s' +        checkIfDone i = runIter i+            (\_ _ -> return Nothing)+            (\k e -> return $ Just $ icont k e)++    -- returns the unconsumed part of the stream; "sequence_ is" consumes as+    -- much of the stream as the iteratee in is that consumes the most; e.g.+    -- sequence_ [I.head, I.last] consumes whole stream+    remainingStream+      :: (Monad m, Nullable s, LL.ListLike s el)+      => [Iteratee s m a] -> Iteratee s m (Stream s)+    remainingStream is = lift $+      return . Prelude.foldl1 shorter <=< mapM (\i -> runIter i od oc) $ is+      where+        od _ s = return s+        oc _ e = return $ case e of+          Nothing -> mempty+          _       -> EOF e++    -- return the shorter one of two streams; errors are propagated with the+    -- priority given to the "left"+    shorter c1@(Chunk xs) c2@(Chunk ys)+      | LL.length xs < LL.length ys = c1+      | otherwise                   = c2+    shorter (EOF e1 ) (EOF e2 ) = EOF (e1 `mplus` e2)+    shorter e@(EOF _) _         = e+    shorter _         e@(EOF _) = e+ -- ------------------------------------------------------------------------ -- Enumerators  -- |The pure n-chunk enumerator -- It passes a given stream of elements to the iteratee in @n@-sized chunks.-enumPureNChunk ::- (Monad m, LL.ListLike s el) => s -> Int -> Enumerator s m a+enumPureNChunk :: (Monad m, LL.ListLike s el) => s -> Int -> Enumerator s m a enumPureNChunk str n iter   | LL.null str = return iter   | n > 0       = enum' str iter@@ -598,9 +749,10 @@  -- | Map a monadic function over the elements of the stream and ignore the -- result.-mapM_ :: (Monad m, LL.ListLike s el, Nullable s)-      => (el -> m b)-      -> Iteratee s m ()+mapM_+  :: (Monad m, LL.ListLike s el, Nullable s)+  => (el -> m b)+  -> Iteratee s m () mapM_ f = liftI step   where     step (Chunk xs) | LL.null xs = liftI step@@ -609,10 +761,11 @@ {-# INLINE mapM_ #-}  -- |The analogue of @Control.Monad.foldM@-foldM :: (Monad m, LL.ListLike s b, Nullable s)-      => (a -> b -> m a)-      -> a-      -> Iteratee s m a+foldM+  :: (Monad m, LL.ListLike s b, Nullable s)+  => (a -> b -> m a)+  -> a+  -> Iteratee s m a foldM f e = liftI step   where     step (Chunk xs) | LL.null xs = liftI step
− tests/foo.hs
@@ -1,11 +0,0 @@-import Control.Monad.Trans (liftIO)-import Data.Iteratee.Iteratee-import qualified Data.Iteratee.ListLike as I--main = enumPure1Chunk [1..10] myIter >>= run--myIter :: Iteratee [Int] IO ()-myIter = do-   I.last-   x <- I.peek-   liftIO $ print x
tests/testIteratee.hs view
@@ -10,14 +10,17 @@  import Test.QuickCheck -import Data.Iteratee hiding (head, break)+import           Data.Iteratee hiding (head, break) import qualified Data.Iteratee.Char as IC import qualified Data.Iteratee as Iter-import Data.Functor.Identity+import           Data.Functor.Identity import qualified Data.List as List (groupBy, unfoldr)-import Data.Monoid+import           Data.Monoid import qualified Data.ListLike as LL +import           Control.Monad as CM+import           Control.Monad.Writer+ import Text.Printf (printf) import System.Environment (getArgs) @@ -53,8 +56,8 @@ -- --------------------------------------------- -- Iteratee instances -runner0 = runIdentity . Iter.run runner1 = runIdentity . Iter.run . runIdentity+enumSpecial xs n = enumPure1Chunk LL.empty >=> enumPureNChunk xs n  prop_iterFmap xs f a = runner1 (enumPure1Chunk xs (fmap f $ return a))                      == runner1 (enumPure1Chunk xs (return $ f a))@@ -64,15 +67,15 @@                       == f (runner1 (enumPure1Chunk xs i))   where types = (xs :: [Int], i :: I, f :: [Int] -> [Int]) -prop_iterMonad1 xs a f = runner1 (enumPureNChunk xs 1 (return a >>= f))+prop_iterMonad1 xs a f = runner1 (enumSpecial xs 1 (return a >>= f))                        == runner1 (enumPure1Chunk xs (f a))   where types = (xs :: [Int], a :: Int, f :: Int -> I) -prop_iterMonad2 m xs = runner1 (enumPureNChunk xs 1 (m >>= return))+prop_iterMonad2 m xs = runner1 (enumSpecial xs 1 (m >>= return))                      == runner1 (enumPure1Chunk xs m)   where types = (xs :: [Int], m :: I) -prop_iterMonad3 m f g xs = runner1 (enumPureNChunk xs 1 ((m >>= f) >>= g))+prop_iterMonad3 m f g xs = runner1 (enumSpecial xs 1 ((m >>= f) >>= g))                          == runner1 (enumPure1Chunk xs (m >>= (\x -> f x >>= g)))   where types = (xs :: [Int], m :: I, f :: [Int] -> I, g :: [Int] -> I) @@ -82,7 +85,7 @@ prop_list xs = runner1 (enumPure1Chunk xs stream2list) == xs   where types = xs :: [Int] -prop_clist xs n = n > 0 ==> runner1 (enumPureNChunk xs n stream2list) == xs+prop_clist xs n = n > 0 ==> runner1 (enumSpecial xs n stream2list) == xs   where types = xs :: [Int]  prop_break f xs = runner1 (enumPure1Chunk xs (Iter.break f)) == fst (break f xs)@@ -104,7 +107,8 @@ prop_head2 xs = P.length xs > 0 ==> runner1 (enumPure1Chunk xs (Iter.head >> stream2list)) == tail xs   where types = xs :: [Int] -prop_heads xs = runner1 (enumPure1Chunk xs $ heads xs) == P.length xs+prop_heads xs n = n > 0 ==>+ runner1 (enumSpecial xs n $ heads xs) == P.length xs   where types = xs :: [Int]  prop_heads2 xs = runner1 (enumPure1Chunk xs $ heads [] >>= \c ->@@ -132,13 +136,25 @@  runner1 (enumPure1Chunk xs (Iter.last >> Iter.peek)) == Nothing   where types = xs :: [Int] +prop_drop xs n k = (n > 0 && k >= 0) ==>+ runner1 (enumSpecial xs n (Iter.drop k >> stream2list)) == P.drop k xs+  where types = xs :: [Int]++prop_dropWhile f xs =+ runner1 (enumPure1Chunk xs (Iter.dropWhile f >> stream2list))+ == P.dropWhile f xs+  where types = (xs :: [Int], f :: Int -> Bool)++prop_length xs = runner1 (enumPure1Chunk xs Iter.length) == P.length xs+  where types = xs :: [Int]+ -- --------------------------------------------- -- Simple enumerator tests  type I = Iteratee [Int] Identity [Int]  prop_enumChunks n xs i = n > 0  ==>-  runner1 (enumPure1Chunk xs i) == runner1 (enumPureNChunk xs n i)+  runner1 (enumPure1Chunk xs i) == runner1 (enumSpecial xs n i)   where types = (n :: Int, xs :: [Int], i :: I)  prop_app1 xs ys i = runner1 (enumPure1Chunk ys (joinIM $ enumPure1Chunk xs i))@@ -170,7 +186,20 @@                 runner1 (enumPure1Chunk xs =<< enumPure1Chunk [] Iter.head)                 == runner1 (enumPure1Chunk xs Iter.head)   where types = xs :: [Int]+ -- ---------------------------------------------+-- Enumerator Combinators++prop_enumWith xs f n = n > 0 ==> runner1 (enumSpecial xs n $ fmap fst $ enumWith (Iter.dropWhile f) (stream2list))+   == runner1 (enumSpecial xs n $ Iter.dropWhile f)+ where types = (xs :: [Int])++prop_enumWith2 xs f n = n > 0 ==> runner1 (enumSpecial xs n $ enumWith (Iter.dropWhile f) (stream2list) >> stream2list)+   == runner1 (enumSpecial xs n $ Iter.dropWhile f >> stream2list)+ where types = (xs :: [Int])+++-- --------------------------------------------- -- Nested Iteratees  -- take, mapStream, convStream, and takeR@@ -182,7 +211,7 @@   where types = (i :: I, xs :: [Int])  prop_mapStream2 xs n i = n > 0 ==>-                         runner2 (enumPureNChunk xs n $ mapStream id i)+                         runner2 (enumSpecial xs n $ mapStream id i)                          == runner1 (enumPure1Chunk xs i)   where types = (i :: I, xs :: [Int]) @@ -191,7 +220,33 @@   == runner1 (enumPure1Chunk xs i)   where types = (i :: I, xs :: [Int]) +prop_rigidMapStream xs n f = n > 0 ==>+ runner2 (enumSpecial xs n $ rigidMapStream f stream2list) == map f xs+  where types = (xs :: [Int]) +prop_foldl xs n f x0 = n > 0 ==>+ runner1 (enumSpecial xs n (Iter.foldl f x0)) == P.foldl f x0 xs+  where types = (xs :: [Int], x0 :: Int)++prop_foldl' xs n f x0 = n > 0 ==>+ runner1 (enumSpecial xs n (Iter.foldl' f x0)) == LL.foldl' f x0 xs+  where types = (xs :: [Int], x0 :: Int)++prop_foldl1 xs n f = (n > 0 && not (null xs)) ==>+ runner1 (enumSpecial xs n (Iter.foldl1 f)) == P.foldl1 f xs+  where types = (xs :: [Int])++prop_foldl1' xs n f = (n > 0 && not (null xs)) ==>+ runner1 (enumSpecial xs n (Iter.foldl1' f)) == P.foldl1 f xs+  where types = (xs :: [Int])++prop_sum xs n = n > 0 ==> runner1 (enumSpecial xs n Iter.sum) == P.sum xs+  where types = (xs :: [Int])++prop_product xs n = n > 0 ==>+ runner1 (enumSpecial xs n Iter.product) == P.product xs+  where types = (xs :: [Int])+ convId :: (LL.ListLike s el, Monad m) => Iteratee s m s convId = liftI (\str -> case str of   s@(Chunk xs) | LL.null xs -> convId@@ -232,6 +287,14 @@                   == runner2 (enumPure1Chunk xs $ takeUpTo n stream2list)   where types = xs :: [Int] +prop_takeUpTo2 xs n = n >= 0 ==>+ runner2 (enumPure1Chunk xs (takeUpTo n identity)) == ()+  where types = xs :: [Int]++prop_filter xs n f = n > 0 ==>+ runner2 (enumSpecial xs n (Iter.filter f stream2list)) == P.filter f xs+  where types = xs :: [Int]+ prop_group xs n = n > 0 ==>                   runner2 (enumPure1Chunk xs $ Iter.group n stream2list)                   == runner1 (enumPure1Chunk groups stream2list)@@ -247,6 +310,18 @@   where types = xs :: [Int]         pred z1 z2 = (z1 `mod` m == z2 `mod` m) +prop_mapM_ xs n = n > 0 ==>+ runWriter ((enumSpecial xs n (Iter.mapM_ f)) >>= run)+ == runWriter (CM.mapM_ f xs)+  where f = const $ tell (Sum 1)+        types = xs :: [Int]++prop_foldM xs x0 n = n > 0 ==>+ runWriter ((enumSpecial xs n (Iter.foldM f x0)) >>= run)+ == runWriter (CM.foldM f x0 xs)+  where f acc el = tell (Sum 1) >> return (acc - el)+        types = xs :: [Int]+ -- --------------------------------------------- -- Data.Iteratee.Char @@ -284,6 +359,9 @@     ,testProperty "peek2" prop_peek2     ,testProperty "last" prop_last1     ,testProperty "last ends properly" prop_last2+    ,testProperty "length" prop_length+    ,testProperty "drop" prop_drop+    ,testProperty "dropWhile" prop_dropWhile     ,testProperty "skipToEof" prop_skip     ,testProperty "iteratee Functor 1" prop_iterFmap     ,testProperty "iteratee Functor 2" prop_iterFmap2@@ -306,20 +384,39 @@     testProperty "mapStream identity" prop_mapStream     ,testProperty "mapStream identity 2" prop_mapStream2     ,testProperty "mapStream identity joinI" prop_mapjoin+    ,testProperty "rigidMapStream" prop_rigidMapStream     ,testProperty "breakE" prop_breakE     ,testProperty "breakE remainder" prop_breakE2     ,testProperty "take" prop_take     ,testProperty "take (finished iteratee)" prop_take2     ,testProperty "takeUpTo" prop_takeUpTo+    ,testProperty "takeUpTo (finished iteratee)" prop_takeUpTo2+    ,testProperty "filter" prop_filter     ,testProperty "group" prop_group     ,testProperty "groupBy" prop_groupBy     ,testProperty "convStream EOF" prop_convstream2     ,testProperty "convStream identity" prop_convstream     ,testProperty "convStream identity 2" prop_convstream3     ]+  ,testGroup "Enumerator Combinators" [+    testProperty "enumWith" prop_enumWith+    ,testProperty "enumWith remaining" prop_enumWith2+    ]+  ,testGroup "Folds" [+    testProperty "foldl" prop_foldl+   ,testProperty "foldl'" prop_foldl'+   ,testProperty "foldl1" prop_foldl1+   ,testProperty "foldl1'" prop_foldl1'+   ,testProperty "sum" prop_sum+   ,testProperty "product" prop_product+   ]   ,testGroup "Data.Iteratee.Char" [     --testProperty "line" prop_line     ]+  ,testGroup "Monadic functions" [+    testProperty "mapM_" prop_mapM_+   ,testProperty "foldM" prop_foldM+   ]   ]  ------------------------------------------------------------------------