on master help sign in
Fix delayPost, add more interspersing combinators

delayPost was actually behaving like delayPre, fixed it. Added: trace_, intersperseM_, interspersePrefix_, delayPre

commit7013f3a5e45538ab9d613ff06e88ba9f6bc457ad authorHarendra Kumar <harendra@composewell.com> dateWed 27 May 2020, 19:26 (6 years ago) parent7f9d4a4
2 files changed+124−15
src/Streamly/Internal/Data/Stream/StreamD.hs+30 src/Streamly/Internal/Prelude.hs+94−15
src/Streamly/Internal/Data/Stream/StreamD.hs+30
@@ -269,8 +269,10 @@ module Streamly.Internal.Data.Stream.StreamD
269269
270270 -- * Inserting
271271 , intersperseM
272+ , intersperseM_
272273 , intersperse
273274 , intersperseSuffix
275+ , intersperseSuffix_
274276 , intersperseSuffixBySpan
275277 , insertBy
276278
@@ -4023,6 +4025,20 @@ intersperseM m (Stream step state) = Stream step' (FirstYield state)
40234025
40244026 step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
40254027
4028+{-# INLINE_NORMAL intersperseM_ #-}
4029+intersperseM_ :: Monad m => m b -> Stream m a -> Stream m a
4030+intersperseM_ m (Stream step1 state1) = Stream step (Left (pure (), state1))
4031+ where
4032+ {-# INLINE_LATE step #-}
4033+ step gst (Left (eff, st)) = do
4034+ r <- step1 gst st
4035+ case r of
4036+ Yield x s -> eff >> return (Yield x (Right s))
4037+ Skip s -> return $ Skip (Left (eff, s))
4038+ Stop -> return Stop
4039+
4040+ step _ (Right st) = return $ Skip $ Left (void m, st)
4041+
40264042data SuffixState s a
40274043 = SuffixElem s
40284044 | SuffixSuffix s
@@ -4045,6 +4061,20 @@ intersperseSuffix action (Stream step state) = Stream step' (SuffixElem state)
40454061
40464062 step' _ (SuffixYield x next) = return $ Yield x next
40474063
4064+{-# INLINE_NORMAL intersperseSuffix_ #-}
4065+intersperseSuffix_ :: Monad m => m b -> Stream m a -> Stream m a
4066+intersperseSuffix_ m (Stream step1 state1) = Stream step (Left state1)
4067+ where
4068+ {-# INLINE_LATE step #-}
4069+ step gst (Left st) = do
4070+ r <- step1 gst st
4071+ case r of
4072+ Yield x s -> return $ Yield x (Right s)
4073+ Skip s -> return $ Skip $ Left s
4074+ Stop -> m >> return Stop
4075+
4076+ step _ (Right st) = m >> return (Skip (Left st))
4077+
40484078data SuffixSpanState s a
40494079 = SuffixSpanElem s Int
40504080 | SuffixSpanSuffix s
src/Streamly/Internal/Prelude.hs+94−15
@@ -191,6 +191,7 @@ module Streamly.Internal.Prelude
191191 -- ** Special Maps
192192 , mapM_
193193 , trace
194+ , trace_
194195 , tap
195196 , tapOffsetEvery
196197 , tapAsync
@@ -252,8 +253,10 @@ module Streamly.Internal.Prelude
252253
253254 , insertBy
254255 , intersperseM
256+ , intersperseM_
255257 , intersperse
256258 , intersperseSuffix
259+ , interspersePrefix_
257260 , intersperseSuffixBySpan
258261 -- , intersperseBySpan
259262 -- , intersperseByIndices -- using an index function/stream
@@ -263,6 +266,7 @@ module Streamly.Internal.Prelude
263266 -- , intersperseByEvent
264267 , interjectSuffix
265268 , delayPost
269+ , delayPre
266270
267271 -- ** Indexing
268272 , indexed
@@ -2458,13 +2462,21 @@ reverse' s = fromStreamD $ D.reverse' $ toStreamD s
24582462
24592463-- intersperseM = intersperseBySpan 1
24602464
2461−-- | Generate a stream by inserting the result of a monadic action between
2462−-- consecutive elements of the given stream. Note that the monadic action is
2463−-- performed after the stream action before which its result is inserted.
2465+-- | Insert the result of an effectful action between consecutive elements of
2466+-- the stream.
24642467--
24652468-- @
2466−-- > S.toList $ S.intersperseM (return ',') $ S.fromList "hello"
2467−-- "h,e,l,l,o"
2469+-- >>> S.toList $ S.trace putChar $ S.intersperseM (putChar '.' >> return ',') $ S.fromList "hello"
2470+-- > h.,e.,l.,l.,o"h,e,l,l,o"
2471+-- @
2472+--
2473+-- After yielding the first element, for every next element the effectful
2474+-- action is evaluated /after/ generating the element, however, its result is
2475+-- yielded /before/ the element.
2476+--
2477+-- @
2478+-- > S.toList $ S.intersperseM (putChar '.' >> return ',') $ S.trace putChar $ S.fromList "hello"
2479+-- he.l.l.o."h,e,l,l,o"
24682480-- @
24692481--
24702482-- @since 0.5.0
@@ -2472,8 +2484,27 @@ reverse' s = fromStreamD $ D.reverse' $ toStreamD s
24722484intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
24732485intersperseM m = fromStreamS . S.intersperseM m . toStreamS
24742486
2475−-- | Generate a stream by inserting a given element between consecutive
2476−-- elements of the given stream.
2487+-- | Insert a side effect between consecutive elements of the stream.
2488+--
2489+-- @
2490+-- >>> S.drain $ S.trace putChar $ S.intersperseM_ (putChar '.') $ S.fromList "hello"
2491+-- > h.e.l.l.o
2492+-- @
2493+--
2494+-- After yielding the first element, for every next element the effect
2495+-- is evaluated after generating the element but before yielding it.
2496+--
2497+-- @
2498+-- >>> S.drain $ S.intersperseM_ (putChar '.') $ S.trace putChar $ S.fromList "hello"
2499+-- > he.l.l.o.
2500+-- @
2501+--
2502+-- /Internal/
2503+{-# INLINE intersperseM_ #-}
2504+intersperseM_ :: (IsStream t, MonadAsync m) => m b -> t m a -> t m a
2505+intersperseM_ m = fromStreamD . D.intersperseM_ m . toStreamD
2506+
2507+-- | Insert a pure value between successive elements of a stream.
24772508--
24782509-- @
24792510-- > S.toList $ S.intersperse ',' $ S.fromList "hello"
@@ -2485,16 +2516,19 @@ intersperseM m = fromStreamS . S.intersperseM m . toStreamS
24852516intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
24862517intersperse a = fromStreamS . S.intersperse a . toStreamS
24872518
2488−-- | Insert a monadic action after each element in the stream.
2519+-- | Insert an effectful action after each element of a stream.
2520+--
2521+-- @
2522+-- >>> S.toList $ S.trace putChar $ S.intersperseSuffix (putChar '.' >> return ',') $ S.fromList "hello"
2523+-- > h.,e.,l.,l.,o.,"h,e,l,l,o,"
2524+-- @
24892525--
24902526-- /Internal/
24912527{-# INLINE intersperseSuffix #-}
24922528intersperseSuffix :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
24932529intersperseSuffix m = fromStreamD . D.intersperseSuffix m . toStreamD
24942530
2495−-- | Perform a side effect after each element of a stream. The output of the
2496−-- effectful action is discarded, therefore, the input stream remains
2497−-- unchanged.
2531+-- | Insert a side effect after each element of a stream.
24982532--
24992533-- @
25002534-- > S.mapM_ putChar $ S.intersperseSuffix_ (threadDelay 1000000) $ S.fromList "hello"
@@ -2504,9 +2538,28 @@ intersperseSuffix m = fromStreamD . D.intersperseSuffix m . toStreamD
25042538--
25052539{-# INLINE intersperseSuffix_ #-}
25062540intersperseSuffix_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
2507−intersperseSuffix_ m = Serial.mapM (\x -> void m >> return x)
2541+intersperseSuffix_ m = fromStreamD . D.intersperseSuffix_ m . toStreamD
2542+
2543+-- | Insert a side effect before each element of a stream.
2544+--
2545+-- @
2546+-- >>> S.toList $ S.trace putChar $ S.interspersePrefix_ (putChar '.' >> return ',') $ S.fromList "hello"
2547+-- > .h.e.l.l.o"hello"
2548+-- @
2549+--
2550+-- See also: 'trace_'
2551+--
2552+-- /Concurrent/
2553+--
2554+-- /Internal/
2555+--
2556+{-# INLINE interspersePrefix_ #-}
2557+interspersePrefix_ :: (IsStream t, MonadAsync m) => m b -> t m a -> t m a
2558+interspersePrefix_ m = mapM (\x -> void m >> return x)
25082559
2509−-- | Introduces a delay of specified seconds after each element of a stream.
2560+-- Note: delay must be serial.
2561+--
2562+-- | Introduce a delay of specified seconds after each element of a stream.
25102563--
25112564-- /Internal/
25122565--
@@ -2514,8 +2567,18 @@ intersperseSuffix_ m = Serial.mapM (\x -> void m >> return x)
25142567delayPost :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
25152568delayPost n = intersperseSuffix_ $ liftIO $ threadDelay $ round $ n * 1000000
25162569
2517−-- | Like 'intersperseSuffix' but intersperses a monadic action into the input
2518−-- stream after every @n@ elements and after the last element.
2570+-- Note: delay must be serial, that's why 'trace_' is used.
2571+--
2572+-- | Introduce a delay of specified seconds before each element of a stream.
2573+--
2574+-- /Internal/
2575+--
2576+{-# INLINE delayPre #-}
2577+delayPre :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
2578+delayPre n = trace_ $ liftIO $ threadDelay $ round $ n * 1000000
2579+
2580+-- | Like 'intersperseSuffix' but intersperses an effectful action into the
2581+-- input stream after every @n@ elements and after the last element.
25192582--
25202583-- @
25212584-- > S.toList $ S.intersperseSuffixBySpan 2 (return ',') $ S.fromList "hello"
@@ -4094,6 +4157,22 @@ tapRate n f xs = D.fromStreamD $ D.tapRate n f $ D.toStreamD xs
40944157trace :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m a
40954158trace f = mapM (\x -> void (f x) >> return x)
40964159
4160+-- | Perform a side effect before yielding each element of the stream and
4161+-- discard the results.
4162+--
4163+-- @
4164+-- > S.drain $ S.trace_ (print "got here") (S.enumerateFromTo 1 2)
4165+-- "got here"
4166+-- "got here"
4167+-- @
4168+--
4169+-- See also: 'trace', 'interspersePrefix_'
4170+--
4171+-- /Internal/
4172+{-# INLINE trace_ #-}
4173+trace_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
4174+trace_ eff = Serial.mapM (\x -> eff >> return x)
4175+
40974176------------------------------------------------------------------------------
40984177-- Windowed classification
40994178------------------------------------------------------------------------------