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 {-# DEPRECATED "Please use \"Streamly.Internal.Data.Stream\" instead." #-}
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-- >>> :set -fno-warn-deprecations
83-- >>> import qualified Streamly.Data.Stream as Stream
84-- >>> import qualified Streamly.Prelude as IsStream
86------------------------------------------------------------------------------
88------------------------------------------------------------------------------
92-- | A serial IO stream of elements of type @a@. See 'SerialT' documentation
95-- /Since: 0.2.0 ("Streamly")/
98type Serial = SerialT IO
100------------------------------------------------------------------------------
102------------------------------------------------------------------------------
105serial :: SerialT m a -> SerialT m a -> SerialT m a
116-- > S.toList $ S.map (+1) $ S.fromList [1,2,3]
122map :: Monad m => (a -> b) -> SerialT m a -> SerialT m b
123map f = Stream.mapM (return . f)
125------------------------------------------------------------------------------
127------------------------------------------------------------------------------
129-- | For 'WSerialT' streams:
132-- (<>) = 'Streamly.Prelude.wSerial' -- 'Semigroup'
133-- (>>=) = flip . 'Streamly.Prelude.concatMapWith' 'Streamly.Prelude.wSerial' -- 'Monad'
136-- Note that '<>' is associative only if we disregard the ordering of elements
137-- in the resulting stream.
139-- A single 'Monad' bind behaves like a @for@ loop:
142-- IsStream.toList $ IsStream.fromWSerial $ do
143-- x <- IsStream.fromList [1,2] -- foreach x in stream
148-- Nested monad binds behave like interleaved nested @for@ loops:
151-- IsStream.toList $ IsStream.fromWSerial $ do
152-- x <- IsStream.fromList [1,2] -- foreach x in stream
153-- y <- IsStream.fromList [3,4] -- foreach y in stream
156-- [(1,3),(2,3),(1,4),(2,4)]
158-- It is a result of interleaving all the nested iterations corresponding to
159-- element @1@ in the first stream with all the nested iterations of element
162-- >>> import Streamly.Prelude (wSerial)
163-- >>> IsStream.toList $ IsStream.fromList [(1,3),(1,4)] `IsStream.wSerial` IsStream.fromList [(2,3),(2,4)]
164-- [(1,3),(2,3),(1,4),(2,4)]
166-- The @W@ in the name stands for @wide@ or breadth wise scheduling in
167-- contrast to the depth wise scheduling behavior of 'Stream'.
169-- /Since: 0.2.0 ("Streamly")/
172newtype WSerialT m a = WSerialT {getWSerialT :: K.Stream m a}
173 deriving (MonadTrans)
175-- | An interleaving serial IO stream of elements of type @a@. See 'WSerialT'
176-- documentation for more details.
178-- /Since: 0.2.0 ("Streamly")/
181type WSerial = WSerialT IO
183{-# INLINE consMWSerial #-}
184{-# SPECIALIZE consMWSerial :: IO a -> WSerialT IO a -> WSerialT IO a #-}
185consMWSerial :: Monad m => m a -> WSerialT m a -> WSerialT m a
186consMWSerial m (WSerialT ms) = WSerialT $ K.consM m ms
188------------------------------------------------------------------------------
190------------------------------------------------------------------------------
194-- | Interleaves two streams, yielding one element from each stream
195-- alternately. When one stream stops the rest of the other stream is used in
198-- This gives exponential priority to earlier streams than the ones joining
199-- later. Because of exponential weighting it can be used with 'concatMapWith'.
205-- Note that evaluation of @a \`wSerial` b \`wSerial` c@ does not interleave
206-- @a@, @b@ and @c@ with equal priority. This expression is equivalent to @a
207-- \`wSerial` (b \`wSerial` c)@, therefore, it fairly interleaves @a@ with the
208-- result of @b \`wSerial` c@. For example, @Stream.fromList [1,2] \`wSerial`
209-- Stream.fromList [3,4] \`wSerial` Stream.fromList [5,6]@ would result in
210-- [1,3,2,5,4,6]. In other words, the leftmost stream gets the same scheduling
211-- priority as the rest of the streams taken together. The same is true for
212-- each subexpression on the right.
214{-# INLINE wSerial #-}
215wSerial :: WSerialT m a -> WSerialT m a -> WSerialT m a
216wSerial (WSerialT m1) (WSerialT m2) = WSerialT $ K.interleave m1 m2
218{-# INLINE wSerialFst #-}
219wSerialFst :: WSerialT m a -> WSerialT m a -> WSerialT m a
220wSerialFst (WSerialT m1) (WSerialT m2) = WSerialT $ K.interleaveFst m1 m2
222{-# INLINE wSerialMin #-}
223wSerialMin :: WSerialT m a -> WSerialT m a -> WSerialT m a
224wSerialMin (WSerialT m1) (WSerialT m2) = WSerialT $ K.interleaveMin m1 m2
226instance Semigroup (WSerialT m a) where
229------------------------------------------------------------------------------
231------------------------------------------------------------------------------
233instance Monoid (WSerialT m a) where
234 mempty = WSerialT K.nil
237{-# INLINE apWSerial #-}
238apWSerial :: Monad m => WSerialT m (a -> b) -> WSerialT m a -> WSerialT m b
239apWSerial (WSerialT m1) (WSerialT m2) =
240 let f x1 = K.concatMapWith K.interleave (pure . x1) m2
241 in WSerialT $ K.concatMapWith K.interleave f m1
243instance Monad m => Applicative (WSerialT m) where
245 pure = WSerialT . K.fromPure
249------------------------------------------------------------------------------
251------------------------------------------------------------------------------
253instance Monad m => Monad (WSerialT m) where
256 (>>=) (WSerialT m) f = WSerialT $ K.bindWith K.interleave m (getWSerialT . f)
258------------------------------------------------------------------------------
260------------------------------------------------------------------------------
262MONAD_COMMON_INSTANCES(WSerialT,)
263LIST_INSTANCES(WSerialT)
264NFDATA1_INSTANCE(WSerialT)
265FOLDABLE_INSTANCE(WSerialT)
266TRAVERSABLE_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