on 42df609 help sign in
streamly/src/Streamly/Streams.hs
985 lines 32 kB history raw
1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving#-}
4{-# LANGUAGE MultiParamTypeClasses #-}
5{-# LANGUAGE RankNTypes #-}
6{-# LANGUAGE StandaloneDeriving #-}
7{-# LANGUAGE UndecidableInstances #-} -- XXX
9-- |
10-- Module : Streamly.Streams
11-- Copyright : (c) 2017 Harendra Kumar
12--
13-- License : BSD3
14-- Maintainer : harendra.kumar@gmail.com
15-- Stability : experimental
16-- Portability : GHC
17--
18--
19module Streamly.Streams
20 (
21 Streaming (..)
22 , MonadAsync
24 -- * SVars
25 , SVarSched (..)
26 , SVarTag (..)
27 , SVarStyle (..)
28 , SVar
29 , newEmptySVar
31 -- * Construction
32 , streamBuild
33 , fromCallback
34 , fromSVar
36 -- * Elimination
37 , cons
38 , nil
39 , streamFold
40 , runStreaming
41 , toSVar
43 -- * Transformation
44 , async
46 -- * Stream Styles
47 , StreamT
48 , InterleavedT
49 , AsyncT
50 , ParallelT
51 , ZipStream
52 , ZipAsync
54 -- * Type Adapters
55 , serially
56 , interleaving
57 , asyncly
58 , parallely
59 , zipping
60 , zippingAsync
61 , adapt
63 -- * Running Streams
64 , runStreamT
65 , runInterleavedT
66 , runAsyncT
67 , runParallelT
68 , runZipStream
69 , runZipAsync
71 -- * Zipping
72 , zipWith
73 , zipAsyncWith
75 -- * Sum Style Composition
76 , (<=>)
77 , (<|)
79 -- * Fold Utilities
80 -- $foldutils
81 , foldWith
82 , foldMapWith
83 , forEachWith
84 )
85where
87import Control.Applicative (Alternative (..), liftA2)
88import Control.Monad (MonadPlus(..), ap)
89import Control.Monad.Base (MonadBase (..))
90import Control.Monad.Catch (MonadThrow)
91import Control.Monad.Error.Class (MonadError(..))
92import Control.Monad.IO.Class (MonadIO(..))
93import Control.Monad.Reader.Class (MonadReader(..))
94import Control.Monad.State.Class (MonadState(..))
95import Control.Monad.Trans.Class (MonadTrans)
96import Data.Semigroup (Semigroup(..))
97import Prelude hiding (drop, take, zipWith)
98import Streamly.Core
100------------------------------------------------------------------------------
101-- Types that can behave as a Stream
102------------------------------------------------------------------------------
104-- | Class of types that can represent a stream of elements of some type 'a' in
105-- some monad 'm'.
106class Streaming t where
107 toStream :: t m a -> Stream m a
108 fromStream :: Stream m a -> t m a
110------------------------------------------------------------------------------
111-- Constructing a stream
112------------------------------------------------------------------------------
114-- | Add an element a the head of a stream.
115cons :: (Streaming t) => a -> t m a -> t m a
116cons a r = fromStream $ scons a (Just (toStream r))
118-- | An empty stream.
119nil :: Streaming t => t m a
120nil = fromStream $ snil
122-- | Build a stream from its church encoding. The function passed maps
123-- directly to the underlying representation of the stream type. The second
124-- parameter to the function is the "yield" function yielding a value and the
125-- remaining stream if any otherwise 'Nothing'. The third parameter is to
126-- represent an "empty" stream.
127streamBuild :: Streaming t
128 => (forall r. Maybe (SVar m a)
129 -> (a -> Maybe (t m a) -> m r)
130 -> m r
131 -> m r)
132 -> t m a
133streamBuild k = fromStream $ Stream $ \sv stp yld ->
134 let yield a Nothing = yld a Nothing
135 yield a (Just r) = yld a (Just (toStream r))
136 in k sv yield stp
138-- | Build a singleton stream from a callback function.
139fromCallback :: (Streaming t) => (forall r. (a -> m r) -> m r) -> t m a
140fromCallback k = fromStream $ Stream $ \_ _ yld -> k (\a -> yld a Nothing)
142-- | Read an SVar to get a stream.
143fromSVar :: (MonadAsync m, Streaming t) => SVar m a -> t m a
144fromSVar sv = fromStream $ fromStreamVar sv
146------------------------------------------------------------------------------
147-- Destroying a stream
148------------------------------------------------------------------------------
150-- | Fold a stream using its church encoding. The second argument is the "step"
151-- function consuming an element and the remaining stream, if any. The third
152-- argument is for consuming an "empty" stream that yields nothing.
153streamFold :: Streaming t
154 => Maybe (SVar m a) -> (a -> Maybe (t m a) -> m r) -> m r -> t m a -> m r
155streamFold sv step blank m =
156 let yield a Nothing = step a Nothing
157 yield a (Just x) = step a (Just (fromStream x))
158 in (runStream (toStream m)) sv blank yield
160-- | Run a streaming composition, discard the results.
161runStreaming :: (Monad m, Streaming t) => t m a -> m ()
162runStreaming m = go (toStream m)
163 where
164 go m1 =
165 let stop = return ()
166 yield _ Nothing = stop
167 yield _ (Just x) = go x
168 in (runStream m1) Nothing stop yield
170-- | Write a stream to an 'SVar' in a non-blocking manner. The stream can then
171-- be read back from the SVar using 'fromSVar'.
172toSVar :: (Streaming t, MonadAsync m) => SVar m a -> t m a -> m ()
173toSVar sv m = toStreamVar sv (toStream m)
175------------------------------------------------------------------------------
176-- Transformation
177------------------------------------------------------------------------------
179-- XXX Get rid of this?
180-- | Make a stream asynchronous, triggers the computation and returns a stream
181-- in the underlying monad representing the output generated by the original
182-- computation. The returned action is exhaustible and must be drained once. If
183-- not drained fully we may have a thread blocked forever and once exhausted it
184-- will always return 'empty'.
186async :: (Streaming t, MonadAsync m) => t m a -> m (t m a)
187async m = do
188 sv <- newStreamVar1 (SVarStyle Disjunction LIFO) (toStream m)
189 return $ fromSVar sv
191------------------------------------------------------------------------------
192-- StreamT
193------------------------------------------------------------------------------
195-- | The 'Monad' instance of 'StreamT' runs the /monadic continuation/ for each
196-- element of the stream, serially.
197--
198-- @
199-- main = 'runStreamT' $ do
200-- x <- return 1 \<\> return 2
201-- liftIO $ print x
202-- @
203-- @
204-- 1
205-- 2
206-- @
207--
208-- 'StreamT' nests streams serially in a depth first manner.
209--
210-- @
211-- main = 'runStreamT' $ do
212-- x <- return 1 \<\> return 2
213-- y <- return 3 \<\> return 4
214-- liftIO $ print (x, y)
215-- @
216-- @
217-- (1,3)
218-- (1,4)
219-- (2,3)
220-- (2,4)
221-- @
222--
223-- This behavior is exactly like a list transformer. We call the monadic code
224-- being run for each element of the stream a monadic continuation. In
225-- imperative paradigm we can think of this composition as nested @for@ loops
226-- and the monadic continuation is the body of the loop. The loop iterates for
227-- all elements of the stream.
228--
229newtype StreamT m a = StreamT {getStreamT :: Stream m a}
230 deriving (Semigroup, Monoid, MonadTrans, MonadIO, MonadThrow)
232deriving instance MonadAsync m => Alternative (StreamT m)
233deriving instance MonadAsync m => MonadPlus (StreamT m)
234deriving instance (MonadBase b m, Monad m) => MonadBase b (StreamT m)
235deriving instance MonadError e m => MonadError e (StreamT m)
236deriving instance MonadReader r m => MonadReader r (StreamT m)
237deriving instance MonadState s m => MonadState s (StreamT m)
239instance Streaming StreamT where
240 toStream = getStreamT
241 fromStream = StreamT
243-- XXX The Functor/Applicative/Num instances for all the types are exactly the
244-- same, how can we reduce this boilerplate (use TH)? We cannot derive them
245-- from a single base type because they depend on the Monad instance which is
246-- different for each type.
248------------------------------------------------------------------------------
249-- Monad
250------------------------------------------------------------------------------
252instance Monad m => Monad (StreamT m) where
253 return = pure
254 (StreamT (Stream m)) >>= f = StreamT $ Stream $ \_ stp yld ->
255 let run x = (runStream x) Nothing stp yld
256 yield a Nothing = run $ getStreamT (f a)
257 yield a (Just r) = run $ getStreamT (f a)
258 <> getStreamT (StreamT r >>= f)
259 in m Nothing stp yield
261------------------------------------------------------------------------------
262-- Applicative
263------------------------------------------------------------------------------
265instance Monad m => Applicative (StreamT m) where
266 pure a = StreamT $ scons a Nothing
267 (<*>) = ap
269------------------------------------------------------------------------------
270-- Functor
271------------------------------------------------------------------------------
273instance Monad m => Functor (StreamT m) where
274 fmap f (StreamT (Stream m)) = StreamT $ Stream $ \_ stp yld ->
275 let yield a Nothing = yld (f a) Nothing
276 yield a (Just r) = yld (f a)
277 (Just (getStreamT (fmap f (StreamT r))))
278 in m Nothing stp yield
280------------------------------------------------------------------------------
281-- Num
282------------------------------------------------------------------------------
284instance (Monad m, Num a) => Num (StreamT m a) where
285 fromInteger n = pure (fromInteger n)
287 negate = fmap negate
288 abs = fmap abs
289 signum = fmap signum
291 (+) = liftA2 (+)
292 (*) = liftA2 (*)
293 (-) = liftA2 (-)
295instance (Monad m, Fractional a) => Fractional (StreamT m a) where
296 fromRational n = pure (fromRational n)
298 recip = fmap recip
300 (/) = liftA2 (/)
302instance (Monad m, Floating a) => Floating (StreamT m a) where
303 pi = pure pi
305 exp = fmap exp
306 sqrt = fmap sqrt
307 log = fmap log
308 sin = fmap sin
309 tan = fmap tan
310 cos = fmap cos
311 asin = fmap asin
312 atan = fmap atan
313 acos = fmap acos
314 sinh = fmap sinh
315 tanh = fmap tanh
316 cosh = fmap cosh
317 asinh = fmap asinh
318 atanh = fmap atanh
319 acosh = fmap acosh
321 (**) = liftA2 (**)
322 logBase = liftA2 logBase
324------------------------------------------------------------------------------
325-- InterleavedT
326------------------------------------------------------------------------------
328-- | Like 'StreamT' but different in nesting behavior. It fairly interleaves
329-- the iterations of the inner and the outer loop, nesting loops in a breadth
330-- first manner.
331--
332--
333-- @
334-- main = 'runInterleavedT' $ do
335-- x <- return 1 \<\> return 2
336-- y <- return 3 \<\> return 4
337-- liftIO $ print (x, y)
338-- @
339-- @
340-- (1,3)
341-- (2,3)
342-- (1,4)
343-- (2,4)
344-- @
345--
346newtype InterleavedT m a = InterleavedT {getInterleavedT :: Stream m a}
347 deriving (Semigroup, Monoid, MonadTrans, MonadIO, MonadThrow)
349deriving instance MonadAsync m => Alternative (InterleavedT m)
350deriving instance MonadAsync m => MonadPlus (InterleavedT m)
351deriving instance (MonadBase b m, Monad m) => MonadBase b (InterleavedT m)
352deriving instance MonadError e m => MonadError e (InterleavedT m)
353deriving instance MonadReader r m => MonadReader r (InterleavedT m)
354deriving instance MonadState s m => MonadState s (InterleavedT m)
356instance Streaming InterleavedT where
357 toStream = getInterleavedT
358 fromStream = InterleavedT
360instance Monad m => Monad (InterleavedT m) where
361 return = pure
362 (InterleavedT (Stream m)) >>= f = InterleavedT $ Stream $ \_ stp yld ->
363 let run x = (runStream x) Nothing stp yld
364 yield a Nothing = run $ getInterleavedT (f a)
365 yield a (Just r) = run $ getInterleavedT (f a)
366 `interleave`
367 getInterleavedT (InterleavedT r >>= f)
368 in m Nothing stp yield
370------------------------------------------------------------------------------
371-- Applicative
372------------------------------------------------------------------------------
374instance Monad m => Applicative (InterleavedT m) where
375 pure a = InterleavedT $ scons a Nothing
376 (<*>) = ap
378------------------------------------------------------------------------------
379-- Functor
380------------------------------------------------------------------------------
382instance Monad m => Functor (InterleavedT m) where
383 fmap f (InterleavedT (Stream m)) = InterleavedT $ Stream $ \_ stp yld ->
384 let yield a Nothing = yld (f a) Nothing
385 yield a (Just r) =
386 yld (f a) (Just (getInterleavedT (fmap f (InterleavedT r))))
387 in m Nothing stp yield
389------------------------------------------------------------------------------
390-- Num
391------------------------------------------------------------------------------
393instance (Monad m, Num a) => Num (InterleavedT m a) where
394 fromInteger n = pure (fromInteger n)
396 negate = fmap negate
397 abs = fmap abs
398 signum = fmap signum
400 (+) = liftA2 (+)
401 (*) = liftA2 (*)
402 (-) = liftA2 (-)
404instance (Monad m, Fractional a) => Fractional (InterleavedT m a) where
405 fromRational n = pure (fromRational n)
407 recip = fmap recip
409 (/) = liftA2 (/)
411instance (Monad m, Floating a) => Floating (InterleavedT m a) where
412 pi = pure pi
414 exp = fmap exp
415 sqrt = fmap sqrt
416 log = fmap log
417 sin = fmap sin
418 tan = fmap tan
419 cos = fmap cos
420 asin = fmap asin
421 atan = fmap atan
422 acos = fmap acos
423 sinh = fmap sinh
424 tanh = fmap tanh
425 cosh = fmap cosh
426 asinh = fmap asinh
427 atanh = fmap atanh
428 acosh = fmap acosh
430 (**) = liftA2 (**)
431 logBase = liftA2 logBase
433------------------------------------------------------------------------------
434-- AsyncT
435------------------------------------------------------------------------------
437-- | Like 'StreamT' but /may/ run each iteration concurrently using demand
438-- driven concurrency. More concurrent iterations are started only if the
439-- previous iterations are not able to produce enough output for the consumer.
440--
441-- @
442-- import "Streamly"
443-- import Control.Concurrent
444--
445-- main = 'runAsyncT' $ do
446-- n <- return 3 \<\> return 2 \<\> return 1
447-- liftIO $ do
448-- threadDelay (n * 1000000)
449-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
450-- @
451-- @
452-- ThreadId 40: Delay 1
453-- ThreadId 39: Delay 2
454-- ThreadId 38: Delay 3
455-- @
456--
457-- All iterations may run in the same thread if they do not block.
458newtype AsyncT m a = AsyncT {getAsyncT :: Stream m a}
459 deriving (Semigroup, Monoid, MonadTrans)
461deriving instance MonadAsync m => Alternative (AsyncT m)
462deriving instance MonadAsync m => MonadPlus (AsyncT m)
463deriving instance MonadAsync m => MonadIO (AsyncT m)
464deriving instance MonadAsync m => MonadThrow (AsyncT m)
465deriving instance (MonadBase b m, MonadAsync m) => MonadBase b (AsyncT m)
466deriving instance (MonadError e m, MonadAsync m) => MonadError e (AsyncT m)
467deriving instance (MonadReader r m, MonadAsync m) => MonadReader r (AsyncT m)
468deriving instance (MonadState s m, MonadAsync m) => MonadState s (AsyncT m)
470instance Streaming AsyncT where
471 toStream = getAsyncT
472 fromStream = AsyncT
474{-# INLINE parbind #-}
475parbind
476 :: (forall c. Stream m c -> Stream m c -> Stream m c)
477 -> Stream m a
478 -> (a -> Stream m b)
479 -> Stream m b
480parbind par m f = go m
481 where
482 go (Stream g) =
483 Stream $ \ctx stp yld ->
484 let run x = (runStream x) ctx stp yld
485 yield a Nothing = run $ f a
486 yield a (Just r) = run $ f a `par` (go r)
487 in g Nothing stp yield
489instance MonadAsync m => Monad (AsyncT m) where
490 return = pure
491 (AsyncT m) >>= f = AsyncT $ parbind par m g
492 where g x = getAsyncT (f x)
493 par = joinStreamVar2 (SVarStyle Conjunction LIFO)
495------------------------------------------------------------------------------
496-- Applicative
497------------------------------------------------------------------------------
499instance MonadAsync m => Applicative (AsyncT m) where
500 pure a = AsyncT $ scons a Nothing
501 (<*>) = ap
503------------------------------------------------------------------------------
504-- Functor
505------------------------------------------------------------------------------
507instance Monad m => Functor (AsyncT m) where
508 fmap f (AsyncT (Stream m)) = AsyncT $ Stream $ \_ stp yld ->
509 let yield a Nothing = yld (f a) Nothing
510 yield a (Just r) = yld (f a) (Just (getAsyncT (fmap f (AsyncT r))))
511 in m Nothing stp yield
513------------------------------------------------------------------------------
514-- Num
515------------------------------------------------------------------------------
517instance (MonadAsync m, Num a) => Num (AsyncT m a) where
518 fromInteger n = pure (fromInteger n)
520 negate = fmap negate
521 abs = fmap abs
522 signum = fmap signum
524 (+) = liftA2 (+)
525 (*) = liftA2 (*)
526 (-) = liftA2 (-)
528instance (MonadAsync m, Fractional a) => Fractional (AsyncT m a) where
529 fromRational n = pure (fromRational n)
531 recip = fmap recip
533 (/) = liftA2 (/)
535instance (MonadAsync m, Floating a) => Floating (AsyncT m a) where
536 pi = pure pi
538 exp = fmap exp
539 sqrt = fmap sqrt
540 log = fmap log
541 sin = fmap sin
542 tan = fmap tan
543 cos = fmap cos
544 asin = fmap asin
545 atan = fmap atan
546 acos = fmap acos
547 sinh = fmap sinh
548 tanh = fmap tanh
549 cosh = fmap cosh
550 asinh = fmap asinh
551 atanh = fmap atanh
552 acosh = fmap acosh
554 (**) = liftA2 (**)
555 logBase = liftA2 logBase
557------------------------------------------------------------------------------
558-- ParallelT
559------------------------------------------------------------------------------
561-- | Like 'StreamT' but runs /all/ iterations fairly concurrently using a round
562-- robin scheduling.
563--
564-- @
565-- import "Streamly"
566-- import Control.Concurrent
567--
568-- main = 'runParallelT' $ do
569-- n <- return 3 \<\> return 2 \<\> return 1
570-- liftIO $ do
571-- threadDelay (n * 1000000)
572-- myThreadId >>= \\tid -> putStrLn (show tid ++ ": Delay " ++ show n)
573-- @
574-- @
575-- ThreadId 40: Delay 1
576-- ThreadId 39: Delay 2
577-- ThreadId 38: Delay 3
578-- @
579--
580-- Unlike 'AsyncT' all iterations are guaranteed to run fairly concurrently,
581-- unconditionally.
582newtype ParallelT m a = ParallelT {getParallelT :: Stream m a}
583 deriving (Semigroup, Monoid, MonadTrans)
585deriving instance MonadAsync m => Alternative (ParallelT m)
586deriving instance MonadAsync m => MonadPlus (ParallelT m)
587deriving instance MonadAsync m => MonadIO (ParallelT m)
588deriving instance MonadAsync m => MonadThrow (ParallelT m)
589deriving instance (MonadBase b m, MonadAsync m) => MonadBase b (ParallelT m)
590deriving instance (MonadError e m, MonadAsync m) => MonadError e (ParallelT m)
591deriving instance (MonadReader r m, MonadAsync m) => MonadReader r (ParallelT m)
592deriving instance (MonadState s m, MonadAsync m) => MonadState s (ParallelT m)
594instance Streaming ParallelT where
595 toStream = getParallelT
596 fromStream = ParallelT
598instance MonadAsync m => Monad (ParallelT m) where
599 return = pure
600 (ParallelT m) >>= f = ParallelT $ parbind par m g
601 where g x = getParallelT (f x)
602 par = joinStreamVar2 (SVarStyle Conjunction FIFO)
604------------------------------------------------------------------------------
605-- Applicative
606------------------------------------------------------------------------------
608instance MonadAsync m => Applicative (ParallelT m) where
609 pure a = ParallelT $ scons a Nothing
610 (<*>) = ap
612------------------------------------------------------------------------------
613-- Functor
614------------------------------------------------------------------------------
616instance Monad m => Functor (ParallelT m) where
617 fmap f (ParallelT (Stream m)) = ParallelT $ Stream $ \_ stp yld ->
618 let yield a Nothing = yld (f a) Nothing
619 yield a (Just r) = yld (f a)
620 (Just (getParallelT (fmap f (ParallelT r))))
621 in m Nothing stp yield
623------------------------------------------------------------------------------
624-- Num
625------------------------------------------------------------------------------
627instance (MonadAsync m, Num a) => Num (ParallelT m a) where
628 fromInteger n = pure (fromInteger n)
630 negate = fmap negate
631 abs = fmap abs
632 signum = fmap signum
634 (+) = liftA2 (+)
635 (*) = liftA2 (*)
636 (-) = liftA2 (-)
638instance (MonadAsync m, Fractional a) => Fractional (ParallelT m a) where
639 fromRational n = pure (fromRational n)
641 recip = fmap recip
643 (/) = liftA2 (/)
645instance (MonadAsync m, Floating a) => Floating (ParallelT m a) where
646 pi = pure pi
648 exp = fmap exp
649 sqrt = fmap sqrt
650 log = fmap log
651 sin = fmap sin
652 tan = fmap tan
653 cos = fmap cos
654 asin = fmap asin
655 atan = fmap atan
656 acos = fmap acos
657 sinh = fmap sinh
658 tanh = fmap tanh
659 cosh = fmap cosh
660 asinh = fmap asinh
661 atanh = fmap atanh
662 acosh = fmap acosh
664 (**) = liftA2 (**)
665 logBase = liftA2 logBase
667------------------------------------------------------------------------------
668-- Serially Zipping Streams
669------------------------------------------------------------------------------
671-- | Zip two streams serially using a pure zipping function.
672zipWith :: Streaming t => (a -> b -> c) -> t m a -> t m b -> t m c
673zipWith f m1 m2 = fromStream $ go (toStream m1) (toStream m2)
674 where
675 go mx my = Stream $ \_ stp yld -> do
676 let merge a ra =
677 let yield2 b Nothing = yld (f a b) Nothing
678 yield2 b (Just rb) = yld (f a b) (Just (go ra rb))
679 in (runStream my) Nothing stp yield2
680 let yield1 a Nothing = merge a snil
681 yield1 a (Just ra) = merge a ra
682 (runStream mx) Nothing stp yield1
684-- | 'ZipStream' zips serially i.e. it produces one element from each stream
685-- serially and then zips the two elements. Note, for convenience we have used
686-- the 'zipping' combinator in the following example instead of using a type
687-- annotation.
688--
689-- @
690-- main = (toList . 'zipping' $ (,) \<$\> s1 \<*\> s2) >>= print
691-- where s1 = pure 1 <> pure 2
692-- s2 = pure 3 <> pure 4
693-- @
694-- @
695-- [(1,3),(2,4)]
696-- @
697--
698-- This applicative operation can be seen as the zipping equivalent of
699-- interleaving with '<=>'.
700newtype ZipStream m a = ZipStream {getZipStream :: Stream m a}
701 deriving (Semigroup, Monoid)
703deriving instance MonadAsync m => Alternative (ZipStream m)
705instance Monad m => Functor (ZipStream m) where
706 fmap f (ZipStream (Stream m)) = ZipStream $ Stream $ \_ stp yld ->
707 let yield a Nothing = yld (f a) Nothing
708 yield a (Just r) = yld (f a)
709 (Just (getZipStream (fmap f (ZipStream r))))
710 in m Nothing stp yield
712instance Monad m => Applicative (ZipStream m) where
713 pure a = ZipStream $ scons a Nothing
714 (<*>) = zipWith id
716instance Streaming ZipStream where
717 toStream = getZipStream
718 fromStream = ZipStream
720instance (Monad m, Num a) => Num (ZipStream m a) where
721 fromInteger n = pure (fromInteger n)
723 negate = fmap negate
724 abs = fmap abs
725 signum = fmap signum
727 (+) = liftA2 (+)
728 (*) = liftA2 (*)
729 (-) = liftA2 (-)
731instance (Monad m, Fractional a) => Fractional (ZipStream m a) where
732 fromRational n = pure (fromRational n)
734 recip = fmap recip
736 (/) = liftA2 (/)
738instance (Monad m, Floating a) => Floating (ZipStream m a) where
739 pi = pure pi
741 exp = fmap exp
742 sqrt = fmap sqrt
743 log = fmap log
744 sin = fmap sin
745 tan = fmap tan
746 cos = fmap cos
747 asin = fmap asin
748 atan = fmap atan
749 acos = fmap acos
750 sinh = fmap sinh
751 tanh = fmap tanh
752 cosh = fmap cosh
753 asinh = fmap asinh
754 atanh = fmap atanh
755 acosh = fmap acosh
757 (**) = liftA2 (**)
758 logBase = liftA2 logBase
760------------------------------------------------------------------------------
761-- Parallely Zipping Streams
762------------------------------------------------------------------------------
764-- | Zip two streams asyncly (i.e. both the elements being zipped are generated
765-- concurrently) using a pure zipping function.
766zipAsyncWith :: (Streaming t, MonadAsync m)
767 => (a -> b -> c) -> t m a -> t m b -> t m c
768zipAsyncWith f m1 m2 = fromStream $ Stream $ \_ stp yld -> do
769 ma <- async m1
770 mb <- async m2
771 (runStream (toStream (zipWith f ma mb))) Nothing stp yld
773-- | Like 'ZipStream' but zips in parallel, it generates both the elements to
774-- be zipped concurrently.
775--
776-- @
777-- main = (toList . 'zippingAsync' $ (,) \<$\> s1 \<*\> s2) >>= print
778-- where s1 = pure 1 <> pure 2
779-- s2 = pure 3 <> pure 4
780-- @
781-- @
782-- [(1,3),(2,4)]
783-- @
784--
785-- This applicative operation can be seen as the zipping equivalent of
786-- parallel composition with '<|>'.
787newtype ZipAsync m a = ZipAsync {getZipAsync :: Stream m a}
788 deriving (Semigroup, Monoid)
790deriving instance MonadAsync m => Alternative (ZipAsync m)
792instance Monad m => Functor (ZipAsync m) where
793 fmap f (ZipAsync (Stream m)) = ZipAsync $ Stream $ \_ stp yld ->
794 let yield a Nothing = yld (f a) Nothing
795 yield a (Just r) = yld (f a)
796 (Just (getZipAsync (fmap f (ZipAsync r))))
797 in m Nothing stp yield
799instance MonadAsync m => Applicative (ZipAsync m) where
800 pure a = ZipAsync $ scons a Nothing
801 (<*>) = zipAsyncWith id
803instance Streaming ZipAsync where
804 toStream = getZipAsync
805 fromStream = ZipAsync
807instance (MonadAsync m, Num a) => Num (ZipAsync m a) where
808 fromInteger n = pure (fromInteger n)
810 negate = fmap negate
811 abs = fmap abs
812 signum = fmap signum
814 (+) = liftA2 (+)
815 (*) = liftA2 (*)
816 (-) = liftA2 (-)
818instance (MonadAsync m, Fractional a) => Fractional (ZipAsync m a) where
819 fromRational n = pure (fromRational n)
821 recip = fmap recip
823 (/) = liftA2 (/)
825instance (MonadAsync m, Floating a) => Floating (ZipAsync m a) where
826 pi = pure pi
828 exp = fmap exp
829 sqrt = fmap sqrt
830 log = fmap log
831 sin = fmap sin
832 tan = fmap tan
833 cos = fmap cos
834 asin = fmap asin
835 atan = fmap atan
836 acos = fmap acos
837 sinh = fmap sinh
838 tanh = fmap tanh
839 cosh = fmap cosh
840 asinh = fmap asinh
841 atanh = fmap atanh
842 acosh = fmap acosh
844 (**) = liftA2 (**)
845 logBase = liftA2 logBase
847-------------------------------------------------------------------------------
848-- Type adapting combinators
849-------------------------------------------------------------------------------
851-- | Adapt one streaming type to another.
852adapt :: (Streaming t1, Streaming t2) => t1 m a -> t2 m a
853adapt = fromStream . toStream
855-- | Interpret an ambiguously typed stream as 'StreamT'.
856serially :: StreamT m a -> StreamT m a
857serially x = x
859-- | Interpret an ambiguously typed stream as 'InterleavedT'.
860interleaving :: InterleavedT m a -> InterleavedT m a
861interleaving x = x
863-- | Interpret an ambiguously typed stream as 'AsyncT'.
864asyncly :: AsyncT m a -> AsyncT m a
865asyncly x = x
867-- | Interpret an ambiguously typed stream as 'ParallelT'.
868parallely :: ParallelT m a -> ParallelT m a
869parallely x = x
871-- | Interpret an ambiguously typed stream as 'ZipStream'.
872zipping :: ZipStream m a -> ZipStream m a
873zipping x = x
875-- | Interpret an ambiguously typed stream as 'ZipAsync'.
876zippingAsync :: ZipAsync m a -> ZipAsync m a
877zippingAsync x = x
879-------------------------------------------------------------------------------
880-- Running Streams, convenience functions specialized to types
881-------------------------------------------------------------------------------
883-- | Same as @runStreaming . serially@.
884runStreamT :: Monad m => StreamT m a -> m ()
885runStreamT = runStreaming
887-- | Same as @runStreaming . interleaving@.
888runInterleavedT :: Monad m => InterleavedT m a -> m ()
889runInterleavedT = runStreaming
891-- | Same as @runStreaming . asyncly@.
892runAsyncT :: Monad m => AsyncT m a -> m ()
893runAsyncT = runStreaming
895-- | Same as @runStreaming . parallely@.
896runParallelT :: Monad m => ParallelT m a -> m ()
897runParallelT = runStreaming
899-- | Same as @runStreaming . zipping@.
900runZipStream :: Monad m => ZipStream m a -> m ()
901runZipStream = runStreaming
903-- | Same as @runStreaming . zippingAsync@.
904runZipAsync :: Monad m => ZipAsync m a -> m ()
905runZipAsync = runStreaming
907------------------------------------------------------------------------------
908-- Sum Style Composition
909------------------------------------------------------------------------------
911infixr 5 <=>
913-- | Sequential interleaved composition, in contrast to '<>' this operator
914-- fairly interleaves two streams instead of appending them; yielding one
915-- element from each stream alternately.
916--
917-- @
918-- main = ('toList' . 'serially' $ (return 1 <> return 2) \<=\> (return 3 <> return 4)) >>= print
919-- @
920-- @
921-- [1,3,2,4]
922-- @
923--
924-- This operator corresponds to the 'InterleavedT' style. Unlike '<>', this
925-- operator cannot be used to fold infinite containers since that might
926-- accumulate too many partially drained streams. To be clear, it can combine
927-- infinite streams but not infinite number of streams.
928{-# INLINE (<=>) #-}
929(<=>) :: Streaming t => t m a -> t m a -> t m a
930m1 <=> m2 = fromStream $ interleave (toStream m1) (toStream m2)
932-- | Demand driven concurrent composition. In contrast to '<|>' this operator
933-- concurrently "merges" streams in a left biased manner rather than fairly
934-- interleaving them. It keeps yielding from the stream on the left as long as
935-- it can. If the left stream blocks or cannot keep up with the pace of the
936-- consumer it can concurrently yield from the stream on the right in parallel.
937--
938-- @
939-- main = ('toList' . 'serially' $ (return 1 <> return 2) \<| (return 3 <> return 4)) >>= print
940-- @
941-- @
942-- [1,2,3,4]
943-- @
944--
945-- Unlike '<|>' it can be used to fold infinite containers of streams. This
946-- operator corresponds to the 'AsyncT' type for product style composition.
947--
948{-# INLINE (<|) #-}
949(<|) :: (Streaming t, MonadAsync m) => t m a -> t m a -> t m a
950m1 <| m2 = fromStream $ parLeft (toStream m1) (toStream m2)
952------------------------------------------------------------------------------
953-- Fold Utilities
954------------------------------------------------------------------------------
956-- $foldutils
957-- These utilities are designed to pass the first argument as one of the sum
958-- style composition operators (i.e. '<>', '<=>', '<|', '<|>') to conveniently
959-- fold a container using any style of stream composition.
961-- | Like the 'Prelude' 'fold' but allows you to specify a binary sum style
962-- stream composition operator to fold a container of streams.
963--
964-- @foldWith (<>) $ map return [1..3]@
965{-# INLINABLE foldWith #-}
966foldWith :: (Streaming t, Foldable f)
967 => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
968foldWith f = foldr f nil
970-- | Like 'foldMap' but allows you to specify a binary sum style composition
971-- operator to fold a container of streams. Maps a monadic streaming action on
972-- the container before folding it.
973--
974-- @foldMapWith (<>) return [1..3]@
975{-# INLINABLE foldMapWith #-}
976foldMapWith :: (Streaming t, Foldable f)
977 => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
978foldMapWith f g = foldr (f . g) nil
980-- | Like 'foldMapWith' but with the last two arguments reversed i.e. the
981-- monadic streaming function is the last argument.
982{-# INLINABLE forEachWith #-}
983forEachWith :: (Streaming t, Foldable f)
984 => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
985forEachWith f xs g = foldr (f . g) nil xs