on master help sign in
implement arraysOf in terms of chunksOf
9c419e6Harendra Kumar
src/Streamly/FileSystem/FD.hs+2−1
@@ -150,6 +150,7 @@ import qualified Streamly.FileSystem.FDIO as RawIO hiding (write)
150-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
150-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
151
151
152import qualified Streamly.Memory.Array as A
152import qualified Streamly.Memory.Array as A
153+import qualified Streamly.Memory.ArrayStream as AS
153import qualified Streamly.Prelude as S
154import qualified Streamly.Prelude as S
154import qualified Streamly.Streams.StreamD.Type as D
155import qualified Streamly.Streams.StreamD.Type as D
155
156
@@ -399,7 +400,7 @@ _writevArraysPackedUpto n h xs =
399-- @since 0.7.0
400-- @since 0.7.0
400{-# INLINE writeInChunksOf #-}
401{-# INLINE writeInChunksOf #-}
401writeInChunksOf :: MonadIO m => Int -> Handle -> SerialT m Word8 -> m ()
402writeInChunksOf :: MonadIO m => Int -> Handle -> SerialT m Word8 -> m ()
402−writeInChunksOf n h m = writeArrays h $ A.arraysOf n m
403+writeInChunksOf n h m = writeArrays h $ AS.arraysOf n m
403
404
404-- > write = 'writeInChunksOf' A.defaultChunkSize
405-- > write = 'writeInChunksOf' A.defaultChunkSize
405--
406--
src/Streamly/FileSystem/File.hs+3−2
@@ -124,6 +124,7 @@ import Streamly.SVar (MonadAsync)
124
124
125import qualified Streamly.FileSystem.Handle as FH
125import qualified Streamly.FileSystem.Handle as FH
126import qualified Streamly.Memory.Array as A
126import qualified Streamly.Memory.Array as A
127+import qualified Streamly.Memory.ArrayStream as AS
127import qualified Streamly.Prelude as S
128import qualified Streamly.Prelude as S
128
129
129-------------------------------------------------------------------------------
130-------------------------------------------------------------------------------
@@ -289,7 +290,7 @@ writeArrays = writeArraysMode WriteMode
289{-# INLINE writeInChunksOf #-}
290{-# INLINE writeInChunksOf #-}
290writeInChunksOf :: (MonadAsync m, MonadCatch m)
291writeInChunksOf :: (MonadAsync m, MonadCatch m)
291 => Int -> FilePath -> SerialT m Word8 -> m ()
292 => Int -> FilePath -> SerialT m Word8 -> m ()
292−writeInChunksOf n file xs = writeArrays file $ A.arraysOf n xs
293+writeInChunksOf n file xs = writeArrays file $ AS.arraysOf n xs
293
294
294-- > write = 'writeInChunksOf' defaultChunkSize
295-- > write = 'writeInChunksOf' defaultChunkSize
295--
296--
@@ -325,7 +326,7 @@ appendArrays = writeArraysMode AppendMode
325{-# INLINE appendByChunks #-}
326{-# INLINE appendByChunks #-}
326appendByChunks :: (MonadAsync m, MonadCatch m)
327appendByChunks :: (MonadAsync m, MonadCatch m)
327 => Int -> FilePath -> SerialT m Word8 -> m ()
328 => Int -> FilePath -> SerialT m Word8 -> m ()
328−appendByChunks n file xs = appendArrays file $ A.arraysOf n xs
329+appendByChunks n file xs = appendArrays file $ AS.arraysOf n xs
329
330
330-- | Append a byte stream to a file. Combines the bytes in chunks of size up to
331-- | Append a byte stream to a file. Combines the bytes in chunks of size up to
331-- 'A.defaultChunkSize' before writing. If the file exists then the new data
332-- 'A.defaultChunkSize' before writing. If the file exists then the new data
src/Streamly/FileSystem/Handle.hs+2−2
@@ -119,7 +119,7 @@ import System.IO (Handle, hGetBufSome)
119import Prelude hiding (read)
119import Prelude hiding (read)
120
120
121import Streamly.FileSystem.Handle.Internal (writeArray)
121import Streamly.FileSystem.Handle.Internal (writeArray)
122−import Streamly.Memory.Array.Types (Array(..))
122+import Streamly.Memory.Array.Types (Array(..), writeNUnsafe)
123import Streamly.Streams.StreamK.Type (IsStream, mkStream)
123import Streamly.Streams.StreamK.Type (IsStream, mkStream)
124import Streamly.Memory.Array.Types
124import Streamly.Memory.Array.Types
125 (defaultChunkSize, shrinkToFit, lpackArraysChunksOf)
125 (defaultChunkSize, shrinkToFit, lpackArraysChunksOf)
@@ -283,7 +283,7 @@ writeArraysInChunksOf n h = lpackArraysChunksOf n (writeArrays h)
283-- @since 0.7.0
283-- @since 0.7.0
284{-# INLINE writeInChunksOf #-}
284{-# INLINE writeInChunksOf #-}
285writeInChunksOf :: MonadIO m => Int -> Handle -> Fold m Word8 ()
285writeInChunksOf :: MonadIO m => Int -> Handle -> Fold m Word8 ()
286−writeInChunksOf n h = FL.lchunksOf n (A.writeN n) (writeArrays h)
286+writeInChunksOf n h = FL.lchunksOf n (writeNUnsafe n) (writeArrays h)
287
287
288-- > write = 'writeInChunksOf' A.defaultChunkSize
288-- > write = 'writeInChunksOf' A.defaultChunkSize
289--
289--
src/Streamly/FileSystem/Handle/Internal.hs+12−1
@@ -46,7 +46,7 @@ import Streamly.Memory.Array.Types (defaultChunkSize)
46
46
47import qualified Streamly.Memory.Array as A
47import qualified Streamly.Memory.Array as A
48import qualified Streamly.Memory.ArrayStream as AS
48import qualified Streamly.Memory.ArrayStream as AS
49−import qualified Streamly.Prelude as S
49+import qualified Streamly.Prelude.Internal as S
50
50
51-------------------------------------------------------------------------------
51-------------------------------------------------------------------------------
52-- Array IO (output)
52-- Array IO (output)
@@ -91,6 +91,16 @@ writeSArraysInChunksOf :: (MonadIO m, Storable a)
91 => Int -> Handle -> SerialT m (Array a) -> m ()
91 => Int -> Handle -> SerialT m (Array a) -> m ()
92writeSArraysInChunksOf n h xs = writeSArrays h $ AS.compact n xs
92writeSArraysInChunksOf n h xs = writeSArrays h $ AS.compact n xs
93
93
94+-- XXX Using custom array chunking with A.arraysOf, writeS gives 2x faster
95+-- readStream/catStream benchmark compared to S.arraysOf based writeS as well
96+-- as compared to the fold IO version of cat benchmark i.e. readStream/cat.
97+-- However, if we use the most optimal A.writeNUnsafe fold then the fold
98+-- version of cat is also as fast. But with the most optimal version of
99+-- A.writeNUnsafe, fusion breaks. Once GHC fusion problem gets fixed we should
100+-- be able to use that.
101+--
102+-- Until then we are keeping the custom A.arraysOf code.
103+--
94-- | @writeSInChunksOf chunkSize handle stream@ writes @stream@ to @handle@ in
104-- | @writeSInChunksOf chunkSize handle stream@ writes @stream@ to @handle@ in
95-- chunks of @chunkSize@. A write is performed to the IO device as soon as we
105-- chunks of @chunkSize@. A write is performed to the IO device as soon as we
96-- collect the required input size.
106-- collect the required input size.
@@ -98,6 +108,7 @@ writeSArraysInChunksOf n h xs = writeSArrays h $ AS.compact n xs
98-- @since 0.7.0
108-- @since 0.7.0
99{-# INLINE writeSInChunksOf #-}
109{-# INLINE writeSInChunksOf #-}
100writeSInChunksOf :: MonadIO m => Int -> Handle -> SerialT m Word8 -> m ()
110writeSInChunksOf :: MonadIO m => Int -> Handle -> SerialT m Word8 -> m ()
111+-- writeSInChunksOf n h m = writeSArrays h $ S.arraysOf n m
101writeSInChunksOf n h m = writeSArrays h $ AS.arraysOf n m
112writeSInChunksOf n h m = writeSArrays h $ AS.arraysOf n m
102
113
103-- > write = 'writeInChunksOf' A.defaultChunkSize
114-- > write = 'writeInChunksOf' A.defaultChunkSize
src/Streamly/Internal.hs+2
@@ -74,6 +74,7 @@ module Streamly.Internal
74
74
75 -- * Streamly.Memory.Array
75 -- * Streamly.Memory.Array
76 , readU
76 , readU
77+ , A.arraysOf
77
78
78 -- * Streamly.FileSystem.Handle
79 -- * Streamly.FileSystem.Handle
79 , writeS
80 , writeS
@@ -88,5 +89,6 @@ import Streamly.Streams.Combinators (inspectMode)
88import Streamly.Streams.Parallel (tapAsync)
89import Streamly.Streams.Parallel (tapAsync)
89import Streamly.Unfold.Types (Unfold(..))
90import Streamly.Unfold.Types (Unfold(..))
90
91
92+import qualified Streamly.Memory.ArrayStream as A
91import Streamly.Prelude.Internal
93import Streamly.Prelude.Internal
92import Streamly.Fold.Types
94import Streamly.Fold.Types
src/Streamly/Memory/Array.hs+2−2
@@ -121,8 +121,8 @@ module Streamly.Memory.Array
121 -}
121 -}
122
122
123 -- * Streams of Arrays
123 -- * Streams of Arrays
124− -- ** Creation
124+ -- -- ** Creation
125− , AS.arraysOf
125+ -- , AS.arraysOf
126
126
127 -- ** Elimination
127 -- ** Elimination
128 , AS.concat
128 , AS.concat
src/Streamly/Memory/Array/Types.hs+45−3
@@ -61,6 +61,7 @@ module Streamly.Memory.Array.Types
61 , toStreamKRev
61 , toStreamKRev
62 , toList
62 , toList
63 , writeN
63 , writeN
64+ , writeNUnsafe
64 , read
65 , read
65 , readU
66 , readU
66
67
@@ -511,15 +512,56 @@ writeN n = Fold step initial extract
511
512
512 where
513 where
513
514
514− initial = do
515− if n < 0 then error "writeN: negative count specified" else return ()
516− liftIO $ newArray n
515+ initial = liftIO $ newArray (max n 0)
517 step arr@(Array _ end bound) _ | end == bound = return arr
516 step arr@(Array _ end bound) _ | end == bound = return arr
518 step (Array start end bound) x = do
517 step (Array start end bound) x = do
519 liftIO $ poke end x
518 liftIO $ poke end x
520 return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
519 return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
521 extract = return -- liftIO . shrinkToFit
520 extract = return -- liftIO . shrinkToFit
522
521
522+-- | Like 'writeN' but does not check the array bounds when writing. The fold
523+-- driver must not call the step function more than 'n' times otherwise it will
524+-- corrupt the memory and crash. This function exists mainly because any
525+-- conditional in the step function blocks fusion causing 10x performance
526+-- slowdown.
527+--
528+-- @since 0.7.0
529+{-# INLINE_NORMAL writeNUnsafe #-}
530+writeNUnsafe :: forall m a. (MonadIO m, Storable a)
531+ => Int -> Fold m a (Array a)
532+writeNUnsafe n = Fold step initial extract
533+
534+ where
535+
536+ {-
537+ -- XXX this implementation is good on all benchmarks except
538+ -- readStream/catStream which uses a stream based writeS instead of a fold
539+ -- based write. In the writeS case it does not fuse and therefore performs
540+ -- 10x worse.
541+ initial = do
542+ (Array start end _) <- liftIO $ newArray (max n 0)
543+ return (start, end)
544+ -- XXX any if condition in the step causes fusion to fail with groupsOf
545+ -- If we need to do bounds check we can use 'n' instead of threading around
546+ -- bound pointer.
547+ step (start, end) x = do
548+ liftIO $ poke end x
549+ return $ (start, (end `plusPtr` sizeOf (undefined :: a)))
550+ extract (start, end) = return $ Array start end end -- liftIO . shrinkToFit
551+ -}
552+ -- This implementation fuses in all known cases as of now. Even though both
553+ -- readStream/cat and readStream/catStream benchmarks perform 2x worse when
554+ -- arraysOf uses this impl compared to their best seen performance.
555+ -- readStream/cat is best with the above implementation and
556+ -- readStream/catStream is best when using the custom arraysOf
557+ -- implementation.
558+ initial = do
559+ liftIO $ newArray (max n 0)
560+ step (Array start end bound) x = do
561+ liftIO $ poke end x
562+ return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
563+ extract = return -- liftIO . shrinkToFit
564+
523{-# INLINE_NORMAL fromStreamDN #-}
565{-# INLINE_NORMAL fromStreamDN #-}
524fromStreamDN :: forall m a. (MonadIO m, Storable a)
566fromStreamDN :: forall m a. (MonadIO m, Storable a)
525 => Int -> D.Stream m a -> m (Array a)
567 => Int -> D.Stream m a -> m (Array a)
src/Streamly/Network/Client.hs+3−2
@@ -67,7 +67,7 @@ import qualified Network.Socket as Net
67
67
68import Streamly (MonadAsync)
68import Streamly (MonadAsync)
69import Streamly.Fold.Types (Fold(..))
69import Streamly.Fold.Types (Fold(..))
70−import Streamly.Memory.Array.Types (Array(..), defaultChunkSize)
70+import Streamly.Memory.Array.Types (Array(..), defaultChunkSize, writeNUnsafe)
71-- import Streamly.Streams.Serial (SerialT)
71-- import Streamly.Streams.Serial (SerialT)
72import Streamly.Streams.StreamK.Type (IsStream)
72import Streamly.Streams.StreamK.Type (IsStream)
73
73
@@ -179,7 +179,8 @@ writeInChunksOf
179 -> (Word8, Word8, Word8, Word8)
179 -> (Word8, Word8, Word8, Word8)
180 -> PortNumber
180 -> PortNumber
181 -> Fold m Word8 ()
181 -> Fold m Word8 ()
182+writeInChunksOf n addr port =
182−writeInChunksOf n addr port = FL.lchunksOf n (A.writeN n) (writeArrays addr port)
183+ FL.lchunksOf n (writeNUnsafe n) (writeArrays addr port)
183
184
184{-
185{-
185-- | Write a stream to the supplied IPv4 host address and port number.
186-- | Write a stream to the supplied IPv4 host address and port number.
src/Streamly/Network/Socket.hs+3−2
@@ -95,6 +95,7 @@ import Streamly.Fold (Fold)
95import qualified Streamly.Fold as FL
95import qualified Streamly.Fold as FL
96import qualified Streamly.Fold.Types as FL
96import qualified Streamly.Fold.Types as FL
97import qualified Streamly.Memory.Array as A
97import qualified Streamly.Memory.Array as A
98+import qualified Streamly.Memory.ArrayStream as AS
98import qualified Streamly.Memory.Array.Types as A
99import qualified Streamly.Memory.Array.Types as A
99import qualified Streamly.Prelude as S
100import qualified Streamly.Prelude as S
100
101
@@ -301,7 +302,7 @@ writeArrays h = FL.drainBy (liftIO . writeArray h)
301-- @since 0.7.0
302-- @since 0.7.0
302{-# INLINE writeInChunksOfS #-}
303{-# INLINE writeInChunksOfS #-}
303writeInChunksOfS :: MonadIO m => Int -> Socket -> SerialT m Word8 -> m ()
304writeInChunksOfS :: MonadIO m => Int -> Socket -> SerialT m Word8 -> m ()
304−writeInChunksOfS n h m = writeArraysS h $ A.arraysOf n m
305+writeInChunksOfS n h m = writeArraysS h $ AS.arraysOf n m
305
306
306-- | Write a byte stream to a socket. Accumulates the input in chunks of
307-- | Write a byte stream to a socket. Accumulates the input in chunks of
307-- specified number of bytes before writing.
308-- specified number of bytes before writing.
@@ -309,7 +310,7 @@ writeInChunksOfS n h m = writeArraysS h $ A.arraysOf n m
309-- @since 0.7.0
310-- @since 0.7.0
310{-# INLINE writeInChunksOf #-}
311{-# INLINE writeInChunksOf #-}
311writeInChunksOf :: MonadIO m => Int -> Socket -> Fold m Word8 ()
312writeInChunksOf :: MonadIO m => Int -> Socket -> Fold m Word8 ()
312−writeInChunksOf n h = FL.lchunksOf n (A.writeN n) (writeArrays h)
313+writeInChunksOf n h = FL.lchunksOf n (A.writeNUnsafe n) (writeArrays h)
313
314
314-- > write = 'writeInChunksOf' A.defaultChunkSize
315-- > write = 'writeInChunksOf' A.defaultChunkSize
315--
316--
src/Streamly/Prelude/Internal.hs+15−1
@@ -260,6 +260,7 @@ module Streamly.Prelude.Internal
260
260
261 -- -- *** Chunks
261 -- -- *** Chunks
262 , chunksOf
262 , chunksOf
263+ , arraysOf
263 , intervalsOf
264 , intervalsOf
264
265
265 -- -- *** Using Element Separators
266 -- -- *** Using Element Separators
@@ -381,7 +382,7 @@ import qualified System.IO as IO
381import Streamly.Enumeration (Enumerable(..), enumerate, enumerateTo)
382import Streamly.Enumeration (Enumerable(..), enumerate, enumerateTo)
382import Streamly.Fold.Types (Fold (..))
383import Streamly.Fold.Types (Fold (..))
383import Streamly.Unfold.Types (Unfold)
384import Streamly.Unfold.Types (Unfold)
384−import Streamly.Memory.Array.Types (Array)
385+import Streamly.Memory.Array.Types (Array, writeNUnsafe)
385-- import Streamly.Memory.Ring (Ring)
386-- import Streamly.Memory.Ring (Ring)
386import Streamly.SVar (MonadAsync, defState)
387import Streamly.SVar (MonadAsync, defState)
387import Streamly.Streams.Async (mkAsync')
388import Streamly.Streams.Async (mkAsync')
@@ -2247,6 +2248,19 @@ chunksOf
2247 => Int -> Fold m a b -> t m a -> t m b
2248 => Int -> Fold m a b -> t m a -> t m b
2248chunksOf n f m = D.fromStreamD $ D.groupsOf n f (D.toStreamD m)
2249chunksOf n f m = D.fromStreamD $ D.groupsOf n f (D.toStreamD m)
2249
2250
2251+-- | @arraysOf n stream@ groups the elements in the input stream into arrays of
2252+-- @n@ elements each.
2253+--
2254+-- Same as the following but may be more efficient:
2255+--
2256+-- > arraysOf n = S.chunksOf n (A.writeN n)
2257+--
2258+-- @since 0.7.0
2259+{-# INLINE arraysOf #-}
2260+arraysOf :: (IsStream t, MonadIO m, Storable a)
2261+ => Int -> t m a -> t m (Array a)
2262+arraysOf n = chunksOf n (writeNUnsafe n)
2263+
2250-- XXX we can implement this by repeatedly applying the 'lrunFor' fold.
2264-- XXX we can implement this by repeatedly applying the 'lrunFor' fold.
2251-- XXX add this example after fixing the serial stream rate control
2265-- XXX add this example after fixing the serial stream rate control
2252-- >>> S.toList $ S.take 5 $ intervalsOf 1 FL.sum $ constRate 2 $ S.enumerateFrom 1
2266-- >>> S.toList $ S.take 5 $ intervalsOf 1 FL.sum $ constRate 2 $ S.enumerateFrom 1
src/Streamly/Streams/StreamD/Type.hs+30−53
@@ -475,43 +475,13 @@ take n (Stream step state) = n `seq` Stream step' (state, 0)
475-- Grouping/Splitting
475-- Grouping/Splitting
476------------------------------------------------------------------------------
476------------------------------------------------------------------------------
477
477
478−{-# INLINE_LATE foldOneGroup #-}
478+-- s = stream state, fs = fold state
479−foldOneGroup
479+data GroupState s fs
480− :: Monad m
480+ = GroupStart s
481− => Int
481+ | GroupBuffer s fs Int
482− -> Fold m a b
482+ | GroupYield fs (GroupState s fs)
483− -> a
483+ | GroupFinish
484− -> State K.Stream m a
485− -> (State K.Stream m a -> s -> m (Step s a))
486− -> s
487− -> m (b, Maybe s)
488−foldOneGroup n (Fold fstep begin done) x gst step state = do
489− acc0 <- begin
490− acc <- fstep acc0 x
491− go SPEC state acc 1
492
484
493− where
494−
495− -- XXX is it strict enough?
496− go !_ st !acc i | i < n = do
497− r <- step gst st
498− case r of
499− Yield y s -> do
500− acc1 <- fstep acc y
501− go SPEC s acc1 (i + 1)
502− Skip s -> go SPEC s acc i
503− Stop -> do
504− res <- done acc
505− return (res, Nothing)
506− go !_ st acc _ = do
507− r <- done acc
508− return (r, Just st)
509−
510−-- groupsOf takes 11 sec to write the file from a stream, whereas just
511−-- reading in the same file as a stream and folding each element of the stream
512−-- using (+) takes just 1.5 sec, so we are still pretty slow (7x slow), there
513−-- is scope to make it faster. There is a possibility of better fusion here.
514−--
515{-# INLINE_NORMAL groupsOf #-}
485{-# INLINE_NORMAL groupsOf #-}
516groupsOf
486groupsOf
517 :: Monad m
487 :: Monad m
@@ -519,31 +489,38 @@ groupsOf
519 -> Fold m a b
489 -> Fold m a b
520 -> Stream m a
490 -> Stream m a
521 -> Stream m b
491 -> Stream m b
522−groupsOf n f (Stream step state) =
492+groupsOf n (Fold fstep initial extract) (Stream step state) =
523− n `seq` Stream stepOuter (Just state)
493+ n `seq` Stream step' (GroupStart state)
524
494
525 where
495 where
526
496
527− {-# INLINE_LATE stepOuter #-}
497+ {-# INLINE_LATE step' #-}
528− stepOuter gst (Just st) = do
498+ step' _ (GroupStart st) = do
529 -- XXX shall we use the Natural type instead? Need to check performance
499 -- XXX shall we use the Natural type instead? Need to check performance
530 -- implications.
500 -- implications.
531 when (n <= 0) $
501 when (n <= 0) $
532 -- XXX we can pass the module string from the higher level API
502 -- XXX we can pass the module string from the higher level API
533 error $ "Streamly.Streams.StreamD.Type.groupsOf: the size of "
503 error $ "Streamly.Streams.StreamD.Type.groupsOf: the size of "
534 ++ "groups [" ++ show n ++ "] must be a natural number"
504 ++ "groups [" ++ show n ++ "] must be a natural number"
505+ -- fs = fold state
506+ fs <- initial
507+ return $ Skip (GroupBuffer st fs 0)
535
508
536− -- We retrieve the first element of the stream before we start to fold
509+ step' gst (GroupBuffer st fs i) = do
537− -- a chunk so that we do not return an empty chunk in case the stream
538− -- is empty.
539− res <- step (adaptState gst) st
510+ r <- step (adaptState gst) st
540− case res of
511+ case r of
541 Yield x s -> do
512 Yield x s -> do
542− -- XXX how to make sure that stepInner and f get fused
513+ fs' <- fstep fs x
543− -- This problem seems to be similar to the concatMap problem
514+ let i' = i + 1
544− (r, s1) <- foldOneGroup n f x (adaptState gst) step s
515+ return $
516+ if i' >= n
517+ then Skip (GroupYield fs' (GroupStart s))
518+ else Skip (GroupBuffer s fs' i')
519+ Skip s -> return $ Skip (GroupBuffer s fs i)
520+ Stop -> return $ Skip (GroupYield fs GroupFinish)
521+
522+ step' _ (GroupYield fs next) = do
523+ r <- extract fs
545− return $ Yield r s1
524+ return $ Yield r next
546− Skip s -> return $ Skip $ Just s
525+
547− Stop -> return Stop
548−
549− stepOuter _ Nothing = return Stop
526+ step' _ GroupFinish = return Stop
test/Arrays.hs+3−2
@@ -13,6 +13,7 @@ import Test.Hspec as H
13
13
14import qualified Streamly.Memory.Array as A
14import qualified Streamly.Memory.Array as A
15import qualified Streamly.Prelude as S
15import qualified Streamly.Prelude as S
16+import qualified Streamly.Internal as Internal
16
17
17-- Coverage build takes too long with default number of tests
18-- Coverage build takes too long with default number of tests
18maxTestCount :: Int
19maxTestCount :: Int
@@ -74,7 +75,7 @@ testArraysOf =
74 monadicIO $ do
75 monadicIO $ do
75 xs <- S.toList
76 xs <- S.toList
76 $ S.concatMap A.read
77 $ S.concatMap A.read
77− $ A.arraysOf 240
78+ $ Internal.arraysOf 240
78 $ S.fromList list
79 $ S.fromList list
79 assert (xs == list)
80 assert (xs == list)
80
81
@@ -85,7 +86,7 @@ testFlattenArrays =
85 monadicIO $ do
86 monadicIO $ do
86 xs <- S.toList
87 xs <- S.toList
87 $ A.concat
88 $ A.concat
88− $ A.arraysOf 240
89+ $ Internal.arraysOf 240
89 $ S.fromList list
90 $ S.fromList list
90 assert (xs == list)
91 assert (xs == list)
91
92