on master help sign in
Use monadic seed in monadic scanning combinators.

- The following functions are updated: scanlM, scanlM', postscanlM, postscanlM', prescanlM'. - Update Changelog.md.

commit8061c97a76888470243fa156f7c1a30e205cf400 authorpranaysashank <pranaysashank@composewell.com> dateTue 8 Sep 2020, 17:15 (6 years ago) parent345fa5d
6 files changed+81−41
Changelog.md+2 benchmark/Streamly/Benchmark/Prelude/Serial.hs+3−3 src/Streamly/Internal/Data/Stream/IsStream.hs+12−8 src/Streamly/Internal/Data/Stream/StreamD.hs+53−19 test/Streamly/Test/Prelude/Common.hs+10−10 test/Streamly/Test/Prelude/Fold.hs+1−1
Changelog.md+2
@@ -11,6 +11,8 @@
1111* Deprecate `Streamly.Data.Unicode.Stream` in favor of `Streamly.Unicode.Stream`
1212* Change the signature of `foldlM'` to make the initial value of the
1313 accumulator monadic.
14+* Change the signature of `scanlM'`, `postscanlM'` to make the initial value of
15+ the accumulator monadic.
1416* Change the signature of `concatMapWith` to ensure that it can be
1517 used with a wide variety of combining functions.
1618* Exception handling functions `bracket`, `handle`, `finally` now
benchmark/Streamly/Benchmark/Prelude/Serial.hs+3−3
@@ -861,7 +861,7 @@ scan n = composeN n $ S.scanl' (+) 0
861861
862862{-# INLINE scanlM' #-}
863863scanlM' :: MonadIO m => Int -> SerialT m Int -> m ()
864−scanlM' n = composeN n $ S.scanlM' (\b a -> return $ b + a) 0
864+scanlM' n = composeN n $ S.scanlM' (\b a -> return $ b + a) (return 0)
865865
866866{-# INLINE scanl1' #-}
867867scanl1' :: MonadIO m => Int -> SerialT m Int -> m ()
@@ -873,7 +873,7 @@ postscanl' n = composeN n $ S.postscanl' (+) 0
873873
874874{-# INLINE postscanlM' #-}
875875postscanlM' :: MonadIO m => Int -> SerialT m Int -> m ()
876−postscanlM' n = composeN n $ S.postscanlM' (\b a -> return $ b + a) 0
876+postscanlM' n = composeN n $ S.postscanlM' (\b a -> return $ b + a) (return 0)
877877
878878{-# INLINE sequence #-}
879879sequence ::
@@ -983,7 +983,7 @@ sieveScan =
983983 let ps = takeWhile (\p -> p * p <= n) primes
984984 in if P.all (\p -> n `mod` p /= 0) ps
985985 then (primes ++ [n], Just n)
986− else (primes, Nothing)) ([2], Just 2)
986+ else (primes, Nothing)) (return ([2], Just 2))
987987
988988o_n_space_mapping :: Int -> [Benchmark]
989989o_n_space_mapping value =
src/Streamly/Internal/Data/Stream/IsStream.hs+12−8
@@ -2201,11 +2201,13 @@ scanx = P.scanlx'
22012201-- complexity when iterated over a stream. We should use StreamK style scanlM'
22022202-- for linear performance on iteration.
22032203--
2204−-- | Like 'scanl'' but with a monadic fold function.
2204+-- | Like 'scanl'' but with a monadic step function and a monadic seed.
22052205--
2206−-- @since 0.4.0
2206+-- /Since: 0.4.0/
2207+--
2208+-- /Since: 0.8.0 (signature change)/
22072209{-# INLINE scanlM' #-}
2208−scanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> t m b
2210+scanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
22092211scanlM' step begin m = fromStreamD $ D.scanlM' step begin $ toStreamD m
22102212
22112213-- | @scanlMAfter' accumulate initial done stream@ is like 'scanlM'' except
@@ -2290,11 +2292,13 @@ postscanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
22902292postscanl' step z m = fromStreamD $ D.postscanl' step z $ toStreamD m
22912293
22922294-- XXX this needs to be concurrent
2293−-- | Like 'postscanl'' but with a monadic step function.
2295+-- | Like 'postscanl'' but with a monadic step function and a monadic seed.
22942296--
2295−-- @since 0.7.0
2297+-- /Since: 0.7.0/
2298+--
2299+-- /Since: 0.8.0 (signature change)/
22962300{-# INLINE postscanlM' #-}
2297−postscanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> t m b
2301+postscanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
22982302postscanlM' step z m = fromStreamD $ D.postscanlM' step z $ toStreamD m
22992303
23002304-- XXX prescanl does not sound very useful, enable only if there is a
@@ -2308,7 +2312,7 @@ prescanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
23082312prescanl' step z m = fromStreamD $ D.prescanl' step z $ toStreamD m
23092313
23102314-- XXX this needs to be concurrent
2311−-- | Like postscanl' but with a monadic step function.
2315+-- | Like prescanl' but with a monadic step function and a monadic seed.
23122316--
23132317-- /Internal/
23142318{-# INLINE prescanlM' #-}
@@ -2605,7 +2609,7 @@ smapM step initial stream =
26052609 -- stream
26062610 let r = concatMap
26072611 (\s0 ->
2608− postscanlM' (\(s, _) a -> step s a) (s0, undefined) stream
2612+ postscanlM' (\(s, _) a -> step s a) (return (s0, undefined)) stream
26092613 )
26102614 (yieldM initial)
26112615 in Serial.map snd r
src/Streamly/Internal/Data/Stream/StreamD.hs+53−19
@@ -3616,23 +3616,27 @@ scanlx' fstep begin done s =
36163616------------------------------------------------------------------------------
36173617
36183618{-# INLINE_NORMAL postscanlM' #-}
3619−postscanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3619+postscanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
36203620postscanlM' fstep begin (Stream step state) =
3621− begin `seq` Stream step' (state, begin)
3621+ Stream step' Nothing
36223622 where
36233623 {-# INLINE_LATE step' #-}
3624− step' gst (st, acc) = acc `seq` do
3624+ step' _ Nothing = do
3625+ !x <- begin
3626+ return $ Skip (Just (state, x))
3627+
3628+ step' gst (Just (st, acc)) = do
36253629 r <- step (adaptState gst) st
36263630 case r of
36273631 Yield x s -> do
3628− y <- fstep acc x
3629− y `seq` return (Yield y (s, y))
3630− Skip s -> return $ Skip (s, acc)
3632+ !y <- fstep acc x
3633+ return $ Yield y (Just (s, y))
3634+ Skip s -> return $ Skip (Just (s, acc))
36313635 Stop -> return Stop
36323636
36333637{-# INLINE_NORMAL postscanl' #-}
36343638postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
3635−postscanl' f = postscanlM' (\a b -> return (f a b))
3639+postscanl' f seed = postscanlM' (\a b -> return (f a b)) (return seed)
36363640
36373641-- We can possibly have the "done" function as a Maybe to provide an option to
36383642-- emit or not emit the accumulator when the stream stops.
@@ -3660,26 +3664,43 @@ postscanlMAfter' fstep initial done (Stream step1 state1) = do
36603664 step _ Nothing = return Stop
36613665
36623666{-# INLINE_NORMAL postscanlM #-}
3663−postscanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3664−postscanlM fstep begin (Stream step state) = Stream step' (state, begin)
3667+postscanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
3668+postscanlM fstep begin (Stream step state) = Stream step' Nothing
36653669 where
36663670 {-# INLINE_LATE step' #-}
3667− step' gst (st, acc) = do
3671+ step' _ Nothing = do
3672+ r <- begin
3673+ return $ Skip (Just (state, r))
3674+
3675+ step' gst (Just (st, acc)) = do
36683676 r <- step (adaptState gst) st
36693677 case r of
36703678 Yield x s -> do
36713679 y <- fstep acc x
3672− return (Yield y (s, y))
3673− Skip s -> return $ Skip (s, acc)
3680+ return (Yield y (Just (s, y)))
3681+ Skip s -> return $ Skip (Just (s, acc))
36743682 Stop -> return Stop
36753683
36763684{-# INLINE_NORMAL postscanl #-}
36773685postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
3678−postscanl f = postscanlM (\a b -> return (f a b))
3686+postscanl f seed = postscanlM (\a b -> return (f a b)) (return seed)
36793687
36803688{-# INLINE_NORMAL scanlM' #-}
3681−scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3682−scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
3689+scanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
3690+scanlM' fstep begin (Stream step state) = Stream step' Nothing
3691+ where
3692+ {-# INLINE_LATE step' #-}
3693+ step' _ Nothing = do
3694+ !x <- begin
3695+ return $ Yield x (Just (state, x))
3696+ step' gst (Just (st, acc)) = do
3697+ r <- step (adaptState gst) st
3698+ case r of
3699+ Yield x s -> do
3700+ !y <- fstep acc x
3701+ return $ Yield y (Just (s, y))
3702+ Skip s -> return $ Skip (Just (s, acc))
3703+ Stop -> return Stop
36833704
36843705{-# INLINE scanlMAfter' #-}
36853706scanlMAfter' :: Monad m
@@ -3690,15 +3711,28 @@ scanlMAfter' fstep initial done s =
36903711
36913712{-# INLINE scanl' #-}
36923713scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3693−scanl' f = scanlM' (\a b -> return (f a b))
3714+scanl' f seed = scanlM' (\a b -> return (f a b)) (return seed)
36943715
36953716{-# INLINE_NORMAL scanlM #-}
3696−scanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3697−scanlM fstep begin s = begin `cons` postscanlM fstep begin s
3717+scanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
3718+scanlM fstep begin (Stream step state) = Stream step' Nothing
3719+ where
3720+ {-# INLINE_LATE step' #-}
3721+ step' _ Nothing = do
3722+ x <- begin
3723+ return $ Yield x (Just (state, x))
3724+ step' gst (Just (st, acc)) = do
3725+ r <- step (adaptState gst) st
3726+ case r of
3727+ Yield x s -> do
3728+ y <- fstep acc x
3729+ return $ Yield y (Just (s, y))
3730+ Skip s -> return $ Skip (Just (s, acc))
3731+ Stop -> return $ Stop
36983732
36993733{-# INLINE scanl #-}
37003734scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3701−scanl f = scanlM (\a b -> return (f a b))
3735+scanl f seed = scanlM (\a b -> return (f a b)) (return seed)
37023736
37033737{-# INLINE_NORMAL scanl1M #-}
37043738scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
test/Streamly/Test/Prelude/Common.hs+10−10
@@ -642,8 +642,8 @@ bindAndComposeHierarchyOps ::
642642bindAndComposeHierarchyOps desc t1 = do
643643 let fldldesc = "Bind and compose foldl, " <> desc <> " Stream "
644644 fldrdesc = "Bind and compose foldr, " <> desc <> " Stream "
645−
646− bindAndComposeHierarchy
645+
646+ bindAndComposeHierarchy
647647 (fldldesc <> "serially") S.serially fldl
648648 bindAndComposeHierarchy
649649 (fldrdesc <> "serially") S.serially fldr
@@ -707,21 +707,21 @@ bindAndComposeHierarchyOps desc t1 = do
707707 mx >>= \x -> my
708708 >>= \y -> mz
709709 >>= \z -> return (x + y + z)
710−
711− fldr, fldl :: (IsStream t, Semigroup (t IO Int))
710+
711+ fldr, fldl :: (IsStream t, Semigroup (t IO Int))
712712 => [t IO Int] -> t IO Int
713713 fldr = foldr (<>) nil
714714 fldl = foldl (<>) nil
715715
716716-- Nest two lists using different styles of product compositions
717−nestTwoStreams
717+nestTwoStreams
718718 :: (IsStream t, Semigroup (t IO Int), Monad (t IO))
719719 => String
720720 -> ([Int] -> [Int])
721721 -> ([Int] -> [Int])
722722 -> (t IO Int -> SerialT IO Int)
723723 -> Spec
724−nestTwoStreams desc streamListT listT t =
724+nestTwoStreams desc streamListT listT t =
725725 it ("Nests two streams using monadic " <> desc <> " composition") $ do
726726 let s1 = S.concatMapFoldableWith (<>) return [1..4]
727727 s2 = S.concatMapFoldableWith (<>) return [5..8]
@@ -731,19 +731,19 @@ nestTwoStreams desc streamListT listT t =
731731 return $ x + y
732732 streamListT r `shouldBe` listT [6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12]
733733
734−nestTwoStreamsApp
734+nestTwoStreamsApp
735735 :: (IsStream t, Semigroup (t IO Int), Monad (t IO))
736736 => String
737737 -> ([Int] -> [Int])
738738 -> ([Int] -> [Int])
739739 -> (t IO Int -> SerialT IO Int)
740740 -> Spec
741−nestTwoStreamsApp desc streamListT listT t =
741+nestTwoStreamsApp desc streamListT listT t =
742742 it ("Nests two streams using applicative " <> desc <> " composition") $ do
743743 let s1 = S.concatMapFoldableWith (<>) return [1..4]
744744 s2 = S.concatMapFoldableWith (<>) return [5..8]
745745 r = (S.toList . t) $ ((+) <$> s1 <*> s2)
746− streamListT <$> r
746+ streamListT <$> r
747747 `shouldReturn` listT [6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12]
748748
749749
@@ -926,7 +926,7 @@ transformCombineOpsCommon constr desc eq t = do
926926 prop (desc <> " scanl'") $ transform (scanl' (flip const) 0) t
927927 (S.scanl' (flip const) 0)
928928 prop (desc <> " scanlM'") $ transform (scanl' (flip const) 0) t
929− (S.scanlM' (\_ a -> return a) 0)
929+ (S.scanlM' (\_ a -> return a) (return 0))
930930 prop (desc <> " scanl") $ transform (scanl' (flip const) 0) t
931931 (S.scanl' (flip const) 0)
932932 prop (desc <> " scanl1'") $ transform (scanl1 (flip const)) t
test/Streamly/Test/Prelude/Fold.hs+1−1
@@ -114,7 +114,7 @@ foldlM'StrictCheck :: IORef Int -> SerialT IO Int -> IO ()
114114foldlM'StrictCheck ref = S.foldlM' (\_ _ -> writeIORef ref 1) (return ())
115115
116116scanlM'StrictCheck :: IORef Int -> SerialT IO Int -> SerialT IO ()
117−scanlM'StrictCheck ref = S.scanlM' (\_ _ -> writeIORef ref 1) ()
117+scanlM'StrictCheck ref = S.scanlM' (\_ _ -> writeIORef ref 1) (return ())
118118
119119checkScanlMStrictness :: (IORef Int -> SerialT IO Int -> SerialT IO ()) -> IO ()
120120checkScanlMStrictness f = do