on 516cab5 help sign in
909 lines 29 kB history raw
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE CPP #-}
3{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE InstanceSigs #-}
7{-# LANGUAGE LambdaCase #-}
8{-# LANGUAGE MagicHash #-}
9{-# LANGUAGE MultiParamTypeClasses #-}
10{-# LANGUAGE RankNTypes #-}
11{-# LANGUAGE UnboxedTuples #-}
12{-# LANGUAGE UndecidableInstances #-} -- XXX
14-- |
15-- Module : Streamly.Streams.StreamK
16-- Copyright : (c) 2017 Harendra Kumar
17--
18-- License : BSD3
19-- Maintainer : harendra.kumar@gmail.com
20-- Stability : experimental
21-- Portability : GHC
22--
23--
24-- Continuation passing style (CPS) stream implementation. The symbol 'K' below
25-- denotes a function as well as a Kontinuation.
26--
27-- @
28-- import qualified Streamly.Streams.StreamK as K
29-- @
30--
31module Streamly.Streams.StreamK
32 (
33 -- * A class for streams
34 IsStream (..)
35 , adapt
37 -- * The stream type
38 , Stream (..)
40 -- * Construction
41 , mkStream
42 , nil
43 , cons
44 , (.:)
46 -- * Asynchronous construction
47 , nilK
48 , yieldK
49 , consK
51 -- * Deconstruction
52 , uncons
54 -- * Generation
55 -- ** Unfolds
56 , unfoldr
57 , unfoldrM
59 -- ** Specialized Generation
60 , repeat
62 -- ** Conversions
63 , yield
64 , yieldM
65 , fromFoldable
66 , fromList
67 , fromStreamK
69 -- * Elimination
70 -- ** General Folds
71 , foldStream
72 , foldr
73 , foldrM
74 , foldl'
75 , foldlM'
76 , foldx
77 , foldxM
79 -- ** Specialized Folds
80 , runStream
81 , null
82 , head
83 , tail
84 , elem
85 , notElem
86 , all
87 , any
88 , last
89 , minimum
90 , maximum
92 -- ** Map and Fold
93 , mapM_
95 -- ** Conversions
96 , toList
97 , toStreamK
99 -- * Transformation
100 -- ** By folding (scans)
101 , scanl'
102 , scanx
104 -- ** Filtering
105 , filter
106 , take
107 , takeWhile
108 , drop
109 , dropWhile
111 -- ** Mapping
112 , map
113 , mapM
114 , sequence
116 -- ** Map and Filter
117 , mapMaybe
119 -- * Semigroup Style Composition
120 , serial
122 -- * Utilities
123 , consMSerial
124 , bindWith
125 , withLocal
127 -- * Deprecated
128 , Streaming -- deprecated
129 , once -- deprecated
130 )
131where
133import Control.Monad (void)
134import Control.Monad.Reader.Class (MonadReader(..))
135import Control.Monad.Trans.Class (MonadTrans(lift))
136import Data.Semigroup (Semigroup(..))
137import Prelude
138 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
139 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
140 maximum, elem, notElem, null, head, tail)
141import qualified Prelude
143import Streamly.SVar
145------------------------------------------------------------------------------
146-- The basic stream type
147------------------------------------------------------------------------------
149-- | The type @Stream m a@ represents a monadic stream of values of type 'a'
150-- constructed using actions in monad 'm'. It uses stop, singleton and yield
151-- continuations equivalent to the following direct style type:
152--
153-- @
154-- data Stream m a = Stop | Singleton a | Yield a (Stream m a)
155-- @
156--
157-- To facilitate parallel composition we maintain a local state in an 'SVar'
158-- that is shared across and is used for synchronization of the streams being
159-- composed.
160--
161-- The singleton case can be expressed in terms of stop and yield but we have
162-- it as a separate case to optimize composition operations for streams with
163-- single element. We build singleton streams in the implementation of 'pure'
164-- for Applicative and Monad, and in 'lift' for MonadTrans.
165--
166newtype Stream m a =
167 Stream {
168 unStream :: forall r.
169 State Stream m a -- state
170 -> m r -- stop
171 -> (a -> m r) -- singleton
172 -> (a -> Stream m a -> m r) -- yield
173 -> m r
174 }
176------------------------------------------------------------------------------
177-- Types that can behave as a Stream
178------------------------------------------------------------------------------
180infixr 5 `consM`
181infixr 5 |:
183-- | Class of types that can represent a stream of elements of some type 'a' in
184-- some monad 'm'.
185--
186-- @since 0.2.0
187class IsStream t where
188 toStream :: t m a -> Stream m a
189 fromStream :: Stream m a -> t m a
190 -- | Constructs a stream by adding a monadic action at the head of an
191 -- existing stream. For example:
192 --
193 -- @
194 -- > toList $ getLine \`consM` getLine \`consM` nil
195 -- hello
196 -- world
197 -- ["hello","world"]
198 -- @
199 --
200 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
201 --
202 -- @since 0.2.0
203 consM :: MonadAsync m => m a -> t m a -> t m a
204 -- | Operator equivalent of 'consM'. We can read it as "@parallel colon@"
205 -- to remember that @|@ comes before ':'.
206 --
207 -- @
208 -- > toList $ getLine |: getLine |: nil
209 -- hello
210 -- world
211 -- ["hello","world"]
212 -- @
213 --
214 -- @
215 -- let delay = threadDelay 1000000 >> print 1
216 -- runStream $ serially $ delay |: delay |: delay |: nil
217 -- runStream $ parallely $ delay |: delay |: delay |: nil
218 -- @
219 --
220 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
221 --
222 -- @since 0.2.0
223 (|:) :: MonadAsync m => m a -> t m a -> t m a
224 -- We can define (|:) just as 'consM' but it is defined explicitly for each
225 -- type because we want to use SPECIALIZE pragma on the definition.
227-- | Same as 'IsStream'.
228--
229-- @since 0.1.0
230{-# DEPRECATED Streaming "Please use IsStream instead." #-}
231type Streaming = IsStream
233-------------------------------------------------------------------------------
234-- Type adapting combinators
235-------------------------------------------------------------------------------
237-- | Adapt any specific stream type to any other specific stream type.
238--
239-- @since 0.1.0
240adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
241adapt = fromStream . toStream
243------------------------------------------------------------------------------
244-- Building a stream
245------------------------------------------------------------------------------
247-- | Build a stream from an 'SVar', a stop continuation, a singleton stream
248-- continuation and a yield continuation.
249mkStream:: IsStream t
250 => (forall r. State Stream m a
251 -> m r
252 -> (a -> m r)
253 -> (a -> t m a -> m r)
254 -> m r)
255 -> t m a
256mkStream k = fromStream $ Stream $ \st stp sng yld ->
257 let yieldk a r = yld a (toStream r)
258 in k (rstState st) stp sng yieldk
260------------------------------------------------------------------------------
261-- Construction
262------------------------------------------------------------------------------
264-- | An empty stream.
265--
266-- @
267-- > toList nil
268-- []
269-- @
270--
271-- @since 0.1.0
272nil :: IsStream t => t m a
273nil = fromStream $ Stream $ \_ stp _ _ -> stp
275infixr 5 `cons`
277-- faster than consM because there is no bind.
278-- | Construct a stream by adding a pure value at the head of an existing
279-- stream. For serial streams this is the same as @(return a) \`consM` r@ but
280-- more efficient. For concurrent streams this is not concurrent whereas
281-- 'consM' is concurrent. For example:
282--
283-- @
284-- > toList $ 1 \`cons` 2 \`cons` 3 \`cons` nil
285-- [1,2,3]
286-- @
287--
288-- @since 0.1.0
289cons :: IsStream t => a -> t m a -> t m a
290cons a r = fromStream $ Stream $ \_ _ _ yld -> yld a (toStream r)
292infixr 5 .:
294-- | Operator equivalent of 'cons'.
295--
296-- @
297-- > toList $ 1 .: 2 .: 3 .: nil
298-- [1,2,3]
299-- @
300--
301-- @since 0.1.1
302(.:) :: IsStream t => a -> t m a -> t m a
303(.:) = cons
305{-# INLINE consMSerial #-}
306consMSerial :: (Monad m) => m a -> Stream m a -> Stream m a
307consMSerial m r = Stream $ \_ _ _ yld -> m >>= \a -> yld a r
309------------------------------------------------------------------------------
310-- Asynchronous construction
311------------------------------------------------------------------------------
313-- | Make an empty stream from a callback function.
314nilK :: IsStream t => (forall r. m r -> m r) -> t m a
315nilK k = fromStream $ Stream $ \_ stp _ _ -> k stp
317-- | Make a singleton stream from a one shot callback function.
318yieldK :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a
319yieldK k = fromStream $ Stream $ \_ _ sng _ -> k sng
321-- | Construct a stream from a callback function.
322consK :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a -> t m a
323consK k r = fromStream $ Stream $ \_ _ _ yld -> k (\x -> yld x (toStream r))
325-- XXX consK with concurrent callbacks
326-- XXX Build a stream from a repeating callback function.
328-------------------------------------------------------------------------------
329-- IsStream Stream
330-------------------------------------------------------------------------------
332instance IsStream Stream where
333 toStream = id
334 fromStream = id
336 {-# INLINE consM #-}
337 {-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-}
338 consM :: Monad m => m a -> Stream m a -> Stream m a
339 consM = consMSerial
341 {-# INLINE (|:) #-}
342 {-# SPECIALIZE (|:) :: IO a -> Stream IO a -> Stream IO a #-}
343 (|:) :: Monad m => m a -> Stream m a -> Stream m a
344 (|:) = consMSerial
346-------------------------------------------------------------------------------
347-- Deconstruction
348-------------------------------------------------------------------------------
350{-# INLINE uncons #-}
351uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
352uncons m =
353 let stop = return Nothing
354 single a = return (Just (a, nil))
355 yieldk a r = return (Just (a, fromStream r))
356 in (unStream (toStream m)) defState stop single yieldk
358-------------------------------------------------------------------------------
359-- Generation
360-------------------------------------------------------------------------------
362{-# INLINE unfoldr #-}
363unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
364unfoldr step = fromStream . go
365 where
366 go s = Stream $ \_ stp _ yld ->
367 case step s of
368 Nothing -> stp
369 Just (a, b) -> yld a (go b)
371{-# INLINE unfoldrM #-}
372unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
373unfoldrM step = go
374 where
375 go s = fromStream $ Stream $ \svr stp sng yld -> do
376 mayb <- step s
377 case mayb of
378 Nothing -> stp
379 Just (a, b) ->
380 unStream (toStream (return a |: go b)) svr stp sng yld
382-------------------------------------------------------------------------------
383-- Special generation
384-------------------------------------------------------------------------------
386-- Faster than yieldM because there is no bind. Usually we can construct a
387-- stream from a pure value using "pure" in an applicative, however in case of
388-- Zip streams pure creates an infinite stream.
389--
390-- | Create a singleton stream from a pure value. In monadic streams, 'pure' or
391-- 'return' can be used in place of 'yield', however, in Zip applicative
392-- streams 'pure' is equivalent to 'repeat'.
393--
394-- @since 0.4.0
395yield :: IsStream t => a -> t m a
396yield a = fromStream $ Stream $ \_ _ single _ -> single a
398-- | Create a singleton stream from a monadic action. Same as @m \`consM` nil@
399-- but more efficient.
400--
401-- @
402-- > toList $ yieldM getLine
403-- hello
404-- ["hello"]
405-- @
406--
407-- @since 0.4.0
408{-# INLINE yieldM #-}
409yieldM :: (Monad m, IsStream t) => m a -> t m a
410yieldM m = fromStream $ Stream $ \_ _ single _ -> m >>= single
412-- | Same as yieldM
413--
414-- @since 0.2.0
415{-# DEPRECATED once "Please use yieldM instead." #-}
416{-# INLINE once #-}
417once :: (Monad m, IsStream t) => m a -> t m a
418once = yieldM
420-- | Generate an infinite stream by repeating a pure value.
421--
422-- @since 0.4.0
423repeat :: IsStream t => a -> t m a
424repeat a = let x = cons a x in x
426-------------------------------------------------------------------------------
427-- Conversions
428-------------------------------------------------------------------------------
430-- | Construct a stream from a 'Foldable' containing pure values.
431--
432-- @since 0.2.0
433{-# INLINE fromFoldable #-}
434fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
435fromFoldable = Prelude.foldr cons nil
437{-# INLINE fromList #-}
438fromList :: IsStream t => [a] -> t m a
439fromList = fromFoldable
441{-# INLINE fromStreamK #-}
442fromStreamK :: Stream m a -> Stream m a
443fromStreamK = id
445-------------------------------------------------------------------------------
446-- Elimination by Folding
447-------------------------------------------------------------------------------
449-- | Fold a stream by providing an SVar, a stop continuation, a singleton
450-- continuation and a yield continuation.
451foldStream
452 :: IsStream t
453 => State Stream m a
454 -> m r
455 -> (a -> m r)
456 -> (a -> t m a -> m r)
457 -> t m a
458 -> m r
459foldStream st blank single step m =
460 let yieldk a x = step a (fromStream x)
461 in (unStream (toStream m)) st blank single yieldk
463-- | Lazy right associative fold.
464foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
465foldr step acc m = go (toStream m)
466 where
467 go m1 =
468 let stop = return acc
469 single a = return (step a acc)
470 yieldk a r = go r >>= \b -> return (step a b)
471 in (unStream m1) defState stop single yieldk
473-- | Lazy right fold with a monadic step function.
474{-# INLINE foldrM #-}
475foldrM :: (IsStream t, Monad m) => (a -> b -> m b) -> b -> t m a -> m b
476foldrM step acc m = go (toStream m)
477 where
478 go m1 =
479 let stop = return acc
480 single a = step a acc
481 yieldk a r = go r >>= step a
482 in (unStream m1) defState stop single yieldk
484-- | Strict left fold with an extraction function. Like the standard strict
485-- left fold, but applies a user supplied extraction function (the third
486-- argument) to the folded value at the end. This is designed to work with the
487-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
488{-# INLINE foldx #-}
489foldx :: (IsStream t, Monad m)
490 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
491foldx step begin done m = get $ go (toStream m) begin
492 where
493 {-# NOINLINE get #-}
494 get m1 =
495 let single = return . done
496 in (unStream m1) undefined undefined single undefined
498 -- Note, this can be implemented by making a recursive call to "go",
499 -- however that is more expensive because of unnecessary recursion
500 -- that cannot be tail call optimized. Unfolding recursion explicitly via
501 -- continuations is much more efficient.
502 go m1 !acc = Stream $ \_ _ sng yld ->
503 let stop = sng acc
504 single a = sng $ step acc a
505 yieldk a r =
506 let stream = go r (step acc a)
507 in (unStream stream) defState undefined sng yld
508 in (unStream m1) defState stop single yieldk
510-- | Strict left associative fold.
511{-# INLINE foldl' #-}
512foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
513foldl' step begin m = foldx step begin id m
515-- XXX replace the recursive "go" with explicit continuations.
516-- | Like 'foldx', but with a monadic step function.
517foldxM :: (IsStream t, Monad m)
518 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
519foldxM step begin done m = go begin (toStream m)
520 where
521 go !acc m1 =
522 let stop = acc >>= done
523 single a = acc >>= \b -> step b a >>= done
524 yieldk a r = acc >>= \b -> go (step b a) r
525 in (unStream m1) defState stop single yieldk
527-- | Like 'foldl'' but with a monadic step function.
528foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
529foldlM' step begin m = foldxM step (return begin) return m
531------------------------------------------------------------------------------
532-- Specialized folds
533------------------------------------------------------------------------------
535{-# INLINE runStream #-}
536runStream :: (Monad m, IsStream t) => t m a -> m ()
537runStream m = go (toStream m)
538 where
539 go m1 =
540 let stop = return ()
541 single _ = return ()
542 yieldk _ r = go (toStream r)
543 in unStream m1 defState stop single yieldk
545{-# INLINE null #-}
546null :: (IsStream t, Monad m) => t m a -> m Bool
547null m =
548 let stop = return True
549 single _ = return False
550 yieldk _ _ = return False
551 in unStream (toStream m) defState stop single yieldk
553{-# INLINE head #-}
554head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
555head m =
556 let stop = return Nothing
557 single a = return (Just a)
558 yieldk a _ = return (Just a)
559 in unStream (toStream m) defState stop single yieldk
561{-# INLINE tail #-}
562tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
563tail m =
564 let stop = return Nothing
565 single _ = return $ Just nil
566 yieldk _ r = return $ Just $ fromStream r
567 in unStream (toStream m) defState stop single yieldk
569{-# INLINE elem #-}
570elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
571elem e m = go (toStream m)
572 where
573 go m1 =
574 let stop = return False
575 single a = return (a == e)
576 yieldk a r = if a == e then return True else go r
577 in (unStream m1) defState stop single yieldk
579{-# INLINE notElem #-}
580notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
581notElem e m = go (toStream m)
582 where
583 go m1 =
584 let stop = return True
585 single a = return (a /= e)
586 yieldk a r = if a == e then return False else go r
587 in (unStream m1) defState stop single yieldk
589all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
590all p m = go (toStream m)
591 where
592 go m1 =
593 let single a | p a = return True
594 | otherwise = return False
595 yieldk a r | p a = go r
596 | otherwise = return False
597 in unStream m1 defState (return True) single yieldk
599any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
600any p m = go (toStream m)
601 where
602 go m1 =
603 let single a | p a = return True
604 | otherwise = return False
605 yieldk a r | p a = return True
606 | otherwise = go r
607 in unStream m1 defState (return False) single yieldk
609-- | Extract the last element of the stream, if any.
610{-# INLINE last #-}
611last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
612last = foldx (\_ y -> Just y) Nothing id
614{-# INLINE minimum #-}
615minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
616minimum m = go Nothing (toStream m)
617 where
618 go Nothing m1 =
619 let stop = return Nothing
620 single a = return (Just a)
621 yieldk a r = go (Just a) r
622 in unStream m1 defState stop single yieldk
624 go (Just res) m1 =
625 let stop = return (Just res)
626 single a =
627 if res <= a
628 then return (Just res)
629 else return (Just a)
630 yieldk a r =
631 if res <= a
632 then go (Just res) r
633 else go (Just a) r
634 in unStream m1 defState stop single yieldk
636{-# INLINE maximum #-}
637maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
638maximum m = go Nothing (toStream m)
639 where
640 go Nothing m1 =
641 let stop = return Nothing
642 single a = return (Just a)
643 yieldk a r = go (Just a) r
644 in unStream m1 defState stop single yieldk
646 go (Just res) m1 =
647 let stop = return (Just res)
648 single a =
649 if res <= a
650 then return (Just a)
651 else return (Just res)
652 yieldk a r =
653 if res <= a
654 then go (Just a) r
655 else go (Just res) r
656 in unStream m1 defState stop single yieldk
658------------------------------------------------------------------------------
659-- Map and Fold
660------------------------------------------------------------------------------
662-- | Apply a monadic action to each element of the stream and discard the
663-- output of the action.
664mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
665mapM_ f m = go (toStream m)
666 where
667 go m1 =
668 let stop = return ()
669 single a = void (f a)
670 yieldk a r = f a >> go r
671 in (unStream m1) defState stop single yieldk
673------------------------------------------------------------------------------
674-- Converting folds
675------------------------------------------------------------------------------
677{-# INLINABLE toList #-}
678toList :: (IsStream t, Monad m) => t m a -> m [a]
679toList = foldr (:) []
681{-# INLINE toStreamK #-}
682toStreamK :: Stream m a -> Stream m a
683toStreamK = id
685-------------------------------------------------------------------------------
686-- Transformation by folding (Scans)
687-------------------------------------------------------------------------------
689{-# INLINE scanx #-}
690scanx :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
691scanx step begin done m =
692 cons (done begin) $ fromStream $ go (toStream m) begin
693 where
694 go m1 !acc = Stream $ \st stp sng yld ->
695 let single a = sng (done $ step acc a)
696 yieldk a r =
697 let s = step acc a
698 in yld (done s) (go r s)
699 in unStream m1 (rstState st) stp single yieldk
701{-# INLINE scanl' #-}
702scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
703scanl' step begin m = scanx step begin id m
705-------------------------------------------------------------------------------
706-- Filtering
707-------------------------------------------------------------------------------
709{-# INLINE filter #-}
710filter :: IsStream t => (a -> Bool) -> t m a -> t m a
711filter p m = fromStream $ go (toStream m)
712 where
713 go m1 = Stream $ \st stp sng yld ->
714 let single a | p a = sng a
715 | otherwise = stp
716 yieldk a r | p a = yld a (go r)
717 | otherwise = (unStream r) (rstState st) stp single yieldk
718 in unStream m1 (rstState st) stp single yieldk
720{-# INLINE take #-}
721take :: IsStream t => Int -> t m a -> t m a
722take n m = fromStream $ go n (toStream m)
723 where
724 go n1 m1 = Stream $ \st stp sng yld ->
725 let yieldk a r = yld a (go (n1 - 1) r)
726 in if n1 <= 0
727 then stp
728 else unStream m1 (rstState st) stp sng yieldk
730{-# INLINE takeWhile #-}
731takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
732takeWhile p m = fromStream $ go (toStream m)
733 where
734 go m1 = Stream $ \st stp sng yld ->
735 let single a | p a = sng a
736 | otherwise = stp
737 yieldk a r | p a = yld a (go r)
738 | otherwise = stp
739 in unStream m1 (rstState st) stp single yieldk
741drop :: IsStream t => Int -> t m a -> t m a
742drop n m = fromStream $ Stream $ \st stp sng yld ->
743 unStream (go n (toStream m)) (rstState st) stp sng yld
744 where
745 go n1 m1 = Stream $ \st stp sng yld ->
746 let single _ = stp
747 yieldk _ r = (unStream $ go (n1 - 1) r) st stp sng yld
748 -- Somehow "<=" check performs better than a ">"
749 in if n1 <= 0
750 then unStream m1 st stp sng yld
751 else unStream m1 st stp single yieldk
753{-# INLINE dropWhile #-}
754dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
755dropWhile p m = fromStream $ go (toStream m)
756 where
757 go m1 = Stream $ \st stp sng yld ->
758 let single a | p a = stp
759 | otherwise = sng a
760 yieldk a r | p a = (unStream r) (rstState st) stp single yieldk
761 | otherwise = yld a r
762 in unStream m1 (rstState st) stp single yieldk
764-------------------------------------------------------------------------------
765-- Mapping
766-------------------------------------------------------------------------------
768{-# INLINE map #-}
769map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b
770map f m = fromStream $ Stream $ \st stp sng yld ->
771 let single = sng . f
772 yieldk a r = yld (f a) (fmap f r)
773 in unStream (toStream m) (rstState st) stp single yieldk
775-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
776-- other stream types to overload it.
777{-# INLINE mapM #-}
778mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
779mapM f m = go (toStream m)
780 where
781 go m1 = fromStream $ Stream $ \st stp sng yld ->
782 let single a = f a >>= sng
783 yieldk a r = unStream (toStream (f a |: (go r))) st stp sng yld
784 in (unStream m1) (rstState st) stp single yieldk
786-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
787-- other stream types to overload it.
788{-# INLINE sequence #-}
789sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
790sequence m = go (toStream m)
791 where
792 go m1 = fromStream $ Stream $ \st stp sng yld ->
793 let single ma = ma >>= sng
794 yieldk ma r = unStream (toStream $ ma |: go r) st stp sng yld
795 in (unStream m1) (rstState st) stp single yieldk
797-------------------------------------------------------------------------------
798-- Map and Filter
799-------------------------------------------------------------------------------
801{-# INLINE mapMaybe #-}
802mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
803mapMaybe f m = go (toStream m)
804 where
805 go m1 = fromStream $ Stream $ \st stp sng yld ->
806 let single a = case f a of
807 Just b -> sng b
808 Nothing -> stp
809 yieldk a r = case f a of
810 Just b -> yld b (toStream $ go r)
811 Nothing -> (unStream r) (rstState st) stp single yieldk
812 in unStream m1 (rstState st) stp single yieldk
814------------------------------------------------------------------------------
815-- Semigroup
816------------------------------------------------------------------------------
818-- | Concatenates two streams sequentially i.e. the first stream is
819-- exhausted completely before yielding any element from the second stream.
820{-# INLINE serial #-}
821serial :: Stream m a -> Stream m a -> Stream m a
822serial m1 m2 = go m1
823 where
824 go (Stream m) = Stream $ \st stp sng yld ->
825 let stop = (unStream m2) (rstState st) stp sng yld
826 single a = yld a m2
827 yieldk a r = yld a (go r)
828 in m (rstState st) stop single yieldk
830instance Semigroup (Stream m a) where
831 (<>) = serial
833------------------------------------------------------------------------------
834-- Monoid
835------------------------------------------------------------------------------
837instance Monoid (Stream m a) where
838 mempty = nil
839 mappend = (<>)
841-------------------------------------------------------------------------------
842-- Functor
843-------------------------------------------------------------------------------
845instance Monad m => Functor (Stream m) where
846 fmap = map
848-------------------------------------------------------------------------------
849-- Bind utility
850-------------------------------------------------------------------------------
852{-# INLINE bindWith #-}
853bindWith
854 :: (forall c. Stream m c -> Stream m c -> Stream m c)
855 -> Stream m a
856 -> (a -> Stream m b)
857 -> Stream m b
858bindWith par m f = go m
859 where
860 go (Stream g) =
861 Stream $ \st stp sng yld ->
862 let run x = (unStream x) st stp sng yld
863 single a = run $ f a
864 yieldk a r = run $ f a `par` go r
865 in g (rstState st) stp single yieldk
867------------------------------------------------------------------------------
868-- Alternative & MonadPlus
869------------------------------------------------------------------------------
871_alt :: Stream m a -> Stream m a -> Stream m a
872_alt m1 m2 = Stream $ \st stp sng yld ->
873 let stop = unStream m2 (rstState st) stp sng yld
874 in unStream m1 (rstState st) stop sng yld
876------------------------------------------------------------------------------
877-- MonadReader
878------------------------------------------------------------------------------
880withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
881withLocal f m =
882 Stream $ \st stp sng yld ->
883 let single = local f . sng
884 yieldk a r = local f $ yld a (withLocal f r)
885 in (unStream m) (rstState st) (local f stp) single yieldk
887------------------------------------------------------------------------------
888-- MonadError
889------------------------------------------------------------------------------
891{-
892-- XXX handle and test cross thread state transfer
893withCatchError
894 :: MonadError e m
895 => Stream m a -> (e -> Stream m a) -> Stream m a
896withCatchError m h =
897 Stream $ \_ stp sng yld ->
898 let run x = unStream x Nothing stp sng yieldk
899 handle r = r `catchError` \e -> run $ h e
900 yieldk a r = yld a (withCatchError r h)
901 in handle $ run m
902-}
904-------------------------------------------------------------------------------
905-- Transformers
906-------------------------------------------------------------------------------
908instance MonadTrans Stream where
909 lift = yieldM