@@ -14,43 +14,100 @@ results together and consume the resulting stream concurrently.
14First, distribute an item to multiple effectful consumer concurrently, for
14First, distribute an item to multiple effectful consumer concurrently, for
17+- Create a stream of actions.
18+- Sequence the actions concurrently.
19+ - Note that we respect the order of input. (`Config.ordered True`)
17−```haskell
21+```haskell ghci
22+{-# LANGUAGE FlexibleContexts #-}
18import Data.Function ((&))
24import Data.Function ((&))
19−import qualified Streamly.Prelude as Stream
25+import qualified Streamly.Data.Fold as Fold
26+import qualified Streamly.Data.Stream as Stream
27+import qualified Streamly.Data.Stream.Concurrent as Concur
22− Prelude.map ($ x) [return . (+ 1), return . (+ 2)]
30+ Prelude.map ($ x) [return . (+ 1), return . (+ 2)] -- List of actions
23− & Stream.fromListM
31+ & Stream.fromList -- Stream of actions
24− & Stream.fromAhead
32+ & Concur.sequenceWith (Concur.ordered True) -- Sequence the actions concurrently
25− & Stream.toList
33+ & Stream.fold Fold.toList -- Fold the resulting stream into a list
28Alternatively, if you want to concurrently zip different types of outputs, you
36Alternatively, if you want to concurrently zip different types of outputs, you
39+- Create 2 streams of actions.
40+- Sequence the actions concurrently.
41+- Zip the resulting streams.
44+import Data.Maybe (fromJust)
47+ let actionStream1 = Stream.fromPure (return $ show x)
48+ actionStream2 = Stream.fromPure (return $ x + 1)
49+ actionStream3 = Stream.fromPure (return $ fromIntegral x / 2)
50+ in Stream.zipWith (\a (b, c) -> (a, b, c))
51+ (Concur.sequence actionStream1)
53+ (Concur.sequence actionStream2)
54+ (Concur.sequence actionStream3))
55+ & Stream.fold Fold.one
59+Alternatively, generate a type with concurrent zipping property to use the
29−can use `Applicative` composition:
60+`Applicative` instance,
63+{-# LANGUAGE UndecidableInstances #-}
64+{-# LANGUAGE FlexibleInstances #-}
65+{-# LANGUAGE MultiParamTypeClasses #-}
66+{-# LANGUAGE TemplateHaskell #-}
68+import Control.Monad.Catch (MonadThrow(..))
69+import Control.Monad.IO.Class (MonadIO(..))
70+import Control.Monad.Reader.Class (MonadReader(..))
71+import Control.Monad.Trans.Class (MonadTrans(..))
72+import Data.Function ((&))
32import Data.Maybe (fromJust)
73import Data.Maybe (fromJust)
74+import Streamly.Data.Stream (Stream)
75+import Streamly.Data.Stream.Concurrent (MonadAsync)
77+import qualified Streamly.Data.Fold as Fold
78+import qualified Streamly.Data.Stream
79+import qualified Streamly.Data.Stream as Stream
80+import qualified Streamly.Data.Stream.Concurrent
81+import qualified Streamly.Data.Stream.Concurrent as Concur
82+import qualified Streamly.Internal.Data.Stream.TypeGen as StreamTypeGen
84+applyConcurrent :: MonadAsync m => Stream m (a -> b) -> Stream m a -> Stream m b
85+applyConcurrent = Concur.zipWith ($)
87+$(StreamTypeGen.mkZippingType "ZipConcurrent" "applyConcurrent" True)
35− <$> Stream.fromEffect (return $ show x)
90+ let actionStream1 = Stream.fromEffect (return $ show x)
36− <*> Stream.fromEffect (return $ x + 1)
91+ actionStream2 = Stream.fromEffect (return $ x + 1)
37− <*> Stream.fromEffect (return $ fromIntegral x / 2)
92+ actionStream3 = Stream.fromEffect (return $ fromIntegral x / 2)
38− & Stream.fromAsync
93+ in ((,,,)
39− & Stream.head
97+ & Stream.fold Fold.one
40− & fmap fromJust
98+ & fmap fromJust
43Then apply the function `f` concurrently to your input stream:
101Then apply the function `f` concurrently to your input stream:
45−```haskell
103+```haskell ghci
47 Stream.fromList xs
105 Stream.fromList xs
48− & Stream.mapM f
106+ & Concur.mapMWith (Concur.ordered True) f -- Map the actions concurrently
49− & Stream.fromAhead
107+ & Stream.fold Fold.toList
53−```
110+```haskell docspec
54>>> g f1 [1,2,3,4::Int]
111>>> g f1 [1,2,3,4::Int]
55[[2,3],[3,4],[4,5],[5,6]]
112[[2,3],[3,4],[4,5],[5,6]]
@@ -60,11 +117,12 @@ g f xs =
61## Sliding Window
118## Sliding Window
63−```
120+```haskell docspec
121+>>> import qualified Streamly.Internal.Data.Array as Array
65 Stream.fromList [1,2,3,4,5::Int]
123 Stream.fromList [1,2,3,4,5::Int]
66& Stream.scan (Array.writeLastN 2)
124& Stream.scan (Array.writeLastN 2)
67−& Stream.toList
125+& Stream.fold Fold.toList
69−[[],[1],[1,2],[2,3],[3,4],[4,5]]
127+[fromList [],fromList [1],fromList [1,2],fromList [2,3],fromList [3,4],fromList [4,5]]