on 628355f help sign in
1071 lines 35 kB history raw
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE CPP #-}
3{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE InstanceSigs #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE RankNTypes #-}
9{-# LANGUAGE UndecidableInstances #-} -- XXX
11-- |
12-- Module : Streamly.Streams.StreamK
13-- Copyright : (c) 2017 Harendra Kumar
14--
15-- License : BSD3
16-- Maintainer : harendra.kumar@gmail.com
17-- Stability : experimental
18-- Portability : GHC
19--
20--
21-- Continuation passing style (CPS) stream implementation. The symbol 'K' below
22-- denotes a function as well as a Kontinuation.
23--
24-- @
25-- import qualified Streamly.Streams.StreamK as K
26-- @
27--
28module Streamly.Streams.StreamK
29 (
30 -- * A class for streams
31 IsStream (..)
32 , adapt
34 -- * The stream type
35 , Stream (..)
36 , unStreamIsolated
37 , isolateStream
38 , unstreamShared
39 , runStreamSVar
41 -- * Construction
42 , mkStream
43 , nil
44 , cons
45 , (.:)
47 -- * Asynchronous construction
48 , nilK
49 , yieldK
50 , consK
52 -- * Deconstruction
53 , uncons
55 -- * Generation
56 -- ** Unfolds
57 , unfoldr
58 , unfoldrM
60 -- ** Specialized Generation
61 , repeat
63 -- ** Conversions
64 , yield
65 , yieldM
66 , fromFoldable
67 , fromList
68 , fromStreamK
70 -- * Elimination
71 -- ** General Folds
72 , foldStream
73 , foldr
74 , foldrM
75 , foldr1
76 , foldl'
77 , foldlM'
78 , foldx
79 , foldxM
81 -- ** Specialized Folds
82 , runStream
83 , null
84 , head
85 , tail
86 , init
87 , elem
88 , notElem
89 , all
90 , any
91 , last
92 , minimum
93 , maximum
94 , findIndices
95 , lookup
96 , find
98 -- ** Map and Fold
99 , mapM_
101 -- ** Conversions
102 , toList
103 , toStreamK
105 -- * Transformation
106 -- ** By folding (scans)
107 , scanl'
108 , scanx
110 -- ** Filtering
111 , filter
112 , take
113 , takeWhile
114 , drop
115 , dropWhile
117 -- ** Mapping
118 , map
119 , mapM
120 , sequence
122 -- ** Inserting
123 , intersperseM
125 -- ** Map and Filter
126 , mapMaybe
128 -- ** Zipping
129 , zipWith
130 , zipWithM
132 -- * Semigroup Style Composition
133 , serial
135 -- * Utilities
136 , consMSerial
137 , bindWith
138 , withLocal
140 -- * Deprecated
141 , Streaming -- deprecated
142 , once -- deprecated
143 )
144where
146import Control.Monad (void)
147import Control.Monad.IO.Class (MonadIO(liftIO))
148import Control.Monad.Reader.Class (MonadReader(..))
149import Control.Monad.Trans.Class (MonadTrans(lift))
150import Data.Semigroup (Semigroup(..))
151import Prelude
152 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
153 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
154 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
155 foldr1)
156import qualified Prelude
158import Streamly.SVar
160------------------------------------------------------------------------------
161-- The basic stream type
162------------------------------------------------------------------------------
164-- | The type @Stream m a@ represents a monadic stream of values of type 'a'
165-- constructed using actions in monad 'm'. It uses stop, singleton and yield
166-- continuations equivalent to the following direct style type:
167--
168-- @
169-- data Stream m a = Stop | Singleton a | Yield a (Stream m a)
170-- @
171--
172-- To facilitate parallel composition we maintain a local state in an 'SVar'
173-- that is shared across and is used for synchronization of the streams being
174-- composed.
175--
176-- The singleton case can be expressed in terms of stop and yield but we have
177-- it as a separate case to optimize composition operations for streams with
178-- single element. We build singleton streams in the implementation of 'pure'
179-- for Applicative and Monad, and in 'lift' for MonadTrans.
180--
181newtype Stream m a =
182 Stream {
183 unStream :: forall r.
184 State Stream m a -- state
185 -> m r -- stop
186 -> (a -> m r) -- singleton
187 -> (a -> Stream m a -> m r) -- yield
188 -> m r
189 }
191-- XXX make this the default "unStream"
192-- | unwraps the Stream type producing the stream function that can be run with
193-- continuations.
194{-# INLINE unStreamIsolated #-}
195unStreamIsolated ::
196 Stream m a
197 -> State Stream m a -- state
198 -> m r -- stop
199 -> (a -> m r) -- singleton
200 -> (a -> Stream m a -> m r) -- yield
201 -> m r
202unStreamIsolated x st = unStream x (rstState st)
204{-# INLINE isolateStream #-}
205isolateStream :: Stream m a -> Stream m a
206isolateStream x = Stream $ \st stp sng yld ->
207 unStreamIsolated x st stp sng yld
209-- | Like unstream, but passes a shared SVar across continuations.
210{-# INLINE unstreamShared #-}
211unstreamShared ::
212 Stream m a
213 -> State Stream m a -- state
214 -> m r -- stop
215 -> (a -> m r) -- singleton
216 -> (a -> Stream m a -> m r) -- yield
217 -> m r
218unstreamShared = unStream
220-- Run the stream using a run function associated with the SVar that runs the
221-- streams with a captured snapshot of the monadic state.
222{-# INLINE runStreamSVar #-}
223runStreamSVar
224 :: MonadIO m
225 => SVar Stream m a
226 -> Stream m a
227 -> State Stream m a -- state
228 -> m r -- stop
229 -> (a -> m r) -- singleton
230 -> (a -> Stream m a -> m r) -- yield
231 -> m ()
232runStreamSVar sv m st stp sng yld =
233 let mrun = runInIO $ svarMrun sv
234 in void $ liftIO $ mrun $ unStream m st stp sng yld
236------------------------------------------------------------------------------
237-- Types that can behave as a Stream
238------------------------------------------------------------------------------
240infixr 5 `consM`
241infixr 5 |:
243-- | Class of types that can represent a stream of elements of some type 'a' in
244-- some monad 'm'.
245--
246-- @since 0.2.0
247class IsStream t where
248 toStream :: t m a -> Stream m a
249 fromStream :: Stream m a -> t m a
250 -- | Constructs a stream by adding a monadic action at the head of an
251 -- existing stream. For example:
252 --
253 -- @
254 -- > toList $ getLine \`consM` getLine \`consM` nil
255 -- hello
256 -- world
257 -- ["hello","world"]
258 -- @
259 --
260 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
261 --
262 -- @since 0.2.0
263 consM :: MonadAsync m => m a -> t m a -> t m a
264 -- | Operator equivalent of 'consM'. We can read it as "@parallel colon@"
265 -- to remember that @|@ comes before ':'.
266 --
267 -- @
268 -- > toList $ getLine |: getLine |: nil
269 -- hello
270 -- world
271 -- ["hello","world"]
272 -- @
273 --
274 -- @
275 -- let delay = threadDelay 1000000 >> print 1
276 -- runStream $ serially $ delay |: delay |: delay |: nil
277 -- runStream $ parallely $ delay |: delay |: delay |: nil
278 -- @
279 --
280 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
281 --
282 -- @since 0.2.0
283 (|:) :: MonadAsync m => m a -> t m a -> t m a
284 -- We can define (|:) just as 'consM' but it is defined explicitly for each
285 -- type because we want to use SPECIALIZE pragma on the definition.
287-- | Same as 'IsStream'.
288--
289-- @since 0.1.0
290{-# DEPRECATED Streaming "Please use IsStream instead." #-}
291type Streaming = IsStream
293-------------------------------------------------------------------------------
294-- Type adapting combinators
295-------------------------------------------------------------------------------
297-- | Adapt any specific stream type to any other specific stream type.
298--
299-- @since 0.1.0
300adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
301adapt = fromStream . toStream
303------------------------------------------------------------------------------
304-- Building a stream
305------------------------------------------------------------------------------
307-- | Build a stream from an 'SVar', a stop continuation, a singleton stream
308-- continuation and a yield continuation.
309mkStream:: IsStream t
310 => (forall r. State Stream m a
311 -> m r
312 -> (a -> m r)
313 -> (a -> t m a -> m r)
314 -> m r)
315 -> t m a
316mkStream k = fromStream $ Stream $ \st stp sng yld ->
317 let yieldk a r = yld a (toStream r)
318 in k (rstState st) stp sng yieldk
320------------------------------------------------------------------------------
321-- Construction
322------------------------------------------------------------------------------
324-- | An empty stream.
325--
326-- @
327-- > toList nil
328-- []
329-- @
330--
331-- @since 0.1.0
332nil :: IsStream t => t m a
333nil = fromStream $ Stream $ \_ stp _ _ -> stp
335infixr 5 `cons`
337-- faster than consM because there is no bind.
338-- | Construct a stream by adding a pure value at the head of an existing
339-- stream. For serial streams this is the same as @(return a) \`consM` r@ but
340-- more efficient. For concurrent streams this is not concurrent whereas
341-- 'consM' is concurrent. For example:
342--
343-- @
344-- > toList $ 1 \`cons` 2 \`cons` 3 \`cons` nil
345-- [1,2,3]
346-- @
347--
348-- @since 0.1.0
349cons :: IsStream t => a -> t m a -> t m a
350cons a r = fromStream $ Stream $ \_ _ _ yld -> yld a (toStream r)
352infixr 5 .:
354-- | Operator equivalent of 'cons'.
355--
356-- @
357-- > toList $ 1 .: 2 .: 3 .: nil
358-- [1,2,3]
359-- @
360--
361-- @since 0.1.1
362(.:) :: IsStream t => a -> t m a -> t m a
363(.:) = cons
365{-# INLINE consMSerial #-}
366consMSerial :: (Monad m) => m a -> Stream m a -> Stream m a
367consMSerial m r = Stream $ \_ _ _ yld -> m >>= \a -> yld a r
369------------------------------------------------------------------------------
370-- Asynchronous construction
371------------------------------------------------------------------------------
373-- | Make an empty stream from a callback function.
374nilK :: IsStream t => (forall r. m r -> m r) -> t m a
375nilK k = fromStream $ Stream $ \_ stp _ _ -> k stp
377-- | Make a singleton stream from a one shot callback function.
378yieldK :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a
379yieldK k = fromStream $ Stream $ \_ _ sng _ -> k sng
381-- | Construct a stream from a callback function.
382consK :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a -> t m a
383consK k r = fromStream $ Stream $ \_ _ _ yld -> k (\x -> yld x (toStream r))
385-- XXX consK with concurrent callbacks
386-- XXX Build a stream from a repeating callback function.
388-------------------------------------------------------------------------------
389-- IsStream Stream
390-------------------------------------------------------------------------------
392instance IsStream Stream where
393 toStream = id
394 fromStream = id
396 {-# INLINE consM #-}
397 {-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-}
398 consM :: Monad m => m a -> Stream m a -> Stream m a
399 consM = consMSerial
401 {-# INLINE (|:) #-}
402 {-# SPECIALIZE (|:) :: IO a -> Stream IO a -> Stream IO a #-}
403 (|:) :: Monad m => m a -> Stream m a -> Stream m a
404 (|:) = consMSerial
406-------------------------------------------------------------------------------
407-- Deconstruction
408-------------------------------------------------------------------------------
410{-# INLINE uncons #-}
411uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
412uncons m =
413 let stop = return Nothing
414 single a = return (Just (a, nil))
415 yieldk a r = return (Just (a, fromStream r))
416 in unStream (toStream m) defState stop single yieldk
418-------------------------------------------------------------------------------
419-- Generation
420-------------------------------------------------------------------------------
422{-# INLINE unfoldr #-}
423unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
424unfoldr step = fromStream . go
425 where
426 go s = Stream $ \_ stp _ yld ->
427 case step s of
428 Nothing -> stp
429 Just (a, b) -> yld a (go b)
431{-# INLINE unfoldrM #-}
432unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
433unfoldrM step = go
434 where
435 go s = fromStream $ Stream $ \svr stp sng yld -> do
436 mayb <- step s
437 case mayb of
438 Nothing -> stp
439 Just (a, b) ->
440 unStream (toStream (return a |: go b)) svr stp sng yld
442-------------------------------------------------------------------------------
443-- Special generation
444-------------------------------------------------------------------------------
446yield :: IsStream t => a -> t m a
447yield a = fromStream $ Stream $ \_ _ single _ -> single a
449{-# INLINE yieldM #-}
450yieldM :: (Monad m, IsStream t) => m a -> t m a
451yieldM m = fromStream $ Stream $ \_ _ single _ -> m >>= single
453-- | Same as yieldM
454--
455-- @since 0.2.0
456{-# DEPRECATED once "Please use yieldM instead." #-}
457{-# INLINE once #-}
458once :: (Monad m, IsStream t) => m a -> t m a
459once = yieldM
461-- | Generate an infinite stream by repeating a pure value.
462-- Can be expressed as @cycle1 . yield@.
463--
464-- @since 0.4.0
465repeat :: IsStream t => a -> t m a
466repeat a = let x = cons a x in x
468-------------------------------------------------------------------------------
469-- Conversions
470-------------------------------------------------------------------------------
472-- | Construct a stream from a 'Foldable' containing pure values. Same as
473-- @'Prelude.foldr' 'cons' 'nil'@.
474--
475-- @since 0.2.0
476{-# INLINE fromFoldable #-}
477fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
478fromFoldable = Prelude.foldr cons nil
480{-# INLINE fromList #-}
481fromList :: IsStream t => [a] -> t m a
482fromList = fromFoldable
484{-# INLINE fromStreamK #-}
485fromStreamK :: Stream m a -> Stream m a
486fromStreamK = id
488-------------------------------------------------------------------------------
489-- Elimination by Folding
490-------------------------------------------------------------------------------
492-- | Fold a stream by providing an SVar, a stop continuation, a singleton
493-- continuation and a yield continuation.
494foldStream
495 :: IsStream t
496 => State Stream m a
497 -> m r
498 -> (a -> m r)
499 -> (a -> t m a -> m r)
500 -> t m a
501 -> m r
502foldStream st blank single step m =
503 let yieldk a x = step a (fromStream x)
504 in unStream (toStream m) st blank single yieldk
506-- | Lazy right associative fold.
507foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
508foldr step acc m = go (toStream m)
509 where
510 go m1 =
511 let stop = return acc
512 single a = return (step a acc)
513 yieldk a r = go r >>= \b -> return (step a b)
514 in unStream m1 defState stop single yieldk
516-- | Lazy right fold with a monadic step function.
517{-# INLINE foldrM #-}
518foldrM :: (IsStream t, Monad m) => (a -> b -> m b) -> b -> t m a -> m b
519foldrM step acc m = go (toStream m)
520 where
521 go m1 =
522 let stop = return acc
523 single a = step a acc
524 yieldk a r = go r >>= step a
525 in unStream m1 defState stop single yieldk
527{-# INLINE foldr1 #-}
528foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
529foldr1 step m = do
530 r <- uncons m
531 case r of
532 Nothing -> return Nothing
533 Just (h, t) -> fmap Just (go h (toStream t))
534 where
535 go p m1 =
536 let stp = return p
537 single a = return $ step a p
538 yieldk a r = fmap (step p) (go a r)
539 in unStream m1 defState stp single yieldk
541-- | Strict left fold with an extraction function. Like the standard strict
542-- left fold, but applies a user supplied extraction function (the third
543-- argument) to the folded value at the end. This is designed to work with the
544-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
545{-# INLINE foldx #-}
546foldx :: (IsStream t, Monad m)
547 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
548foldx step begin done m = get $ go (toStream m) begin
549 where
550 {-# NOINLINE get #-}
551 get m1 =
552 let single = return . done
553 in unStream m1 undefined undefined single undefined
555 -- Note, this can be implemented by making a recursive call to "go",
556 -- however that is more expensive because of unnecessary recursion
557 -- that cannot be tail call optimized. Unfolding recursion explicitly via
558 -- continuations is much more efficient.
559 go m1 !acc = Stream $ \_ _ sng yld ->
560 let stop = sng acc
561 single a = sng $ step acc a
562 yieldk a r =
563 let stream = go r (step acc a)
564 in unStream stream defState undefined sng yld
565 in unStream m1 defState stop single yieldk
567-- | Strict left associative fold.
568{-# INLINE foldl' #-}
569foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
570foldl' step begin = foldx step begin id
572-- XXX replace the recursive "go" with explicit continuations.
573-- | Like 'foldx', but with a monadic step function.
574foldxM :: (IsStream t, Monad m)
575 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
576foldxM step begin done m = go begin (toStream m)
577 where
578 go !acc m1 =
579 let stop = acc >>= done
580 single a = acc >>= \b -> step b a >>= done
581 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
582 in unStream m1 defState stop single yieldk
584-- | Like 'foldl'' but with a monadic step function.
585foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
586foldlM' step begin = foldxM step (return begin) return
588------------------------------------------------------------------------------
589-- Specialized folds
590------------------------------------------------------------------------------
592{-# INLINE runStream #-}
593runStream :: (Monad m, IsStream t) => t m a -> m ()
594runStream m = go (toStream m)
595 where
596 go m1 =
597 let stop = return ()
598 single _ = return ()
599 yieldk _ r = go (toStream r)
600 in unStream m1 defState stop single yieldk
602{-# INLINE null #-}
603null :: (IsStream t, Monad m) => t m a -> m Bool
604null m =
605 let stop = return True
606 single _ = return False
607 yieldk _ _ = return False
608 in unStream (toStream m) defState stop single yieldk
610{-# INLINE head #-}
611head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
612head m =
613 let stop = return Nothing
614 single a = return (Just a)
615 yieldk a _ = return (Just a)
616 in unStream (toStream m) defState stop single yieldk
618{-# INLINE tail #-}
619tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
620tail m =
621 let stop = return Nothing
622 single _ = return $ Just nil
623 yieldk _ r = return $ Just $ fromStream r
624 in unStream (toStream m) defState stop single yieldk
626{-# INLINE init #-}
627init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
628init m = go1 (toStream m)
629 where
630 go1 m1 = do
631 r <- uncons m1
632 case r of
633 Nothing -> return Nothing
634 Just (h, t) -> return . Just . fromStream $ go h t
635 go p m1 = Stream $ \_ stp sng yld ->
636 let single _ = sng p
637 yieldk a x = yld p $ go a x
638 in unStream m1 defState stp single yieldk
640{-# INLINE elem #-}
641elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
642elem e m = go (toStream m)
643 where
644 go m1 =
645 let stop = return False
646 single a = return (a == e)
647 yieldk a r = if a == e then return True else go r
648 in unStream m1 defState stop single yieldk
650{-# INLINE notElem #-}
651notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
652notElem e m = go (toStream m)
653 where
654 go m1 =
655 let stop = return True
656 single a = return (a /= e)
657 yieldk a r = if a == e then return False else go r
658 in unStream m1 defState stop single yieldk
660all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
661all p m = go (toStream m)
662 where
663 go m1 =
664 let single a | p a = return True
665 | otherwise = return False
666 yieldk a r | p a = go r
667 | otherwise = return False
668 in unStream m1 defState (return True) single yieldk
670any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
671any p m = go (toStream m)
672 where
673 go m1 =
674 let single a | p a = return True
675 | otherwise = return False
676 yieldk a r | p a = return True
677 | otherwise = go r
678 in unStream m1 defState (return False) single yieldk
680-- | Extract the last element of the stream, if any.
681{-# INLINE last #-}
682last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
683last = foldx (\_ y -> Just y) Nothing id
685{-# INLINE minimum #-}
686minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
687minimum m = go Nothing (toStream m)
688 where
689 go Nothing m1 =
690 let stop = return Nothing
691 single a = return (Just a)
692 yieldk a r = go (Just a) r
693 in unStream m1 defState stop single yieldk
695 go (Just res) m1 =
696 let stop = return (Just res)
697 single a =
698 if res <= a
699 then return (Just res)
700 else return (Just a)
701 yieldk a r =
702 if res <= a
703 then go (Just res) r
704 else go (Just a) r
705 in unStream m1 defState stop single yieldk
707{-# INLINE maximum #-}
708maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
709maximum m = go Nothing (toStream m)
710 where
711 go Nothing m1 =
712 let stop = return Nothing
713 single a = return (Just a)
714 yieldk a r = go (Just a) r
715 in unStream m1 defState stop single yieldk
717 go (Just res) m1 =
718 let stop = return (Just res)
719 single a =
720 if res <= a
721 then return (Just a)
722 else return (Just res)
723 yieldk a r =
724 if res <= a
725 then go (Just a) r
726 else go (Just res) r
727 in unStream m1 defState stop single yieldk
729{-# INLINE lookup #-}
730lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
731lookup e m = go (toStream m)
732 where
733 go m1 =
734 let single (a, b) | a == e = return $ Just b
735 | otherwise = return Nothing
736 yieldk (a, b) x | a == e = return $ Just b
737 | otherwise = go x
738 in unStream m1 defState (return Nothing) single yieldk
740{-# INLINE find #-}
741find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
742find p m = go (toStream m)
743 where
744 go m1 =
745 let single a | p a = return $ Just a
746 | otherwise = return Nothing
747 yieldk a x | p a = return $ Just a
748 | otherwise = go x
749 in unStream m1 defState (return Nothing) single yieldk
751{-# INLINE findIndices #-}
752findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
753findIndices p = fromStream . go 0 . toStream
754 where
755 go offset m1 = Stream $ \st stp sng yld ->
756 let single a | p a = sng offset
757 | otherwise = stp
758 yieldk a x | p a = yld offset $ go (offset + 1) x
759 | otherwise = unStream (go (offset + 1) x) st stp sng yld
760 in unStream m1 (rstState st) stp single yieldk
762------------------------------------------------------------------------------
763-- Map and Fold
764------------------------------------------------------------------------------
766-- | Apply a monadic action to each element of the stream and discard the
767-- output of the action.
768mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
769mapM_ f m = go (toStream m)
770 where
771 go m1 =
772 let stop = return ()
773 single a = void (f a)
774 yieldk a r = f a >> go r
775 in unStream m1 defState stop single yieldk
777------------------------------------------------------------------------------
778-- Converting folds
779------------------------------------------------------------------------------
781{-# INLINABLE toList #-}
782toList :: (IsStream t, Monad m) => t m a -> m [a]
783toList = foldr (:) []
785{-# INLINE toStreamK #-}
786toStreamK :: Stream m a -> Stream m a
787toStreamK = id
789-------------------------------------------------------------------------------
790-- Transformation by folding (Scans)
791-------------------------------------------------------------------------------
793{-# INLINE scanx #-}
794scanx :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
795scanx step begin done m =
796 cons (done begin) $ fromStream $ go (toStream m) begin
797 where
798 go m1 !acc = Stream $ \st stp sng yld ->
799 let single a = sng (done $ step acc a)
800 yieldk a r =
801 let s = step acc a
802 in yld (done s) (go r s)
803 in unStream m1 (rstState st) stp single yieldk
805{-# INLINE scanl' #-}
806scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
807scanl' step begin = scanx step begin id
809-------------------------------------------------------------------------------
810-- Filtering
811-------------------------------------------------------------------------------
813{-# INLINE filter #-}
814filter :: IsStream t => (a -> Bool) -> t m a -> t m a
815filter p m = fromStream $ go (toStream m)
816 where
817 go m1 = Stream $ \st stp sng yld ->
818 let single a | p a = sng a
819 | otherwise = stp
820 yieldk a r | p a = yld a (go r)
821 | otherwise = unStream r (rstState st) stp single yieldk
822 in unStream m1 (rstState st) stp single yieldk
824{-# INLINE take #-}
825take :: IsStream t => Int -> t m a -> t m a
826take n m = fromStream $ go n (toStream m)
827 where
828 go n1 m1 = Stream $ \st stp sng yld ->
829 let yieldk a r = yld a (go (n1 - 1) r)
830 in if n1 <= 0
831 then stp
832 else unStream m1 (rstState st) stp sng yieldk
834{-# INLINE takeWhile #-}
835takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
836takeWhile p m = fromStream $ go (toStream m)
837 where
838 go m1 = Stream $ \st stp sng yld ->
839 let single a | p a = sng a
840 | otherwise = stp
841 yieldk a r | p a = yld a (go r)
842 | otherwise = stp
843 in unStream m1 (rstState st) stp single yieldk
845drop :: IsStream t => Int -> t m a -> t m a
846drop n m = fromStream $ Stream $ \st stp sng yld ->
847 unStream (go n (toStream m)) (rstState st) stp sng yld
848 where
849 go n1 m1 = Stream $ \st stp sng yld ->
850 let single _ = stp
851 yieldk _ r = (unStream $ go (n1 - 1) r) st stp sng yld
852 -- Somehow "<=" check performs better than a ">"
853 in if n1 <= 0
854 then unStream m1 st stp sng yld
855 else unStream m1 st stp single yieldk
857{-# INLINE dropWhile #-}
858dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
859dropWhile p m = fromStream $ go (toStream m)
860 where
861 go m1 = Stream $ \st stp sng yld ->
862 let single a | p a = stp
863 | otherwise = sng a
864 yieldk a r | p a = unStream r (rstState st) stp single yieldk
865 | otherwise = yld a r
866 in unStream m1 (rstState st) stp single yieldk
868-------------------------------------------------------------------------------
869-- Mapping
870-------------------------------------------------------------------------------
872{-# INLINE map #-}
873map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b
874map f m = fromStream $ Stream $ \st stp sng yld ->
875 let single = sng . f
876 yieldk a r = yld (f a) (fmap f r)
877 in unStream (toStream m) (rstState st) stp single yieldk
879-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
880-- other stream types to overload it.
881{-# INLINE mapM #-}
882mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
883mapM f m = go (toStream m)
884 where
885 go m1 = fromStream $ Stream $ \st stp sng yld ->
886 let single a = f a >>= sng
887 yieldk a r = unStream (toStream (f a |: go r)) st stp sng yld
888 in unStream m1 (rstState st) stp single yieldk
890-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
891-- other stream types to overload it.
892{-# INLINE sequence #-}
893sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
894sequence m = go (toStream m)
895 where
896 go m1 = fromStream $ Stream $ \st stp sng yld ->
897 let single ma = ma >>= sng
898 yieldk ma r = unStream (toStream $ ma |: go r) st stp sng yld
899 in unStream m1 (rstState st) stp single yieldk
901-------------------------------------------------------------------------------
902-- Inserting
903-------------------------------------------------------------------------------
905{-# INLINE intersperseM #-}
906intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
907intersperseM a m = fromStream $ prependingStart (toStream m)
908 where
909 prependingStart m1 = Stream $ \st stp sng yld ->
910 let yieldk i x = unStream (return i |: go x) st stp sng yld
911 in unStream m1 (rstState st) stp sng yieldk
912 go m2 = fromStream $ Stream $ \st stp sng yld ->
913 let single i = unStream (a |: yield i) st stp sng yld
914 yieldk i x = unStream (a |: return i |: go x) st stp sng yld
915 in unStream m2 (rstState st) stp single yieldk
917-------------------------------------------------------------------------------
918-- Map and Filter
919-------------------------------------------------------------------------------
921{-# INLINE mapMaybe #-}
922mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
923mapMaybe f m = go (toStream m)
924 where
925 go m1 = fromStream $ Stream $ \st stp sng yld ->
926 let single a = case f a of
927 Just b -> sng b
928 Nothing -> stp
929 yieldk a r = case f a of
930 Just b -> yld b (toStream $ go r)
931 Nothing -> unStream r (rstState st) stp single yieldk
932 in unStream m1 (rstState st) stp single yieldk
934------------------------------------------------------------------------------
935-- Serial Zipping
936------------------------------------------------------------------------------
938{-# INLINE zipWithS #-}
939zipWithS :: (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
940zipWithS f = go
941 where
942 go mx my = Stream $ \st stp sng yld -> do
943 let merge a ra =
944 let single2 b = sng (f a b)
945 yield2 b rb = yld (f a b) (go ra rb)
946 in unStream my (rstState st) stp single2 yield2
947 let single1 a = merge a nil
948 yield1 = merge
949 unStream mx (rstState st) stp single1 yield1
951-- | Zip two streams serially using a pure zipping function.
952--
953-- @since 0.1.0
954{-# INLINABLE zipWith #-}
955zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
956zipWith f m1 m2 = fromStream $ zipWithS f (toStream m1) (toStream m2)
958-- | Zip two streams serially using a monadic zipping function.
959--
960-- @since 0.1.0
961zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
962zipWithM f m1 m2 = fromStream $ go (toStream m1) (toStream m2)
963 where
964 go mx my = Stream $ \st stp sng yld -> do
965 let merge a ra =
966 let runIt x = unStream x (rstState st) stp sng yld
967 single2 b = f a b >>= sng
968 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
969 in unStream my (rstState st) stp single2 yield2
970 let single1 a = merge a nil
971 yield1 = merge
972 unStream mx (rstState st) stp single1 yield1
974------------------------------------------------------------------------------
975-- Semigroup
976------------------------------------------------------------------------------
978-- | Concatenates two streams sequentially i.e. the first stream is
979-- exhausted completely before yielding any element from the second stream.
980{-# INLINE serial #-}
981serial :: Stream m a -> Stream m a -> Stream m a
982serial m1 m2 = go m1
983 where
984 go (Stream m) = Stream $ \st stp sng yld ->
985 let stop = unStream m2 (rstState st) stp sng yld
986 single a = yld a m2
987 yieldk a r = yld a (go r)
988 in m (rstState st) stop single yieldk
990instance Semigroup (Stream m a) where
991 (<>) = serial
993------------------------------------------------------------------------------
994-- Monoid
995------------------------------------------------------------------------------
997instance Monoid (Stream m a) where
998 mempty = nil
999 mappend = (<>)
1001-------------------------------------------------------------------------------
1002-- Functor
1003-------------------------------------------------------------------------------
1005instance Monad m => Functor (Stream m) where
1006 fmap = map
1008-------------------------------------------------------------------------------
1009-- Bind utility
1010-------------------------------------------------------------------------------
1012{-# INLINE bindWith #-}
1013bindWith
1014 :: (forall c. Stream m c -> Stream m c -> Stream m c)
1015 -> Stream m a
1016 -> (a -> Stream m b)
1017 -> Stream m b
1018bindWith par m f = go m
1019 where
1020 go (Stream g) =
1021 Stream $ \st stp sng yld ->
1022 let runShared x = unstreamShared x st stp sng yld
1023 runIsolated x = unStreamIsolated x st stp sng yld
1025 single a = runIsolated $ f a
1026 yieldk a r = runShared $ isolateStream (f a) `par` go r
1027 in g (rstState st) stp single yieldk
1029------------------------------------------------------------------------------
1030-- Alternative & MonadPlus
1031------------------------------------------------------------------------------
1033_alt :: Stream m a -> Stream m a -> Stream m a
1034_alt m1 m2 = Stream $ \st stp sng yld ->
1035 let stop = unStream m2 (rstState st) stp sng yld
1036 in unStream m1 (rstState st) stop sng yld
1038------------------------------------------------------------------------------
1039-- MonadReader
1040------------------------------------------------------------------------------
1042withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1043withLocal f m =
1044 Stream $ \st stp sng yld ->
1045 let single = local f . sng
1046 yieldk a r = local f $ yld a (withLocal f r)
1047 in unStream m (rstState st) (local f stp) single yieldk
1049------------------------------------------------------------------------------
1050-- MonadError
1051------------------------------------------------------------------------------
1054-- XXX handle and test cross thread state transfer
1055withCatchError
1056 :: MonadError e m
1057 => Stream m a -> (e -> Stream m a) -> Stream m a
1058withCatchError m h =
1059 Stream $ \_ stp sng yld ->
1060 let run x = unStream x Nothing stp sng yieldk
1061 handle r = r `catchError` \e -> run $ h e
1062 yieldk a r = yld a (withCatchError r h)
1063 in handle $ run m
1066-------------------------------------------------------------------------------
1067-- Transformers
1068-------------------------------------------------------------------------------
1070instance MonadTrans Stream where
1071 lift = yieldM