on master help sign in
Use unfolds instead of streams for array reading
commit58d1d61afd428df37c58f416aa2d65858e0a98b8 authorHarendra Kumar <harendra.kumar@gmail.com> dateSun 29 Sep 2019, 20:49 (7 years ago) parenta5b8b07
16 files changed+101−89
Changelog.md+4−4 benchmark/Array.hs+3−2 benchmark/ArrayOps.hs+2−2 examples/FileSinkServer.hs+1−1 examples/WordClassifier.hs+4−3 src/Streamly/Benchmark/FileIO/Array.hs+2−1 src/Streamly/Benchmark/FileIO/Stream.hs+3−3 src/Streamly/Benchmark/Prelude.hs+1−1 src/Streamly/Data/String.hs+2−3 src/Streamly/Internal/Memory/Array.hs+58−11 src/Streamly/Internal/Memory/Array/Types.hs−40 src/Streamly/Internal/Memory/ArrayStream.hs+4−3 src/Streamly/Internal/Prelude.hs+8−7 src/Streamly/Memory/Array.hs−1 src/Streamly/Prelude.hs+2 test/Arrays.hs+7−7
Changelog.md+4−4
@@ -30,7 +30,8 @@
3030 add newlines to a stream, `Streamly.Data.String.encodeUtf8` for encoding and
3131 `Streamly.FileSystem.Handle.write` for writing to a file handle.
3232 * Deprecate `scanx`, `foldx`, `foldxM`, `foldr1`
33− * Remove deprecated APIs `scan`, `foldl`, `foldlM`
33+ * Remove deprecated APIs `foldl`, `foldlM`
34+ * Replace deprecated API `scan` with a new signature, to scan using Fold.
3435
3536* In `Streamly` module:
3637 * `runStream` has been deprecated, please use `Streamly.Prelude.drain`
@@ -87,11 +88,10 @@ example, concat streams concurrently using this.
8788 character streams and other character stream operations.
8889 * _Arrays_: `Streamly.Memory.Array` module provides arrays for efficient
8990 in-memory buffering and efficient interfacing with IO.
90− * `Streamly.Memory.ArrayStream` module provide combinators to work on streams
91− of arrays.
9291
9392* Add the following to `Streamly.Prelude`:
94− * `runFold`, `runScan` and `runPostscan`
93+ * `unfold`, `fold`, `scan` and `postscan`
94+ * `concatUnfold` to concat a stream after unfolding each element
9595 * `intervalsOf` and `chunksOf`
9696 * `splitOn`, `splitOnSuffix`, `splitWithSuffix`, and `wordsBy`
9797 * `groups`, `groupsBy` and `groupsByRolling`
benchmark/Array.hs+3−2
@@ -13,6 +13,7 @@ import System.Random (randomRIO)
1313import qualified GHC.Exts as GHC
1414
1515import qualified ArrayOps as Ops
16+import qualified Streamly.Internal.Memory.Array as IA
1617import qualified Streamly.Memory.Array as A
1718import qualified Streamly.Prelude as S
1819
@@ -87,8 +88,8 @@ main =
8788 , benchPureSink "min" Ops.ordInstanceMin
8889 , benchPureSink "IsList.toList" GHC.toList
8990 , benchIOSink "foldl'" Ops.pureFoldl'
90− , benchIOSink "read" (S.drain . A.read)
91− , benchIOSink "readRev" (S.drain . A.readRev)
91+ , benchIOSink "read" (S.drain . S.unfold A.read)
92+ , benchIOSink "toStreamRev" (S.drain . IA.toStreamRev)
9293#ifdef DEVBUILD
9394 , benchPureSink "foldable/foldl'" Ops.foldableFoldl'
9495 , benchPureSink "foldable/sum" Ops.foldableSum
benchmark/ArrayOps.hs+2−2
@@ -280,7 +280,7 @@ onArray
280280 :: MonadIO m => (S.SerialT m Int -> S.SerialT m Int)
281281 -> Stream Int
282282 -> m (Stream Int)
283−onArray f arr = S.fold (A.writeN value) $ f $ A.read arr
283+onArray f arr = S.fold (A.writeN value) $ f $ (S.unfold A.read arr)
284284
285285scanl' n = composeN n $ onArray $ S.scanl' (+) 0
286286scanl1' n = composeN n $ onArray $ S.scanl1' (+)
@@ -511,7 +511,7 @@ readInstance str =
511511
512512{-# INLINE pureFoldl' #-}
513513pureFoldl' :: MonadIO m => Stream Int -> m Int
514−pureFoldl' = S.foldl' (+) 0 . A.read
514+pureFoldl' = S.foldl' (+) 0 . S.unfold A.read
515515
516516#ifdef DEVBUILD
517517{-# INLINE foldableFoldl' #-}
examples/FileSinkServer.hs+1−1
@@ -23,7 +23,7 @@ main = do
2323 withFile file AppendMode
2424 (\src -> S.fold (FH.write src)
2525 $ encodeChar8Unchecked
26− $ S.concatMap A.read
26+ $ S.concatUnfold A.read
2727 $ S.concatMapWith parallel (flip NS.withSocketS recv)
2828 $ NS.connectionsOnAllAddrs 8090)
2929
examples/WordClassifier.hs+4−3
@@ -19,16 +19,17 @@ import Foreign.Storable (Storable(..))
1919import qualified Streamly.Data.String as Streamly
2020import qualified Streamly.FileSystem.Handle as FH
2121import qualified Streamly.Data.Fold as FL
22−import qualified Streamly.Internal.Data.Fold as Internal
22+import qualified Streamly.Internal.Data.Fold as IFL
23+import qualified Streamly.Internal.Data.Unfold as IUF
2324import qualified Streamly.Memory.Array as A
2425import qualified Streamly.Prelude as Streamly
2526import System.Environment (getArgs)
2627import System.IO (openFile, IOMode(..))
2728
2829instance (Enum a, Storable a) => Hashable (A.Array a) where
29− hash arr = runIdentity $ Streamly.fold Internal.rollingHash (A.read arr)
30+ hash arr = runIdentity $ IUF.fold A.read IFL.rollingHash arr
3031 hashWithSalt salt arr = runIdentity $
31− Streamly.fold (Internal.rollingHashWithSalt salt) (A.read arr)
32+ IUF.fold A.read (IFL.rollingHashWithSalt salt) arr
3233
3334{-# INLINE toLower #-}
3435toLower :: Char -> Char
src/Streamly/Benchmark/FileIO/Array.hs+2−1
@@ -44,6 +44,7 @@ import qualified Streamly.Memory.Array as A
4444import qualified Streamly.Prelude as S
4545import qualified Streamly.Data.String as SS
4646import qualified Streamly.Internal.Prelude as Internal
47+import qualified Streamly.Internal.Memory.Array as IA
4748import qualified Streamly.Internal.Memory.ArrayStream as AS
4849
4950#ifdef INSPECTION
@@ -104,7 +105,7 @@ inspect $ 'countWords `hasNoType` ''Step
104105{-# INLINE sumBytes #-}
105106sumBytes :: Handle -> IO Word8
106107sumBytes inh = do
107− let foldlArr' f z = runIdentity . S.foldl' f z . A.read
108+ let foldlArr' f z = runIdentity . S.foldl' f z . IA.toStream
108109 let s = FH.readArrays inh
109110 S.foldl' (\acc arr -> acc + foldlArr' (+) 0 arr) 0 s
110111
src/Streamly/Benchmark/FileIO/Stream.hs+3−3
@@ -135,7 +135,7 @@ countLinesU inh =
135135 S.length
136136 $ SS.foldLines FL.drain
137137 $ SS.decodeChar8
138− $ IP.concatMapU AT.readU (FH.readArrays inh)
138+ $ S.concatUnfold A.read (FH.readArrays inh)
139139
140140#ifdef INSPECTION
141141inspect $ hasNoTypeClasses 'countLinesU
@@ -344,7 +344,7 @@ isSp = isSpace . chr . fromIntegral
344344wordsUnwordsCopyWord8 :: Handle -> Handle -> IO ()
345345wordsUnwordsCopyWord8 inh outh =
346346 S.fold (FH.write outh)
347− $ IP.concatMapU IUF.fromList
347+ $ S.concatUnfold IUF.fromList
348348 $ S.intersperse [32]
349349 $ S.wordsBy isSp FL.toList
350350 $ FH.read inh
@@ -361,7 +361,7 @@ wordsUnwordsCopy :: Handle -> Handle -> IO ()
361361wordsUnwordsCopy inh outh =
362362 S.fold (FH.write outh)
363363 $ SS.encodeChar8
364− $ IP.concatMapU IUF.fromList
364+ $ S.concatUnfold IUF.fromList
365365 $ S.intersperse " "
366366 -- Array allocation is too expensive for such small strings. So just use
367367 -- lists instead.
src/Streamly/Benchmark/Prelude.hs+1−1
@@ -720,7 +720,7 @@ inspect $ hasNoTypeClasses 'concatMapRepl4xN
720720{-# INLINE concatUnfoldRepl4xN #-}
721721concatUnfoldRepl4xN :: Int -> IO ()
722722concatUnfoldRepl4xN n =
723− S.drain $ Internal.concatMapU
723+ S.drain $ S.concatUnfold
724724 (UF.replicateM 4)
725725 (sourceUnfoldrMN (value `div` 4) n)
726726
src/Streamly/Data/String.hs+2−3
@@ -95,7 +95,6 @@ import Streamly.Internal.Data.Unfold (Unfold)
9595
9696import qualified Streamly.Internal.Prelude as S
9797import qualified Streamly.Memory.Array as A
98−import qualified Streamly.Internal.Memory.Array.Types as A
9998import qualified Streamly.Internal.Memory.ArrayStream as AS
10099import qualified Streamly.Streams.StreamD as D
101100import qualified Streamly.Internal.Data.Unfold as UF
@@ -284,14 +283,14 @@ unfoldLines unf = S.intercalateSuffix UF.singleton '\n' unf
284283-- >>> S.toList $ unlines $ S.fromList ["lines", "this", "string"]
285284-- "lines\nthis\nstring\n"
286285--
287−-- > unlines = unfoldLines A.readU
286+-- > unlines = unfoldLines A.read
288287--
289288-- Note that, in general
290289--
291290-- > unlines . lines /= id
292291{-# INLINE unlines #-}
293292unlines :: (MonadIO m, IsStream t) => t m (Array Char) -> t m Char
294−unlines = unfoldLines A.readU
293+unlines = unfoldLines A.read
295294
296295-- | Flattens the stream of @Array Char@, after appending a separating
297296-- space to each string.
src/Streamly/Internal/Memory/Array.hs+58−11
@@ -64,8 +64,9 @@ module Streamly.Internal.Memory.Array
6464 -- list.
6565
6666 , A.toList
67− , A.read
68− , readRev
67+ , toStream
68+ , toStreamRev
69+ , read
6970
7071 -- * Random Access
7172 , length
@@ -96,19 +97,25 @@ where
9697
9798import Control.Monad.IO.Class (MonadIO(..))
9899-- import Data.Functor.Identity (Identity)
99−import Foreign.ForeignPtr (withForeignPtr)
100+import Foreign.ForeignPtr (withForeignPtr, touchForeignPtr)
101+import Foreign.Ptr (plusPtr)
100102import Foreign.Storable (Storable(..))
101103import Prelude hiding (length, null, last, map, (!!), read, concat)
102104
105+import GHC.ForeignPtr (ForeignPtr(..))
106+import GHC.Ptr (Ptr(..))
107+
108+import Streamly.Internal.Data.Fold.Types (Fold(..))
109+import Streamly.Internal.Data.Unfold.Types (Unfold(..))
103110import Streamly.Internal.Memory.Array.Types (Array(..), length)
104111import Streamly.Streams.Serial (SerialT)
105112import Streamly.Streams.StreamK.Type (IsStream)
106−import Streamly.Internal.Data.Fold.Types (Fold(..))
107113
108114import qualified Streamly.Internal.Memory.Array.Types as A
109115import qualified Streamly.Streams.Prelude as P
110116import qualified Streamly.Streams.Serial as Serial
111117import qualified Streamly.Streams.StreamD as D
118+import qualified Streamly.Streams.StreamK as K
112119
113120-------------------------------------------------------------------------------
114121-- Construction
@@ -151,16 +158,56 @@ fromStream = P.runFold A.write
151158-- Elimination
152159-------------------------------------------------------------------------------
153160
161+-- | Convert an 'Array' into a stream.
162+--
163+-- /Internal/
164+{-# INLINE_EARLY toStream #-}
165+toStream :: (Monad m, K.IsStream t, Storable a) => Array a -> t m a
166+toStream = D.fromStreamD . A.toStreamD
167+-- XXX add fallback to StreamK rule
168+-- {-# RULES "Streamly.Array.read fallback to StreamK" [1]
169+-- forall a. S.readK (read a) = K.fromArray a #-}
170+
154171-- | Convert an 'Array' into a stream in reverse order.
155172--
156−-- @since 0.7.0
157−{-# INLINE_EARLY readRev #-}
158−readRev :: (Monad m, IsStream t, Storable a) => Array a -> t m a
159−readRev = D.fromStreamD . A.toStreamDRev
173+-- /Internal/
174+{-# INLINE_EARLY toStreamRev #-}
175+toStreamRev :: (Monad m, IsStream t, Storable a) => Array a -> t m a
176+toStreamRev = D.fromStreamD . A.toStreamDRev
160177-- XXX add fallback to StreamK rule
161178-- {-# RULES "Streamly.Array.readRev fallback to StreamK" [1]
162179-- forall a. S.toStreamK (readRev a) = K.revFromArray a #-}
163180
181+data ReadUState a = ReadUState
182+ {-# UNPACK #-} !(ForeignPtr a) -- foreign ptr with end of array pointer
183+ {-# UNPACK #-} !(Ptr a) -- current pointer
184+
185+-- | Unfold an array into a stream.
186+--
187+-- @since 0.7.0
188+{-# INLINE_NORMAL read #-}
189+read :: forall m a. (Monad m, Storable a) => Unfold m (Array a) a
190+read = Unfold step inject
191+ where
192+
193+ inject (Array (ForeignPtr start contents) (Ptr end) _) =
194+ return $ ReadUState (ForeignPtr end contents) (Ptr start)
195+
196+ {-# INLINE_LATE step #-}
197+ step (ReadUState fp@(ForeignPtr end _) p) | p == (Ptr end) =
198+ let x = A.unsafeInlineIO $ touchForeignPtr fp
199+ in x `seq` return D.Stop
200+ step (ReadUState fp p) = do
201+ -- unsafeInlineIO allows us to run this in Identity monad for pure
202+ -- toList/foldr case which makes them much faster due to not
203+ -- accumulating the list and fusing better with the pure consumers.
204+ --
205+ -- This should be safe as the array contents are guaranteed to be
206+ -- evaluated/written to before we peek at them.
207+ let !x = A.unsafeInlineIO $ peek p
208+ return $ D.Yield x
209+ (ReadUState fp (p `plusPtr` (sizeOf (undefined :: a))))
210+
164211-- | > null arr = length arr == 0
165212--
166213-- /Internal/
@@ -375,18 +422,18 @@ streamTransform :: forall m a b. (MonadIO m, Storable a, Storable b)
375422 => (SerialT m a -> SerialT m b) -> Array a -> m (Array b)
376423streamTransform f arr =
377424 P.runFold (A.toArrayMinChunk (alignment (undefined :: a)) (length arr))
378− $ f (A.read arr)
425+ $ f (toStream arr)
379426
380427-- | Fold an array using a 'Fold'.
381428--
382429-- /Internal/
383430{-# INLINE fold #-}
384431fold :: forall m a b. (MonadIO m, Storable a) => Fold m a b -> Array a -> m b
385−fold f arr = P.runFold f $ (A.read arr :: Serial.SerialT m a)
432+fold f arr = P.runFold f $ (toStream arr :: Serial.SerialT m a)
386433
387434-- | Fold an array using a stream fold operation.
388435--
389436-- /Internal/
390437{-# INLINE streamFold #-}
391438streamFold :: (MonadIO m, Storable a) => (SerialT m a -> m b) -> Array a -> m b
392−streamFold f arr = f (A.read arr)
439+streamFold f arr = f (toStream arr)
src/Streamly/Internal/Memory/Array/Types.hs−40
@@ -68,8 +68,6 @@ module Streamly.Internal.Memory.Array.Types
6868 , writeNUnsafe
6969 , write
7070 , writeAligned
71− , read
72− , readU
7371
7472 -- * Utilities
7573 , defaultChunkSize
@@ -111,7 +109,6 @@ import GHC.IO (IO(IO), unsafePerformIO)
111109import GHC.Ptr (Ptr(..))
112110
113111import Streamly.Internal.Data.Fold.Types (Fold(..))
114−import Streamly.Internal.Data.Unfold.Types (Unfold(..))
115112import Streamly.Internal.Data.Strict (Tuple'(..))
116113import Streamly.Internal.Data.SVar (adaptState)
117114
@@ -407,33 +404,6 @@ byteCapacity Array{..} =
407404 len = aBound `minusPtr` p
408405 in assert (len >= 0) len
409406
410−data ReadUState a = ReadUState
411− {-# UNPACK #-} !(ForeignPtr a) -- foreign ptr with end of array pointer
412− {-# UNPACK #-} !(Ptr a) -- current pointer
413−
414−{-# INLINE_NORMAL readU #-}
415−readU :: forall m a. (Monad m, Storable a) => Unfold m (Array a) a
416−readU = Unfold step inject
417− where
418−
419− inject (Array (ForeignPtr start contents) (Ptr end) _) =
420− return $ ReadUState (ForeignPtr end contents) (Ptr start)
421−
422− {-# INLINE_LATE step #-}
423− step (ReadUState fp@(ForeignPtr end _) p) | p == (Ptr end) =
424− let x = unsafeInlineIO $ touchForeignPtr fp
425− in x `seq` return D.Stop
426− step (ReadUState fp p) = do
427− -- unsafeInlineIO allows us to run this in Identity monad for pure
428− -- toList/foldr case which makes them much faster due to not
429− -- accumulating the list and fusing better with the pure consumers.
430− --
431− -- This should be safe as the array contents are guaranteed to be
432− -- evaluated/written to before we peek at them.
433− let !x = unsafeInlineIO $ peek p
434− return $ D.Yield x
435− (ReadUState fp (p `plusPtr` (sizeOf (undefined :: a))))
436−
437407{-# INLINE_NORMAL toStreamD #-}
438408toStreamD :: forall m a. (Monad m, Storable a) => Array a -> D.Stream m a
439409toStreamD Array{..} =
@@ -905,16 +875,6 @@ instance Foldable Array where
905875 foldr = _foldr
906876#endif
907877
908−-- | Convert an 'Array' into a stream.
909−--
910−-- @since 0.7.0
911−{-# INLINE_EARLY read #-}
912−read :: (Monad m, K.IsStream t, Storable a) => Array a -> t m a
913−read = D.fromStreamD . toStreamD
914−-- XXX add fallback to StreamK rule
915−-- {-# RULES "Streamly.Array.read fallback to StreamK" [1]
916−-- forall a. S.readK (read a) = K.fromArray a #-}
917−
918878-------------------------------------------------------------------------------
919879-- Semigroup and Monoid
920880-------------------------------------------------------------------------------
src/Streamly/Internal/Memory/ArrayStream.hs+4−3
@@ -52,6 +52,7 @@ import Streamly.Streams.Serial (SerialT)
5252import Streamly.Streams.StreamK.Type (IsStream)
5353
5454import qualified Streamly.Internal.Data.Unfold as UF
55+import qualified Streamly.Internal.Memory.Array as A
5556import qualified Streamly.Internal.Memory.Array.Types as A
5657import qualified Streamly.Internal.Prelude as S
5758import qualified Streamly.Streams.StreamD as D
@@ -72,7 +73,7 @@ import qualified Streamly.Streams.Prelude as P
7273concat :: (IsStream t, MonadIO m, Storable a) => t m (Array a) -> t m a
7374-- concat m = D.fromStreamD $ A.flattenArrays (D.toStreamD m)
7475-- concat m = D.fromStreamD $ D.concatMap A.toStreamD (D.toStreamD m)
75−concat m = D.fromStreamD $ D.concatMapU A.readU (D.toStreamD m)
76+concat m = D.fromStreamD $ D.concatMapU A.read (D.toStreamD m)
7677
7778-- XXX should we have a reverseArrays API to reverse the stream of arrays
7879-- instead?
@@ -88,7 +89,7 @@ concatRev m = D.fromStreamD $ A.flattenArraysRev (D.toStreamD m)
8889{-# INLINE intercalateSuffix #-}
8990intercalateSuffix :: (MonadIO m, IsStream t, Storable a)
9091 => Array a -> t m (Array a) -> t m a
91−intercalateSuffix arr = S.intercalateSuffix A.readU arr A.readU
92+intercalateSuffix arr = S.intercalateSuffix A.read arr A.read
9293
9394-- | Flatten a stream of arrays appending the given element after each
9495-- array.
@@ -98,7 +99,7 @@ intercalateSuffix arr = S.intercalateSuffix A.readU arr A.readU
9899interposeSuffix :: (MonadIO m, IsStream t, Storable a)
99100 => a -> t m (Array a) -> t m a
100101-- interposeSuffix x = D.fromStreamD . A.unlines x . D.toStreamD
101−interposeSuffix x = S.intercalateSuffix UF.singleton x A.readU
102+interposeSuffix x = S.intercalateSuffix UF.singleton x A.read
102103
103104-- | Split a stream of arrays on a given separator byte, dropping the separator
104105-- and coalescing all the arrays between two separators into a single array.
src/Streamly/Internal/Prelude.hs+8−7
@@ -248,7 +248,7 @@ module Streamly.Internal.Prelude
248248
249249 -- ** Nested Streams
250250 , concatMapM
251− , concatMapU
251+ , concatUnfold
252252 , concatUnfoldInterleave
253253 , concatUnfoldRoundrobin
254254 , concatMap
@@ -426,7 +426,7 @@ import Streamly.Internal.Data.Time.Units
426426
427427import Streamly.Internal.Data.Strict
428428
429−import qualified Streamly.Internal.Memory.Array.Types as A
429+import qualified Streamly.Internal.Memory.Array as A
430430import qualified Streamly.Data.Fold as FL
431431import qualified Streamly.Internal.Data.Fold.Types as FL
432432import qualified Streamly.Streams.Prelude as P
@@ -542,7 +542,7 @@ unfoldrMSerial step seed = fromStreamS (S.unfoldrM step seed)
542542--
543543-- >>> unfold UF.replicateM 10 (putStrLn "hello")
544544--
545−-- /Internal/
545+-- /Since: 0.7.0/
546546{-# INLINE unfold #-}
547547unfold :: (IsStream t, Monad m) => Unfold m a b -> a -> t m b
548548unfold unf x = fromStreamD $ D.unfold unf x
@@ -2210,9 +2210,9 @@ concatMapM f m = fromStreamD $ D.concatMapM (fmap toStreamD . f) (toStreamD m)
22102210-- therefore provide many times better performance.
22112211--
22122212-- @since 0.7.0
2213−{-# INLINE concatMapU #-}
2214−concatMapU ::(IsStream t, Monad m) => Unfold m a b -> t m a -> t m b
2215−concatMapU u m = fromStreamD $ D.concatMapU u (toStreamD m)
2213+{-# INLINE concatUnfold #-}
2214+concatUnfold ::(IsStream t, Monad m) => Unfold m a b -> t m a -> t m b
2215+concatUnfold u m = fromStreamD $ D.concatMapU u (toStreamD m)
22162216
22172217-- | Like 'concatUnfold' but interleaves the streams in the same way as
22182218-- 'interleave' behaves instead of appending them.
@@ -2988,7 +2988,8 @@ wordsOn subseq f m = undefined -- D.fromStreamD $ D.wordsOn f subseq (D.toStream
29882988splitBySeq
29892989 :: (IsStream t, MonadAsync m, Storable a, Enum a, Eq a)
29902990 => Array a -> Fold m a b -> t m a -> t m b
2991−splitBySeq patt f m = intersperseM (fold f (A.read patt)) $ splitOnSeq patt f m
2991+splitBySeq patt f m =
2992+ intersperseM (fold f (A.toStream patt)) $ splitOnSeq patt f m
29922993
29932994-- | Like 'splitSuffixOn' but keeps the suffix intact in the splits.
29942995--
src/Streamly/Memory/Array.hs−1
@@ -90,7 +90,6 @@ module Streamly.Memory.Array
9090
9191 , A.toList
9292 , A.read
93− , readRev
9493
9594 -- ** Random Access
9695 , A.length
src/Streamly/Prelude.hs+2
@@ -92,6 +92,7 @@ module Streamly.Prelude
9292 -- | Generate a monadic stream from a seed value and a generator function.
9393 , unfoldr
9494 , unfoldrM
95+ , unfold
9596 , iterate
9697 , iterateM
9798 , fromIndices
@@ -662,6 +663,7 @@ module Streamly.Prelude
662663 --, bindWith
663664 , concatMap
664665 , concatMapM
666+ , concatUnfold
665667
666668 -- * Exceptions
667669 , before
test/Arrays.hs+7−7
@@ -11,8 +11,8 @@ import Test.QuickCheck.Monadic (monadicIO, assert)
1111
1212import Test.Hspec as H
1313
14+import qualified Streamly.Internal.Memory.Array as IA
1415import qualified Streamly.Memory.Array as A
15−import qualified Streamly.Internal.Memory.Array.Types as AT
1616import qualified Streamly.Prelude as S
1717import qualified Streamly.Internal.Prelude as IP
1818
@@ -55,7 +55,7 @@ testFromToStreamN =
5555 arr <- S.fold (A.writeN len)
5656 $ S.fromList list
5757 xs <- S.toList
58− $ A.read arr
58+ $ S.unfold A.read arr
5959 assert (xs == list)
6060
6161testToStreamRev :: Property
@@ -66,7 +66,7 @@ testToStreamRev =
6666 arr <- S.fold (A.writeN len)
6767 $ S.fromList list
6868 xs <- S.toList
69− $ A.readRev arr
69+ $ IA.toStreamRev arr
7070 assert (xs == reverse list)
7171
7272testArraysOf :: Property
@@ -75,7 +75,7 @@ testArraysOf =
7575 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
7676 monadicIO $ do
7777 xs <- S.toList
78− $ S.concatMap A.read
78+ $ S.concatUnfold A.read
7979 $ IP.arraysOf 240
8080 $ S.fromList list
8181 assert (xs == list)
@@ -86,7 +86,7 @@ testFlattenArrays =
8686 forAll (vectorOf len (arbitrary :: Gen Int)) $ \list ->
8787 monadicIO $ do
8888 xs <- S.toList
89− $ IP.concatMapU AT.readU
89+ $ S.concatUnfold A.read
9090 $ IP.arraysOf 240
9191 $ S.fromList list
9292 assert (xs == list)
@@ -98,7 +98,7 @@ testFromToStream =
9898 monadicIO $ do
9999 arr <- S.fold A.write $ S.fromList list
100100 xs <- S.toList
101− $ A.read arr
101+ $ S.unfold A.read arr
102102 assert (xs == list)
103103
104104main :: IO ()
@@ -109,7 +109,7 @@ main = hspec
109109 describe "Construction" $ do
110110 prop "length . writeN n === n" $ testLength
111111 prop "read . writeN n === id" $ testFromToStreamN
112− prop "readRev . write === reverse" $ testToStreamRev
112+ prop "toStreamRev . write === reverse" $ testToStreamRev
113113 prop "arraysOf concats to original" $ testArraysOf
114114 prop "concats to original" $ testFlattenArrays
115115 prop "read . write === id" $ testFromToStream