1{-# LANGUAGE UndecidableInstances #-}
4-- Module : Streamly.Internal.Data.Stream.Serial
5-- Copyright : (c) 2017 Composewell Technologies
8-- Maintainer : streamly@composewell.com
9-- Stability : experimental
12-- To run examples in this module:
14-- >>> import qualified Streamly.Data.Stream as Stream
15-- >>> import qualified Streamly.Prelude as IsStream
17module Streamly.Internal.Data.Stream.Serial
19 -- * Serial appending stream
24 -- * Serial interleaving stream
48import Control.Applicative (liftA2)
49import Control.DeepSeq (NFData(..), NFData1(..))
50import Control.Monad.Base (MonadBase(..), liftBaseDefault)
51import Control.Monad.Catch (MonadThrow, throwM)
52import Control.Monad.IO.Class (MonadIO(..))
53import Control.Monad.Reader.Class (MonadReader(..))
54import Control.Monad.State.Class (MonadState(..))
55import Control.Monad.Trans.Class (MonadTrans(lift))
56import Data.Foldable (Foldable(foldl'), fold)
57import Data.Functor.Identity (Identity(..), runIdentity)
58import Data.Maybe (fromMaybe)
59import Data.Semigroup (Endo(..))
60import GHC.Exts (IsList(..), IsString(..), oneShot)
62 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
63 , readListPrecDefault)
64import Streamly.Internal.BaseCompat ((#.))
65import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
66import Streamly.Data.Stream (Stream)
68import qualified Streamly.Data.Stream as Stream
69import qualified Streamly.Internal.Data.Stream.Common as P
70import qualified Streamly.Internal.Data.Stream.StreamD as D
71 (fromStreamK, toStreamK, mapM)
72import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
73 (Stream, cons, consM, nil, concatMapWith, fromPure, bindWith
74 , withLocal, interleave, interleaveFst, interleaveMin)
76import Prelude hiding (map, mapM, repeat, filter)
78#include "Instances.hs"
82-- >>> import qualified Streamly.Data.Stream as Stream
83-- >>> import qualified Streamly.Prelude as IsStream
85------------------------------------------------------------------------------
87------------------------------------------------------------------------------
91-- | A serial IO stream of elements of type @a@. See 'SerialT' documentation
94-- /Since: 0.2.0 ("Streamly")/
97type Serial = SerialT IO
99------------------------------------------------------------------------------
101------------------------------------------------------------------------------
104serial :: SerialT m a -> SerialT m a -> SerialT m a
115-- > S.toList $ S.map (+1) $ S.fromList [1,2,3]
121map :: Monad m => (a -> b) -> SerialT m a -> SerialT m b
122map f = Stream.mapM (return . f)
124------------------------------------------------------------------------------
126------------------------------------------------------------------------------
128-- | For 'WSerialT' streams:
131-- (<>) = 'Streamly.Prelude.wSerial' -- 'Semigroup'
132-- (>>=) = flip . 'Streamly.Prelude.concatMapWith' 'Streamly.Prelude.wSerial' -- 'Monad'
135-- Note that '<>' is associative only if we disregard the ordering of elements
136-- in the resulting stream.
138-- A single 'Monad' bind behaves like a @for@ loop:
141-- IsStream.toList $ IsStream.fromWSerial $ do
142-- x <- IsStream.fromList [1,2] -- foreach x in stream
147-- Nested monad binds behave like interleaved nested @for@ loops:
150-- IsStream.toList $ IsStream.fromWSerial $ do
151-- x <- IsStream.fromList [1,2] -- foreach x in stream
152-- y <- IsStream.fromList [3,4] -- foreach y in stream
155-- [(1,3),(2,3),(1,4),(2,4)]
157-- It is a result of interleaving all the nested iterations corresponding to
158-- element @1@ in the first stream with all the nested iterations of element
161-- >>> import Streamly.Prelude (wSerial)
162-- >>> IsStream.toList $ IsStream.fromList [(1,3),(1,4)] `IsStream.wSerial` IsStream.fromList [(2,3),(2,4)]
163-- [(1,3),(2,3),(1,4),(2,4)]
165-- The @W@ in the name stands for @wide@ or breadth wise scheduling in
166-- contrast to the depth wise scheduling behavior of 'Stream'.
168-- /Since: 0.2.0 ("Streamly")/
171newtype WSerialT m a = WSerialT {getWSerialT :: K.Stream m a}
172 deriving (MonadTrans)
174-- | An interleaving serial IO stream of elements of type @a@. See 'WSerialT'
175-- documentation for more details.
177-- /Since: 0.2.0 ("Streamly")/
180type WSerial = WSerialT IO
182{-# INLINE consMWSerial #-}
183{-# SPECIALIZE consMWSerial :: IO a -> WSerialT IO a -> WSerialT IO a #-}
184consMWSerial :: Monad m => m a -> WSerialT m a -> WSerialT m a
185consMWSerial m (WSerialT ms) = WSerialT $ K.consM m ms
187------------------------------------------------------------------------------
189------------------------------------------------------------------------------
193-- | Interleaves two streams, yielding one element from each stream
194-- alternately. When one stream stops the rest of the other stream is used in
197-- This gives exponential priority to earlier streams than the ones joining
198-- later. Because of exponential weighting it can be used with 'concatMapWith'.
204-- Note that evaluation of @a \`wSerial` b \`wSerial` c@ does not interleave
205-- @a@, @b@ and @c@ with equal priority. This expression is equivalent to @a
206-- \`wSerial` (b \`wSerial` c)@, therefore, it fairly interleaves @a@ with the
207-- result of @b \`wSerial` c@. For example, @Stream.fromList [1,2] \`wSerial`
208-- Stream.fromList [3,4] \`wSerial` Stream.fromList [5,6]@ would result in
209-- [1,3,2,5,4,6]. In other words, the leftmost stream gets the same scheduling
210-- priority as the rest of the streams taken together. The same is true for
211-- each subexpression on the right.
213{-# INLINE wSerial #-}
214wSerial :: WSerialT m a -> WSerialT m a -> WSerialT m a
215wSerial (WSerialT m1) (WSerialT m2) = WSerialT $ K.interleave m1 m2
217{-# INLINE wSerialFst #-}
218wSerialFst :: WSerialT m a -> WSerialT m a -> WSerialT m a
219wSerialFst (WSerialT m1) (WSerialT m2) = WSerialT $ K.interleaveFst m1 m2
221{-# INLINE wSerialMin #-}
222wSerialMin :: WSerialT m a -> WSerialT m a -> WSerialT m a
223wSerialMin (WSerialT m1) (WSerialT m2) = WSerialT $ K.interleaveMin m1 m2
225instance Semigroup (WSerialT m a) where
228------------------------------------------------------------------------------
230------------------------------------------------------------------------------
232instance Monoid (WSerialT m a) where
233 mempty = WSerialT K.nil
236{-# INLINE apWSerial #-}
237apWSerial :: Monad m => WSerialT m (a -> b) -> WSerialT m a -> WSerialT m b
238apWSerial (WSerialT m1) (WSerialT m2) =
239 let f x1 = K.concatMapWith K.interleave (pure . x1) m2
240 in WSerialT $ K.concatMapWith K.interleave f m1
242instance Monad m => Applicative (WSerialT m) where
244 pure = WSerialT . K.fromPure
248------------------------------------------------------------------------------
250------------------------------------------------------------------------------
252instance Monad m => Monad (WSerialT m) where
255 (>>=) (WSerialT m) f = WSerialT $ K.bindWith K.interleave m (getWSerialT . f)
257------------------------------------------------------------------------------
259------------------------------------------------------------------------------
261MONAD_COMMON_INSTANCES(WSerialT,)
262LIST_INSTANCES(WSerialT)
263NFDATA1_INSTANCE(WSerialT)
264FOLDABLE_INSTANCE(WSerialT)
265TRAVERSABLE_INSTANCE(WSerialT)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list