on 74ce247 help sign in
1004 lines 33 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 , init
85 , elem
86 , notElem
87 , all
88 , any
89 , last
90 , minimum
91 , maximum
92 , findIndices
93 , lookup
94 , find
96 -- ** Map and Fold
97 , mapM_
99 -- ** Conversions
100 , toList
101 , toStreamK
103 -- * Transformation
104 -- ** By folding (scans)
105 , scanl'
106 , scanx
108 -- ** Filtering
109 , filter
110 , take
111 , takeWhile
112 , drop
113 , dropWhile
115 -- ** Mapping
116 , map
117 , mapM
118 , sequence
120 -- ** Map and Filter
121 , mapMaybe
123 -- ** Zipping
124 , zipWith
125 , zipWithM
127 -- * Semigroup Style Composition
128 , serial
130 -- * Utilities
131 , consMSerial
132 , bindWith
133 , withLocal
135 -- * Deprecated
136 , Streaming -- deprecated
137 , once -- deprecated
138 )
139where
141import Control.Monad (void)
142import Control.Monad.Reader.Class (MonadReader(..))
143import Control.Monad.Trans.Class (MonadTrans(lift))
144import Data.Semigroup (Semigroup(..))
145import Prelude
146 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
147 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
148 maximum, elem, notElem, null, head, tail, init, zipWith, lookup)
149import qualified Prelude
151import Streamly.SVar
153------------------------------------------------------------------------------
154-- The basic stream type
155------------------------------------------------------------------------------
157-- | The type @Stream m a@ represents a monadic stream of values of type 'a'
158-- constructed using actions in monad 'm'. It uses stop, singleton and yield
159-- continuations equivalent to the following direct style type:
160--
161-- @
162-- data Stream m a = Stop | Singleton a | Yield a (Stream m a)
163-- @
164--
165-- To facilitate parallel composition we maintain a local state in an 'SVar'
166-- that is shared across and is used for synchronization of the streams being
167-- composed.
168--
169-- The singleton case can be expressed in terms of stop and yield but we have
170-- it as a separate case to optimize composition operations for streams with
171-- single element. We build singleton streams in the implementation of 'pure'
172-- for Applicative and Monad, and in 'lift' for MonadTrans.
173--
174newtype Stream m a =
175 Stream {
176 unStream :: forall r.
177 State Stream m a -- state
178 -> m r -- stop
179 -> (a -> m r) -- singleton
180 -> (a -> Stream m a -> m r) -- yield
181 -> m r
182 }
184------------------------------------------------------------------------------
185-- Types that can behave as a Stream
186------------------------------------------------------------------------------
188infixr 5 `consM`
189infixr 5 |:
191-- | Class of types that can represent a stream of elements of some type 'a' in
192-- some monad 'm'.
193--
194-- @since 0.2.0
195class IsStream t where
196 toStream :: t m a -> Stream m a
197 fromStream :: Stream m a -> t m a
198 -- | Constructs a stream by adding a monadic action at the head of an
199 -- existing stream. For example:
200 --
201 -- @
202 -- > toList $ getLine \`consM` getLine \`consM` nil
203 -- hello
204 -- world
205 -- ["hello","world"]
206 -- @
207 --
208 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
209 --
210 -- @since 0.2.0
211 consM :: MonadAsync m => m a -> t m a -> t m a
212 -- | Operator equivalent of 'consM'. We can read it as "@parallel colon@"
213 -- to remember that @|@ comes before ':'.
214 --
215 -- @
216 -- > toList $ getLine |: getLine |: nil
217 -- hello
218 -- world
219 -- ["hello","world"]
220 -- @
221 --
222 -- @
223 -- let delay = threadDelay 1000000 >> print 1
224 -- runStream $ serially $ delay |: delay |: delay |: nil
225 -- runStream $ parallely $ delay |: delay |: delay |: nil
226 -- @
227 --
228 -- /Concurrent (do not use 'parallely' to construct infinite streams)/
229 --
230 -- @since 0.2.0
231 (|:) :: MonadAsync m => m a -> t m a -> t m a
232 -- We can define (|:) just as 'consM' but it is defined explicitly for each
233 -- type because we want to use SPECIALIZE pragma on the definition.
235-- | Same as 'IsStream'.
236--
237-- @since 0.1.0
238{-# DEPRECATED Streaming "Please use IsStream instead." #-}
239type Streaming = IsStream
241-------------------------------------------------------------------------------
242-- Type adapting combinators
243-------------------------------------------------------------------------------
245-- | Adapt any specific stream type to any other specific stream type.
246--
247-- @since 0.1.0
248adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a
249adapt = fromStream . toStream
251------------------------------------------------------------------------------
252-- Building a stream
253------------------------------------------------------------------------------
255-- | Build a stream from an 'SVar', a stop continuation, a singleton stream
256-- continuation and a yield continuation.
257mkStream:: IsStream t
258 => (forall r. State Stream m a
259 -> m r
260 -> (a -> m r)
261 -> (a -> t m a -> m r)
262 -> m r)
263 -> t m a
264mkStream k = fromStream $ Stream $ \st stp sng yld ->
265 let yieldk a r = yld a (toStream r)
266 in k (rstState st) stp sng yieldk
268------------------------------------------------------------------------------
269-- Construction
270------------------------------------------------------------------------------
272-- | An empty stream.
273--
274-- @
275-- > toList nil
276-- []
277-- @
278--
279-- @since 0.1.0
280nil :: IsStream t => t m a
281nil = fromStream $ Stream $ \_ stp _ _ -> stp
283infixr 5 `cons`
285-- faster than consM because there is no bind.
286-- | Construct a stream by adding a pure value at the head of an existing
287-- stream. For serial streams this is the same as @(return a) \`consM` r@ but
288-- more efficient. For concurrent streams this is not concurrent whereas
289-- 'consM' is concurrent. For example:
290--
291-- @
292-- > toList $ 1 \`cons` 2 \`cons` 3 \`cons` nil
293-- [1,2,3]
294-- @
295--
296-- @since 0.1.0
297cons :: IsStream t => a -> t m a -> t m a
298cons a r = fromStream $ Stream $ \_ _ _ yld -> yld a (toStream r)
300infixr 5 .:
302-- | Operator equivalent of 'cons'.
303--
304-- @
305-- > toList $ 1 .: 2 .: 3 .: nil
306-- [1,2,3]
307-- @
308--
309-- @since 0.1.1
310(.:) :: IsStream t => a -> t m a -> t m a
311(.:) = cons
313{-# INLINE consMSerial #-}
314consMSerial :: (Monad m) => m a -> Stream m a -> Stream m a
315consMSerial m r = Stream $ \_ _ _ yld -> m >>= \a -> yld a r
317------------------------------------------------------------------------------
318-- Asynchronous construction
319------------------------------------------------------------------------------
321-- | Make an empty stream from a callback function.
322nilK :: IsStream t => (forall r. m r -> m r) -> t m a
323nilK k = fromStream $ Stream $ \_ stp _ _ -> k stp
325-- | Make a singleton stream from a one shot callback function.
326yieldK :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a
327yieldK k = fromStream $ Stream $ \_ _ sng _ -> k sng
329-- | Construct a stream from a callback function.
330consK :: IsStream t => (forall r. (a -> m r) -> m r) -> t m a -> t m a
331consK k r = fromStream $ Stream $ \_ _ _ yld -> k (\x -> yld x (toStream r))
333-- XXX consK with concurrent callbacks
334-- XXX Build a stream from a repeating callback function.
336-------------------------------------------------------------------------------
337-- IsStream Stream
338-------------------------------------------------------------------------------
340instance IsStream Stream where
341 toStream = id
342 fromStream = id
344 {-# INLINE consM #-}
345 {-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-}
346 consM :: Monad m => m a -> Stream m a -> Stream m a
347 consM = consMSerial
349 {-# INLINE (|:) #-}
350 {-# SPECIALIZE (|:) :: IO a -> Stream IO a -> Stream IO a #-}
351 (|:) :: Monad m => m a -> Stream m a -> Stream m a
352 (|:) = consMSerial
354-------------------------------------------------------------------------------
355-- Deconstruction
356-------------------------------------------------------------------------------
358{-# INLINE uncons #-}
359uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
360uncons m =
361 let stop = return Nothing
362 single a = return (Just (a, nil))
363 yieldk a r = return (Just (a, fromStream r))
364 in (unStream (toStream m)) defState stop single yieldk
366-------------------------------------------------------------------------------
367-- Generation
368-------------------------------------------------------------------------------
370{-# INLINE unfoldr #-}
371unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
372unfoldr step = fromStream . go
373 where
374 go s = Stream $ \_ stp _ yld ->
375 case step s of
376 Nothing -> stp
377 Just (a, b) -> yld a (go b)
379{-# INLINE unfoldrM #-}
380unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
381unfoldrM step = go
382 where
383 go s = fromStream $ Stream $ \svr stp sng yld -> do
384 mayb <- step s
385 case mayb of
386 Nothing -> stp
387 Just (a, b) ->
388 unStream (toStream (return a |: go b)) svr stp sng yld
390-------------------------------------------------------------------------------
391-- Special generation
392-------------------------------------------------------------------------------
394-- Faster than yieldM because there is no bind. Usually we can construct a
395-- stream from a pure value using "pure" in an applicative, however in case of
396-- Zip streams pure creates an infinite stream.
397--
398-- | Create a singleton stream from a pure value. In monadic streams, 'pure' or
399-- 'return' can be used in place of 'yield', however, in Zip applicative
400-- streams 'pure' is equivalent to 'repeat'.
401--
402-- @since 0.4.0
403yield :: IsStream t => a -> t m a
404yield a = fromStream $ Stream $ \_ _ single _ -> single a
406-- | Create a singleton stream from a monadic action. Same as @m \`consM` nil@
407-- but more efficient.
408--
409-- @
410-- > toList $ yieldM getLine
411-- hello
412-- ["hello"]
413-- @
414--
415-- @since 0.4.0
416{-# INLINE yieldM #-}
417yieldM :: (Monad m, IsStream t) => m a -> t m a
418yieldM m = fromStream $ Stream $ \_ _ single _ -> m >>= single
420-- | Same as yieldM
421--
422-- @since 0.2.0
423{-# DEPRECATED once "Please use yieldM instead." #-}
424{-# INLINE once #-}
425once :: (Monad m, IsStream t) => m a -> t m a
426once = yieldM
428-- | Generate an infinite stream by repeating a pure value.
429--
430-- @since 0.4.0
431repeat :: IsStream t => a -> t m a
432repeat a = let x = cons a x in x
434-------------------------------------------------------------------------------
435-- Conversions
436-------------------------------------------------------------------------------
438-- | Construct a stream from a 'Foldable' containing pure values.
439--
440-- @since 0.2.0
441{-# INLINE fromFoldable #-}
442fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
443fromFoldable = Prelude.foldr cons nil
445{-# INLINE fromList #-}
446fromList :: IsStream t => [a] -> t m a
447fromList = fromFoldable
449{-# INLINE fromStreamK #-}
450fromStreamK :: Stream m a -> Stream m a
451fromStreamK = id
453-------------------------------------------------------------------------------
454-- Elimination by Folding
455-------------------------------------------------------------------------------
457-- | Fold a stream by providing an SVar, a stop continuation, a singleton
458-- continuation and a yield continuation.
459foldStream
460 :: IsStream t
461 => State Stream m a
462 -> m r
463 -> (a -> m r)
464 -> (a -> t m a -> m r)
465 -> t m a
466 -> m r
467foldStream st blank single step m =
468 let yieldk a x = step a (fromStream x)
469 in (unStream (toStream m)) st blank single yieldk
471-- | Lazy right associative fold.
472foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
473foldr step acc m = go (toStream m)
474 where
475 go m1 =
476 let stop = return acc
477 single a = return (step a acc)
478 yieldk a r = go r >>= \b -> return (step a b)
479 in (unStream m1) defState stop single yieldk
481-- | Lazy right fold with a monadic step function.
482{-# INLINE foldrM #-}
483foldrM :: (IsStream t, Monad m) => (a -> b -> m b) -> b -> t m a -> m b
484foldrM step acc m = go (toStream m)
485 where
486 go m1 =
487 let stop = return acc
488 single a = step a acc
489 yieldk a r = go r >>= step a
490 in (unStream m1) defState stop single yieldk
492-- | Strict left fold with an extraction function. Like the standard strict
493-- left fold, but applies a user supplied extraction function (the third
494-- argument) to the folded value at the end. This is designed to work with the
495-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
496{-# INLINE foldx #-}
497foldx :: (IsStream t, Monad m)
498 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
499foldx step begin done m = get $ go (toStream m) begin
500 where
501 {-# NOINLINE get #-}
502 get m1 =
503 let single = return . done
504 in (unStream m1) undefined undefined single undefined
506 -- Note, this can be implemented by making a recursive call to "go",
507 -- however that is more expensive because of unnecessary recursion
508 -- that cannot be tail call optimized. Unfolding recursion explicitly via
509 -- continuations is much more efficient.
510 go m1 !acc = Stream $ \_ _ sng yld ->
511 let stop = sng acc
512 single a = sng $ step acc a
513 yieldk a r =
514 let stream = go r (step acc a)
515 in (unStream stream) defState undefined sng yld
516 in (unStream m1) defState stop single yieldk
518-- | Strict left associative fold.
519{-# INLINE foldl' #-}
520foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
521foldl' step begin m = foldx step begin id m
523-- XXX replace the recursive "go" with explicit continuations.
524-- | Like 'foldx', but with a monadic step function.
525foldxM :: (IsStream t, Monad m)
526 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
527foldxM step begin done m = go begin (toStream m)
528 where
529 go !acc m1 =
530 let stop = acc >>= done
531 single a = acc >>= \b -> step b a >>= done
532 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
533 in (unStream m1) defState stop single yieldk
535-- | Like 'foldl'' but with a monadic step function.
536foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
537foldlM' step begin m = foldxM step (return begin) return m
539------------------------------------------------------------------------------
540-- Specialized folds
541------------------------------------------------------------------------------
543{-# INLINE runStream #-}
544runStream :: (Monad m, IsStream t) => t m a -> m ()
545runStream m = go (toStream m)
546 where
547 go m1 =
548 let stop = return ()
549 single _ = return ()
550 yieldk _ r = go (toStream r)
551 in unStream m1 defState stop single yieldk
553{-# INLINE null #-}
554null :: (IsStream t, Monad m) => t m a -> m Bool
555null m =
556 let stop = return True
557 single _ = return False
558 yieldk _ _ = return False
559 in unStream (toStream m) defState stop single yieldk
561{-# INLINE head #-}
562head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
563head m =
564 let stop = return Nothing
565 single a = return (Just a)
566 yieldk a _ = return (Just a)
567 in unStream (toStream m) defState stop single yieldk
569{-# INLINE tail #-}
570tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
571tail m =
572 let stop = return Nothing
573 single _ = return $ Just nil
574 yieldk _ r = return $ Just $ fromStream r
575 in unStream (toStream m) defState stop single yieldk
577{-# INLINE init #-}
578init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
579init m = go1 (toStream m)
580 where
581 go1 m1 = do
582 r <- uncons m1
583 case r of
584 Nothing -> return Nothing
585 Just (h, t) -> return . Just . fromStream $ go h t
586 go p m1 = Stream $ \_ stp sng yld ->
587 let single _ = sng p
588 yieldk a x = yld p $ go a x
589 in unStream m1 defState stp single yieldk
591{-# INLINE elem #-}
592elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
593elem e m = go (toStream m)
594 where
595 go m1 =
596 let stop = return False
597 single a = return (a == e)
598 yieldk a r = if a == e then return True else go r
599 in (unStream m1) defState stop single yieldk
601{-# INLINE notElem #-}
602notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
603notElem e m = go (toStream m)
604 where
605 go m1 =
606 let stop = return True
607 single a = return (a /= e)
608 yieldk a r = if a == e then return False else go r
609 in (unStream m1) defState stop single yieldk
611all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
612all p m = go (toStream m)
613 where
614 go m1 =
615 let single a | p a = return True
616 | otherwise = return False
617 yieldk a r | p a = go r
618 | otherwise = return False
619 in unStream m1 defState (return True) single yieldk
621any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
622any p m = go (toStream m)
623 where
624 go m1 =
625 let single a | p a = return True
626 | otherwise = return False
627 yieldk a r | p a = return True
628 | otherwise = go r
629 in unStream m1 defState (return False) single yieldk
631-- | Extract the last element of the stream, if any.
632{-# INLINE last #-}
633last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
634last = foldx (\_ y -> Just y) Nothing id
636{-# INLINE minimum #-}
637minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
638minimum 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 res)
651 else return (Just a)
652 yieldk a r =
653 if res <= a
654 then go (Just res) r
655 else go (Just a) r
656 in unStream m1 defState stop single yieldk
658{-# INLINE maximum #-}
659maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
660maximum m = go Nothing (toStream m)
661 where
662 go Nothing m1 =
663 let stop = return Nothing
664 single a = return (Just a)
665 yieldk a r = go (Just a) r
666 in unStream m1 defState stop single yieldk
668 go (Just res) m1 =
669 let stop = return (Just res)
670 single a =
671 if res <= a
672 then return (Just a)
673 else return (Just res)
674 yieldk a r =
675 if res <= a
676 then go (Just a) r
677 else go (Just res) r
678 in unStream m1 defState stop single yieldk
680{-# INLINE lookup #-}
681lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
682lookup e m = go (toStream m)
683 where
684 go m1 =
685 let single (a, b) | a == e = return $ Just b
686 | otherwise = return Nothing
687 yieldk (a, b) x | a == e = return $ Just b
688 | otherwise = go x
689 in unStream m1 defState (return Nothing) single yieldk
691{-# INLINE find #-}
692find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
693find p m = go (toStream m)
694 where
695 go m1 =
696 let single a | p a = return $ Just a
697 | otherwise = return Nothing
698 yieldk a x | p a = return $ Just a
699 | otherwise = go x
700 in unStream m1 defState (return Nothing) single yieldk
702{-# INLINE findIndices #-}
703findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
704findIndices p = fromStream . go 0 . toStream
705 where
706 go offset m1 = Stream $ \st stp sng yld ->
707 let single a | p a = sng offset
708 | otherwise = stp
709 yieldk a x | p a = yld offset $ go (offset + 1) x
710 | otherwise = unStream (go (offset + 1) x) st stp sng yld
711 in unStream m1 (rstState st) stp single yieldk
713------------------------------------------------------------------------------
714-- Map and Fold
715------------------------------------------------------------------------------
717-- | Apply a monadic action to each element of the stream and discard the
718-- output of the action.
719mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
720mapM_ f m = go (toStream m)
721 where
722 go m1 =
723 let stop = return ()
724 single a = void (f a)
725 yieldk a r = f a >> go r
726 in (unStream m1) defState stop single yieldk
728------------------------------------------------------------------------------
729-- Converting folds
730------------------------------------------------------------------------------
732{-# INLINABLE toList #-}
733toList :: (IsStream t, Monad m) => t m a -> m [a]
734toList = foldr (:) []
736{-# INLINE toStreamK #-}
737toStreamK :: Stream m a -> Stream m a
738toStreamK = id
740-------------------------------------------------------------------------------
741-- Transformation by folding (Scans)
742-------------------------------------------------------------------------------
744{-# INLINE scanx #-}
745scanx :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
746scanx step begin done m =
747 cons (done begin) $ fromStream $ go (toStream m) begin
748 where
749 go m1 !acc = Stream $ \st stp sng yld ->
750 let single a = sng (done $ step acc a)
751 yieldk a r =
752 let s = step acc a
753 in yld (done s) (go r s)
754 in unStream m1 (rstState st) stp single yieldk
756{-# INLINE scanl' #-}
757scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
758scanl' step begin m = scanx step begin id m
760-------------------------------------------------------------------------------
761-- Filtering
762-------------------------------------------------------------------------------
764{-# INLINE filter #-}
765filter :: IsStream t => (a -> Bool) -> t m a -> t m a
766filter p m = fromStream $ go (toStream m)
767 where
768 go m1 = Stream $ \st stp sng yld ->
769 let single a | p a = sng a
770 | otherwise = stp
771 yieldk a r | p a = yld a (go r)
772 | otherwise = (unStream r) (rstState st) stp single yieldk
773 in unStream m1 (rstState st) stp single yieldk
775{-# INLINE take #-}
776take :: IsStream t => Int -> t m a -> t m a
777take n m = fromStream $ go n (toStream m)
778 where
779 go n1 m1 = Stream $ \st stp sng yld ->
780 let yieldk a r = yld a (go (n1 - 1) r)
781 in if n1 <= 0
782 then stp
783 else unStream m1 (rstState st) stp sng yieldk
785{-# INLINE takeWhile #-}
786takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
787takeWhile p m = fromStream $ go (toStream m)
788 where
789 go m1 = Stream $ \st stp sng yld ->
790 let single a | p a = sng a
791 | otherwise = stp
792 yieldk a r | p a = yld a (go r)
793 | otherwise = stp
794 in unStream m1 (rstState st) stp single yieldk
796drop :: IsStream t => Int -> t m a -> t m a
797drop n m = fromStream $ Stream $ \st stp sng yld ->
798 unStream (go n (toStream m)) (rstState st) stp sng yld
799 where
800 go n1 m1 = Stream $ \st stp sng yld ->
801 let single _ = stp
802 yieldk _ r = (unStream $ go (n1 - 1) r) st stp sng yld
803 -- Somehow "<=" check performs better than a ">"
804 in if n1 <= 0
805 then unStream m1 st stp sng yld
806 else unStream m1 st stp single yieldk
808{-# INLINE dropWhile #-}
809dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
810dropWhile p m = fromStream $ go (toStream m)
811 where
812 go m1 = Stream $ \st stp sng yld ->
813 let single a | p a = stp
814 | otherwise = sng a
815 yieldk a r | p a = (unStream r) (rstState st) stp single yieldk
816 | otherwise = yld a r
817 in unStream m1 (rstState st) stp single yieldk
819-------------------------------------------------------------------------------
820-- Mapping
821-------------------------------------------------------------------------------
823{-# INLINE map #-}
824map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b
825map f m = fromStream $ Stream $ \st stp sng yld ->
826 let single = sng . f
827 yieldk a r = yld (f a) (fmap f r)
828 in unStream (toStream m) (rstState st) stp single yieldk
830-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
831-- other stream types to overload it.
832{-# INLINE mapM #-}
833mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
834mapM f m = go (toStream m)
835 where
836 go m1 = fromStream $ Stream $ \st stp sng yld ->
837 let single a = f a >>= sng
838 yieldk a r = unStream (toStream (f a |: (go r))) st stp sng yld
839 in (unStream m1) (rstState st) stp single yieldk
841-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
842-- other stream types to overload it.
843{-# INLINE sequence #-}
844sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
845sequence m = go (toStream m)
846 where
847 go m1 = fromStream $ Stream $ \st stp sng yld ->
848 let single ma = ma >>= sng
849 yieldk ma r = unStream (toStream $ ma |: go r) st stp sng yld
850 in (unStream m1) (rstState st) stp single yieldk
852-------------------------------------------------------------------------------
853-- Map and Filter
854-------------------------------------------------------------------------------
856{-# INLINE mapMaybe #-}
857mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
858mapMaybe f m = go (toStream m)
859 where
860 go m1 = fromStream $ Stream $ \st stp sng yld ->
861 let single a = case f a of
862 Just b -> sng b
863 Nothing -> stp
864 yieldk a r = case f a of
865 Just b -> yld b (toStream $ go r)
866 Nothing -> (unStream r) (rstState st) stp single yieldk
867 in unStream m1 (rstState st) stp single yieldk
869------------------------------------------------------------------------------
870-- Serial Zipping
871------------------------------------------------------------------------------
873{-# INLINE zipWithS #-}
874zipWithS :: (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
875zipWithS f m1 m2 = go m1 m2
876 where
877 go mx my = Stream $ \st stp sng yld -> do
878 let merge a ra =
879 let single2 b = sng (f a b)
880 yield2 b rb = yld (f a b) (go ra rb)
881 in unStream my (rstState st) stp single2 yield2
882 let single1 a = merge a nil
883 yield1 a ra = merge a ra
884 unStream mx (rstState st) stp single1 yield1
886-- | Zip two streams serially using a pure zipping function.
887--
888-- @since 0.1.0
889{-# INLINABLE zipWith #-}
890zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
891zipWith f m1 m2 = fromStream $ zipWithS f (toStream m1) (toStream m2)
893-- | Zip two streams serially using a monadic zipping function.
894--
895-- @since 0.1.0
896zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
897zipWithM f m1 m2 = fromStream $ go (toStream m1) (toStream m2)
898 where
899 go mx my = Stream $ \st stp sng yld -> do
900 let merge a ra =
901 let runIt x = unStream x (rstState st) stp sng yld
902 single2 b = f a b >>= sng
903 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
904 in unStream my (rstState st) stp single2 yield2
905 let single1 a = merge a nil
906 yield1 a ra = merge a ra
907 unStream mx (rstState st) stp single1 yield1
909------------------------------------------------------------------------------
910-- Semigroup
911------------------------------------------------------------------------------
913-- | Concatenates two streams sequentially i.e. the first stream is
914-- exhausted completely before yielding any element from the second stream.
915{-# INLINE serial #-}
916serial :: Stream m a -> Stream m a -> Stream m a
917serial m1 m2 = go m1
918 where
919 go (Stream m) = Stream $ \st stp sng yld ->
920 let stop = (unStream m2) (rstState st) stp sng yld
921 single a = yld a m2
922 yieldk a r = yld a (go r)
923 in m (rstState st) stop single yieldk
925instance Semigroup (Stream m a) where
926 (<>) = serial
928------------------------------------------------------------------------------
929-- Monoid
930------------------------------------------------------------------------------
932instance Monoid (Stream m a) where
933 mempty = nil
934 mappend = (<>)
936-------------------------------------------------------------------------------
937-- Functor
938-------------------------------------------------------------------------------
940instance Monad m => Functor (Stream m) where
941 fmap = map
943-------------------------------------------------------------------------------
944-- Bind utility
945-------------------------------------------------------------------------------
947{-# INLINE bindWith #-}
948bindWith
949 :: (forall c. Stream m c -> Stream m c -> Stream m c)
950 -> Stream m a
951 -> (a -> Stream m b)
952 -> Stream m b
953bindWith par m f = go m
954 where
955 go (Stream g) =
956 Stream $ \st stp sng yld ->
957 let run x = (unStream x) st stp sng yld
958 single a = run $ f a
959 yieldk a r = run $ f a `par` go r
960 in g (rstState st) stp single yieldk
962------------------------------------------------------------------------------
963-- Alternative & MonadPlus
964------------------------------------------------------------------------------
966_alt :: Stream m a -> Stream m a -> Stream m a
967_alt m1 m2 = Stream $ \st stp sng yld ->
968 let stop = unStream m2 (rstState st) stp sng yld
969 in unStream m1 (rstState st) stop sng yld
971------------------------------------------------------------------------------
972-- MonadReader
973------------------------------------------------------------------------------
975withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
976withLocal f m =
977 Stream $ \st stp sng yld ->
978 let single = local f . sng
979 yieldk a r = local f $ yld a (withLocal f r)
980 in (unStream m) (rstState st) (local f stp) single yieldk
982------------------------------------------------------------------------------
983-- MonadError
984------------------------------------------------------------------------------
986{-
987-- XXX handle and test cross thread state transfer
988withCatchError
989 :: MonadError e m
990 => Stream m a -> (e -> Stream m a) -> Stream m a
991withCatchError m h =
992 Stream $ \_ stp sng yld ->
993 let run x = unStream x Nothing stp sng yieldk
994 handle r = r `catchError` \e -> run $ h e
995 yieldk a r = yld a (withCatchError r h)
996 in handle $ run m
997-}
999-------------------------------------------------------------------------------
1000-- Transformers
1001-------------------------------------------------------------------------------
1003instance MonadTrans Stream where
1004 lift = yieldM