@@ -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------------------------------------------------------------------------------