2{-# LANGUAGE ConstraintKinds #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving#-}
6{-# LANGUAGE InstanceSigs #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE UndecidableInstances #-} -- XXX
11-- Module : Streamly.Streams.Serial
12-- Copyright : (c) 2017 Harendra Kumar
15-- Maintainer : harendra.kumar@gmail.com
16-- Stability : experimental
20module Streamly.Streams.Serial
22 -- * Serial appending stream
24 , StreamT -- deprecated
29 -- * Serial interleaving stream
31 , InterleavedT -- deprecated
36 , interleaving -- deprecated
44import Control.Monad (ap)
45import Control.Monad.Base (MonadBase(..), liftBaseDefault)
46import Control.Monad.Catch (MonadThrow, throwM)
47-- import Control.Monad.Error.Class (MonadError(..))
48import Control.Monad.IO.Class (MonadIO(..))
49import Control.Monad.Reader.Class (MonadReader(..))
50import Control.Monad.State.Class (MonadState(..))
51import Control.Monad.Trans.Class (MonadTrans(lift))
52import Data.Semigroup (Semigroup(..))
53import Prelude hiding (map, mapM)
55import Streamly.SVar (rstState)
56import Streamly.Streams.StreamK (IsStream(..), adapt, Stream(..))
57import qualified Streamly.Streams.StreamK as K
58import qualified Streamly.Streams.StreamD as D
60#include "Instances.hs"
63------------------------------------------------------------------------------
65------------------------------------------------------------------------------
67-- | Deep serial composition or serial composition with depth first traversal.
68-- The 'Semigroup' instance of 'SerialT' appends two streams serially in a
69-- depth first manner, yielding all elements from the first stream, and then
70-- all elements from the second stream.
74-- import qualified "Streamly.Prelude" as S
76-- main = ('toList' . 'serially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
82-- The 'Monad' instance runs the /monadic continuation/ for each
83-- element of the stream, serially.
86-- main = 'runStream' . 'serially' $ do
87-- x <- return 1 \<\> return 2
95-- 'SerialT' nests streams serially in a depth first manner.
98-- main = 'runStream' . 'serially' $ do
99-- x <- return 1 \<\> return 2
100-- y <- return 3 \<\> return 4
101-- S.yieldM $ print (x, y)
110-- This behavior of 'SerialT' is exactly like a list transformer. We call the
111-- monadic code being run for each element of the stream a monadic
112-- continuation. In imperative paradigm we can think of this composition as
113-- nested @for@ loops and the monadic continuation is the body of the loop. The
114-- loop iterates for all elements of the stream.
116-- The 'serially' combinator can be omitted as the default stream type is
118-- Note that serial composition with depth first traversal can be used to
119-- combine an infinite number of streams as it explores only one stream at a
123newtype SerialT m a = SerialT {getSerialT :: Stream m a}
124 deriving (Semigroup, Monoid, MonadTrans)
126-- | A serial IO stream of elements of type @a@. See 'SerialT' documentation
130type Serial = SerialT IO
134{-# DEPRECATED StreamT "Please use 'SerialT' instead." #-}
135type StreamT = SerialT
137-- | Fix the type of a polymorphic stream as 'SerialT'.
140serially :: IsStream t => SerialT m a -> t m a
143instance IsStream SerialT where
144 toStream = getSerialT
148 {-# SPECIALIZE consM :: IO a -> SerialT IO a -> SerialT IO a #-}
149 consM :: Monad m => m a -> SerialT m a -> SerialT m a
150 consM m r = fromStream $ K.consMSerial m (toStream r)
153 {-# SPECIALIZE (|:) :: IO a -> SerialT IO a -> SerialT IO a #-}
154 (|:) :: Monad m => m a -> SerialT m a -> SerialT m a
155 m |: r = fromStream $ K.consMSerial m (toStream r)
157------------------------------------------------------------------------------
159------------------------------------------------------------------------------
161-- | Polymorphic version of the 'Semigroup' operation '<>' of 'SerialT'.
162-- Appends two streams sequentially, yielding all elements from the first
163-- stream, and then all elements from the second stream.
167serial :: IsStream t => t m a -> t m a -> t m a
168serial m1 m2 = fromStream $ Stream $ \st stp sng yld ->
169 unStream (K.serial (toStream m1) (toStream m2))
170 (rstState st) stp sng yld
172------------------------------------------------------------------------------
174------------------------------------------------------------------------------
176instance Monad m => Monad (SerialT m) where
178 (SerialT (Stream m)) >>= f = SerialT $ Stream $ \st stp sng yld ->
179 let run x = unStream x (rstState st) stp sng yld
180 single a = run $ toStream (f a)
181 yieldk a r = run $ toStream $ f a <> (fromStream r >>= f)
182 in m (rstState st) stp single yieldk
184------------------------------------------------------------------------------
186------------------------------------------------------------------------------
188{-# INLINE_EARLY mapM #-}
189mapM :: (IsStream t, Monad m) => (a -> m b) -> t m a -> t m b
190mapM f m = fromStream $ D.toStreamK $ D.mapM f $ D.fromStreamK (toStream m)
196map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b
197map f = mapM (return . f)
199MONAD_APPLICATIVE_INSTANCE(SerialT,)
200MONAD_COMMON_INSTANCES(SerialT,)
202------------------------------------------------------------------------------
204------------------------------------------------------------------------------
206-- | Wide serial composition or serial composition with a breadth first
207-- traversal. The 'Semigroup' instance of 'WSerialT' traverses
208-- the two streams in a breadth first manner. In other words, it interleaves
209-- two streams, yielding one element from each stream alternately.
213-- import qualified "Streamly.Prelude" as S
215-- main = ('toList' . 'wSerially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
221-- Similarly, the 'Monad' instance interleaves the iterations of the
222-- inner and the outer loop, nesting loops in a breadth first manner.
226-- main = 'runStream' . 'wSerially' $ do
227-- x <- return 1 \<\> return 2
228-- y <- return 3 \<\> return 4
229-- S.yieldM $ print (x, y)
238-- Note that a serial composition with breadth first traversal can only combine
239-- a finite number of streams as it needs to retain state for each unfinished
243newtype WSerialT m a = WSerialT {getWSerialT :: Stream m a}
244 deriving (MonadTrans)
246-- | An interleaving serial IO stream of elements of type @a@. See 'WSerialT'
247-- documentation for more details.
250type WSerial = WSerialT IO
254{-# DEPRECATED InterleavedT "Please use 'WSerialT' instead." #-}
255type InterleavedT = WSerialT
257-- | Fix the type of a polymorphic stream as 'WSerialT'.
260wSerially :: IsStream t => WSerialT m a -> t m a
263-- | Same as 'wSerially'.
266{-# DEPRECATED interleaving "Please use wSerially instead." #-}
267interleaving :: IsStream t => WSerialT m a -> t m a
268interleaving = wSerially
270instance IsStream WSerialT where
271 toStream = getWSerialT
272 fromStream = WSerialT
275 {-# SPECIALIZE consM :: IO a -> WSerialT IO a -> WSerialT IO a #-}
276 consM :: Monad m => m a -> WSerialT m a -> WSerialT m a
277 consM m r = fromStream $ K.consMSerial m (toStream r)
280 {-# SPECIALIZE (|:) :: IO a -> WSerialT IO a -> WSerialT IO a #-}
281 (|:) :: Monad m => m a -> WSerialT m a -> WSerialT m a
282 m |: r = fromStream $ K.consMSerial m (toStream r)
284------------------------------------------------------------------------------
286------------------------------------------------------------------------------
288{-# INLINE interleave #-}
289interleave :: Stream m a -> Stream m a -> Stream m a
290interleave m1 m2 = Stream $ \st stp sng yld -> do
291 let stop = unStream m2 (rstState st) stp sng yld
293 yieldk a r = yld a (interleave m2 r)
294 unStream m1 (rstState st) stop single yieldk
296-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WSerialT'.
297-- Interleaves two streams, yielding one element from each stream alternately.
300{-# INLINE wSerial #-}
301wSerial :: IsStream t => t m a -> t m a -> t m a
302wSerial m1 m2 = fromStream $ Stream $ \st stp sng yld ->
303 unStream (interleave (toStream m1) (toStream m2))
304 (rstState st) stp sng yld
306instance Semigroup (WSerialT m a) where
311-- | Same as 'wSerial'.
314{-# DEPRECATED (<=>) "Please use 'wSerial' instead." #-}
316(<=>) :: IsStream t => t m a -> t m a -> t m a
319------------------------------------------------------------------------------
321------------------------------------------------------------------------------
323instance Monoid (WSerialT m a) where
327------------------------------------------------------------------------------
329------------------------------------------------------------------------------
331instance Monad m => Monad (WSerialT m) where
333 (WSerialT (Stream m)) >>= f = WSerialT $ Stream $ \st stp sng yld ->
334 let run x = unStream x (rstState st) stp sng yld
335 single a = run $ toStream (f a)
336 yieldk a r = run $ toStream $ f a <> (fromStream r >>= f)
337 in m (rstState st) stp single yieldk
339------------------------------------------------------------------------------
341------------------------------------------------------------------------------
343MONAD_APPLICATIVE_INSTANCE(WSerialT,)
344MONAD_COMMON_INSTANCES(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