iteratee 0.8.6.2 → 0.8.7
raw patch · 9 files changed
+306/−67 lines, 9 filesdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Data.Iteratee.Iteratee: eneeCheckIfDoneHandle :: (Monad m, NullPoint elo) => EnumerateeHandler eli elo m a -> ((Stream eli -> Iteratee eli m a) -> Maybe SomeException -> Iteratee elo m (Iteratee eli m a)) -> Enumeratee elo eli m a
+ Data.Iteratee.Iteratee: eneeCheckIfDoneIgnore :: (Monad m, NullPoint elo) => ((Stream eli -> Iteratee eli m a) -> Maybe SomeException -> Iteratee elo m (Iteratee eli m a)) -> Enumeratee elo eli m a
+ Data.Iteratee.Iteratee: eneeCheckIfDonePass :: (Monad m, NullPoint elo) => ((Stream eli -> Iteratee eli m a) -> Maybe SomeException -> Iteratee elo m (Iteratee eli m a)) -> Enumeratee elo eli m a
+ Data.Iteratee.Iteratee: foldChunksM :: (Monad m, Nullable s) => (a -> s -> m a) -> a -> Iteratee s m a
+ Data.Iteratee.Iteratee: mapChunksM :: (Monad m, NullPoint s, Nullable s) => (s -> m s') -> Enumeratee s s' m a
+ Data.Iteratee.Iteratee: type EnumerateeHandler eli elo m a = (Stream eli -> Iteratee eli m a) -> SomeException -> Iteratee elo m (Iteratee eli m a)
+ Data.Iteratee.Iteratee: unfoldConvStreamCheck :: (Monad m, Nullable elo, Monoid elo) => (((Stream eli -> Iteratee eli m a) -> Maybe SomeException -> Iteratee elo m (Iteratee eli m a)) -> Enumeratee elo eli m a) -> (acc -> Iteratee elo m (acc, eli)) -> acc -> Enumeratee elo eli m a
+ Data.Iteratee.ListLike: takeWhile :: (ListLike s el, Monad m) => (el -> Bool) -> Iteratee s m s
+ Data.Iteratee.ListLike: takeWhileE :: (Monad m, ListLike s el, NullPoint s) => (el -> Bool) -> Enumeratee s s m a
- Data.Iteratee.Iteratee: enumChunk :: (Monad m, Monoid s) => Stream s -> Enumerator s m a
+ Data.Iteratee.Iteratee: enumChunk :: Monad m => Stream s -> Enumerator s m a
- Data.Iteratee.Iteratee: enumPure1Chunk :: (Monad m, Monoid s) => s -> Enumerator s m a
+ Data.Iteratee.Iteratee: enumPure1Chunk :: Monad m => s -> Enumerator s m a
Files
- iteratee.cabal +4/−19
- src/Data/Iteratee/Base.hs +5/−6
- src/Data/Iteratee/IO/Handle.hs +2/−2
- src/Data/Iteratee/Iteratee.hs +103/−14
- src/Data/Iteratee/ListLike.hs +80/−16
- tests/QCUtils.hs +4/−0
- tests/benchmarkHandle.hs +1/−0
- tests/benchmarks.hs +13/−2
- tests/testIteratee.hs +94/−8
iteratee.cabal view
@@ -1,5 +1,5 @@ name: iteratee-version: 0.8.6.2+version: 0.8.7 synopsis: Iteratee-based I/O description: The Iteratee monad provides strict, safe, and functional I/O. In addition@@ -12,7 +12,7 @@ license: BSD3 license-file: LICENSE homepage: http://www.tiresiaspress.us/haskell/iteratee-tested-with: GHC == 7.0.3, GHC == 6.12.3+tested-with: GHC == 7.0.4, GHC == 7.2.1 stability: experimental cabal-version: >= 1.6@@ -26,9 +26,6 @@ Examples/*.txt tests/*.hs -flag splitBase- description: Use the split-up base package.- flag buildTests description: Build test executables. default: False@@ -37,13 +34,6 @@ hs-source-dirs: src - if flag(splitBase)- build-depends:- base >= 3 && < 6- else- build-depends:- base < 3- if os(windows) cpp-options: -DUSE_WINDOWS exposed-modules:@@ -57,6 +47,7 @@ unix >= 2 && < 3 build-depends:+ base >= 3 && < 6, ListLike >= 1.0 && < 4, MonadCatchIO-transformers > 0.2 && < 0.3, bytestring >= 0.9 && < 0.10,@@ -100,19 +91,13 @@ if flag(buildTests) build-depends:+ base >= 3 && < 6, mtl >= 2 && < 3, QuickCheck >= 2 && < 3, test-framework >= 0.3 && < 0.4, test-framework-quickcheck2 >= 0.2 && < 0.3 else buildable: False-- if flag(splitBase)- build-depends:- base >= 3 && < 5- else- build-depends:- base < 3 source-repository head type: darcs
src/Data/Iteratee/Base.hs view
@@ -27,17 +27,15 @@ -- ** Stream Functions ,setEOF -- * Classes- ,module Data.NullPoint- ,module Data.Nullable- ,module Data.Iteratee.Base.LooseMap+ ,module X ) where import Prelude hiding (null, catch)-import Data.Iteratee.Base.LooseMap import Data.Iteratee.Exception-import Data.Nullable-import Data.NullPoint+import Data.Iteratee.Base.LooseMap as X+import Data.Nullable as X+import Data.NullPoint as X import Data.Monoid import Control.Monad.IO.Class@@ -186,6 +184,7 @@ -- Note that only internal iteratee exceptions will be returned; exceptions -- thrown with @Control.Exception.throw@ or @Control.Monad.CatchIO.throw@ will -- not be returned.+-- -- See 'Data.Iteratee.Exception.IFException' for details. tryRun :: (Exception e, Monad m) => Iteratee s m a -> m (Either e a) tryRun iter = runIter iter onDone onCont
src/Data/Iteratee/IO/Handle.hs view
@@ -76,8 +76,8 @@ forall e s el m a.(IException e, NullPoint s, ReadableChunk s el,- MonadCatchIO m) =>- Int -- ^Buffer size (number of elements per read)+ MonadCatchIO m)+ => Int -- ^Buffer size (number of elements per read) -> Handle -> (e -> m (Maybe EnumException)) -> Enumerator s m a
src/Data/Iteratee/Iteratee.hs view
@@ -10,8 +10,9 @@ module Data.Iteratee.Iteratee ( -- * Types+ EnumerateeHandler -- ** Error handling- throwErr+ ,throwErr ,throwRecoverableErr ,checkErr -- ** Basic Iteratees@@ -20,12 +21,15 @@ ,isStreamFinished -- ** Chunkwise Iteratees ,mapChunksM_+ ,foldChunksM ,getChunk ,getChunks -- ** Nested iteratee combinators ,mapChunks+ ,mapChunksM ,convStream ,unfoldConvStream+ ,unfoldConvStreamCheck ,joinI ,joinIM -- * Enumerators@@ -43,6 +47,9 @@ -- ** Enumerator Combinators ,(>>>) ,eneeCheckIfDone+ ,eneeCheckIfDoneHandle+ ,eneeCheckIfDoneIgnore+ ,eneeCheckIfDonePass ,mergeEnums -- ** Enumeratee Combinators ,(><>)@@ -150,6 +157,14 @@ step s@(EOF _) = idone () s {-# INLINE mapChunksM_ #-} +-- | A fold over chunks+foldChunksM :: (Monad m, Nullable s) => (a -> s -> m a) -> a -> Iteratee s m a+foldChunksM f = liftI . go+ where+ go a (Chunk c) = lift (f a c) >>= liftI . go+ go a e = idone a e+{-# INLINE foldChunksM #-}+ -- | Get the current chunk from the stream. getChunk :: (Monad m, Nullable s, NullPoint s) => Iteratee s m s getChunk = liftI step@@ -209,6 +224,47 @@ onCont _ (Just e) = runIter (throwErr e) od oc in runIter inner onDone onCont ++type EnumerateeHandler eli elo m a =+ (Stream eli -> Iteratee eli m a)+ -> SomeException+ -> Iteratee elo m (Iteratee eli m a)++-- | The same as eneeCheckIfDonePass, with one extra argument:+-- a handler which is used+-- to process any exceptions in a separate method.+eneeCheckIfDoneHandle+ :: (Monad m, NullPoint elo)+ => EnumerateeHandler eli elo m a+ -> ((Stream eli -> Iteratee eli m a)+ -> Maybe SomeException+ -> Iteratee elo m (Iteratee eli m a)+ )+ -> Enumeratee elo eli m a+eneeCheckIfDoneHandle h f inner = Iteratee $ \od oc ->+ let onDone x s = od (idone x s) (Chunk empty)+ onCont k Nothing = runIter (f k Nothing) od oc+ onCont k (Just e) = runIter (h k e) od oc+ in runIter inner onDone onCont++eneeCheckIfDonePass+ :: (Monad m, NullPoint elo)+ => ((Stream eli -> Iteratee eli m a)+ -> Maybe SomeException+ -> Iteratee elo m (Iteratee eli m a)+ )+ -> Enumeratee elo eli m a+eneeCheckIfDonePass f = eneeCheckIfDoneHandle (\k e -> f k (Just e)) f++eneeCheckIfDoneIgnore+ :: (Monad m, NullPoint elo)+ => ((Stream eli -> Iteratee eli m a)+ -> Maybe SomeException+ -> Iteratee elo m (Iteratee eli m a)+ )+ -> Enumeratee elo eli m a+eneeCheckIfDoneIgnore f = eneeCheckIfDoneHandle (\k _ -> f k Nothing) f+ -- | Convert one stream into another with the supplied mapping function. -- This function operates on whole chunks at a time, contrasting to -- @mapStream@ which operates on single elements.@@ -223,6 +279,17 @@ step k str@(EOF mErr) = idone (k $ EOF mErr) str {-# INLINE mapChunks #-} +-- | Convert a stream of @s@ to a stream of @s'@ using the supplied function.+mapChunksM+ :: (Monad m, NullPoint s, Nullable s)+ => (s -> m s')+ -> Enumeratee s s' m a+mapChunksM f = eneeCheckIfDone (liftI . step)+ where+ step k (Chunk xs) = lift (f xs) >>=+ eneeCheckIfDone (liftI . step) . k . Chunk+ step k str@(EOF mErr) = idone (k $ EOF mErr) str+{-# INLINE mapChunksM #-} -- |Convert one stream into another, not necessarily in lockstep. -- The transformer mapStream maps one element of the outer stream@@ -255,6 +322,27 @@ step acc k = f acc >>= \(acc', s') -> eneeCheckIfDone (check acc') . k . Chunk $ s' +unfoldConvStreamCheck+ :: (Monad m, Nullable elo, Monoid elo)+ => (((Stream eli -> Iteratee eli m a)+ -> Maybe SomeException+ -> Iteratee elo m (Iteratee eli m a)+ )+ -> Enumeratee elo eli m a+ )+ -> (acc -> Iteratee elo m (acc, eli))+ -> acc+ -> Enumeratee elo eli m a+unfoldConvStreamCheck checkDone f acc0 = checkDone (check acc0)+ where+ check acc k mX = isStreamFinished >>=+ maybe (step acc k mX) (idone (icont k mX) . EOF . Just)+ step acc k Nothing = f acc >>= \(acc', s') ->+ (checkDone (check acc') . k $ Chunk s')+ step acc k (Just ex) = throwRecoverableErr ex $ \str' ->+ let i = f acc >>= \(acc', s') ->+ (checkDone (check acc') . k $ Chunk s')+ in joinIM $ enumChunk str' i -- | Collapse a nested iteratee. The inner iteratee is terminated by @EOF@. -- Errors are propagated through the result.@@ -294,7 +382,7 @@ -- |Applies the iteratee to the given stream. This wraps 'enumEof', -- 'enumErr', and 'enumPure1Chunk', calling the appropriate enumerator -- based upon 'Stream'.-enumChunk :: (Monad m, Monoid s) => Stream s -> Enumerator s m a+enumChunk :: (Monad m) => Stream s -> Enumerator s m a enumChunk (Chunk xs) = enumPure1Chunk xs enumChunk (EOF Nothing) = enumEof enumChunk (EOF (Just e)) = enumErr e@@ -371,10 +459,9 @@ -- -- It passes a given list of elements to the iteratee in one chunk -- This enumerator does no IO and is useful for testing of base parsing-enumPure1Chunk :: (Monad m, Monoid s) => s -> Enumerator s m a-enumPure1Chunk str iter = runIter iter onDone onCont+enumPure1Chunk :: (Monad m) => s -> Enumerator s m a+enumPure1Chunk str iter = runIter iter idoneM onCont where- onDone a str' = idoneM a (Chunk str `mappend` str') onCont k Nothing = return $ k $ Chunk str onCont k e = return $ icont k e @@ -423,22 +510,24 @@ -- |Create an enumerator from a callback function with an exception handler. -- The exception handler is called if an iteratee reports an exception.-enumFromCallbackCatch ::- (IException e, Monad m, NullPoint s) =>- (st -> m (Either SomeException ((Bool, st), s)))+enumFromCallbackCatch+ :: (IException e, Monad m, NullPoint s)+ => (st -> m (Either SomeException ((Bool, st), s))) -> (e -> m (Maybe EnumException)) -> st -> Enumerator s m a enumFromCallbackCatch c handler = loop where loop st iter = runIter iter idoneM (onCont st)- onCont st k Nothing = c st >>=- either (return . k . EOF . Just) (uncurry check)- where- check (b,st') = if b then loop st' . k . Chunk else return . k . Chunk+ check k (True, st') = loop st' . k . Chunk+ check k (False,_st') = return . k . Chunk+ onCont st k Nothing = c st >>=+ either (return . k . EOF . Just) (uncurry (check k)) onCont st k j@(Just e) = case fromException e of- Just e' -> handler e' >>= maybe (loop st . k $ Chunk empty)- (return . icont k . Just) . fmap toException+ Just e' -> handler e' >>=+ maybe (loop st . k $ Chunk empty)+ (return . icont k . Just) . fmap toException Nothing -> return (icont k j) {-# INLINE enumFromCallbackCatch #-}+
src/Data/Iteratee/ListLike.hs view
@@ -30,6 +30,8 @@ ,breakE ,take ,takeUpTo+ ,takeWhile+ ,takeWhileE ,mapStream ,rigidMapStream ,filter@@ -64,7 +66,7 @@ ) where -import Prelude hiding (mapM_, null, head, last, drop, dropWhile, take, break, foldl, foldl1, length, filter, sum, product, zip, zip3, sequence_)+import Prelude hiding (mapM_, null, head, last, drop, dropWhile, take, takeWhile, break, foldl, foldl1, length, filter, sum, product, zip, zip3, sequence_) import qualified Prelude as Prelude @@ -412,7 +414,28 @@ {-# SPECIALIZE takeUpTo :: Monad m => Int -> Enumeratee B.ByteString B.ByteString m a #-} {-# INLINABLE takeUpTo #-} +-- | Takes an element predicate and returns the (possibly empty)+-- prefix of the stream. All characters+-- in the string will satisfy the character predicate. If the stream+-- is not terminated, the first character of the+-- remaining stream will not satisfy the predicate.+-- +-- The analogue of @List.takeWhile@, see also @break@ and @takeWhileE@+takeWhile :: (LL.ListLike s el, Monad m) => (el -> Bool) -> Iteratee s m s+takeWhile = break . (not .)+{-# INLINEABLE takeWhile #-} +-- |Takes an element predicate and an iteratee, running the iteratee+-- on all elements of the stream while the predicate is met.+-- +-- This is preferred to @takeWhile@.+takeWhileE+ :: (Monad m, LL.ListLike s el, NullPoint s)+ => (el -> Bool)+ -> Enumeratee s s m a+takeWhileE = breakE . (not .)+{-# INLINEABLE takeWhileE #-}+ -- |Map the stream: another iteratee transformer -- Given the stream of elements of the type @el@ and the function @(el->el')@, -- build a nested stream of elements of the type @el'@ and apply the@@ -481,9 +504,17 @@ | otherwise = let (full, rest) = gsplit . mconcat $ pfxd [s] pfxd' = if LL.null rest then id else (rest:)+ onDone x str = return $ Left (x,str)+ onCont k Nothing = return . Right . Left . k $ Chunk full+ onCont k e = return . Right $ Right (liftI k, e) in do- inext <- lift $ enumPure1Chunk full icur- liftI $ step (LL.length rest) pfxd' inext+ res <- lift $ runIter icur onDone onCont+ case res of+ Left (x,str) -> idone (idone x str) (Chunk rest)+ Right (Left inext) -> liftI $ step (LL.length rest) pfxd' inext+ Right (Right (inext, e)) -> icont (step (LL.length rest)+ pfxd' inext)+ e step _ pfxd icur mErr = case pfxd [] of [] -> idone icur mErr rest -> do@@ -521,8 +552,19 @@ -- accumulator. go icurr pfx (Chunk s) = case gsplit pfx s of ([], partial) -> liftI $ go icurr partial- (full, partial) -> do inext <- lift $ enumPure1Chunk full icurr- liftI $ go inext partial+ (full, partial) -> do+ -- if the inner iteratee is done, the outer iteratee needs to be+ -- notified to terminate.+ -- if the inner iteratee is in an error state, that error should+ -- be lifted to the outer iteratee+ let onCont k Nothing = return $ Right $ Left $ k $ Chunk full+ onCont k e = return $ Right $ Right (liftI k, e)+ onDone x str = return $ Left (x,str)+ res <- lift $ runIter icurr onDone onCont+ case res of+ Left (x,str) -> idone (idone x str) (Chunk (mconcat $ snd partial []))+ Right (Left inext) -> liftI $ go inext partial+ Right (Right (inext,e)) -> icont (go inext partial) e go icurr (_inpfx, pfxd) (EOF mex) = case pfxd [] of [] -> lift . enumChunk (EOF mex) $ icurr rest -> do inext <- lift . enumPure1Chunk [mconcat rest] $ icurr@@ -750,7 +792,6 @@ -> Iteratee s m (a, b) enumPair = zip - -- |Enumerate two iteratees over a single stream simultaneously. -- -- Compare to @List.zip@.@@ -759,25 +800,38 @@ => Iteratee s m a -> Iteratee s m b -> Iteratee s m (a, b)-zip x y = liftI step+zip x0 y0 = do+ -- need to check if both iteratees are initially finished. If so,+ -- we don't want to push a chunk which will be dropped+ (a', x') <- lift $ runIter x0 od oc+ (b', y') <- lift $ runIter y0 od oc+ case checkDone a' b' of+ Just (Right (a,b,s)) -> idone (a,b) s -- 's' may be EOF, needs to stay+ Just (Left (Left a)) -> liftM (a,) y'+ Just (Left (Right b)) -> liftM (,b) x'+ Nothing -> liftI (step x' y') where- step (Chunk xs) | nullC xs = liftI step- step (Chunk xs) = do+ step x y (Chunk xs) | nullC xs = liftI (step x y)+ step x y (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+ Just (Right (a,b,s)) -> idone (a,b) s+ Just (Left (Left a)) -> liftM (a,) y'+ Just (Left (Right b)) -> liftM (,b) x'+ Nothing -> liftI (step x' y')+ step x y (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)+ checkDone r1 r2 = case (r1, r2) of+ (Just (a, s1), Just (b,s2)) -> Just $ Right (a, b, shorter s1 s2)+ (Just (a, _), Nothing) -> Just . Left $ Left a+ (Nothing, Just (b, _)) -> Just . Left $ Right b+ (Nothing, Nothing) -> Nothing shorter c1@(Chunk xs) c2@(Chunk ys) | LL.length xs < LL.length ys = c1@@ -825,7 +879,17 @@ => Iteratee s m a -> Iteratee s m b -> Iteratee s m (a, b)-enumWith i1 i2 = go i1 i2+enumWith i1 i2 = do+ -- as with zip, first check to see if the initial iteratee is complete,+ -- otherwise data would be dropped.+ -- running the second iteratee as well to prevent a monadic effect mismatch+ -- although I think that would be highly unlikely to happen in common+ -- code+ (a', x') <- lift $ runIter i1 od oc+ (_, y') <- lift $ runIter i2 od oc+ case a' of+ Just (a, s) -> flip idone s =<< lift (liftM (a,) $ run i2)+ Nothing -> go x' y' where od a s = return (Just (a, s), idone a s) oc k e = return (Nothing , icont k e)
tests/QCUtils.hs view
@@ -43,7 +43,11 @@ ns <- arbitrary elements [ I.drop n >> stream2list+ ,I.drop n >> return ns ,I.break (< 5) ,I.heads ns >> stream2list ,I.peek >> stream2list+ ,I.peek >> return ns+ ,I.identity >> return []+ ,I.identity >> return ns ]
tests/benchmarkHandle.hs view
@@ -9,6 +9,7 @@ import Data.Monoid import Data.Word import Data.Iteratee+import Data.Iteratee.Parallel import Data.Iteratee.Base.ReadableChunk import Data.Iteratee.IO.Fd (fileDriverFd) import Data.Iteratee.IO.Handle (fileDriverHandle)
tests/benchmarks.hs view
@@ -6,6 +6,7 @@ import Data.Iteratee import qualified Data.Iteratee.ListLike as I+import qualified Data.Iteratee.Parallel as I import Data.Iteratee.ListLike (enumPureNChunk, stream2list, stream2stream) import Data.Word import Data.Monoid@@ -76,6 +77,7 @@ breakbench = makeGroup "break" $ break0 : break0' : breakBenches headsbench = makeGroup "heads" headsBenches dropbench = makeGroup "drop" $ drop0 : dropBenches+zipbench = makeGroup "zip" $ zipBenches lengthbench = makeGroup "length" listBenches takebench = makeGroup "take" $ take0 : takeBenches takeUpTobench = makeGroup "takeUpTo" takeUpToBenches@@ -90,6 +92,7 @@ breakbenchbs = makeGroupBS "break" breakBenches headsbenchbs = makeGroupBS "heads" headsBenches dropbenchbs = makeGroupBS "drop" dropBenches+zipbenchbs = makeGroupBS "zip" zipBenches lengthbenchbs = makeGroupBS "length" listBenches takebenchbs = makeGroupBS "take" takeBenches takeUpTobenchbs = makeGroupBS "takeUpTo" takeUpToBenches@@ -100,9 +103,9 @@ miscbenchbs = makeGroupBS "other" miscBenches -allListBenches = bgroup "list" [listbench, streambench, breakbench, headsbench, dropbench, lengthbench, takebench, takeUpTobench, groupbench, mapbench, foldbench, convbench, miscbench]+allListBenches = bgroup "list" [listbench, streambench, breakbench, headsbench, dropbench, zipbench, lengthbench, takebench, takeUpTobench, groupbench, mapbench, foldbench, convbench, miscbench] -allByteStringBenches = bgroup "bytestring" [listbenchbs, streambenchbs, breakbenchbs, headsbenchbs, dropbenchbs, lengthbenchbs, takebenchbs, takeUpTobenchbs, groupbenchbs, mapbenchbs, foldbenchbs, convbenchbs, miscbenchbs]+allByteStringBenches = bgroup "bytestring" [listbenchbs, streambenchbs, breakbenchbs, headsbenchbs, dropbenchbs, zipbenchbs, lengthbenchbs, takebenchbs, takeUpTobenchbs, groupbenchbs, mapbenchbs, foldbenchbs, convbenchbs, miscbenchbs] list0 = makeList "list one go" deepseq list1 = BDIter1 "stream2list one go" (flip deepseq ()) stream2list@@ -146,6 +149,14 @@ dropw3 = id1 "dropWhile small" (I.dropWhile ( < 100)) dropw4 = id1 "dropWhile large" (I.dropWhile ( < 6000)) dropBenches = [drop1, drop2, drop3, dropw1, dropw2, dropw3, dropw4]++b_zip0 = idN "zip balanced" (I.zip (I.dropWhile (<100)) (I.dropWhile (<200))+ >> identity)+b_zip1 = idN "zip unbalanced" (I.zip (I.dropWhile (<8000)) (I.head) >> identity)+b_zip2 = idN "zip unbalanced 2" (I.zip identity I.length >> identity)+b_zip3 = idN "zip complete" (I.zip identity identity >> identity)+b_zip4 = idN "zip nonterminating" (I.zip I.length I.stream2stream >> identity)+zipBenches = [b_zip0, b_zip1, b_zip2, b_zip3, b_zip4 ] l1 = makeList "length of list" Prelude.length
tests/testIteratee.hs view
@@ -150,17 +150,34 @@ prop_length xs = runner1 (enumPure1Chunk xs Iter.length) == P.length xs where types = xs :: [Int] +-- length 0 is an odd case. enumPureNChunk skips null inputs, returning+-- the original iteratee, which is then given to `enumEof` by `run`.+-- This is different from enumPure1Chunk, which will provide a null chunk+-- to the iteratee.+-- +-- not certain ATM which should be correct...+prop_chunkLength xs n = n > 0 ==>+ runner1 (enumPureNChunk xs n (liftM2 (,) chunkLength stream2list))+ == case P.length xs of+ 0 -> (Nothing, xs)+ xl | xl >= n -> (Just n, xs)+ | otherwise -> (Just (P.length xs), xs)+ where types = xs :: [Int]++prop_chunkLength2 xs =+ runner1 ((enumEof >=> enumPure1Chunk xs) chunkLength) == Nothing+ where types = xs :: [Int]++prop_takeFromChunk xs n k = n > 0 ==>+ runner1 (enumPureNChunk xs n (liftM2 (,) (takeFromChunk k) stream2list))+ == if k > n then splitAt n xs else splitAt k xs+ where types = xs :: [Int]+ -- --------------------------------------------- -- Simple enumerator tests type I = Iteratee [Int] Identity [Int] -prop_enumNoStream xs =- runIdentity (enumPure1Chunk xs (return 'a') >>= \i ->- Iter.run (i >> stream2list))- == xs- where types = xs :: [Int]- prop_enumChunks n xs i = n > 0 ==> runner1 (enumPure1Chunk xs i) == runner1 (enumSpecial xs n i) where types = (n :: Int, xs :: [Int], i :: I)@@ -195,6 +212,17 @@ == runner1 (enumPure1Chunk xs Iter.head) where types = xs :: [Int] +prop_enumList xs i =+ not (P.null xs) ==>+ runner1 (enumList (replicate 100 xs) i)+ == runner1 (enumPure1Chunk (concat $ replicate 100 xs) i)+ where types = (xs :: [Int], i :: I)++prop_enumCheckIfDone xs i =+ runner1 (enumPure1Chunk xs (lift (enumCheckIfDone i) >>= snd))+ == runner1 (enumPure1Chunk xs i)+ where types = (xs :: [Int], i :: I)+ -- --------------------------------------------- -- Enumerator Combinators @@ -206,7 +234,13 @@ == runner1 (enumSpecial xs n $ Iter.dropWhile f >> stream2list) where types = (xs :: [Int]) +prop_enumWith3 xs i n =+ n > 0+ ==> runner1 (enumSpecial xs n $ enumWith i stream2list >> stream2list)+ == runner1 (enumSpecial xs n (i >> stream2list))+ where types = (xs :: [Int], i :: I) + -- --------------------------------------------- -- Nested Iteratees @@ -305,6 +339,11 @@ == P.drop (min t d) xs where types = xs :: [Int] +prop_takeWhile xs n f = n > 0 ==>+ runner1 (enumSpecial xs n (liftM2 (,) (Iter.takeWhile f) stream2list))+ == (P.takeWhile f xs, P.dropWhile f xs)+ 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]@@ -324,18 +363,53 @@ == runner1 (enumPure1Chunk (List.groupBy pred xs) stream2list) where types = xs :: [Int] +prop_mapChunksM xs n = n > 0 ==>+ runWriter ((enumSpecial xs n (joinI $ Iter.mapChunksM f stream2list)) >>= run)+ == (xs, Sum (P.length xs))+ where f ck = tell (Sum $ P.length ck) >> return ck+ types = xs :: [Int]+{-+prop_mapjoin xs i =+ runIdentity (run (joinI . runIdentity $ enumPure1Chunk xs $ mapStream id i))+ == runner1 (enumPure1Chunk xs i)+ where types = (i :: I, xs :: [Int])+-}++prop_mapChunksM_ xs n = n > 0 ==>+ snd (runWriter ((enumSpecial xs n (Iter.mapChunksM_ f)) >>= run))+ == Sum (P.length xs)+ where f ck = tell (Sum $ P.length ck)+ types = xs :: [Int]+ 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_foldChunksM xs x0 n = n > 0 ==>+ runWriter ((enumSpecial xs n (Iter.foldChunksM f x0)) >>= run)+ == runWriter (f x0 xs)+ where f acc ck = CM.foldM f' acc ck+ f' acc el = tell (Sum 1) >> return (acc+el)+ 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]+-- ---------------------------------------------+-- Zips +prop_zip xs i1 i2 n = n > 0 ==>+ runner1 (enumPureNChunk xs n $ liftM2 (,) (Iter.zip i1 i2) stream2list)+ == let (r1, t1) = runner1 $ enumPure1Chunk xs $ liftM2 (,) i1 stream2list+ (r2, t2) = runner1 $ enumPure1Chunk xs $ liftM2 (,) i2 stream2list+ shorter = if P.length t1 > P.length t2 then t2 else t1+ in ((r1,r2), shorter)+ where types = (i1 :: I, i2 :: I, xs :: [Int])+ -- --------------------------------------------- -- Data.Iteratee.Char @@ -375,6 +449,9 @@ ,testProperty "last" prop_last1 ,testProperty "last ends properly" prop_last2 ,testProperty "length" prop_length+ ,testProperty "chunkLength" prop_chunkLength+ ,testProperty "chunkLength of EoF" prop_chunkLength2+ ,testProperty "takeFromChunk" prop_takeFromChunk ,testProperty "drop" prop_drop ,testProperty "dropWhile" prop_dropWhile ,testProperty "skipToEof" prop_skip@@ -385,8 +462,7 @@ ,testProperty "iteratee Monad Assc" prop_iterMonad3 ] ,testGroup "Simple Enumerators/Combinators" [- testProperty "enumPure1Chunk - final stream state" prop_enumNoStream- ,testProperty "enumPureNChunk" prop_enumChunks+ testProperty "enumPureNChunk" prop_enumChunks ,testProperty "enum append 1" prop_app1 ,testProperty "enum sequencing" prop_app2 ,testProperty "enum sequencing 2" prop_app3@@ -395,6 +471,8 @@ ,testProperty "isFinished error" prop_isFinished2 ,testProperty "null data idempotence" prop_null ,testProperty "null data head idempotence" prop_nullH+ ,testProperty "enumList" prop_enumList+ ,testProperty "enumCheckIfDone" prop_enumCheckIfDone ] ,testGroup "Nested iteratees" [ testProperty "mapStream identity" prop_mapStream@@ -408,6 +486,7 @@ ,testProperty "takeUpTo" prop_takeUpTo ,testProperty "takeUpTo (finished iteratee)" prop_takeUpTo2 ,testProperty "takeUpTo (remaining stream)" prop_takeUpTo3+ ,testProperty "takeWhile" prop_takeWhile ,testProperty "filter" prop_filter ,testProperty "group" prop_group ,testProperty "groupBy" prop_groupBy@@ -418,6 +497,7 @@ ,testGroup "Enumerator Combinators" [ testProperty "enumWith" prop_enumWith ,testProperty "enumWith remaining" prop_enumWith2+ ,testProperty "enumWith remaining 2" prop_enumWith3 ] ,testGroup "Folds" [ testProperty "foldl" prop_foldl@@ -427,12 +507,18 @@ ,testProperty "sum" prop_sum ,testProperty "product" prop_product ]+ ,testGroup "Zips" [+ testProperty "zip" prop_zip+ ] ,testGroup "Data.Iteratee.Char" [ --testProperty "line" prop_line ] ,testGroup "Monadic functions" [ testProperty "mapM_" prop_mapM_ ,testProperty "foldM" prop_foldM+ ,testProperty "mapChunksM" prop_mapChunksM+ ,testProperty "mapChunksM_" prop_mapChunksM_+ ,testProperty "foldChunksM" prop_foldChunksM ] ]