2{-# LANGUAGE ConstraintKinds #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving#-}
6{-# LANGUAGE InstanceSigs #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE TypeFamilies #-}
9{-# LANGUAGE UndecidableInstances #-} -- XXX
12-- Module : Streamly.Streams.Serial
13-- Copyright : (c) 2017 Harendra Kumar
16-- Maintainer : harendra.kumar@gmail.com
17-- Stability : experimental
21module Streamly.Streams.Serial
23 -- * Serial appending stream
25 , StreamT -- deprecated
30 -- * Serial interleaving stream
32 , InterleavedT -- deprecated
39 , interleaving -- deprecated
47import Control.Applicative (liftA2)
48import Control.DeepSeq (NFData(..), NFData1(..), rnf1)
49import Control.Monad (ap)
50import Control.Monad.Base (MonadBase(..), liftBaseDefault)
51import Control.Monad.Catch (MonadThrow, throwM)
52-- import Control.Monad.Error.Class (MonadError(..))
53import Control.Monad.IO.Class (MonadIO(..))
54import Control.Monad.Reader.Class (MonadReader(..))
55import Control.Monad.State.Class (MonadState(..))
56import Control.Monad.Trans.Class (MonadTrans(lift))
57import Data.Functor.Identity (Identity(..), runIdentity)
58import Data.Foldable (fold)
59import Data.Semigroup (Semigroup(..))
60import GHC.Exts (IsList(..), IsString(..))
61import Text.Read (Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec,
63import Prelude hiding (map, mapM)
65import Streamly.Streams.StreamK (IsStream(..), adapt, Stream, mkStream,
67import qualified Streamly.Streams.Prelude as P
68import qualified Streamly.Streams.StreamK as K
69import qualified Streamly.Streams.StreamD as D
71#include "Instances.hs"
74------------------------------------------------------------------------------
76------------------------------------------------------------------------------
78-- | Deep serial composition or serial composition with depth first traversal.
79-- The 'Semigroup' instance of 'SerialT' appends two streams serially in a
80-- depth first manner, yielding all elements from the first stream, and then
81-- all elements from the second stream.
85-- import qualified "Streamly.Prelude" as S
87-- main = ('toList' . 'serially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
93-- The 'Monad' instance runs the /monadic continuation/ for each
94-- element of the stream, serially.
97-- main = 'drain' . 'serially' $ do
98-- x <- return 1 \<\> return 2
106-- 'SerialT' nests streams serially in a depth first manner.
109-- main = 'drain' . 'serially' $ do
110-- x <- return 1 \<\> return 2
111-- y <- return 3 \<\> return 4
112-- S.yieldM $ print (x, y)
121-- This behavior of 'SerialT' is exactly like a list transformer. We call the
122-- monadic code being run for each element of the stream a monadic
123-- continuation. In imperative paradigm we can think of this composition as
124-- nested @for@ loops and the monadic continuation is the body of the loop. The
125-- loop iterates for all elements of the stream.
127-- The 'serially' combinator can be omitted as the default stream type is
129-- Note that serial composition with depth first traversal can be used to
130-- combine an infinite number of streams as it explores only one stream at a
134newtype SerialT m a = SerialT {getSerialT :: Stream m a}
135 deriving (Semigroup, Monoid, MonadTrans)
137-- | A serial IO stream of elements of type @a@. See 'SerialT' documentation
141type Serial = SerialT IO
145{-# DEPRECATED StreamT "Please use 'SerialT' instead." #-}
146type StreamT = SerialT
148-- | Fix the type of a polymorphic stream as 'SerialT'.
151serially :: IsStream t => SerialT m a -> t m a
154{-# INLINE consMSerial #-}
155{-# SPECIALIZE consMSerial :: IO a -> SerialT IO a -> SerialT IO a #-}
156consMSerial :: Monad m => m a -> SerialT m a -> SerialT m a
157consMSerial m ms = fromStream $ K.consMStream m (toStream ms)
159instance IsStream SerialT where
160 toStream = getSerialT
165------------------------------------------------------------------------------
167------------------------------------------------------------------------------
169instance Monad m => Monad (SerialT m) where
172 (>>=) = K.bindWith K.serial
174 -- StreamD based implementation
175 -- return = SerialT . D.fromStreamD . D.yield
176 -- m >>= f = D.fromStreamD $ D.concatMap (\a -> D.toStreamD (f a)) (D.toStreamD m)
178------------------------------------------------------------------------------
180------------------------------------------------------------------------------
182{-# INLINE_EARLY mapM #-}
183mapM :: (IsStream t, Monad m) => (a -> m b) -> t m a -> t m b
184mapM f m = fromStream $ D.toStreamK $ D.mapM f $ D.fromStreamK (toStream m)
194-- > S.toList $ S.map (+1) $ S.fromList [1,2,3]
200map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b
201map f = mapM (return . f)
203MONAD_APPLICATIVE_INSTANCE(SerialT,)
204MONAD_COMMON_INSTANCES(SerialT,)
205LIST_INSTANCES(SerialT)
206FOLDABLE_INSTANCE(SerialT)
207TRAVERSABLE_INSTANCE(SerialT)
209------------------------------------------------------------------------------
211------------------------------------------------------------------------------
213-- | Wide serial composition or serial composition with a breadth first
214-- traversal. The 'Semigroup' instance of 'WSerialT' traverses
215-- the two streams in a breadth first manner. In other words, it interleaves
216-- two streams, yielding one element from each stream alternately.
220-- import qualified "Streamly.Prelude" as S
222-- main = ('toList' . 'wSerially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
228-- Similarly, the 'Monad' instance interleaves the iterations of the
229-- inner and the outer loop, nesting loops in a breadth first manner.
233-- main = 'drain' . 'wSerially' $ do
234-- x <- return 1 \<\> return 2
235-- y <- return 3 \<\> return 4
236-- S.yieldM $ print (x, y)
245-- Note that a serial composition with breadth first traversal can only combine
246-- a finite number of streams as it needs to retain state for each unfinished
250newtype WSerialT m a = WSerialT {getWSerialT :: Stream m a}
251 deriving (MonadTrans)
253-- | An interleaving serial IO stream of elements of type @a@. See 'WSerialT'
254-- documentation for more details.
257type WSerial = WSerialT IO
261{-# DEPRECATED InterleavedT "Please use 'WSerialT' instead." #-}
262type InterleavedT = WSerialT
264-- | Fix the type of a polymorphic stream as 'WSerialT'.
267wSerially :: IsStream t => WSerialT m a -> t m a
270-- | Same as 'wSerially'.
273{-# DEPRECATED interleaving "Please use wSerially instead." #-}
274interleaving :: IsStream t => WSerialT m a -> t m a
275interleaving = wSerially
277consMWSerial :: Monad m => m a -> WSerialT m a -> WSerialT m a
278consMWSerial m ms = fromStream $ K.consMStream m (toStream ms)
280instance IsStream WSerialT where
281 toStream = getWSerialT
282 fromStream = WSerialT
285 {-# SPECIALIZE consM :: IO a -> WSerialT IO a -> WSerialT IO a #-}
286 consM :: Monad m => m a -> WSerialT m a -> WSerialT m a
290 {-# SPECIALIZE (|:) :: IO a -> WSerialT IO a -> WSerialT IO a #-}
291 (|:) :: Monad m => m a -> WSerialT m a -> WSerialT m a
294------------------------------------------------------------------------------
296------------------------------------------------------------------------------
298-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WSerialT'.
299-- Interleaves two streams, yielding one element from each stream alternately.
300-- When one stream stops the rest of the other stream is used in the output
304{-# INLINE wSerial #-}
305wSerial :: IsStream t => t m a -> t m a -> t m a
306wSerial m1 m2 = mkStream $ \st yld sng stp -> do
307 let stop = foldStream st yld sng stp m2
309 yieldk a r = yld a (wSerial m2 r)
310 foldStream st yieldk single stop m1
312-- | Like `wSerial` but stops interleaving as soon as the first stream stops.
315{-# INLINE wSerialEndByFirst #-}
316wSerialEndByFirst :: IsStream t => t m a -> t m a -> t m a
317wSerialEndByFirst m1 m2 = mkStream $ \st yld sng stp -> do
318 let yieldFirst a r = yld a (yieldSecond r m2)
319 in foldStream st yieldFirst sng stp m1
323 yieldSecond s1 s2 = mkStream $ \st yld sng stp -> do
324 let stop = foldStream st yld sng stp s1
326 yieldk a r = yld a (wSerial s1 r)
327 in foldStream st yieldk single stop s2
329-- | Like `wSerial` but stops interleaving as soon as any of the two streams
333{-# INLINE wSerialEndByAny #-}
334wSerialEndByAny :: IsStream t => t m a -> t m a -> t m a
335wSerialEndByAny m1 m2 = mkStream $ \st yld sng stp -> do
338 yieldk a r = yld a (wSerial m2 r)
339 foldStream st yieldk single stop m1
341instance Semigroup (WSerialT m a) where
346-- | Same as 'wSerial'.
349{-# DEPRECATED (<=>) "Please use 'wSerial' instead." #-}
351(<=>) :: IsStream t => t m a -> t m a -> t m a
354------------------------------------------------------------------------------
356------------------------------------------------------------------------------
358instance Monoid (WSerialT m a) where
362------------------------------------------------------------------------------
364------------------------------------------------------------------------------
366instance Monad m => Monad (WSerialT m) where
369 (>>=) = K.bindWith wSerial
371------------------------------------------------------------------------------
373------------------------------------------------------------------------------
375MONAD_APPLICATIVE_INSTANCE(WSerialT,)
376MONAD_COMMON_INSTANCES(WSerialT,)
377LIST_INSTANCES(WSerialT)
378FOLDABLE_INSTANCE(WSerialT)
379TRAVERSABLE_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