packages feed

iteratee 0.8.0.1 → 0.8.0.2

raw patch · 5 files changed

+86/−17 lines, 5 filesPVP: minor bump suggested

API additions: PVP suggests at least a minor version bump

API changes (from Hackage documentation)

+ Data.Iteratee.ListLike: group :: (ListLike s el, Monad m, Nullable s) => Int -> Enumeratee s [s] m a
+ Data.Iteratee.ListLike: groupBy :: (ListLike s el, Monad m, Nullable s) => (el -> el -> Bool) -> Enumeratee s [s] m a

Files

CONTRIBUTORS view
@@ -2,6 +2,7 @@  Oleg Kiselyov Gregory Collins+Nick Ingolia Brian Lewis John Lato Antoine Latter
iteratee.cabal view
@@ -1,5 +1,5 @@ name:          iteratee-version:       0.8.0.1+version:       0.8.0.2 synopsis:      Iteratee-based I/O description:   The Iteratee monad provides strict, safe, and functional I/O. In addition
src/Data/Iteratee/ListLike.hs view
@@ -29,6 +29,8 @@   ,mapStream   ,rigidMapStream   ,filter+  ,group+  ,groupBy   -- ** Folds   ,foldl   ,foldl'@@ -362,6 +364,59 @@       | True       = idone (LL.filter p xs) mempty     step _ = f' {-# INLINE filter #-}++-- |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 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+                          | otherwise    -> do inext <- lift $ enumPure1Chunk full icurr+                                               liftI $ go inext partial+        go icurr pfx (EOF mex) +          | LL.null pfx = lift . enumChunk (EOF mex) $ icurr+          | otherwise = do inext <- lift $ enumPure1Chunk (LL.singleton pfx) icurr        +                           lift . enumChunk (EOF mex) $ inext+        gsplit ls = case LL.splitAt sz ls of+          (g, rest) | LL.null rest -> if LL.length g == sz+                                         then (LL.singleton g, LL.empty)+                                         else (LL.empty, g)+                    | otherwise -> let (grest, leftover) = gsplit rest+                                       g' = g `LL.cons` grest+                                   in g' `seq` (g', leftover)+{-# INLINE group #-}++-- |Creates an 'enumeratee' in which elements are grouped into+-- contiguous blocks that are equal according to a predicate.+-- +-- The analogue of @List.groupBy#+          +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)+                                              | LL.null full -> liftI $ go icurr partial+                                              | otherwise -> do inext <- lift . enumPure1Chunk full $ icurr+                                                                liftI $ go inext partial+          go icurr pfx (EOF mex) +            | LL.null pfx = lift . enumChunk (EOF mex) $ icurr+            | otherwise = do inext <- lift . enumPure1Chunk (LL.singleton pfx) $ icurr+                             lift . enumChunk (EOF mex) $ inext+          gsplit ll | LL.null ll = (LL.empty, LL.empty)+                    | otherwise = let groups = llGroupBy same ll+                                      full = LL.init groups+                                      partial = LL.last groups+                                  in full `seq` partial `seq` (full, partial)+          llGroupBy eq l -- Copied from Data.ListLike, avoid spurious (Eq el) constraint+              | LL.null l = LL.empty+              | otherwise = LL.cons (LL.cons x ys) (llGroupBy eq zs)+              where (ys, zs) = LL.span (eq x) xs+                    x = LL.head l+                    xs = LL.tail l+{-# INLINE groupBy #-}  -- ------------------------------------------------------------------------ -- Folds
tests/benchmarks.hs view
@@ -77,8 +77,7 @@ dropbench = makeGroup "drop" $ drop0 : dropBenches lengthbench = makeGroup "length" listBenches takebench = makeGroup "take" $ take0 : takeBenches---takeRbench = makeGroup "takeR" $ takeR0 : takeRBenches-takeRbench = makeGroup "takeR" []+takeUpTobench = makeGroup "takeUpTo" takeUpToBenches mapbench = makeGroup "map" $ mapBenches convbench = makeGroup "convStream" convBenches miscbench = makeGroup "other" miscBenches@@ -90,15 +89,15 @@ dropbenchbs = makeGroupBS "drop" dropBenches lengthbenchbs = makeGroupBS "length" listBenches takebenchbs = makeGroupBS "take" takeBenches-takeRbenchbs = makeGroupBS "takeR" takeRBenches+takeUpTobenchbs = makeGroupBS "takeUpTo" takeUpToBenches mapbenchbs = makeGroupBS "map" mapBenches convbenchbs = makeGroupBS "convStream" convBenches miscbenchbs = makeGroupBS "other" miscBenches  -allListBenches = bgroup "list" [listbench, streambench, breakbench, headsbench, dropbench, lengthbench, takebench, takeRbench, mapbench, convbench, miscbench]+allListBenches = bgroup "list" [listbench, streambench, breakbench, headsbench, dropbench, lengthbench, takebench, takeUpTobench, mapbench, convbench, miscbench] -allByteStringBenches = bgroup "bytestring" [listbenchbs, streambenchbs, breakbenchbs, headsbenchbs, dropbenchbs, lengthbenchbs, takebenchbs, takeRbenchbs, mapbenchbs, convbenchbs, miscbenchbs]+allByteStringBenches = bgroup "bytestring" [listbenchbs, streambenchbs, breakbenchbs, headsbenchbs, dropbenchbs, lengthbenchbs, takebenchbs, takeUpTobenchbs, mapbenchbs, convbenchbs, miscbenchbs]  list0 = makeList "list one go" deepseq list1 = BDIter1 "stream2list one go" (flip deepseq ()) stream2list@@ -158,17 +157,13 @@ take6 = idN "take length long chunked" (I.joinI $ I.take 1000 I.length) takeBenches = [take1, take2, take3, take4, take5, take6] -{--takeR0 = makeList "take length of list long" (Prelude.length . Prelude.take 1000)-takeR1 = id1 "takeR head short one go" (I.joinI $ I.take 20 I.head)-takeR2 = id1 "takeR head long one go" (I.joinI $ I.takeR 1000 I.head)-takeR3 = idN "takeR head short chunked" (I.joinI $ I.takeR 20 I.head)-takeR4 = idN "takeR head long chunked" (I.joinI $ I.takeR 1000 I.head)-takeR5 = id1 "takeR length long one go" (I.joinI $ I.takeR 1000 I.length)-takeR6 = idN "takeR length long chunked" (I.joinI $ I.takeR 1000 I.length)-takeRBenches = [takeR1, takeR2, takeR3, takeR4, takeR5, takeR6]--}-takeRBenches = []+takeUpTo1 = id1 "takeUpTo head short one go" (I.joinI $ I.take 20 I.head)+takeUpTo2 = id1 "takeUpTo head long one go" (I.joinI $ I.takeUpTo 1000 I.head)+takeUpTo3 = idN "takeUpTo head short chunked" (I.joinI $ I.takeUpTo 20 I.head)+takeUpTo4 = idN "takeUpTo head long chunked" (I.joinI $ I.takeUpTo 1000 I.head)+takeUpTo5 = id1 "takeUpTo length long one go" (I.joinI $ I.takeUpTo 1000 I.length)+takeUpTo6 = idN "takeUpTo length long chunked" (I.joinI $ I.takeUpTo 1000 I.length)+takeUpToBenches = [takeUpTo1, takeUpTo2, takeUpTo3, takeUpTo4, takeUpTo5, takeUpTo6]  map1 = id1 "map length one go" (I.joinI $ I.rigidMapStream id I.length) map2 = idN "map length chunked" (I.joinI $ I.rigidMapStream id I.length)
tests/testIteratee.hs view
@@ -14,6 +14,7 @@ import qualified Data.Iteratee.Char as IC import qualified Data.Iteratee as Iter import Data.Functor.Identity+import qualified Data.List as List (groupBy, unfoldr) import Data.Monoid import qualified Data.ListLike as LL @@ -216,6 +217,21 @@                   == runner2 (enumPure1Chunk xs $ takeUpTo n stream2list)   where types = xs :: [Int] +prop_group xs n = n > 0 ==>+                  runner2 (enumPure1Chunk xs $ Iter.group n stream2list)+                  == runner1 (enumPure1Chunk groups stream2list)+  where types = xs :: [Int]+        groups :: [[Int]]+        groups = List.unfoldr groupOne xs+          where groupOne [] = Nothing+                groupOne elts@(_:_) = Just . splitAt n $ elts+                           +prop_groupBy xs m = m > 0 ==>+                  runner2 (enumPure1Chunk xs $ Iter.groupBy pred stream2list)+                  == runner1 (enumPure1Chunk (List.groupBy pred xs) stream2list)+  where types = xs :: [Int]+        pred z1 z2 = (z1 `mod` m == z2 `mod` m)+ -- --------------------------------------------- -- Data.Iteratee.Char @@ -276,6 +292,8 @@     ,testProperty "take" prop_take     ,testProperty "take (finished iteratee)" prop_take2     ,testProperty "takeUpTo" prop_takeUpTo+    ,testProperty "group" prop_group+    ,testProperty "groupBy" prop_groupBy     ,testProperty "convStream EOF" prop_convstream2     ,testProperty "convStream identity" prop_convstream     ,testProperty "convStream identity 2" prop_convstream3