@@ -595,8 +595,16 @@ forkSVarAhead m1 m2 = mkStream $ \st yld sng stp -> do
595595
596596infixr 6 `ahead`
597597
598−-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AheadT'.
599−-- Merges two streams sequentially but with concurrent lookahead.
598+-- | Appends two streams, some future actions may be evaluated concurrently,
599+-- ahead of time. The behavior is similar to 'consM' for 'AheadT' streams:
600+--
601+-- >>> stream = Stream.yieldM (delay 2) `ahead` Stream.yieldM (delay 1)
602+-- >>> Stream.toList stream -- IO [Int]
603+-- 1 sec
604+-- 2 sec
605+-- [2,1]
606+--
607+-- This operation can be used to fold an infinite lazy container of streams.
600608--
601609-- /Since: 0.3.0 ("Streamly")/
602610--
@@ -625,46 +633,43 @@ consMAhead m r = fromStream $ K.yieldM m `ahead` (toStream r)
625633-- AheadT
626634------------------------------------------------------------------------------
627635
628−-- | The 'Semigroup' operation for 'AheadT' appends two streams. The combined
629−-- stream behaves like a single stream with the actions from the second stream
630−-- appended to the first stream. The combined stream is evaluated in the
631−-- speculative style. This operation can be used to fold an infinite lazy
632−-- container of streams.
636+-- | For 'AheadT' streams:
633637--
634638-- @
635−-- import "Streamly.Prelude"
636−-- import qualified "Streamly.Prelude" as S
637−-- import Control.Concurrent
638−--
639−-- main = do
640−-- xs \<- S.'toList' . S.'aheadly' $ (p 1 |: p 2 |: nil) <> (p 3 |: p 4 |: nil)
641−-- print xs
642−-- where p n = threadDelay 1000000 >> return n
643−-- @
644−-- @
645−-- [1,2,3,4]
639+-- (<>) = 'Streamly.Prelude.ahead'
640+-- (>>=) = flip . 'Streamly.Prelude.concatMapWith' 'Streamly.Prelude.ahead'
646641-- @
647642--
648−-- Any exceptions generated by a constituent stream are propagated to the
649−-- output stream.
643+-- Any exceptions generated by concurrent evaluation are propagated to the
644+-- output stream as soon as they occur.
650645--
651−-- The monad instance of 'AheadT' may run each monadic continuation (bind)
652−-- concurrently in a speculative manner, performing side effects in a partially
653−-- ordered manner but producing the outputs in an ordered manner like
654−-- 'SerialT'.
646+-- A single 'Monad' bind behaves like a @for@ loop with iterations executed
647+-- concurrently, ahead of time, producing side effects of iterations out of
648+-- order, but results in order:
655649--
656−-- @
657−-- main = S.drain . S.'aheadly' $ do
658−-- n <- return 3 \<\> return 2 \<\> return 1
659−-- S.yieldM $ do
660−-- threadDelay (n * 1000000)
661−-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
662−-- @
663−-- @
664−-- ThreadId 40: Delay 1
665−-- ThreadId 39: Delay 2
666−-- ThreadId 38: Delay 3
667−-- @
650+-- >>> :{
651+-- Stream.toList $ Stream.aheadly $ do
652+-- x <- Stream.fromList [2,1] -- foreach x in stream
653+-- Stream.yieldM $ delay x
654+-- :}
655+-- 1 sec
656+-- 2 sec
657+-- [2,1]
658+--
659+-- Nested monad binds behave like nested @for@ loops with nested iterations
660+-- executed concurrently, ahead of time:
661+--
662+-- >>> :{
663+-- Stream.toList $ Stream.aheadly $ do
664+-- x <- Stream.fromList [1,2] -- foreach x in stream
665+-- y <- Stream.fromList [2,4] -- foreach y in stream
666+-- Stream.yieldM $ delay (x + y)
667+-- :}
668+-- 3 sec
669+-- 4 sec
670+-- 5 sec
671+-- 6 sec
672+-- [3,5,4,6]
668673--
669674-- /Since: 0.3.0 ("Streamly")/
670675--