2{-# LANGUAGE ConstraintKinds #-}
3{-# LANGUAGE DeriveTraversable #-}
4{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE GeneralizedNewtypeDeriving#-}
7{-# LANGUAGE InstanceSigs #-}
8{-# LANGUAGE MultiParamTypeClasses #-}
9{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE UndecidableInstances #-} -- XXX
13-- Module : Streamly.Streams.Serial
14-- Copyright : (c) 2017 Harendra Kumar
17-- Maintainer : harendra.kumar@gmail.com
18-- Stability : experimental
22module Streamly.Streams.Serial
24 -- * Serial appending stream
26 , StreamT -- deprecated
31 -- * Serial interleaving stream
33 , InterleavedT -- deprecated
38 , interleaving -- deprecated
46import Control.DeepSeq (NFData(..), NFData1(..), rnf1)
47import Control.Monad (ap)
48import Control.Monad.Base (MonadBase(..), liftBaseDefault)
49import Control.Monad.Catch (MonadThrow, throwM)
50-- import Control.Monad.Error.Class (MonadError(..))
51import Control.Monad.IO.Class (MonadIO(..))
52import Control.Monad.Reader.Class (MonadReader(..))
53import Control.Monad.State.Class (MonadState(..))
54import Control.Monad.Trans.Class (MonadTrans(lift))
55import Data.Functor.Identity (Identity, runIdentity)
56import Data.Semigroup (Semigroup(..))
57import GHC.Exts (IsList(..), IsString(..))
58import Text.Read (Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec,
60import Prelude hiding (map, mapM)
62import Streamly.SVar (rstState)
63import Streamly.Streams.StreamK (IsStream(..), adapt, Stream(..))
64import qualified Streamly.Streams.Prelude as P
65import qualified Streamly.Streams.StreamK as K
66import qualified Streamly.Streams.StreamD as D
68#include "Instances.hs"
71------------------------------------------------------------------------------
73------------------------------------------------------------------------------
75-- | Deep serial composition or serial composition with depth first traversal.
76-- The 'Semigroup' instance of 'SerialT' appends two streams serially in a
77-- depth first manner, yielding all elements from the first stream, and then
78-- all elements from the second stream.
82-- import qualified "Streamly.Prelude" as S
84-- main = ('toList' . 'serially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
90-- The 'Monad' instance runs the /monadic continuation/ for each
91-- element of the stream, serially.
94-- main = 'runStream' . 'serially' $ do
95-- x <- return 1 \<\> return 2
103-- 'SerialT' nests streams serially in a depth first manner.
106-- main = 'runStream' . 'serially' $ do
107-- x <- return 1 \<\> return 2
108-- y <- return 3 \<\> return 4
109-- S.yieldM $ print (x, y)
118-- This behavior of 'SerialT' is exactly like a list transformer. We call the
119-- monadic code being run for each element of the stream a monadic
120-- continuation. In imperative paradigm we can think of this composition as
121-- nested @for@ loops and the monadic continuation is the body of the loop. The
122-- loop iterates for all elements of the stream.
124-- The 'serially' combinator can be omitted as the default stream type is
126-- Note that serial composition with depth first traversal can be used to
127-- combine an infinite number of streams as it explores only one stream at a
131newtype SerialT m a = SerialT {getSerialT :: Stream m a}
132 deriving (Semigroup, Monoid, MonadTrans, Foldable, Traversable)
134-- | A serial IO stream of elements of type @a@. See 'SerialT' documentation
138type Serial = SerialT IO
142{-# DEPRECATED StreamT "Please use 'SerialT' instead." #-}
143type StreamT = SerialT
145-- | Fix the type of a polymorphic stream as 'SerialT'.
148serially :: IsStream t => SerialT m a -> t m a
151instance IsStream SerialT where
152 toStream = getSerialT
156 {-# SPECIALIZE consM :: IO a -> SerialT IO a -> SerialT IO a #-}
157 consM :: Monad m => m a -> SerialT m a -> SerialT m a
158 consM m r = fromStream $ K.consMSerial m (toStream r)
161 {-# SPECIALIZE (|:) :: IO a -> SerialT IO a -> SerialT IO a #-}
162 (|:) :: Monad m => m a -> SerialT m a -> SerialT m a
163 m |: r = fromStream $ K.consMSerial m (toStream r)
165------------------------------------------------------------------------------
167------------------------------------------------------------------------------
169-- | Polymorphic version of the 'Semigroup' operation '<>' of 'SerialT'.
170-- Appends two streams sequentially, yielding all elements from the first
171-- stream, and then all elements from the second stream.
175serial :: IsStream t => t m a -> t m a -> t m a
176serial m1 m2 = fromStream $ Stream $ \st stp sng yld ->
177 unStream (K.serial (toStream m1) (toStream m2))
178 (rstState st) stp sng yld
180------------------------------------------------------------------------------
182------------------------------------------------------------------------------
184instance Monad m => Monad (SerialT m) where
186 (SerialT (Stream m)) >>= f = SerialT $ Stream $ \st stp sng yld ->
187 let run x = unStream x (rstState st) stp sng yld
188 single a = run $ toStream (f a)
189 yieldk a r = run $ toStream $ f a <> (fromStream r >>= f)
190 in m (rstState st) stp single yieldk
192------------------------------------------------------------------------------
194------------------------------------------------------------------------------
196{-# INLINE_EARLY mapM #-}
197mapM :: (IsStream t, Monad m) => (a -> m b) -> t m a -> t m b
198mapM f m = fromStream $ D.toStreamK $ D.mapM f $ D.fromStreamK (toStream m)
204map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b
205map f = mapM (return . f)
207MONAD_APPLICATIVE_INSTANCE(SerialT,)
208MONAD_COMMON_INSTANCES(SerialT,)
210------------------------------------------------------------------------------
212------------------------------------------------------------------------------
214-- | Wide serial composition or serial composition with a breadth first
215-- traversal. The 'Semigroup' instance of 'WSerialT' traverses
216-- the two streams in a breadth first manner. In other words, it interleaves
217-- two streams, yielding one element from each stream alternately.
221-- import qualified "Streamly.Prelude" as S
223-- main = ('toList' . 'wSerially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
229-- Similarly, the 'Monad' instance interleaves the iterations of the
230-- inner and the outer loop, nesting loops in a breadth first manner.
234-- main = 'runStream' . 'wSerially' $ do
235-- x <- return 1 \<\> return 2
236-- y <- return 3 \<\> return 4
237-- S.yieldM $ print (x, y)
246-- Note that a serial composition with breadth first traversal can only combine
247-- a finite number of streams as it needs to retain state for each unfinished
251newtype WSerialT m a = WSerialT {getWSerialT :: Stream m a}
252 deriving (MonadTrans, Foldable, Traversable)
254-- | An interleaving serial IO stream of elements of type @a@. See 'WSerialT'
255-- documentation for more details.
258type WSerial = WSerialT IO
262{-# DEPRECATED InterleavedT "Please use 'WSerialT' instead." #-}
263type InterleavedT = WSerialT
265-- | Fix the type of a polymorphic stream as 'WSerialT'.
268wSerially :: IsStream t => WSerialT m a -> t m a
271-- | Same as 'wSerially'.
274{-# DEPRECATED interleaving "Please use wSerially instead." #-}
275interleaving :: IsStream t => WSerialT m a -> t m a
276interleaving = wSerially
278instance IsStream WSerialT where
279 toStream = getWSerialT
280 fromStream = WSerialT
283 {-# SPECIALIZE consM :: IO a -> WSerialT IO a -> WSerialT IO a #-}
284 consM :: Monad m => m a -> WSerialT m a -> WSerialT m a
285 consM m r = fromStream $ K.consMSerial m (toStream r)
288 {-# SPECIALIZE (|:) :: IO a -> WSerialT IO a -> WSerialT IO a #-}
289 (|:) :: Monad m => m a -> WSerialT m a -> WSerialT m a
290 m |: r = fromStream $ K.consMSerial m (toStream r)
292------------------------------------------------------------------------------
294------------------------------------------------------------------------------
296{-# INLINE interleave #-}
297interleave :: Stream m a -> Stream m a -> Stream m a
298interleave m1 m2 = Stream $ \st stp sng yld -> do
299 let stop = unStream m2 (rstState st) stp sng yld
301 yieldk a r = yld a (interleave m2 r)
302 unStream m1 (rstState st) stop single yieldk
304-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WSerialT'.
305-- Interleaves two streams, yielding one element from each stream alternately.
308{-# INLINE wSerial #-}
309wSerial :: IsStream t => t m a -> t m a -> t m a
310wSerial m1 m2 = fromStream $ Stream $ \st stp sng yld ->
311 unStream (interleave (toStream m1) (toStream m2))
312 (rstState st) stp sng yld
314instance Semigroup (WSerialT m a) where
319-- | Same as 'wSerial'.
322{-# DEPRECATED (<=>) "Please use 'wSerial' instead." #-}
324(<=>) :: IsStream t => t m a -> t m a -> t m a
327------------------------------------------------------------------------------
329------------------------------------------------------------------------------
331instance Monoid (WSerialT m a) where
335------------------------------------------------------------------------------
337------------------------------------------------------------------------------
339instance Monad m => Monad (WSerialT m) where
341 (WSerialT (Stream m)) >>= f = WSerialT $ Stream $ \st stp sng yld ->
342 let run x = unStream x (rstState st) stp sng yld
343 single a = run $ toStream (f a)
344 yieldk a r = run $ toStream $ f a <> (fromStream r >>= f)
345 in m (rstState st) stp single yieldk
347------------------------------------------------------------------------------
349------------------------------------------------------------------------------
351MONAD_APPLICATIVE_INSTANCE(WSerialT,)
352MONAD_COMMON_INSTANCES(WSerialT,)
354LIST_INSTANCES(SerialT)
355LIST_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