on master help sign in
Implement fold in terms of fold_.
7650587Pranay Sashank
src/Streamly/Internal/Data/Array.hs+2−2
@@ -151,7 +151,7 @@ fromStreamDN limit str = do
151
151
152{-# INLINE fromStreamD #-}
152{-# INLINE fromStreamD #-}
153fromStreamD :: MonadIO m => D.Stream m a -> m (Array a)
153fromStreamD :: MonadIO m => D.Stream m a -> m (Array a)
154−fromStreamD = D.foldOnce write
154+fromStreamD = D.fold write
155
155
156{-# INLINABLE fromListN #-}
156{-# INLINABLE fromListN #-}
157fromListN :: Int -> [a] -> Array a
157fromListN :: Int -> [a] -> Array a
@@ -187,7 +187,7 @@ toStreamRev = D.fromStreamD . toStreamDRev
187
187
188{-# INLINE fold #-}
188{-# INLINE fold #-}
189fold :: Monad m => Fold m a b -> Array a -> m b
189fold :: Monad m => Fold m a b -> Array a -> m b
190−fold f arr = D.foldOnce f (toStreamD arr)
190+fold f arr = D.fold f (toStreamD arr)
191
191
192{-# INLINE streamFold #-}
192{-# INLINE streamFold #-}
193streamFold :: Monad m => (SerialT m a -> m b) -> Array a -> m b
193streamFold :: Monad m => (SerialT m a -> m b) -> Array a -> m b
src/Streamly/Internal/Data/Array/Foreign.hs+3−3
@@ -201,7 +201,7 @@ fromStreamN n m = do
201-- /Pre-release/
201-- /Pre-release/
202{-# INLINE fromStream #-}
202{-# INLINE fromStream #-}
203fromStream :: (MonadIO m, Storable a) => SerialT m a -> m (Array a)
203fromStream :: (MonadIO m, Storable a) => SerialT m a -> m (Array a)
204−fromStream = P.foldOnce A.write
204+fromStream = P.fold A.write
205-- write m = A.fromStreamD $ D.toStreamD m
205-- write m = A.fromStreamD $ D.toStreamD m
206
206
207-------------------------------------------------------------------------------
207-------------------------------------------------------------------------------
@@ -492,7 +492,7 @@ runPipe f arr = P.runPipe (toArrayMinChunk (length arr)) $ f (A.read arr)
492streamTransform :: forall m a b. (MonadIO m, Storable a, Storable b)
492streamTransform :: forall m a b. (MonadIO m, Storable a, Storable b)
493 => (SerialT m a -> SerialT m b) -> Array a -> m (Array b)
493 => (SerialT m a -> SerialT m b) -> Array a -> m (Array b)
494streamTransform f arr =
494streamTransform f arr =
495− P.foldOnce (A.toArrayMinChunk (alignment (undefined :: a)) (length arr))
495+ P.fold (A.toArrayMinChunk (alignment (undefined :: a)) (length arr))
496 $ f (A.toStream arr)
496 $ f (A.toStream arr)
497
497
498-------------------------------------------------------------------------------
498-------------------------------------------------------------------------------
@@ -566,7 +566,7 @@ asCString arr act = do
566-- /Pre-release/
566-- /Pre-release/
567{-# INLINE fold #-}
567{-# INLINE fold #-}
568fold :: forall m a b. (MonadIO m, Storable a) => Fold m a b -> Array a -> m b
568fold :: forall m a b. (MonadIO m, Storable a) => Fold m a b -> Array a -> m b
569−fold f arr = P.foldOnce f (A.toStream arr :: Serial.SerialT m a)
569+fold f arr = P.fold f (A.toStream arr :: Serial.SerialT m a)
570
570
571-- | Fold an array using a stream fold operation.
571-- | Fold an array using a stream fold operation.
572--
572--
src/Streamly/Internal/Data/Array/Prim/MutTypesInclude.hs+1−1
@@ -216,7 +216,7 @@ fromStreamDN limit str = do
216
216
217{-# INLINE fromStreamD #-}
217{-# INLINE fromStreamD #-}
218fromStreamD :: (MonadIO m, Prim a) => D.Stream m a -> m (Array a)
218fromStreamD :: (MonadIO m, Prim a) => D.Stream m a -> m (Array a)
219−fromStreamD str = D.foldOnce write str
219+fromStreamD str = D.fold write str
220
220
221{-# INLINABLE fromListNM #-}
221{-# INLINABLE fromListNM #-}
222fromListNM :: (MonadIO m, Prim a) => Int -> [a] -> m (Array a)
222fromListNM :: (MonadIO m, Prim a) => Int -> [a] -> m (Array a)
src/Streamly/Internal/Data/Array/PrimInclude.hs+2−2
@@ -45,7 +45,7 @@ fromStreamN n m = do
45-- /Pre-release/
45-- /Pre-release/
46{-# INLINE fromStream #-}
46{-# INLINE fromStream #-}
47fromStream :: (MonadIO m, Prim a) => SerialT m a -> m (Array a)
47fromStream :: (MonadIO m, Prim a) => SerialT m a -> m (Array a)
48−fromStream = P.foldOnce A.write
48+fromStream = P.fold A.write
49-- write m = A.fromStreamD $ D.toStreamD m
49-- write m = A.fromStreamD $ D.toStreamD m
50
50
51-------------------------------------------------------------------------------
51-------------------------------------------------------------------------------
@@ -128,7 +128,7 @@ null arr = length arr == 0
128-- /Pre-release/
128-- /Pre-release/
129{-# INLINE fold #-}
129{-# INLINE fold #-}
130fold :: forall m a b. (MonadIO m, Prim a) => Fold m a b -> Array a -> m b
130fold :: forall m a b. (MonadIO m, Prim a) => Fold m a b -> Array a -> m b
131−fold f arr = P.foldOnce f (toStream arr :: Serial.SerialT m a)
131+fold f arr = P.fold f (toStream arr :: Serial.SerialT m a)
132
132
133-- | Fold an array using a stream fold operation.
133-- | Fold an array using a stream fold operation.
134--
134--
src/Streamly/Internal/Data/SmallArray.hs+1−1
@@ -169,7 +169,7 @@ toStreamRev = D.fromStreamD . toStreamDRev
169
169
170{-# INLINE fold #-}
170{-# INLINE fold #-}
171fold :: Monad m => Fold m a b -> SmallArray a -> m b
171fold :: Monad m => Fold m a b -> SmallArray a -> m b
172−fold f arr = D.foldOnce f (toStreamD arr)
172+fold f arr = D.fold f (toStreamD arr)
173
173
174{-# INLINE streamFold #-}
174{-# INLINE streamFold #-}
175streamFold :: Monad m => (SerialT m a -> m b) -> SmallArray a -> m b
175streamFold :: Monad m => (SerialT m a -> m b) -> SmallArray a -> m b
src/Streamly/Internal/Data/Stream/IsStream/Common.hs+10−1
@@ -23,6 +23,7 @@ module Streamly.Internal.Data.Stream.IsStream.Common
23
23
24 -- * Elimination
24 -- * Elimination
25 , fold
25 , fold
26+ , fold_
26
27
27 -- * Transformation
28 -- * Transformation
28 , scanlMAfter'
29 , scanlMAfter'
@@ -248,7 +249,15 @@ relTimesWith = fmap snd . timesWith
248-- @since 0.7.0
249-- @since 0.7.0
249{-# INLINE fold #-}
250{-# INLINE fold #-}
250fold :: Monad m => Fold m a b -> SerialT m a -> m b
251fold :: Monad m => Fold m a b -> SerialT m a -> m b
251−fold = P.foldOnce
252+fold fl strm = do
253+ (b, _) <- fold_ fl strm
254+ return $! b
255+
256+{-# INLINE fold_ #-}
257+fold_ :: Monad m => Fold m a b -> SerialT m a -> m (b, SerialT m a)
258+fold_ fl strm = do
259+ (b, str) <- D.fold_ fl $ D.toStreamD strm
260+ return $! (b, D.fromStreamD str)
252
261
253------------------------------------------------------------------------------
262------------------------------------------------------------------------------
254-- Transformation
263-- Transformation
src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs+3−1
@@ -20,6 +20,7 @@ module Streamly.Internal.Data.Stream.IsStream.Eliminate
20 -- * Running a 'Fold'
20 -- * Running a 'Fold'
21 -- See "Streamly.Internal.Data.Fold".
21 -- See "Streamly.Internal.Data.Fold".
22 fold
22 fold
23+ , fold_
23
24
24 -- * Running a 'Parser'
25 -- * Running a 'Parser'
25 -- "Streamly.Internal.Data.Parser".
26 -- "Streamly.Internal.Data.Parser".
@@ -150,7 +151,8 @@ import Foreign.Storable (Storable)
150import Streamly.Internal.Data.Parser (Parser (..))
151import Streamly.Internal.Data.Parser (Parser (..))
151import Streamly.Internal.Data.SVar (MonadAsync, defState)
152import Streamly.Internal.Data.SVar (MonadAsync, defState)
152import Streamly.Internal.Data.Stream.IsStream.Common
153import Streamly.Internal.Data.Stream.IsStream.Common
153− (fold, drop, findIndices, reverse, splitOnSeq, take, takeWhile)
154+ ( fold, fold_, drop, findIndices, reverse, splitOnSeq, take
155+ , takeWhile)
154import Streamly.Internal.Data.Stream.Prelude (toStreamS)
156import Streamly.Internal.Data.Stream.Prelude (toStreamS)
155import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
157import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
156import Streamly.Internal.Data.Stream.StreamK (IsStream)
158import Streamly.Internal.Data.Stream.StreamK (IsStream)
src/Streamly/Internal/Data/Stream/Prelude.hs+4−4
@@ -33,7 +33,7 @@ module Streamly.Internal.Data.Stream.Prelude
33 , foldlx'
33 , foldlx'
34 , foldlMx'
34 , foldlMx'
35 , foldl'
35 , foldl'
36− , foldOnce
36+ , fold
37
37
38 -- Lazy left folds are useful only for reversing the stream
38 -- Lazy left folds are useful only for reversing the stream
39 , foldlS
39 , foldlS
@@ -188,9 +188,9 @@ foldlT :: (Monad m, IsStream t, Monad (s m), MonadTrans s)
188 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
188 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
189foldlT f z s = S.foldlT f z (toStreamS s)
189foldlT f z s = S.foldlT f z (toStreamS s)
190
190
191−{-# INLINE foldOnce #-}
191+{-# INLINE fold #-}
192−foldOnce :: (Monad m, IsStream t) => Fold m a b -> t m a -> m b
192+fold :: (Monad m, IsStream t) => Fold m a b -> t m a -> m b
193−foldOnce fld m = S.foldOnce fld $ toStreamS m
193+fold fld m = S.fold fld $ toStreamS m
194
194
195------------------------------------------------------------------------------
195------------------------------------------------------------------------------
196-- Scans
196-- Scans
src/Streamly/Internal/Data/Stream/SVar.hs+3−3
@@ -374,10 +374,10 @@ toSVarParallel st sv xs =
374 where
374 where
375
375
376 {-# NOINLINE work #-}
376 {-# NOINLINE work #-}
377− work info = D.foldOnce (write sv info) xs
377+ work info = D.fold (write sv info) xs
378
378
379 {-# NOINLINE workLim #-}
379 {-# NOINLINE workLim #-}
380− workLim info = D.foldOnce (writeLimited sv info) xs
380+ workLim info = D.fold (writeLimited sv info) xs
381
381
382 {-# NOINLINE forkWithDiag #-}
382 {-# NOINLINE forkWithDiag #-}
383 forkWithDiag = do
383 forkWithDiag = do
@@ -567,7 +567,7 @@ newFoldSVarF stt f = do
567 where
567 where
568
568
569 {-# NOINLINE work #-}
569 {-# NOINLINE work #-}
570− work sv = void $ D.foldOnce f $ fromProducerD sv
570+ work sv = void $ D.fold f $ fromProducerD sv
571
571
572-------------------------------------------------------------------------------
572-------------------------------------------------------------------------------
573-- Process events received by the producer thread from the consumer side
573-- Process events received by the producer thread from the consumer side
src/Streamly/Internal/Data/Stream/StreamD/Eliminate.hs+1−1
@@ -13,7 +13,7 @@
13module Streamly.Internal.Data.Stream.StreamD.Eliminate
13module Streamly.Internal.Data.Stream.StreamD.Eliminate
14 (
14 (
15 -- * Running a 'Fold'
15 -- * Running a 'Fold'
16− foldOnce -- XXX rename to "fold"
16+ fold
17
17
18 -- -- * Running a 'Parser'
18 -- -- * Running a 'Parser'
19 , parse
19 , parse
src/Streamly/Internal/Data/Stream/StreamD/Nesting.hs+4−4
@@ -1762,8 +1762,8 @@ splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1762 rh1 <- liftIO $ RB.unsafeInsert rb rh x
1762 rh1 <- liftIO $ RB.unsafeInsert rb rh x
1763 if idx == maxIndex
1763 if idx == maxIndex
1764 then do
1764 then do
1765− let fold = RB.unsafeFoldRing (RB.ringBound rb)
1765+ let fld = RB.unsafeFoldRing (RB.ringBound rb)
1766− let !ringHash = fold addCksum 0 rb
1766+ let !ringHash = fld addCksum 0 rb
1767 if ringHash == patHash
1767 if ringHash == patHash
1768 then skip $ SplitOnSeqKRCheck fs s rb rh1
1768 then skip $ SplitOnSeqKRCheck fs s rb rh1
1769 else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
1769 else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
@@ -2137,8 +2137,8 @@ splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2137 if idx /= maxIndex
2137 if idx /= maxIndex
2138 then go SPEC (idx + 1) rh1 s fs1
2138 then go SPEC (idx + 1) rh1 s fs1
2139 else skip $
2139 else skip $
2140− let fold = RB.unsafeFoldRing (RB.ringBound rb)
2140+ let fld = RB.unsafeFoldRing (RB.ringBound rb)
2141− !ringHash = fold addCksum 0 rb
2141+ !ringHash = fld addCksum 0 rb
2142 in if ringHash == patHash
2142 in if ringHash == patHash
2143 then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2143 then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2144 else SplitOnSuffixSeqKRLoop
2144 else SplitOnSuffixSeqKRLoop
src/Streamly/Internal/Data/Stream/StreamD/Transform.hs+1−1
@@ -346,7 +346,7 @@ pollCounts predicate transf fld (Stream step state) = Stream step' Nothing
346 -- However, an Int on a 32-bit machine may overflow quickly.
346 -- However, an Int on a 32-bit machine may overflow quickly.
347 countVar <- liftIO $ Prim.newIORef (0 :: Int)
347 countVar <- liftIO $ Prim.newIORef (0 :: Int)
348 tid <- forkManaged
348 tid <- forkManaged
349− $ void $ foldOnce fld
349+ $ void $ fold fld
350 $ transf $ Prim.toStreamD countVar
350 $ transf $ Prim.toStreamD countVar
351 return $ Skip (Just (countVar, tid, state))
351 return $ Skip (Just (countVar, tid, state))
352
352
src/Streamly/Internal/Data/Stream/StreamD/Type.hs+16−7
@@ -43,7 +43,8 @@ module Streamly.Internal.Data.Stream.StreamD.Type
43 , fromStreamD
43 , fromStreamD
44
44
45 -- * Running a 'Fold'
45 -- * Running a 'Fold'
46− , foldOnce
46+ , fold
47+ , fold_
47
48
48 -- * Right Folds
49 -- * Right Folds
49 , foldrT
50 , foldrT
@@ -268,13 +269,19 @@ toStreamD = fromStreamK . K.toStream
268-- Running a 'Fold'
269-- Running a 'Fold'
269------------------------------------------------------------------------------
270------------------------------------------------------------------------------
270
271
271−{-# INLINE_NORMAL foldOnce #-}
272+{-# INLINE_NORMAL fold #-}
272−foldOnce :: (Monad m) => Fold m a b -> Stream m a -> m b
273+fold :: (Monad m) => Fold m a b -> Stream m a -> m b
274+fold fld strm = do
275+ (b, _) <- fold_ fld strm
276+ return b
277+
278+{-# INLINE_NORMAL fold_ #-}
279+fold_ :: Monad m => Fold m a b -> Stream m a -> m (b, Stream m a)
273−foldOnce (Fold fstep begin done) (Stream step state) = do
280+fold_ (Fold fstep begin done) (Stream step state) = do
274 res <- begin
281 res <- begin
275 case res of
282 case res of
276 FL.Partial fs -> go SPEC fs state
283 FL.Partial fs -> go SPEC fs state
277− FL.Done fb -> return fb
284+ FL.Done fb -> return $! (fb, Stream step state)
278
285
279 where
286 where
280
287
@@ -285,10 +292,12 @@ foldOnce (Fold fstep begin done) (Stream step state) = do
285 Yield x s -> do
292 Yield x s -> do
286 res <- fstep fs x
293 res <- fstep fs x
287 case res of
294 case res of
288− FL.Done b -> return b
295+ FL.Done b -> return $! (b, Stream step s)
289 FL.Partial fs1 -> go SPEC fs1 s
296 FL.Partial fs1 -> go SPEC fs1 s
290 Skip s -> go SPEC fs s
297 Skip s -> go SPEC fs s
298+ Stop -> do
291− Stop -> done fs
299+ b <- done fs
300+ return $! (b, Stream (\ _ _ -> return Stop) ())
292
301
293------------------------------------------------------------------------------
302------------------------------------------------------------------------------
294-- Right Folds
303-- Right Folds
src/Streamly/Internal/Data/Stream/StreamK.hs+4−4
@@ -88,7 +88,7 @@ module Streamly.Internal.Data.Stream.StreamK
88 , foldlT
88 , foldlT
89 , foldlx'
89 , foldlx'
90 , foldlMx'
90 , foldlMx'
91− , foldOnce
91+ , fold
92
92
93 -- ** Specialized Folds
93 -- ** Specialized Folds
94 , drain
94 , drain
@@ -400,9 +400,9 @@ foldlMx' step begin done m = go begin m
400 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
400 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
401 in foldStream defState yieldk single stop m1
401 in foldStream defState yieldk single stop m1
402
402
403−{-# INLINABLE foldOnce #-}
403+{-# INLINABLE fold #-}
404−foldOnce :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> m b
404+fold :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> m b
405−foldOnce (FL.Fold step begin done) m = do
405+fold (FL.Fold step begin done) m = do
406 res <- begin
406 res <- begin
407 case res of
407 case res of
408 FL.Partial fs -> go fs m
408 FL.Partial fs -> go fs m
src/Streamly/Internal/Unicode/Stream.hs+1−1
@@ -182,7 +182,7 @@ utf8d =
182 unsafePerformIO
182 unsafePerformIO
183 -- Aligning to cacheline makes a barely noticeable difference
183 -- Aligning to cacheline makes a barely noticeable difference
184 -- XXX currently alignment is not implemented for unmanaged allocation
184 -- XXX currently alignment is not implemented for unmanaged allocation
185− $ D.foldOnce (A.writeNAlignedUnmanaged 64 (length decodeTable))
185+ $ D.fold (A.writeNAlignedUnmanaged 64 (length decodeTable))
186 (D.fromList decodeTable)
186 (D.fromList decodeTable)
187
187
188-- | Return element at the specified index without checking the bounds.
188-- | Return element at the specified index without checking the bounds.
test/Streamly/Test/Data/Fold.hs+23−8
@@ -1,7 +1,7 @@
1module Main (main) where
1module Main (main) where
2
2
3import Data.Semigroup (Sum(..), getSum)
3import Data.Semigroup (Sum(..), getSum)
4−import Streamly.Test.Common (checkListEqual)
4+import Streamly.Test.Common (checkListEqual, listEquals)
5import Test.QuickCheck
5import Test.QuickCheck
6 ( Gen
6 ( Gen
7 , Property
7 , Property
@@ -18,7 +18,8 @@ import Test.QuickCheck.Monadic (monadicIO, assert, run)
18
18
19import qualified Prelude
19import qualified Prelude
20import qualified Streamly.Internal.Data.Fold as F
20import qualified Streamly.Internal.Data.Fold as F
21−import qualified Streamly.Internal.Data.Stream.IsStream as S
21+import qualified Streamly.Prelude as S
22+import qualified Streamly.Internal.Data.Stream.IsStream as Stream
22import qualified Streamly.Data.Fold as FL
23import qualified Streamly.Data.Fold as FL
23
24
24import Prelude hiding
25import Prelude hiding
@@ -60,10 +61,9 @@ rollingHashFirstN =
60head :: [Int] -> Expectation
61head :: [Int] -> Expectation
61head ls = S.fold FL.head (S.fromList ls) `shouldReturn` headl ls
62head ls = S.fold FL.head (S.fromList ls) `shouldReturn` headl ls
62
63
63− where
64+headl :: [a] -> Maybe a
64−
65− headl [] = Nothing
65+headl [] = Nothing
66− headl (x:_) = Just x
66+headl (x:_) = Just x
67
67
68length :: [Int] -> Expectation
68length :: [Int] -> Expectation
69length ls = S.fold FL.length (S.fromList ls) `shouldReturn` Prelude.length ls
69length ls = S.fold FL.length (S.fromList ls) `shouldReturn` Prelude.length ls
@@ -424,15 +424,28 @@ many =
424 monadicIO $ do
424 monadicIO $ do
425 let strm = S.fromList lst
425 let strm = S.fromList lst
426 r1 <- S.fold (F.many (split i) F.toList) strm
426 r1 <- S.fold (F.many (split i) F.toList) strm
427− r2 <- S.toList $ S.foldMany (split i) strm
427+ r2 <- S.toList $ Stream.foldMany (split i) strm
428 assert $ r1 == r2
428 assert $ r1 == r2
429
429
430 where
430 where
431
431
432 split i = F.take i F.toList
432 split i = F.take i F.toList
433
433
434+headAndRest :: [Int] -> Property
435+headAndRest ls = monadicIO $ do
436+ (mbh, rest) <- run $ Stream.fold_ FL.head (S.fromList ls)
437+ rests <- run $ S.toList rest
438+ assert (mbh == headl ls)
439+ listEquals (==) rests (taill ls)
440+
441+ where
442+
443+ taill :: [a] -> [a]
444+ taill [] = []
445+ taill (_:xs) = xs
446+
434main :: IO ()
447main :: IO ()
435−main = hspec $
448+main = hspec $ do
436 describe "Fold" $ do
449 describe "Fold" $ do
437 -- Folds
450 -- Folds
438 -- Accumulators
451 -- Accumulators
@@ -510,3 +523,5 @@ main = hspec $
510 prop "many" Main.many
523 prop "many" Main.many
511 -- concatMap
524 -- concatMap
512 -- chunksOf
525 -- chunksOf
526+ describe "FoldAndReturn s" $ do
527+ prop "head from fold_" headAndRest
test/Streamly/Test/FileSystem/Handle.hs+2−2
@@ -120,7 +120,7 @@ testWrite hfold =
120 writeFile fpathWrite ""
120 writeFile fpathWrite ""
121 h <- openFile fpathWrite ReadWriteMode
121 h <- openFile fpathWrite ReadWriteMode
122 hSeek h AbsoluteSeek 0
122 hSeek h AbsoluteSeek 0
123− Stream.fold (hfold h) $ Stream.fromList list
123+ _ <- Stream.fold (hfold h) $ Stream.fromList list
124 hFlush h
124 hFlush h
125 hSeek h AbsoluteSeek 0
125 hSeek h AbsoluteSeek 0
126 ls <- Stream.toList $ Stream.unfold Handle.read h
126 ls <- Stream.toList $ Stream.unfold Handle.read h
@@ -144,7 +144,7 @@ testWriteWithChunk =
144 hr <- openFile fpathRead ReadMode
144 hr <- openFile fpathRead ReadMode
145 hw <- openFile fpathWrite ReadWriteMode
145 hw <- openFile fpathWrite ReadWriteMode
146 hSeek hw AbsoluteSeek 0
146 hSeek hw AbsoluteSeek 0
147− Stream.fold (Handle.writeChunks hw)
147+ _ <- Stream.fold (Handle.writeChunks hw)
148 $ Stream.unfold Handle.readChunksWithBufferOf (1024, hr)
148 $ Stream.unfold Handle.readChunksWithBufferOf (1024, hr)
149 hFlush hw
149 hFlush hw
150 hSeek hw AbsoluteSeek 0
150 hSeek hw AbsoluteSeek 0