on master help sign in
update documentation and rename toArray => write
e621237Harendra Kumar
benchmark/FileIO.hs+2−2
@@ -168,9 +168,9 @@ main = do
168 $ FH.read inh
168 $ FH.read inh
169 ]
169 ]
170 , bgroup "grouping"
170 , bgroup "grouping"
171− [ mkBench "chunksOf 1 (toArray)" href $ do
171+ [ mkBench "chunksOf 1 (A.writeNF)" href $ do
172 Handles inh _ <- readIORef href
172 Handles inh _ <- readIORef href
173− S.length $ S.chunksOf fileSize (A.toArrayN fileSize)
173+ S.length $ S.chunksOf fileSize (A.writeNF fileSize)
174 (FH.read inh)
174 (FH.read inh)
175
175
176 , mkBench "chunksOf 1" href $ do
176 , mkBench "chunksOf 1" href $ do
benchmark/Linear.hs+1−1
@@ -223,7 +223,7 @@ main =
223 -- , benchIOSink "toListRev" (S.runFold FL.toListRev)
223 -- , benchIOSink "toListRev" (S.runFold FL.toListRev)
224 -- , benchIOSink "toStream" (S.runFold FL.toStream)
224 -- , benchIOSink "toStream" (S.runFold FL.toStream)
225 -- , benchIOSink "toStreamRev" (S.runFold FL.toStreamRev)
225 -- , benchIOSink "toStreamRev" (S.runFold FL.toStreamRev)
226− , benchIOSink "toArrayN" (S.runFold (A.toArrayN Ops.value))
226+ , benchIOSink "writeNF" (S.runFold (A.writeNF Ops.value))
227
227
228 , benchIOSink "index" (S.runFold (FL.index Ops.maxValue))
228 , benchIOSink "index" (S.runFold (FL.index Ops.maxValue))
229 , benchIOSink "head" (S.runFold FL.head)
229 , benchIOSink "head" (S.runFold FL.head)
examples/FileSinkServer.hs+1−1
@@ -30,6 +30,6 @@ main = do
30 where
30 where
31
31
32 recv =
32 recv =
33− S.splitBySuffix (== '\n') A.toArray
33+ S.splitBySuffix (== '\n') A.writeF
34 . decodeChar8
34 . decodeChar8
35 . NS.read
35 . NS.read
src/Streamly/Mem/Array.hs+95−140
@@ -16,57 +16,40 @@
16-- Stability : experimental
16-- Stability : experimental
17-- Portability : GHC
17-- Portability : GHC
18--
18--
19−-- Arrays are the computing duals of streams. Streams are good at sequential
19+-- This module provides immutable arrays suitable for storage and random
20−-- access and immutable transformations of in-transit data whereas arrays are
20+-- access. Once created an array cannot be mutated without copying. Arrays in
21−-- good at random access and in-place transformations of buffered data. Unlike
21+-- this module are chunks of memory that hold a sequence of 'Storable' values
22−-- streams which are potentially infinite, arrays are necessarily /finite/.
22+-- of a given type. They are designed to store serializable data, they cannot
23−-- Arrays can be used as an efficient interface between streams and external
23+-- store non-serializable data like functions, this is reflected by the
24−-- storage systems like memory, files and network. Streams and arrays complete
24+-- 'Storable' constraint. For efficient buffering of data, arrays use pinned
25−-- each other to provide a general purpose computing system. The design of
25+-- memory and therefore can hold arbitrary number of elements with a single
26−-- streamly as a general purpose computing framework is centered around these
26+-- movable pointer visible to GC, therefore, adding no pressure to GC.
27−-- two fundamental aspects of computing and storage.
27+-- Moreover, pinned memory allows communication with foreign consumers and
28+-- producers (e.g. file or network IO) without copying the data.
29+--
30+-- By design, there are no array transformation operations provided in this
31+-- module, only conversion to and from stream is provided. Arrays can be
32+-- operated upon /efficiently/ by converting them into a stream, applying the
33+-- desired stream transformations from "Streamly.Prelude" and then converting
34+-- it back to an array.
28--
35--
29−-- Even though the implementation allows for in-place mutation, the current
36+-- This module is designed to be imported qualified:
30−-- implementation of arrays is immutable. Arrays are of fixed size. The size of
37+--
31−-- an array is fixed at creation and cannot be changed later without copying.
38+-- > import qualified Streamly.Array as A
32−-- Arrays are chunks of memory that hold a sequence of 'Storable' values of a
39+
33−-- given type. They are designed to store serializable data, they cannot store
40+-- To summarize:
34−-- non-serializable data like functions, this is reflected by the 'Storable'
41+--
35−-- constraint. For efficient buffering of data, arrays use pinned memory and
42+-- Arrays are finite and fixed in size
36−-- therefore can hold arbitrary number of elements with a single movable
43+-- provide /O(1)/ access to elements
37−-- pointer visible to GC, therefore, adding no pressure to GC. Moreover,
44+-- store only data and not functions
38−-- pinned memory allows communication with foreign consumers and producers
45+-- provide efficient IO interfacing
39−-- (e.g. file or network IO) without copying the data.
40--
46--
41−-- By design, there are no transformation operations provided in this module,
42−-- only stream conversion and IO routines are provided. An array is purely a
43−-- data store, therefore, it is not a 'Functor'. Arrays can be operated upon
44−-- /efficiently/ by converting them into a stream, applying the desired
45−-- transformations on the stream and then converting it back to an array.
46-- 'Foldable' instance is not provided because the implementation would be much
47-- 'Foldable' instance is not provided because the implementation would be much
47-- less efficient compared to folding via streams. 'Semigroup' and 'Monoid'
48-- less efficient compared to folding via streams. 'Semigroup' and 'Monoid'
48-- instances are deliberately not provided to avoid misuse; concatenating
49-- instances are deliberately not provided to avoid misuse; concatenating
49-- arrays using binary operations can be highly inefficient. Instead, use
50-- arrays using binary operations can be highly inefficient. Instead, use
50−-- 'spliceArrays' to concatenate N arrays at once.
51+-- 'Streamly.Mem.Array.Stream.toArray' to concatenate N arrays at once.
51−--
52−-- To summarize:
53−--
54−-- * Arrays are finite and fixed in size
55−-- * provide /O(1)/ access to elements
56−-- * store only data and not functions
57−-- * provide efficient IO interfacing
58--
52--
59−-- 'ByteString' data type from the 'bytestring' package and the 'Text' data
60−-- type from the 'text' package are just special cases of arrays. 'ByteString'
61−-- is equivalent to @Array Word8@ and 'Text' is equivalent to a @utf16@ encoded
62−-- @Array Word8@. All the 'bytestring' and 'text' operations can be performed
63−-- on arrays with equivalent or better performance by converting them to and
64−-- from streams.
65−--
66−-- This module is designed to be imported qualified:
67−--
68−-- > import qualified Streamly.Array as A
69−
70-- Each array is one pointer visible to the GC. Too many small arrays (e.g.
53-- Each array is one pointer visible to the GC. Too many small arrays (e.g.
71-- single byte) are only as good as holding those elements in a Haskell list.
54-- single byte) are only as good as holding those elements in a Haskell list.
72-- However, small arrays can be compacted into large ones to reduce the
55-- However, small arrays can be compacted into large ones to reduce the
@@ -100,9 +83,8 @@ module Streamly.Mem.Array
100 , write
83 , write
101
84
102 -- Stream Folds
85 -- Stream Folds
103− , A.toArrayN
86+ , A.writeNF
104− -- , toArrays
87+ , writeF
105− , toArray
106
88
107 -- * Elimination
89 -- * Elimination
108 -- 'GHC.Exts.toList' from "GHC.Exts" can be used to convert an array to a
90 -- 'GHC.Exts.toList' from "GHC.Exts" can be used to convert an array to a
@@ -128,12 +110,14 @@ module Streamly.Mem.Array
128 , writeSliceRev
110 , writeSliceRev
129 -}
111 -}
130
112
113+ {-
131 -- * Immutable Transformations
114 -- * Immutable Transformations
132 , runTransform
115 , runTransform
133
116
134 -- * Folding Arrays
117 -- * Folding Arrays
135 -- , runStreamFold
118 -- , runStreamFold
136 , runFold
119 , runFold
120+ -}
137 )
121 )
138where
122where
139
123
@@ -179,6 +163,64 @@ writeN n m = do
179 if n < 0 then error "writeN: negative write count specified" else return ()
163 if n < 0 then error "writeN: negative write count specified" else return ()
180 A.fromStreamDN n $ D.toStreamD m
164 A.fromStreamDN n $ D.toStreamD m
181
165
166+-- XXX The realloc based implementation needs to make one extra copy if we use
167+-- shrinkToFit. On the other hand, the stream of arrays implementation may
168+-- buffer the array chunk pointers in memory but it does not have to shrink as
169+-- we know the exact size in the end. However, memory copying does not seems to
170+-- be as expensive as the allocations. Therefore, we need to reduce the number
171+-- of allocations instead. Also, the size of allocations matters, right sizing
172+-- an allocation even at the cost of copying sems to help. Should be measured
173+-- on a big stream with heavy calls to toArray to see the effect.
174+--
175+-- XXX check if GHC's memory allocator is efficient enough. We can try the C
176+-- malloc to compare against.
177+
178+{-# INLINE_NORMAL toArrayMinChunk #-}
179+toArrayMinChunk :: forall m a. (MonadIO m, Storable a)
180+ => Int -> Fold m a (Array a)
181+-- toArrayMinChunk n = FL.mapM spliceArrays $ toArraysOf n
182+toArrayMinChunk elemCount = Fold step initial extract
183+
184+ where
185+
186+ insertElem (Array start end bound) x = do
187+ liftIO $ poke end x
188+ return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
189+
190+ initial = do
191+ when (elemCount < 0) $ error "toArrayMinChunk: elemCount is negative"
192+ liftIO $ A.newArray elemCount
193+ step arr@(Array start end bound) x | end == bound = do
194+ let p = unsafeForeignPtrToPtr start
195+ oldSize = end `minusPtr` p
196+ newSize = max (oldSize * 2) 1
197+ arr1 <- liftIO $ A.realloc newSize arr
198+ insertElem arr1 x
199+ step arr x = insertElem arr x
200+ extract = liftIO . A.shrinkToFit
201+
202+-- | Fold the whole input to a single array.
203+--
204+-- /Caution! Do not use this on infinite streams./
205+--
206+-- @since 0.7.0
207+{-# INLINE writeF #-}
208+writeF :: forall m a. (MonadIO m, Storable a) => Fold m a (Array a)
209+writeF = toArrayMinChunk (A.bytesToCount (undefined :: a) (A.mkChunkSize 1024))
210+
211+-- | Create an 'Array' from a stream. This is useful when we want to create a
212+-- single array from a stream of unknown size. 'writeN' is at least twice
213+-- as efficient when the size is already known.
214+--
215+-- Note that if the input stream is too large memory allocation for the array
216+-- may fail. When the stream size is not known, `arraysOf` followed by
217+-- processing of indvidual arrays in the resulting stream should be preferred.
218+--
219+{-# INLINE write #-}
220+write :: (MonadIO m, Storable a) => SerialT m a -> m (Array a)
221+write = P.runFold writeF
222+-- write m = A.fromStreamD $ D.toStreamD m
223+
182-------------------------------------------------------------------------------
224-------------------------------------------------------------------------------
183-- Elimination
225-- Elimination
184-------------------------------------------------------------------------------
226-------------------------------------------------------------------------------
@@ -373,93 +415,6 @@ writeSliceRev :: (IsStream t, Monad m, Storable a)
373writeSliceRev arr i len s = undefined
415writeSliceRev arr i len s = undefined
374-}
416-}
375
417
376−-------------------------------------------------------------------------------
377−-- Streams of Arrays
378−-------------------------------------------------------------------------------
379−
380−-- exponentially increasing sizes of the chunks upto the max limit.
381−-- XXX this will be easier to implement with parsers/terminating folds
382−-- With this we should be able to reduce the number of chunks/allocations.
383−-- The reallocation/copy based toArray can also be implemented using this.
384−--
385−{-
386−{-# INLINE toArraysInRange #-}
387−toArraysInRange :: (IsStream t, MonadIO m, Storable a)
388− => Int -> Int -> Fold m (Array a) b -> Fold m a b
389−toArraysInRange low high (Fold step initial extract) =
390−-}
391−
392−{-
393−-- | Fold the input to a pure buffered stream (List) of arrays.
394−{-# INLINE _toArraysOf #-}
395−_toArraysOf :: (MonadIO m, Storable a)
396− => Int -> Fold m a (SerialT Identity (Array a))
397−_toArraysOf n = FL.lchunksOf n (A.toArrayN n) FL.toStream
398−-}
399−
400−-- XXX The realloc based implementation needs to make one extra copy if we use
401−-- shrinkToFit. On the other hand, the stream of arrays implementation may
402−-- buffer the array chunk pointers in memory but it does not have to shrink as
403−-- we know the exact size in the end. However, memory copying does not seems to
404−-- be as expensive as the allocations. Therefore, we need to reduce the number
405−-- of allocations instead. Also, the size of allocations matters, right sizing
406−-- an allocation even at the cost of copying sems to help. Should be measured
407−-- on a big stream with heavy calls to toArray to see the effect.
408−--
409−-- XXX check if GHC's memory allocator is efficient enough. We can try the C
410−-- malloc to compare against.
411−
412−{-# INLINE_NORMAL toArrayMinChunk #-}
413−toArrayMinChunk :: forall m a. (MonadIO m, Storable a)
414− => Int -> Fold m a (Array a)
415−-- toArrayMinChunk n = FL.mapM spliceArrays $ toArraysOf n
416−toArrayMinChunk elemCount = Fold step initial extract
417−
418− where
419−
420− insertElem (Array start end bound) x = do
421− liftIO $ poke end x
422− return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
423−
424− initial = do
425− when (elemCount < 0) $ error "toArrayMinChunk: elemCount is negative"
426− liftIO $ A.newArray elemCount
427− step arr@(Array start end bound) x | end == bound = do
428− let p = unsafeForeignPtrToPtr start
429− oldSize = end `minusPtr` p
430− newSize = max (oldSize * 2) 1
431− arr1 <- liftIO $ A.realloc newSize arr
432− insertElem arr1 x
433− step arr x = insertElem arr x
434− extract = liftIO . A.shrinkToFit
435−
436−-- | Fold the whole input to a single array.
437−--
438−-- /Caution! Do not use this on infinite streams./
439−--
440−-- @since 0.7.0
441−{-# INLINE toArray #-}
442−toArray :: forall m a. (MonadIO m, Storable a) => Fold m a (Array a)
443−toArray =
444− toArrayMinChunk (A.bytesToCount (undefined :: a) (A.mkChunkSize 1024))
445−
446−-- | Create an 'Array' from a stream. This is useful when we want to create a
447−-- single array from a stream of unknown size. 'writeN' is at least twice
448−-- as efficient when the size is already known.
449−--
450−-- Note that if the input stream is too large memory allocation for the array
451−-- may fail. When the stream size is not known, `arraysOf` followed by
452−-- processing of indvidual arrays in the resulting stream should be preferred.
453−--
454−{-# INLINE write #-}
455−write :: (MonadIO m, Storable a) => SerialT m a -> m (Array a)
456−write = P.runFold toArray
457−-- write m = A.fromStreamD $ D.toStreamD m
458−
459−-- XXX efficiently compare two streams of arrays. Two streams can have chunks
460−-- of different sizes, we can handle that in the stream comparison abstraction.
461−-- This could be useful e.g. to fast compare whether two files differ.
462−
463-------------------------------------------------------------------------------
418-------------------------------------------------------------------------------
464-- Transform via stream operations
419-- Transform via stream operations
465-------------------------------------------------------------------------------
420-------------------------------------------------------------------------------
@@ -483,17 +438,17 @@ runPipe f arr = P.runPipe (toArrayMinChunk (length arr)) $ f (A.read arr)
483-- operation.
438-- operation.
484--
439--
485-- @since 0.7.0
440-- @since 0.7.0
486−{-# INLINE runTransform #-}
441+{-# INLINE _runTransform #-}
487−runTransform :: (MonadIO m, Storable a, Storable b)
442+_runTransform :: (MonadIO m, Storable a, Storable b)
488 => (SerialT m a -> SerialT m b) -> Array a -> m (Array b)
443 => (SerialT m a -> SerialT m b) -> Array a -> m (Array b)
489−runTransform f arr = P.runFold (toArrayMinChunk (length arr)) $ f (A.read arr)
444+_runTransform f arr = P.runFold (toArrayMinChunk (length arr)) $ f (A.read arr)
490
445
491-- | Fold an array using a 'Fold'.
446-- | Fold an array using a 'Fold'.
492--
447--
493-- @since 0.7.0
448-- @since 0.7.0
494−{-# INLINE runFold #-}
449+{-# INLINE _runFold #-}
495−runFold :: forall m a b. (MonadIO m, Storable a) => Fold m a b -> Array a -> m b
450+_runFold :: forall m a b. (MonadIO m, Storable a) => Fold m a b -> Array a -> m b
496−runFold f arr = P.runFold f $ (A.read arr :: Serial.SerialT m a)
451+_runFold f arr = P.runFold f $ (A.read arr :: Serial.SerialT m a)
497
452
498-- | Fold an array using a stream fold operation.
453-- | Fold an array using a stream fold operation.
499--
454--
src/Streamly/Mem/Array/Stream.hs+29−6
@@ -54,6 +54,10 @@ import qualified Streamly.Prelude as S
54import qualified Streamly.Streams.StreamD as D
54import qualified Streamly.Streams.StreamD as D
55import qualified Streamly.Streams.Prelude as P
55import qualified Streamly.Streams.Prelude as P
56
56
57+-- XXX efficiently compare two streams of arrays. Two streams can have chunks
58+-- of different sizes, we can handle that in the stream comparison abstraction.
59+-- This could be useful e.g. to fast compare whether two files differ.
60+
57-- | Convert a stream of arrays into a stream of their elements.
61-- | Convert a stream of arrays into a stream of their elements.
58--
62--
59-- Same as the following but more efficient:
63-- Same as the following but more efficient:
@@ -100,21 +104,21 @@ splitOn
100 -> t m (Array Word8)
104 -> t m (Array Word8)
101splitOn byte s = D.fromStreamD $ A.splitOn byte $ D.toStreamD s
105splitOn byte s = D.fromStreamD $ A.splitOn byte $ D.toStreamD s
102
106
103−-- | Coalesce adajcent arrays in incoming stream to form bigger arrays of a
107+-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
104−-- maximum specified size.
108+-- maximum specified size in bytes.
105--
109--
106-- @since 0.7.0
110-- @since 0.7.0
107{-# INLINE compact #-}
111{-# INLINE compact #-}
108compact :: (MonadIO m, Storable a)
112compact :: (MonadIO m, Storable a)
109 => Int -> SerialT m (Array a) -> SerialT m (Array a)
113 => Int -> SerialT m (Array a) -> SerialT m (Array a)
110−compact n xs =
111− D.fromStreamD $ A.packArraysChunksOf n (D.toStreamD xs)
114+compact n xs = D.fromStreamD $ A.packArraysChunksOf n (D.toStreamD xs)
112
115
113−-- | Groups the elements in an input stream into arrays of given size.
116+-- | @arraysOf n stream@ groups the elements in the input stream into arrays of
117+-- @n@ elements each.
114--
118--
115-- Same as the following but more efficient:
119-- Same as the following but more efficient:
116--
120--
117−-- > arraysOf n = FL.groupsOf n (FL.toArrayN n)
121+-- > arraysOf n = FL.chunksOf n (A.writeNF n)
118--
122--
119-- @since 0.7.0
123-- @since 0.7.0
120{-# INLINE arraysOf #-}
124{-# INLINE arraysOf #-}
@@ -171,3 +175,22 @@ toArray :: (MonadIO m, Storable a) => SerialT m (Array a) -> m (Array a)
171toArray = spliceArraysRealloced
175toArray = spliceArraysRealloced
172-- spliceArrays = _spliceArraysBuffered
176-- spliceArrays = _spliceArraysBuffered
173
177
178+-- exponentially increasing sizes of the chunks upto the max limit.
179+-- XXX this will be easier to implement with parsers/terminating folds
180+-- With this we should be able to reduce the number of chunks/allocations.
181+-- The reallocation/copy based toArray can also be implemented using this.
182+--
183+{-
184+{-# INLINE toArraysInRange #-}
185+toArraysInRange :: (IsStream t, MonadIO m, Storable a)
186+ => Int -> Int -> Fold m (Array a) b -> Fold m a b
187+toArraysInRange low high (Fold step initial extract) =
188+-}
189+
190+{-
191+-- | Fold the input to a pure buffered stream (List) of arrays.
192+{-# INLINE _toArraysOf #-}
193+_toArraysOf :: (MonadIO m, Storable a)
194+ => Int -> Fold m a (SerialT Identity (Array a))
195+_toArraysOf n = FL.lchunksOf n (A.writeNF n) FL.toStream
196+-}
src/Streamly/Mem/Array/Types.hs+8−8
@@ -59,7 +59,7 @@ module Streamly.Mem.Array.Types
59 , toStreamK
59 , toStreamK
60 , toStreamKRev
60 , toStreamKRev
61 , toList
61 , toList
62− , toArrayN
62+ , writeNF
63 , read
63 , read
64
64
65 -- * Utilities
65 -- * Utilities
@@ -472,18 +472,18 @@ foldr f z arr = runIdentity $ D.foldr f z $ toStreamD arr
472-- Instances
472-- Instances
473-------------------------------------------------------------------------------
473-------------------------------------------------------------------------------
474
474
475−-- | @toArrayN n@ folds a maximum of @n@ elements from the input stream to an
475+-- | @writeNF n@ folds a maximum of @n@ elements from the input stream to an
476-- 'Array'.
476-- 'Array'.
477--
477--
478-- @since 0.7.0
478-- @since 0.7.0
479−{-# INLINE_NORMAL toArrayN #-}
479+{-# INLINE_NORMAL writeNF #-}
480−toArrayN :: forall m a. (MonadIO m, Storable a) => Int -> Fold m a (Array a)
480+writeNF :: forall m a. (MonadIO m, Storable a) => Int -> Fold m a (Array a)
481−toArrayN n = Fold step initial extract
481+writeNF n = Fold step initial extract
482
482
483 where
483 where
484
484
485 initial = do
485 initial = do
486− if n < 0 then error "toArrayN: negative count specified" else return ()
486+ if n < 0 then error "writeNF: negative count specified" else return ()
487 liftIO $ newArray n
487 liftIO $ newArray n
488 step arr@(Array _ end bound) _ | end == bound = return arr
488 step arr@(Array _ end bound) _ | end == bound = return arr
489 step (Array start end bound) x = do
489 step (Array start end bound) x = do
@@ -516,7 +516,7 @@ data GroupState s start end bound
516{-# INLINE_NORMAL fromStreamDArraysOf #-}
516{-# INLINE_NORMAL fromStreamDArraysOf #-}
517fromStreamDArraysOf :: forall m a. (MonadIO m, Storable a)
517fromStreamDArraysOf :: forall m a. (MonadIO m, Storable a)
518 => Int -> D.Stream m a -> D.Stream m (Array a)
518 => Int -> D.Stream m a -> D.Stream m (Array a)
519−-- fromStreamDArraysOf n str = D.groupsOf n (toArrayN n) str
519+-- fromStreamDArraysOf n str = D.groupsOf n (writeNF n) str
520fromStreamDArraysOf n (D.Stream step state) =
520fromStreamDArraysOf n (D.Stream step state) =
521 D.Stream step' (GroupStart state)
521 D.Stream step' (GroupStart state)
522
522
@@ -886,7 +886,7 @@ data SpliceState s arr
886 | SpliceFinish
886 | SpliceFinish
887
887
888-- XXX can use general grouping combinators to achieve this?
888-- XXX can use general grouping combinators to achieve this?
889−-- | Coalesce adajcent arrays in incoming stream to form bigger arrays of a
889+-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
890-- maximum specified size.
890-- maximum specified size.
891--
891--
892-- @since 0.7.0
892-- @since 0.7.0
src/Streamly/String.hs+3−3
@@ -70,7 +70,7 @@ import GHC.Base (unsafeChr)
70import Streamly (IsStream, MonadAsync)
70import Streamly (IsStream, MonadAsync)
71import Prelude hiding (String, lines, words, unlines, unwords)
71import Prelude hiding (String, lines, words, unlines, unwords)
72import Streamly.Fold (Fold)
72import Streamly.Fold (Fold)
73−import Streamly.Mem.Array (Array, toArray)
73+import Streamly.Mem.Array (Array)
74
74
75import qualified Streamly.Prelude as S
75import qualified Streamly.Prelude as S
76import qualified Streamly.Mem.Array.Types as A (unlines)
76import qualified Streamly.Mem.Array.Types as A (unlines)
@@ -204,7 +204,7 @@ isSpace c
204-- 'foldLines' instead.
204-- 'foldLines' instead.
205{-# INLINE lines #-}
205{-# INLINE lines #-}
206lines :: (MonadIO m, IsStream t) => t m Char -> t m (Array Char)
206lines :: (MonadIO m, IsStream t) => t m Char -> t m (Array Char)
207−lines = S.splitOnSuffix (== '\n') toArray
207+lines = S.splitOnSuffix (== '\n') A.writeF
208
208
209-- | Break a string up into a list of strings, which were delimited
209-- | Break a string up into a list of strings, which were delimited
210-- by characters representing white space.
210-- by characters representing white space.
@@ -216,7 +216,7 @@ lines = S.splitOnSuffix (== '\n') toArray
216-- 'foldWords' instead.
216-- 'foldWords' instead.
217{-# INLINE words #-}
217{-# INLINE words #-}
218words :: (MonadIO m, IsStream t) => t m Char -> t m (Array Char)
218words :: (MonadIO m, IsStream t) => t m Char -> t m (Array Char)
219−words = S.wordsBy isSpace toArray
219+words = S.wordsBy isSpace A.writeF
220
220
221-- | Flattens the stream of @Array Char@, after appending a terminating
221-- | Flattens the stream of @Array Char@, after appending a terminating
222-- newline to each string.
222-- newline to each string.