on acd550c help sign in
streamly/src/Streamly/Streams.hs
1178 lines 39 kB history raw
1{-# LANGUAGE ConstraintKinds #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE GeneralizedNewtypeDeriving#-}
5{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE RankNTypes #-}
7{-# LANGUAGE StandaloneDeriving #-}
8{-# LANGUAGE UndecidableInstances #-} -- XXX
10-- |
11-- Module : Streamly.Streams
12-- Copyright : (c) 2017 Harendra Kumar
13--
14-- License : BSD3
15-- Maintainer : harendra.kumar@gmail.com
16-- Stability : experimental
17-- Portability : GHC
18--
19--
20module Streamly.Streams
21 (
22 IsStream (..)
23 , Streaming -- deprecated
24 , MonadAsync
26 -- * SVars
27 , SVarSched (..)
28 , SVarTag (..)
29 , SVarStyle (..)
30 , SVar
31 , S.newEmptySVar
33 -- * Construction
34 , nil
35 , cons
36 , (.:)
37 , streamBuild
38 , fromCallback
39 , fromSVar
41 -- * Elimination
42 , streamFold
43 , runStream
44 , runStreaming -- deprecated
45 , toSVar
47 -- * Transformation
48 , async
50 -- * Merging Streams
51 , serial
52 , coserial
53 , coparallel
54 , parallel
55 , (<=>) --deprecated
56 , (<|) --deprecated
58 -- * Stream Styles
59 , SerialT
60 , StreamT -- deprecated
61 , CoserialT
62 , InterleavedT -- deprecated
63 , CoparallelT
64 , AsyncT -- deprecated
65 , ParallelT
66 , ZipSerial
67 , ZipStream -- deprecated
68 , ZipAsync
70 -- * Type Adapters
71 , serially
72 , coserially
73 , interleaving -- deprecated
74 , coparallely
75 , asyncly -- deprecated
76 , parallely
77 , zipping
78 , zippingAsync
79 , adapt
81 -- * Running Streams
82 , runStreamT -- deprecated
83 , runInterleavedT -- deprecated
84 , runAsyncT -- deprecated
85 , runParallelT -- deprecated
86 , runZipStream -- deprecated
87 , runZipAsync -- deprecated
89 -- * Zipping
90 , zipWith
91 , zipAsyncWith
93 -- * Fold Utilities
94 -- $foldutils
95 , foldWith
96 , foldMapWith
97 , forEachWith
98 )
99where
101import Control.Applicative (Alternative (..), liftA2)
102import Control.Monad (MonadPlus(..), ap)
103import Control.Monad.Base (MonadBase (..))
104import Control.Monad.Catch (MonadThrow)
105import Control.Monad.Error.Class (MonadError(..))
106import Control.Monad.IO.Class (MonadIO(..))
107import Control.Monad.Reader.Class (MonadReader(..))
108import Control.Monad.State.Class (MonadState(..))
109import Control.Monad.Trans.Class (MonadTrans)
110import Data.Semigroup (Semigroup(..))
111import Prelude hiding (zipWith)
112import Streamly.Core ( MonadAsync, Stream(Stream)
113 , SVar, SVarStyle(..)
114 , SVarTag(..), SVarSched(..))
115import qualified Streamly.Core as S
117------------------------------------------------------------------------------
118-- Types that can behave as a Stream
119------------------------------------------------------------------------------
121-- | Class of types that can represent a stream of elements of some type 'a' in
122-- some monad 'm'.
123class IsStream t where
124 toStream :: t m a -> Stream m a
125 fromStream :: Stream m a -> t m a
127-- | Same as 'IsStream'.
128{-# Deprecated Streaming "Please use IsStream instead." #-}
129type Streaming = IsStream
131------------------------------------------------------------------------------
132-- Constructing a stream
133------------------------------------------------------------------------------
135-- | Represesnts an empty stream just like @[]@ represents an empty list.
136nil :: IsStream t => t m a
137nil = fromStream S.nil
139infixr 5 `cons`
141-- | Constructs a stream by adding a pure value at the head of an existing
142-- stream, just like ':' constructs lists. For example:
143--
144-- @
145-- > let stream = 1 \`cons` 2 \`cons` 3 \`cons` nil
146-- > (toList . serially) stream
147-- [1,2,3]
148-- @
149cons :: IsStream t => a -> t m a -> t m a
150cons a r = fromStream $ S.cons a (Just (toStream r))
152infixr 5 .:
154-- | Operator equivalent of 'cons' so that you can construct a stream of pure
155-- values more succinctly like this:
156--
157-- @
158-- > let stream = 1 .: 2 .: 3 .: nil
159-- > (toList . serially) stream
160-- [1,2,3]
161-- @
162--
163-- '.:' constructs a stream just like ':' constructs a list.
164--
165-- Also note that another equivalent way of building streams from pure values
166-- is:
167--
168-- @
169-- > let stream = pure 1 <> pure 2 <> pure 3
170-- > (toList . serially) stream
171-- [1,2,3]
172-- @
173--
174-- In the first method we construct a stream by adding one element at a time.
175-- In the second method we first construct singleton streams using 'pure' and
176-- then compose all those streams together using the 'Semigroup' style
177-- composition of streams. The former method is a bit more efficient than the
178-- latter.
179--
180(.:) :: IsStream t => a -> t m a -> t m a
181(.:) = cons
183-- | Build a stream from its church encoding. The function passed maps
184-- directly to the underlying representation of the stream type. The second
185-- parameter to the function is the "yield" function yielding a value and the
186-- remaining stream if any otherwise 'Nothing'. The third parameter is to
187-- represent an "empty" stream.
188streamBuild :: IsStream t
189 => (forall r. Maybe (SVar m a)
190 -> (a -> Maybe (t m a) -> m r)
191 -> m r
192 -> m r)
193 -> t m a
194streamBuild k = fromStream $ Stream $ \sv stp yld ->
195 let yield a Nothing = yld a Nothing
196 yield a (Just r) = yld a (Just (toStream r))
197 in k sv yield stp
199-- | Build a singleton stream from a callback function.
200fromCallback :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a
201fromCallback k = fromStream $ Stream $ \_ _ yld -> k (\a -> yld a Nothing)
203-- | Read an SVar to get a stream.
204fromSVar :: (MonadAsync m, IsStream t) => SVar m a -> t m a
205fromSVar sv = fromStream $ S.fromStreamVar sv
207------------------------------------------------------------------------------
208-- Destroying a stream
209------------------------------------------------------------------------------
211-- | Fold a stream using its church encoding. The second argument is the "step"
212-- function consuming an element and the remaining stream, if any. The third
213-- argument is for consuming an "empty" stream that yields nothing.
214streamFold :: IsStream t
215 => Maybe (SVar m a) -> (a -> Maybe (t m a) -> m r) -> m r -> t m a -> m r
216streamFold sv step blank m =
217 let yield a Nothing = step a Nothing
218 yield a (Just x) = step a (Just (fromStream x))
219 in (S.runStream (toStream m)) sv blank yield
221-- | Run a streaming composition, discard the results.
222runStream :: Monad m => SerialT m a -> m ()
223runStream m = go (toStream m)
224 where
225 go m1 =
226 let stop = return ()
227 yield _ Nothing = stop
228 yield _ (Just x) = go x
229 in (S.runStream m1) Nothing stop yield
231-- | Same as 'runStream'
232{-# Deprecated runStreaming "Please use runStream instead." #-}
233runStreaming :: (Monad m, IsStream t) => t m a -> m ()
234runStreaming = runStream . adapt
236-- | Write a stream to an 'SVar' in a non-blocking manner. The stream can then
237-- be read back from the SVar using 'fromSVar'.
238toSVar :: (IsStream t, MonadAsync m) => SVar m a -> t m a -> m ()
239toSVar sv m = S.toStreamVar sv (toStream m)
241------------------------------------------------------------------------------
242-- Transformation
243------------------------------------------------------------------------------
245-- XXX Get rid of this?
246-- | Make a stream asynchronous, triggers the computation and returns a stream
247-- in the underlying monad representing the output generated by the original
248-- computation. The returned action is exhaustible and must be drained once. If
249-- not drained fully we may have a thread blocked forever and once exhausted it
250-- will always return 'empty'.
252async :: (IsStream t, MonadAsync m) => t m a -> m (t m a)
253async m = do
254 sv <- S.newStreamVar1 (SVarStyle Disjunction LIFO) (toStream m)
255 return $ fromSVar sv
257------------------------------------------------------------------------------
258-- SerialT
259------------------------------------------------------------------------------
261-- | The 'Semigroup' instance of 'SerialT' appends two streams sequentially,
262-- yielding all elements from the first stream, and then all elements from the
263-- second stream.
264--
265-- @
266-- main = ('toList' . 'serially' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
267-- @
268-- @
269-- [1,2,3,4]
270-- @
271--
272-- The 'Monad' instance runs the /monadic continuation/ for each
273-- element of the stream, serially.
274--
275-- @
276-- main = 'runStream' . 'serially' $ do
277-- x <- return 1 \<\> return 2
278-- liftIO $ print x
279-- @
280-- @
281-- 1
282-- 2
283-- @
284--
285-- 'SerialT' nests streams serially in a depth first manner.
286--
287-- @
288-- main = 'runStream' . 'serially' $ do
289-- x <- return 1 \<\> return 2
290-- y <- return 3 \<\> return 4
291-- liftIO $ print (x, y)
292-- @
293-- @
294-- (1,3)
295-- (1,4)
296-- (2,3)
297-- (2,4)
298-- @
299--
300-- This behavior of 'SerialT' is exactly like a list transformer. We call the
301-- monadic code being run for each element of the stream a monadic
302-- continuation. In imperative paradigm we can think of this composition as
303-- nested @for@ loops and the monadic continuation is the body of the loop. The
304-- loop iterates for all elements of the stream.
305--
306-- The 'serially' combinator can be omitted as the default stream type is
307-- 'SerialT'.
308-- Note that serial composition can be used to combine an infinite number of
309-- streams as it explores only one stream at a time.
310--
311newtype SerialT m a = SerialT {getSerialT :: Stream m a}
312 deriving (Semigroup, Monoid, MonadTrans, MonadIO, MonadThrow)
314deriving instance MonadAsync m => Alternative (SerialT m)
315deriving instance MonadAsync m => MonadPlus (SerialT m)
316deriving instance (MonadBase b m, Monad m) => MonadBase b (SerialT m)
317deriving instance MonadError e m => MonadError e (SerialT m)
318deriving instance MonadReader r m => MonadReader r (SerialT m)
319deriving instance MonadState s m => MonadState s (SerialT m)
321instance IsStream SerialT where
322 toStream = getSerialT
323 fromStream = SerialT
325-- | Same as SerialT.
326{-# Deprecated StreamT "Please use SerialT instead." #-}
327type StreamT = SerialT
329-- XXX The Functor/Applicative/Num instances for all the types are exactly the
330-- same, how can we reduce this boilerplate (use TH)? We cannot derive them
331-- from a single base type because they depend on the Monad instance which is
332-- different for each type.
334------------------------------------------------------------------------------
335-- Semigroup
336------------------------------------------------------------------------------
338-- | Polymorphic version of the 'Semigroup' operation '<>' of 'SerialT'.
339-- Appends two streams sequentially, yielding all elements from the first
340-- stream, and then all elements from the second stream.
341{-# INLINE serial #-}
342serial :: IsStream t => t m a -> t m a -> t m a
343serial m1 m2 = fromStream $ S.serial (toStream m1) (toStream m2)
345------------------------------------------------------------------------------
346-- Monad
347------------------------------------------------------------------------------
349instance Monad m => Monad (SerialT m) where
350 return = pure
351 (SerialT (Stream m)) >>= f = SerialT $ Stream $ \_ stp yld ->
352 let run x = (S.runStream x) Nothing stp yld
353 yield a Nothing = run $ toStream (f a)
354 yield a (Just r) = run $ toStream $ f a <> (fromStream r >>= f)
355 in m Nothing stp yield
357------------------------------------------------------------------------------
358-- Applicative
359------------------------------------------------------------------------------
361instance Monad m => Applicative (SerialT m) where
362 pure a = SerialT $ S.cons a Nothing
363 (<*>) = ap
365------------------------------------------------------------------------------
366-- Functor
367------------------------------------------------------------------------------
369instance Monad m => Functor (SerialT m) where
370 fmap f (SerialT (Stream m)) = SerialT $ Stream $ \_ stp yld ->
371 let yield a Nothing = yld (f a) Nothing
372 yield a (Just r) = yld (f a)
373 (Just (getSerialT (fmap f (SerialT r))))
374 in m Nothing stp yield
376------------------------------------------------------------------------------
377-- Num
378------------------------------------------------------------------------------
380instance (Monad m, Num a) => Num (SerialT m a) where
381 fromInteger n = pure (fromInteger n)
383 negate = fmap negate
384 abs = fmap abs
385 signum = fmap signum
387 (+) = liftA2 (+)
388 (*) = liftA2 (*)
389 (-) = liftA2 (-)
391instance (Monad m, Fractional a) => Fractional (SerialT m a) where
392 fromRational n = pure (fromRational n)
394 recip = fmap recip
396 (/) = liftA2 (/)
398instance (Monad m, Floating a) => Floating (SerialT m a) where
399 pi = pure pi
401 exp = fmap exp
402 sqrt = fmap sqrt
403 log = fmap log
404 sin = fmap sin
405 tan = fmap tan
406 cos = fmap cos
407 asin = fmap asin
408 atan = fmap atan
409 acos = fmap acos
410 sinh = fmap sinh
411 tanh = fmap tanh
412 cosh = fmap cosh
413 asinh = fmap asinh
414 atanh = fmap atanh
415 acosh = fmap acosh
417 (**) = liftA2 (**)
418 logBase = liftA2 logBase
420------------------------------------------------------------------------------
421-- CoserialT
422------------------------------------------------------------------------------
424-- | The 'Semigroup' instance of 'CoserialT' interleaves two streams,
425-- yielding one element from each stream alternately.
426--
427-- @
428-- main = ('toList' . 'interleaving' $ (fromFoldable [1,2]) \<\> (fromFoldable [3,4])) >>= print
429-- @
430-- @
431-- [1,3,2,4]
432-- @
433--
434-- Similarly, the 'Monad' instance fairly interleaves the iterations of the
435-- inner and the outer loop, nesting loops in a breadth first manner.
436--
437--
438-- @
439-- main = 'runStream' . 'interleaving' $ do
440-- x <- return 1 \<\> return 2
441-- y <- return 3 \<\> return 4
442-- liftIO $ print (x, y)
443-- @
444-- @
445-- (1,3)
446-- (2,3)
447-- (1,4)
448-- (2,4)
449-- @
450--
451-- Note that interleaving composition can only combine a finite number of
452-- streams as it needs to retain state for each unfinished stream.
453--
454newtype CoserialT m a = CoserialT {getCoserialT :: Stream m a}
455 deriving (Monoid, MonadTrans, MonadIO, MonadThrow)
457deriving instance MonadAsync m => Alternative (CoserialT m)
458deriving instance MonadAsync m => MonadPlus (CoserialT m)
459deriving instance (MonadBase b m, Monad m) => MonadBase b (CoserialT m)
460deriving instance MonadError e m => MonadError e (CoserialT m)
461deriving instance MonadReader r m => MonadReader r (CoserialT m)
462deriving instance MonadState s m => MonadState s (CoserialT m)
464{-# DEPRECATED InterleavedT "Please use 'CoserialT' instead." #-}
465type InterleavedT = CoserialT
467instance IsStream CoserialT where
468 toStream = getCoserialT
469 fromStream = CoserialT
471------------------------------------------------------------------------------
472-- Semigroup
473------------------------------------------------------------------------------
475-- | Polymorphic version of the 'Semigroup' operation '<>' of 'CoserialT'.
476-- Interleaves two streams, yielding one element from each stream alternately.
477{-# INLINE coserial #-}
478coserial :: IsStream t => t m a -> t m a -> t m a
479coserial m1 m2 = fromStream $ S.coserial (toStream m1) (toStream m2)
481instance Semigroup (CoserialT m a) where
482 (<>) = coserial
484infixr 5 <=>
486-- | Same as 'coserial'.
487{-# DEPRECATED (<=>) "Please use 'coserial' instead." #-}
488{-# INLINE (<=>) #-}
489(<=>) :: IsStream t => t m a -> t m a -> t m a
490(<=>) = coserial
492------------------------------------------------------------------------------
493-- Monad
494------------------------------------------------------------------------------
496instance Monad m => Monad (CoserialT m) where
497 return = pure
498 (CoserialT (Stream m)) >>= f = CoserialT $ Stream $ \_ stp yld ->
499 let run x = (S.runStream x) Nothing stp yld
500 yield a Nothing = run $ toStream (f a)
501 yield a (Just r) = run $ toStream $ f a <> (fromStream r >>= f)
502 in m Nothing stp yield
504------------------------------------------------------------------------------
505-- Applicative
506------------------------------------------------------------------------------
508instance Monad m => Applicative (CoserialT m) where
509 pure a = CoserialT $ S.cons a Nothing
510 (<*>) = ap
512------------------------------------------------------------------------------
513-- Functor
514------------------------------------------------------------------------------
516instance Monad m => Functor (CoserialT m) where
517 fmap f (CoserialT (Stream m)) = CoserialT $ Stream $ \_ stp yld ->
518 let yield a Nothing = yld (f a) Nothing
519 yield a (Just r) =
520 yld (f a) (Just (getCoserialT (fmap f (CoserialT r))))
521 in m Nothing stp yield
523------------------------------------------------------------------------------
524-- Num
525------------------------------------------------------------------------------
527instance (Monad m, Num a) => Num (CoserialT m a) where
528 fromInteger n = pure (fromInteger n)
530 negate = fmap negate
531 abs = fmap abs
532 signum = fmap signum
534 (+) = liftA2 (+)
535 (*) = liftA2 (*)
536 (-) = liftA2 (-)
538instance (Monad m, Fractional a) => Fractional (CoserialT m a) where
539 fromRational n = pure (fromRational n)
541 recip = fmap recip
543 (/) = liftA2 (/)
545instance (Monad m, Floating a) => Floating (CoserialT m a) where
546 pi = pure pi
548 exp = fmap exp
549 sqrt = fmap sqrt
550 log = fmap log
551 sin = fmap sin
552 tan = fmap tan
553 cos = fmap cos
554 asin = fmap asin
555 atan = fmap atan
556 acos = fmap acos
557 sinh = fmap sinh
558 tanh = fmap tanh
559 cosh = fmap cosh
560 asinh = fmap asinh
561 atanh = fmap atanh
562 acosh = fmap acosh
564 (**) = liftA2 (**)
565 logBase = liftA2 logBase
567------------------------------------------------------------------------------
568-- CoparallelT
569------------------------------------------------------------------------------
571-- | Adaptive parallel, in a left to right 'Semigroup' composition it tries to
572-- yield elements from the left stream as long as it can, but it can run the
573-- right stream in parallel if it needs to based on demand. The right stream
574-- can be run if the left stream blocks on IO or cannot produce elements fast
575-- enough for the consumer.
576--
577-- @
578-- main = ('toList' . 'coparallely' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
579-- @
580-- @
581-- [1,2,3,4]
582-- @
583--
584-- Similarly, the monad instance of 'ParallelT' /may/ run each iteration
585-- concurrently based on demand. More concurrent iterations are started only
586-- if the previous iterations are not able to produce enough output for the
587-- consumer.
588--
589-- @
590-- import "Streamly"
591-- import Control.Concurrent
592--
593-- main = 'runStream' . 'coparallely' $ do
594-- n <- return 3 \<\> return 2 \<\> return 1
595-- liftIO $ do
596-- threadDelay (n * 1000000)
597-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
598-- @
599-- @
600-- ThreadId 40: Delay 1
601-- ThreadId 39: Delay 2
602-- ThreadId 38: Delay 3
603-- @
604--
605-- All iterations may run in the same thread if they do not block.
606--
607-- Note that this composition can be used to combine infinite number of streams
608-- as it explores only a bounded number of streams at a time.
609--
610newtype CoparallelT m a = CoparallelT {getCoparallelT :: Stream m a}
611 deriving (MonadTrans)
613deriving instance MonadAsync m => Monoid (CoparallelT m a)
614deriving instance MonadAsync m => Alternative (CoparallelT m)
615deriving instance MonadAsync m => MonadPlus (CoparallelT m)
616deriving instance MonadAsync m => MonadIO (CoparallelT m)
617deriving instance MonadAsync m => MonadThrow (CoparallelT m)
618deriving instance (MonadBase b m, MonadAsync m) => MonadBase b (CoparallelT m)
619deriving instance (MonadError e m, MonadAsync m) => MonadError e (CoparallelT m)
620deriving instance (MonadReader r m, MonadAsync m) => MonadReader r (CoparallelT m)
621deriving instance (MonadState s m, MonadAsync m) => MonadState s (CoparallelT m)
623{-# DEPRECATED AsyncT "Please use 'CoparallelT' instead." #-}
624type AsyncT = CoparallelT
626instance IsStream CoparallelT where
627 toStream = getCoparallelT
628 fromStream = CoparallelT
630------------------------------------------------------------------------------
631-- Semigroup
632------------------------------------------------------------------------------
634-- | Polymorphic version of the 'Semigroup' operation '<>' of 'CoparallelT', but
635-- polymorphic. Merges two streams possibly concurrently, preferring the
636-- elements from the left one when available.
637{-# INLINE coparallel #-}
638coparallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
639coparallel m1 m2 = fromStream $ S.coparallel (toStream m1) (toStream m2)
641instance MonadAsync m => Semigroup (CoparallelT m a) where
642 (<>) = coparallel
644-- | Same as 'coparallel'.
645{-# DEPRECATED (<|) "Please use 'coparallel' instead." #-}
646{-# INLINE (<|) #-}
647(<|) :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
648(<|) = coparallel
650------------------------------------------------------------------------------
651-- Monad
652------------------------------------------------------------------------------
654{-# INLINE parbind #-}
655parbind
656 :: (forall c. Stream m c -> Stream m c -> Stream m c)
657 -> Stream m a
658 -> (a -> Stream m b)
659 -> Stream m b
660parbind par m f = go m
661 where
662 go (Stream g) =
663 Stream $ \ctx stp yld ->
664 let run x = (S.runStream x) ctx stp yld
665 yield a Nothing = run $ f a
666 yield a (Just r) = run $ f a `par` go r
667 in g Nothing stp yield
669instance MonadAsync m => Monad (CoparallelT m) where
670 return = pure
671 (CoparallelT m) >>= f = CoparallelT $ parbind par m g
672 where g x = getCoparallelT (f x)
673 par = S.joinStreamVar2 (SVarStyle Conjunction LIFO)
675------------------------------------------------------------------------------
676-- Applicative
677------------------------------------------------------------------------------
679instance MonadAsync m => Applicative (CoparallelT m) where
680 pure a = CoparallelT $ S.cons a Nothing
681 (<*>) = ap
683------------------------------------------------------------------------------
684-- Functor
685------------------------------------------------------------------------------
687instance Monad m => Functor (CoparallelT m) where
688 fmap f (CoparallelT (Stream m)) = CoparallelT $ Stream $ \_ stp yld ->
689 let yield a Nothing = yld (f a) Nothing
690 yield a (Just r) = yld (f a) (Just (getCoparallelT (fmap f (CoparallelT r))))
691 in m Nothing stp yield
693------------------------------------------------------------------------------
694-- Num
695------------------------------------------------------------------------------
697instance (MonadAsync m, Num a) => Num (CoparallelT m a) where
698 fromInteger n = pure (fromInteger n)
700 negate = fmap negate
701 abs = fmap abs
702 signum = fmap signum
704 (+) = liftA2 (+)
705 (*) = liftA2 (*)
706 (-) = liftA2 (-)
708instance (MonadAsync m, Fractional a) => Fractional (CoparallelT m a) where
709 fromRational n = pure (fromRational n)
711 recip = fmap recip
713 (/) = liftA2 (/)
715instance (MonadAsync m, Floating a) => Floating (CoparallelT m a) where
716 pi = pure pi
718 exp = fmap exp
719 sqrt = fmap sqrt
720 log = fmap log
721 sin = fmap sin
722 tan = fmap tan
723 cos = fmap cos
724 asin = fmap asin
725 atan = fmap atan
726 acos = fmap acos
727 sinh = fmap sinh
728 tanh = fmap tanh
729 cosh = fmap cosh
730 asinh = fmap asinh
731 atanh = fmap atanh
732 acosh = fmap acosh
734 (**) = liftA2 (**)
735 logBase = liftA2 logBase
737------------------------------------------------------------------------------
738-- ParallelT
739------------------------------------------------------------------------------
741-- | Round robin concurrent composition.
742--
743-- The Semigroup instance of 'ParallelT' concurrently /merges/ streams in a
744-- round robin fashion, yielding elements from both streams alternately.
745--
746-- @
747-- main = ('toList' . 'parallely' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
748-- @
749-- @
750-- [1,3,2,4]
751-- @
752--
753-- Similarly, the 'Monad' instance of 'ParallelT' runs /all/ iterations fairly
754-- concurrently using a round robin scheduling.
755--
756-- @
757-- import "Streamly"
758-- import Control.Concurrent
759--
760-- main = 'runStream' . 'parallely' $ do
761-- n <- return 3 \<\> return 2 \<\> return 1
762-- liftIO $ do
763-- threadDelay (n * 1000000)
764-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
765-- @
766-- @
767-- ThreadId 40: Delay 1
768-- ThreadId 39: Delay 2
769-- ThreadId 38: Delay 3
770-- @
771--
772-- Unlike 'CoparallelT' all iterations are guaranteed to run fairly
773-- concurrently, unconditionally.
774--
775-- Note that round robin composition can only combine a finite number of
776-- streams as it needs to retain state for each unfinished stream.
777--
778newtype ParallelT m a = ParallelT {getParallelT :: Stream m a}
779 deriving (MonadTrans)
781deriving instance MonadAsync m => Monoid (ParallelT m a)
782deriving instance MonadAsync m => Alternative (ParallelT m)
783deriving instance MonadAsync m => MonadPlus (ParallelT m)
784deriving instance MonadAsync m => MonadIO (ParallelT m)
785deriving instance MonadAsync m => MonadThrow (ParallelT m)
786deriving instance (MonadBase b m, MonadAsync m) => MonadBase b (ParallelT m)
787deriving instance (MonadError e m, MonadAsync m) => MonadError e (ParallelT m)
788deriving instance (MonadReader r m, MonadAsync m) => MonadReader r (ParallelT m)
789deriving instance (MonadState s m, MonadAsync m) => MonadState s (ParallelT m)
791instance IsStream ParallelT where
792 toStream = getParallelT
793 fromStream = ParallelT
795------------------------------------------------------------------------------
796-- Semigroup
797------------------------------------------------------------------------------
799-- | Polymorphic version of the 'Semigroup' operation '<>' of 'ParallelT'.
800-- Merges two streams concurrently choosing elements from both fairly.
801{-# INLINE parallel #-}
802parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a
803parallel m1 m2 = fromStream $ S.parallel (toStream m1) (toStream m2)
805instance MonadAsync m => Semigroup (ParallelT m a) where
806 (<>) = parallel
808------------------------------------------------------------------------------
809-- Monad
810------------------------------------------------------------------------------
812instance MonadAsync m => Monad (ParallelT m) where
813 return = pure
814 (ParallelT m) >>= f = ParallelT $ parbind par m g
815 where g x = getParallelT (f x)
816 par = S.joinStreamVar2 (SVarStyle Conjunction FIFO)
818------------------------------------------------------------------------------
819-- Applicative
820------------------------------------------------------------------------------
822instance MonadAsync m => Applicative (ParallelT m) where
823 pure a = ParallelT $ S.cons a Nothing
824 (<*>) = ap
826------------------------------------------------------------------------------
827-- Functor
828------------------------------------------------------------------------------
830instance Monad m => Functor (ParallelT m) where
831 fmap f (ParallelT (Stream m)) = ParallelT $ Stream $ \_ stp yld ->
832 let yield a Nothing = yld (f a) Nothing
833 yield a (Just r) = yld (f a)
834 (Just (getParallelT (fmap f (ParallelT r))))
835 in m Nothing stp yield
837------------------------------------------------------------------------------
838-- Num
839------------------------------------------------------------------------------
841instance (MonadAsync m, Num a) => Num (ParallelT m a) where
842 fromInteger n = pure (fromInteger n)
844 negate = fmap negate
845 abs = fmap abs
846 signum = fmap signum
848 (+) = liftA2 (+)
849 (*) = liftA2 (*)
850 (-) = liftA2 (-)
852instance (MonadAsync m, Fractional a) => Fractional (ParallelT m a) where
853 fromRational n = pure (fromRational n)
855 recip = fmap recip
857 (/) = liftA2 (/)
859instance (MonadAsync m, Floating a) => Floating (ParallelT m a) where
860 pi = pure pi
862 exp = fmap exp
863 sqrt = fmap sqrt
864 log = fmap log
865 sin = fmap sin
866 tan = fmap tan
867 cos = fmap cos
868 asin = fmap asin
869 atan = fmap atan
870 acos = fmap acos
871 sinh = fmap sinh
872 tanh = fmap tanh
873 cosh = fmap cosh
874 asinh = fmap asinh
875 atanh = fmap atanh
876 acosh = fmap acosh
878 (**) = liftA2 (**)
879 logBase = liftA2 logBase
881------------------------------------------------------------------------------
882-- Serially Zipping Streams
883------------------------------------------------------------------------------
885-- | Zip two streams serially using a pure zipping function.
886zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
887zipWith f m1 m2 = fromStream $ go (toStream m1) (toStream m2)
888 where
889 go mx my = Stream $ \_ stp yld -> do
890 let merge a ra =
891 let yield2 b Nothing = yld (f a b) Nothing
892 yield2 b (Just rb) = yld (f a b) (Just (go ra rb))
893 in (S.runStream my) Nothing stp yield2
894 let yield1 a Nothing = merge a S.nil
895 yield1 a (Just ra) = merge a ra
896 (S.runStream mx) Nothing stp yield1
898-- | The applicative instance of 'ZipSerial' zips a number of streams serially
899-- i.e. it produces one element from each stream serially and then zips all
900-- those elements. Note, for convenience we have used the 'zipping' combinator
901-- in the following example instead of using a 'ZipSerial' type annotation.
902--
903-- @
904-- main = (toList . 'zipping' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
905-- where s1 = fromFoldable [1, 2]
906-- s2 = fromFoldable [3, 4]
907-- s3 = fromFoldable [5, 6]
908-- @
909-- @
910-- [(1,3,5),(2,4,6)]
911-- @
912--
913-- The 'Semigroup' instance of this type works the same way as that of
914-- 'SerialT'.
915--
916newtype ZipSerial m a = ZipSerial {getZipSerial :: Stream m a}
917 deriving (Semigroup, Monoid)
919{-# Deprecated ZipStream "Please use ZipSerial instead." #-}
920-- | Same as ZipSerial.
921type ZipStream = ZipSerial
923deriving instance MonadAsync m => Alternative (ZipSerial m)
925instance Monad m => Functor (ZipSerial m) where
926 fmap f (ZipSerial (Stream m)) = ZipSerial $ Stream $ \_ stp yld ->
927 let yield a Nothing = yld (f a) Nothing
928 yield a (Just r) = yld (f a)
929 (Just (getZipSerial (fmap f (ZipSerial r))))
930 in m Nothing stp yield
932instance Monad m => Applicative (ZipSerial m) where
933 pure = ZipSerial . S.repeat
934 (<*>) = zipWith id
936instance IsStream ZipSerial where
937 toStream = getZipSerial
938 fromStream = ZipSerial
940instance (Monad m, Num a) => Num (ZipSerial m a) where
941 fromInteger n = pure (fromInteger n)
943 negate = fmap negate
944 abs = fmap abs
945 signum = fmap signum
947 (+) = liftA2 (+)
948 (*) = liftA2 (*)
949 (-) = liftA2 (-)
951instance (Monad m, Fractional a) => Fractional (ZipSerial m a) where
952 fromRational n = pure (fromRational n)
954 recip = fmap recip
956 (/) = liftA2 (/)
958instance (Monad m, Floating a) => Floating (ZipSerial m a) where
959 pi = pure pi
961 exp = fmap exp
962 sqrt = fmap sqrt
963 log = fmap log
964 sin = fmap sin
965 tan = fmap tan
966 cos = fmap cos
967 asin = fmap asin
968 atan = fmap atan
969 acos = fmap acos
970 sinh = fmap sinh
971 tanh = fmap tanh
972 cosh = fmap cosh
973 asinh = fmap asinh
974 atanh = fmap atanh
975 acosh = fmap acosh
977 (**) = liftA2 (**)
978 logBase = liftA2 logBase
980------------------------------------------------------------------------------
981-- Parallely Zipping Streams
982------------------------------------------------------------------------------
984-- | Zip two streams asyncly (i.e. both the elements being zipped are generated
985-- concurrently) using a pure zipping function.
986zipAsyncWith :: (IsStream t, MonadAsync m)
987 => (a -> b -> c) -> t m a -> t m b -> t m c
988zipAsyncWith f m1 m2 = fromStream $ Stream $ \_ stp yld -> do
989 ma <- async m1
990 mb <- async m2
991 (S.runStream (toStream (zipWith f ma mb))) Nothing stp yld
993-- | Like 'ZipSerial' but zips in parallel, it generates all the elements to
994-- be zipped concurrently.
995--
996-- @
997-- main = (toList . 'zippingAsync' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
998-- where s1 = fromFoldable [1, 2]
999-- s2 = fromFoldable [3, 4]
1000-- s3 = fromFoldable [5, 6]
1001-- @
1002-- @
1003-- [(1,3,5),(2,4,6)]
1004-- @
1006-- The 'Semigroup' instance of this type works the same way as that of
1007-- 'SerialT'.
1009newtype ZipAsync m a = ZipAsync {getZipAsync :: Stream m a}
1010 deriving (Semigroup, Monoid)
1012deriving instance MonadAsync m => Alternative (ZipAsync m)
1014instance Monad m => Functor (ZipAsync m) where
1015 fmap f (ZipAsync (Stream m)) = ZipAsync $ Stream $ \_ stp yld ->
1016 let yield a Nothing = yld (f a) Nothing
1017 yield a (Just r) = yld (f a)
1018 (Just (getZipAsync (fmap f (ZipAsync r))))
1019 in m Nothing stp yield
1021instance MonadAsync m => Applicative (ZipAsync m) where
1022 pure = ZipAsync . S.repeat
1023 (<*>) = zipAsyncWith id
1025instance IsStream ZipAsync where
1026 toStream = getZipAsync
1027 fromStream = ZipAsync
1029instance (MonadAsync m, Num a) => Num (ZipAsync m a) where
1030 fromInteger n = pure (fromInteger n)
1032 negate = fmap negate
1033 abs = fmap abs
1034 signum = fmap signum
1036 (+) = liftA2 (+)
1037 (*) = liftA2 (*)
1038 (-) = liftA2 (-)
1040instance (MonadAsync m, Fractional a) => Fractional (ZipAsync m a) where
1041 fromRational n = pure (fromRational n)
1043 recip = fmap recip
1045 (/) = liftA2 (/)
1047instance (MonadAsync m, Floating a) => Floating (ZipAsync m a) where
1048 pi = pure pi
1050 exp = fmap exp
1051 sqrt = fmap sqrt
1052 log = fmap log
1053 sin = fmap sin
1054 tan = fmap tan
1055 cos = fmap cos
1056 asin = fmap asin
1057 atan = fmap atan
1058 acos = fmap acos
1059 sinh = fmap sinh
1060 tanh = fmap tanh
1061 cosh = fmap cosh
1062 asinh = fmap asinh
1063 atanh = fmap atanh
1064 acosh = fmap acosh
1066 (**) = liftA2 (**)
1067 logBase = liftA2 logBase
1069-------------------------------------------------------------------------------
1070-- Type adapting combinators
1071-------------------------------------------------------------------------------
1073-- | Adapt any specific stream type to any other specific stream type.
1074adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
1075adapt = fromStream . toStream
1077-- | Fix the type of a polymorphic stream as 'SerialT'.
1078serially :: IsStream t => SerialT m a -> t m a
1079serially = adapt
1081-- | Fix the type of a polymorphic stream as 'CoserialT'.
1082coserially :: IsStream t => CoserialT m a -> t m a
1083coserially = adapt
1085-- | Same as 'coserially'.
1086{-# DEPRECATED interleaving "Please use coserially instead." #-}
1087interleaving :: IsStream t => CoserialT m a -> t m a
1088interleaving = coserially
1090-- | Fix the type of a polymorphic stream as 'CoparallelT'.
1091coparallely :: IsStream t => CoparallelT m a -> t m a
1092coparallely = adapt
1094-- | Same as 'coparallely'.
1095{-# DEPRECATED asyncly "Please use coparallely instead." #-}
1096asyncly :: IsStream t => CoparallelT m a -> t m a
1097asyncly = coparallely
1099-- | Fix the type of a polymorphic stream as 'ParallelT'.
1100parallely :: IsStream t => ParallelT m a -> t m a
1101parallely = adapt
1103-- | Fix the type of a polymorphic stream as 'ZipSerial'.
1104zipping :: IsStream t => ZipSerial m a -> t m a
1105zipping = adapt
1107-- | Fix the type of a polymorphic stream as 'ZipAsync'.
1108zippingAsync :: IsStream t => ZipAsync m a -> t m a
1109zippingAsync = adapt
1111-------------------------------------------------------------------------------
1112-- Running Streams, convenience functions specialized to types
1113-------------------------------------------------------------------------------
1115-- | Same as @runStream@.
1116{-# DEPRECATED runStreamT "Please use runStream instead." #-}
1117runStreamT :: Monad m => SerialT m a -> m ()
1118runStreamT = runStream
1120-- | Same as @runStream . coserially@.
1121{-# DEPRECATED runInterleavedT "Please use 'runStream . interleaving' instead." #-}
1122runInterleavedT :: Monad m => InterleavedT m a -> m ()
1123runInterleavedT = runStream . coserially
1125-- | Same as @runStream . coparallely@.
1126{-# DEPRECATED runAsyncT "Please use 'runStream . coparallely' instead." #-}
1127runAsyncT :: Monad m => CoparallelT m a -> m ()
1128runAsyncT = runStream . coparallely
1130-- | Same as @runStream . parallely@.
1131{-# DEPRECATED runParallelT "Please use 'runStream . parallely' instead." #-}
1132runParallelT :: Monad m => ParallelT m a -> m ()
1133runParallelT = runStream . parallely
1135-- | Same as @runStream . zipping@.
1136{-# DEPRECATED runZipStream "Please use 'runStream . zipping instead." #-}
1137runZipStream :: Monad m => ZipSerial m a -> m ()
1138runZipStream = runStream . zipping
1140-- | Same as @runStream . zippingAsync@.
1141{-# DEPRECATED runZipAsync "Please use 'runStream . zippingAsync instead." #-}
1142runZipAsync :: Monad m => ZipAsync m a -> m ()
1143runZipAsync = runStream . zippingAsync
1145------------------------------------------------------------------------------
1146-- Fold Utilities
1147------------------------------------------------------------------------------
1149-- $foldutils
1150-- These utilities are designed to pass the first argument as one of the sum
1151-- style composition operators (i.e. '<>', '<=>', '<|', '<|>') to conveniently
1152-- fold a container using any style of stream composition.
1154-- | Like the 'Prelude' 'fold' but allows you to specify a binary sum style
1155-- stream composition operator to fold a container of streams.
1157-- @foldWith (<>) $ map return [1..3]@
1158{-# INLINABLE foldWith #-}
1159foldWith :: (IsStream t, Foldable f)
1160 => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
1161foldWith f = foldr f nil
1163-- | Like 'foldMap' but allows you to specify a binary sum style composition
1164-- operator to fold a container of streams. Maps a monadic streaming action on
1165-- the container before folding it.
1167-- @foldMapWith (<>) return [1..3]@
1168{-# INLINABLE foldMapWith #-}
1169foldMapWith :: (IsStream t, Foldable f)
1170 => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
1171foldMapWith f g = foldr (f . g) nil
1173-- | Like 'foldMapWith' but with the last two arguments reversed i.e. the
1174-- monadic streaming function is the last argument.
1175{-# INLINABLE forEachWith #-}
1176forEachWith :: (IsStream t, Foldable f)
1177 => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
1178forEachWith f xs g = foldr (f . g) nil xs