1{-# LANGUAGE UndecidableInstances #-}
6-- Module : Streamly.Internal.Data.Stream.StreamK
7-- Copyright : (c) 2017 Composewell Technologies
10-- Maintainer : streamly@composewell.com
11-- Stability : experimental
15-- Continuation passing style (CPS) stream implementation. The symbol 'K' below
16-- denotes a function as well as a Kontinuation.
19-- import qualified Streamly.Internal.Data.Stream.StreamK as K
22module Streamly.Internal.Data.Stream.StreamK
24 -- * A class for streams
31 -- * Construction Primitives
38 -- * Elimination Primitives
42 -- * Transformation Primitives
53 -- ** Specialized Generation
93 -- ** Specialized Folds
123 -- ** By folding (scans)
171 -- ** Transformation comprehensions
174 -- * Semigroup Style Composition
183 , Streaming -- deprecated
188import Control.Monad.Trans.Class (MonadTrans(lift))
189import Control.Monad (void, join)
190import Control.Monad.Reader.Class (MonadReader(..))
191import Data.Function (fix)
193 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
194 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
195 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
196 foldr1, (!!), replicate, reverse, concatMap, iterate)
197import qualified Prelude
199import Streamly.Internal.Data.SVar
200import Streamly.Internal.Data.Stream.StreamK.Type
202import qualified Streamly.Internal.Data.Fold.Types as FL
204-------------------------------------------------------------------------------
206-------------------------------------------------------------------------------
209uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
211 let stop = return Nothing
212 single a = return (Just (a, nil))
213 yieldk a r = return (Just (a, r))
214 in foldStream defState yieldk single stop m
216-------------------------------------------------------------------------------
218-------------------------------------------------------------------------------
220{-# INLINE unfoldr #-}
221unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
222unfoldr next s0 = build $ \yld stp ->
225 Just (a, b) -> yld a (go b)
229{-# INLINE unfoldrM #-}
230unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
233 go s = sharedM $ \yld _ stp -> do
236 Just (a, b) -> yld a (go b)
240-- Generalization of concurrent streams/SVar via unfoldr.
242-- Unfold a value into monadic actions and then run the resulting monadic
243-- actions to generate a stream. Since the step of generating the monadic
244-- action and running them are decoupled we can run the monadic actions
245-- cooncurrently. For example, the seed could be a list of monadic actions or a
246-- pure stream of monadic actions.
248-- We can have different flavors of this depending on the stream type t. The
249-- concurrent version could be async or ahead etc. Depending on how we queue
250-- back the feedback portion b, it could be DFS or BFS style.
252unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
256-------------------------------------------------------------------------------
258-------------------------------------------------------------------------------
263{-# DEPRECATED once "Please use yieldM instead." #-}
265once :: (Monad m, IsStream t) => m a -> t m a
270-- repeatM = fix . cons
271-- repeatM = cycle1 . yield
274-- Generate an infinite stream by repeating a monadic value.
277repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
279 where go m = m |: go m
281-- Generate an infinite stream by repeating a pure value.
285repeat :: IsStream t => a -> t m a
286repeat a = let x = cons a x in x
288{-# INLINE replicateM #-}
289replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
292 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
294{-# INLINE replicate #-}
295replicate :: IsStream t => Int -> a -> t m a
298 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
300{-# INLINE fromIndicesM #-}
301fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
302fromIndicesM gen = go 0
304 go i = mkStream $ \st stp sng yld -> do
305 foldStreamShared st stp sng yld (gen i |: go (i + 1))
307{-# INLINE fromIndices #-}
308fromIndices :: IsStream t => (Int -> a) -> t m a
309fromIndices gen = go 0
311 go n = (gen n) `cons` go (n + 1)
313{-# INLINE iterate #-}
314iterate :: IsStream t => (a -> a) -> a -> t m a
315iterate step = fromStream . go
317 go s = cons s (go (step s))
319{-# INLINE iterateM #-}
320iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
323 go s = mkStream $ \st stp sng yld -> do
325 foldStreamShared st stp sng yld (return next |: go (step next))
327-------------------------------------------------------------------------------
329-------------------------------------------------------------------------------
333-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
336-- Construct a stream from a 'Foldable' containing pure values:
339{-# INLINE fromFoldable #-}
340fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
341fromFoldable = Prelude.foldr cons nil
343{-# INLINE fromList #-}
344fromList :: IsStream t => [a] -> t m a
345fromList = fromFoldable
347{-# INLINE fromStreamK #-}
348fromStreamK :: IsStream t => Stream m a -> t m a
349fromStreamK = fromStream
351-------------------------------------------------------------------------------
352-- Elimination by Folding
353-------------------------------------------------------------------------------
355-- | Lazy right associative fold.
357foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
358foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
360-- | Right associative fold to an arbitrary transformer monad.
362foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
363 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
364foldrT step final m = go m
367 res <- lift $ uncons m1
369 Just (h, t) -> step h (go t)
373foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
377 Nothing -> return Nothing
378 Just (h, t) -> fmap Just (go h t)
382 single a = return $ step a p
383 yieldk a r = fmap (step p) (go a r)
384 in foldStream defState yieldk single stp m1
386-- | Strict left fold with an extraction function. Like the standard strict
387-- left fold, but applies a user supplied extraction function (the third
388-- argument) to the folded value at the end. This is designed to work with the
389-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
391-- Note that the accumulator is always evaluated including the initial value.
392{-# INLINE foldlx' #-}
393foldlx' :: forall t m a b x. (IsStream t, Monad m)
394 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
395foldlx' step begin done m = get $ go m begin
400 -- XXX we are not strictly evaluating the accumulator here. Is this
402 let single = return . done
403 -- XXX this is foldSingleton. why foldStreamShared?
404 in foldStreamShared undefined undefined single undefined m1
406 -- Note, this can be implemented by making a recursive call to "go",
407 -- however that is more expensive because of unnecessary recursion
408 -- that cannot be tail call optimized. Unfolding recursion explicitly via
409 -- continuations is much more efficient.
410 go :: t m a -> x -> t m x
411 go m1 !acc = mkStream $ \_ yld sng _ ->
413 single a = sng $ step acc a
414 -- XXX this is foldNonEmptyStream
415 yieldk a r = foldStream defState yld sng undefined $
417 in foldStream defState yieldk single stop m1
419-- | Strict left associative fold.
421foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
422foldl' step begin = foldlx' step begin id
424-- XXX replace the recursive "go" with explicit continuations.
425-- | Like 'foldx', but with a monadic step function.
426{-# INLINABLE foldlMx' #-}
427foldlMx' :: (IsStream t, Monad m)
428 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
429foldlMx' step begin done m = go begin m
432 let stop = acc >>= done
433 single a = acc >>= \b -> step b a >>= done
434 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
435 in foldStream defState yieldk single stop m1
437{-# INLINABLE foldOnce #-}
438foldOnce :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> m b
439foldOnce (FL.Fold step begin done) m = do
442 FL.Partial fs -> go fs m
443 FL.Done fb -> return fb
448 single a = step acc a
450 FL.Partial s -> done s
451 FL.Done b1 -> return b1
452 yieldk a r = step acc a
454 FL.Partial s -> go s r
455 FL.Done b1 -> return b1
456 in foldStream defState yieldk single stop m1
458-- | Like 'foldl'' but with a monadic step function.
459{-# INLINE foldlM' #-}
460foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> m b
461foldlM' step begin = foldlMx' step begin return
463-- | Lazy left fold to a stream.
465foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
466foldlS step begin m = go begin m
468 go acc rest = mkStream $ \st yld sng stp ->
469 let run x = foldStream st yld sng stp x
471 single a = run $ step acc a
472 yieldk a r = run $ go (step acc a) r
473 in foldStream (adaptState st) yieldk single stop rest
475-- | Lazy left fold to an arbitrary transformer monad.
477foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
478 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
479foldlT step begin m = go begin m
482 res <- lift $ uncons m1
484 Just (h, t) -> go (step acc h) t
487------------------------------------------------------------------------------
489------------------------------------------------------------------------------
491-- XXX use foldrM to implement folds where possible
492-- XXX This (commented) definition of drain and mapM_ perform much better on
493-- some benchmarks but worse on others. Need to investigate why, may there is
494-- an optimization opportunity that we can exploit.
495-- drain = foldrM (\_ xs -> return () >> xs) (return ())
498-- > drain = foldl' (\_ _ -> ()) ()
499-- > drain = mapM_ (\_ -> return ())
501drain :: (Monad m, IsStream t) => t m a -> m ()
502drain = foldrM (\_ xs -> xs) (return ())
510 in foldStream defState yieldk single stop m1
514null :: (IsStream t, Monad m) => t m a -> m Bool
515-- null = foldrM (\_ _ -> return True) (return False)
517 let stop = return True
518 single _ = return False
519 yieldk _ _ = return False
520 in foldStream defState yieldk single stop m
523head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
524-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
526 let stop = return Nothing
527 single a = return (Just a)
528 yieldk a _ = return (Just a)
529 in foldStream defState yieldk single stop m
532tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
534 let stop = return Nothing
535 single _ = return $ Just nil
536 yieldk _ r = return $ Just r
537 in foldStream defState yieldk single stop m
539{-# INLINE headPartial #-}
540headPartial :: (IsStream t, Monad m) => t m a -> m a
541headPartial = foldrM (\x _ -> return x) (error "head of nil")
543{-# INLINE tailPartial #-}
544tailPartial :: IsStream t => t m a -> t m a
545tailPartial m = mkStream $ \st yld sng stp ->
546 let stop = error "tail of nil"
548 yieldk _ r = foldStream st yld sng stp r
549 in foldStream st yieldk single stop m
551-- | We can define cyclic structures using @let@:
553-- >>> let (a, b) = ([1, b], head a) in (a, b)
556-- The function @fix@ defined as:
558-- > fix f = let x = f x in x
560-- ensures that the argument of a function and its output refer to the same
561-- lazy value @x@ i.e. the same location in memory. Thus @x@ can be defined
562-- in terms of itself, creating structures with cyclic references.
564-- >>> f ~(a, b) = ([1, b], head a)
568-- 'Control.Monad.mfix' is essentially the same as @fix@ but for monadic
571-- Using 'mfix' for streams we can construct a stream in which each element of
572-- the stream is defined in a cyclic fashion. The argument of the function
573-- being fixed represents the current element of the stream which is being
574-- returned by the stream monad. Thus, we can use the argument to construct
577-- In the following example, the argument @action@ of the function @f@
578-- represents the tuple @(x,y)@ returned by it in a given iteration. We define
579-- the first element of the tuple in terms of the second.
582-- import Streamly.Internal.Data.Stream.IsStream as Stream
583-- import System.IO.Unsafe (unsafeInterleaveIO)
586-- Stream.mapM_ print $ Stream.mfix f
591-- let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
592-- x <- Stream.fromListM [incr 1 action, incr 2 action]
593-- y <- Stream.fromList [4,5]
597-- Note: you cannot achieve this by just changing the order of the monad
598-- statements because that would change the order in which the stream elements
601-- Note that the function @f@ must be lazy in its argument, that's why we use
602-- 'unsafeInterleaveIO' on @action@ because IO monad is strict.
606mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
607mfix f = mkStream $ \st yld sng stp ->
608 let single a = foldStream st yld sng stp $ a `cons` ys
609 yieldk a _ = foldStream st yld sng stp $ a `cons` ys
610 in foldStream st yieldk single stp xs
614 -- fix the head element of the stream
615 xs = fix (f . headPartial)
617 -- now fix the tail recursively
618 ys = mfix (tailPartial . f)
621init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
627 Nothing -> return Nothing
628 Just (h, t) -> return . Just $ go h t
629 go p m1 = mkStream $ \_ yld sng stp ->
631 yieldk a x = yld p $ go a x
632 in foldStream defState yieldk single stp m1
635elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
639 let stop = return False
640 single a = return (a == e)
641 yieldk a r = if a == e then return True else go r
642 in foldStream defState yieldk single stop m1
644{-# INLINE notElem #-}
645notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
649 let stop = return True
650 single a = return (a /= e)
651 yieldk a r = if a == e then return False else go r
652 in foldStream defState yieldk single stop m1
655all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
659 let single a | p a = return True
660 | otherwise = return False
661 yieldk a r | p a = go r
662 | otherwise = return False
663 in foldStream defState yieldk single (return True) m1
666any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
670 let single a | p a = return True
671 | otherwise = return False
672 yieldk a r | p a = return True
674 in foldStream defState yieldk single (return False) m1
676-- | Extract the last element of the stream, if any.
678last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
679last = foldlx' (\_ y -> Just y) Nothing id
681{-# INLINE minimum #-}
682minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
683minimum m = go Nothing m
686 let stop = return Nothing
687 single a = return (Just a)
688 yieldk a r = go (Just a) r
689 in foldStream defState yieldk single stop m1
692 let stop = return (Just res)
695 then return (Just res)
701 in foldStream defState yieldk single stop m1
703{-# INLINE minimumBy #-}
705 :: (IsStream t, Monad m)
706 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
707minimumBy cmp m = go Nothing m
710 let stop = return Nothing
711 single a = return (Just a)
712 yieldk a r = go (Just a) r
713 in foldStream defState yieldk single stop m1
716 let stop = return (Just res)
717 single a = case cmp res a of
718 GT -> return (Just a)
719 _ -> return (Just res)
720 yieldk a r = case cmp res a of
723 in foldStream defState yieldk single stop m1
725{-# INLINE maximum #-}
726maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
727maximum m = go Nothing m
730 let stop = return Nothing
731 single a = return (Just a)
732 yieldk a r = go (Just a) r
733 in foldStream defState yieldk single stop m1
736 let stop = return (Just res)
740 else return (Just res)
745 in foldStream defState yieldk single stop m1
747{-# INLINE maximumBy #-}
748maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
749maximumBy cmp m = go Nothing m
752 let stop = return Nothing
753 single a = return (Just a)
754 yieldk a r = go (Just a) r
755 in foldStream defState yieldk single stop m1
758 let stop = return (Just res)
759 single a = case cmp res a of
760 GT -> return (Just res)
762 yieldk a r = case cmp res a of
763 GT -> go (Just res) r
765 in foldStream defState yieldk single stop m1
768(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
772 let single a | n == 0 = return $ Just a
773 | otherwise = return Nothing
774 yieldk a x | n < 0 = return Nothing
775 | n == 0 = return $ Just a
776 | otherwise = go (n - 1) x
777 in foldStream defState yieldk single (return Nothing) m1
780lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
784 let single (a, b) | a == e = return $ Just b
785 | otherwise = return Nothing
786 yieldk (a, b) x | a == e = return $ Just b
788 in foldStream defState yieldk single (return Nothing) m1
791findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
797 if b then return $ Just a else return Nothing
800 if b then return $ Just a else go x
801 in foldStream defState yieldk single (return Nothing) m1
804find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
805find p = findM (return . p)
807{-# INLINE findIndices #-}
808findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
811 go offset m1 = mkStream $ \st yld sng stp ->
812 let single a | p a = sng offset
814 yieldk a x | p a = yld offset $ go (offset + 1) x
815 | otherwise = foldStream (adaptState st) yld sng stp $
817 in foldStream (adaptState st) yieldk single stp m1
819------------------------------------------------------------------------------
821------------------------------------------------------------------------------
823-- | Apply a monadic action to each element of the stream and discard the
824-- output of the action.
826mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
831 single a = void (f a)
832 yieldk a r = f a >> go r
833 in foldStream defState yieldk single stop m1
835------------------------------------------------------------------------------
837------------------------------------------------------------------------------
839{-# INLINABLE toList #-}
840toList :: (IsStream t, Monad m) => t m a -> m [a]
843{-# INLINE toStreamK #-}
844toStreamK :: Stream m a -> Stream m a
847-- Based on suggestions by David Feuer and Pranay Sashank
849hoist :: (IsStream t, Monad m, Monad n)
850 => (forall x. m x -> n x) -> t m a -> t n a
852 mkStream $ \st yld sng stp ->
853 let single = return . sng
854 yieldk a s = return $ yld a (hoist f s)
856 state = adaptState st
857 in join . f $ foldStreamShared state yieldk single stop str
859-------------------------------------------------------------------------------
860-- Transformation by folding (Scans)
861-------------------------------------------------------------------------------
863{-# INLINE scanlx' #-}
864scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
865scanlx' step begin done m =
866 cons (done begin) $ go m begin
868 go m1 !acc = mkStream $ \st yld sng stp ->
869 let single a = sng (done $ step acc a)
872 in yld (done s) (go r s)
873 in foldStream (adaptState st) yieldk single stp m1
876scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
877scanl' step begin = scanlx' step begin id
879-------------------------------------------------------------------------------
881-------------------------------------------------------------------------------
884filter :: IsStream t => (a -> Bool) -> t m a -> t m a
887 go m1 = mkStream $ \st yld sng stp ->
888 let single a | p a = sng a
890 yieldk a r | p a = yld a (go r)
891 | otherwise = foldStream st yieldk single stp r
892 in foldStream st yieldk single stp m1
895take :: IsStream t => Int -> t m a -> t m a
898 go n1 m1 = mkStream $ \st yld sng stp ->
899 let yieldk a r = yld a (go (n1 - 1) r)
902 else foldStream st yieldk sng stp m1
904{-# INLINE takeWhile #-}
905takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
908 go m1 = mkStream $ \st yld sng stp ->
909 let single a | p a = sng a
911 yieldk a r | p a = yld a (go r)
913 in foldStream st yieldk single stp m1
916drop :: IsStream t => Int -> t m a -> t m a
917drop n m = fromStream $ unShare (go n (toStream m))
919 go n1 m1 = mkStream $ \st yld sng stp ->
921 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
922 -- Somehow "<=" check performs better than a ">"
924 then foldStreamShared st yld sng stp m1
925 else foldStreamShared st yieldk single stp m1
927{-# INLINE dropWhile #-}
928dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
931 go m1 = mkStream $ \st yld sng stp ->
932 let single a | p a = stp
934 yieldk a r | p a = foldStream st yieldk single stp r
935 | otherwise = yld a r
936 in foldStream st yieldk single stp m1
938-------------------------------------------------------------------------------
940-------------------------------------------------------------------------------
942-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
943-- other stream types to overload it.
944{-# INLINE sequence #-}
945sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
948 go m1 = mkStream $ \st yld sng stp ->
949 let single ma = ma >>= sng
950 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
951 in foldStream (adaptState st) yieldk single stp m1
953-------------------------------------------------------------------------------
955-------------------------------------------------------------------------------
957{-# INLINE intersperseM #-}
958intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
959intersperseM a m = prependingStart m
961 prependingStart m1 = mkStream $ \st yld sng stp ->
962 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
963 in foldStream st yieldk sng stp m1
964 go m2 = mkStream $ \st yld sng stp ->
965 let single i = foldStreamShared st yld sng stp $ a |: yield i
966 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
967 in foldStream st yieldk single stp m2
969{-# INLINE intersperse #-}
970intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
971intersperse a = intersperseM (return a)
973{-# INLINE insertBy #-}
974insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
975insertBy cmp x m = go m
977 go m1 = mkStream $ \st yld _ _ ->
978 let single a = case cmp x a of
979 GT -> yld a (yield x)
982 yieldk a r = case cmp x a of
984 _ -> yld x (a `cons` r)
985 in foldStream st yieldk single stop m1
987------------------------------------------------------------------------------
989------------------------------------------------------------------------------
991{-# INLINE deleteBy #-}
992deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
993deleteBy eq x m = go m
995 go m1 = mkStream $ \st yld sng stp ->
996 let single a = if eq x a then stp else sng a
997 yieldk a r = if eq x a
998 then foldStream st yld sng stp r
1000 in foldStream st yieldk single stp m1
1002------------------------------------------------------------------------------
1004------------------------------------------------------------------------------
1006{-# INLINE reverse #-}
1007reverse :: IsStream t => t m a -> t m a
1008reverse = foldlS (flip cons) nil
1010-------------------------------------------------------------------------------
1012-------------------------------------------------------------------------------
1014{-# INLINE mapMaybe #-}
1015mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
1018 go m1 = mkStream $ \st yld sng stp ->
1019 let single a = case f a of
1022 yieldk a r = case f a of
1023 Just b -> yld b $ go r
1024 Nothing -> foldStream (adaptState st) yieldk single stp r
1025 in foldStream (adaptState st) yieldk single stp m1
1027------------------------------------------------------------------------------
1029------------------------------------------------------------------------------
1031-- | Zip two streams serially using a pure zipping function.
1034{-# INLINABLE zipWith #-}
1035zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
1038 go mx my = mkStream $ \st yld sng stp -> do
1040 let single2 b = sng (f a b)
1041 yield2 b rb = yld (f a b) (go ra rb)
1042 in foldStream (adaptState st) yield2 single2 stp my
1043 let single1 a = merge a nil
1045 foldStream (adaptState st) yield1 single1 stp mx
1047-- | Zip two streams serially using a monadic zipping function.
1050{-# INLINABLE zipWithM #-}
1051zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
1052zipWithM f m1 m2 = go m1 m2
1054 go mx my = mkStream $ \st yld sng stp -> do
1056 let runIt x = foldStream st yld sng stp x
1057 single2 b = f a b >>= sng
1058 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
1059 in foldStream (adaptState st) yield2 single2 stp my
1060 let single1 a = merge a nil
1062 foldStream (adaptState st) yield1 single1 stp mx
1064------------------------------------------------------------------------------
1066------------------------------------------------------------------------------
1068{-# INLINE mergeByM #-}
1070 :: (IsStream t, Monad m)
1071 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1074 go mx my = mkStream $ \st yld sng stp -> do
1075 let mergeWithY a ra =
1076 let stop2 = foldStream st yld sng stp mx
1080 GT -> yld b (go (a `cons` ra) nil)
1081 _ -> yld a (go ra (b `cons` nil))
1085 GT -> yld b (go (a `cons` ra) rb)
1086 _ -> yld a (go ra (b `cons` rb))
1087 in foldStream st yield2 single2 stop2 my
1088 let stopX = foldStream st yld sng stp my
1089 singleX a = mergeWithY a nil
1091 foldStream st yieldX singleX stopX mx
1093{-# INLINABLE mergeBy #-}
1095 :: (IsStream t, Monad m)
1096 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1097mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1099------------------------------------------------------------------------------
1100-- Transformation comprehensions
1101------------------------------------------------------------------------------
1104the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
1108 Nothing -> return Nothing
1109 Just (h, t) -> go h t
1112 let single a | h == a = return $ Just h
1113 | otherwise = return Nothing
1114 yieldk a r | h == a = go h r
1115 | otherwise = return Nothing
1116 in foldStream defState yieldk single (return $ Just h) m1
1118------------------------------------------------------------------------------
1119-- Alternative & MonadPlus
1120------------------------------------------------------------------------------
1122_alt :: Stream m a -> Stream m a -> Stream m a
1123_alt m1 m2 = mkStream $ \st yld sng stp ->
1124 let stop = foldStream st yld sng stp m2
1125 in foldStream st yld sng stop m1
1127------------------------------------------------------------------------------
1129------------------------------------------------------------------------------
1131{-# INLINABLE withLocal #-}
1132withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1134 mkStream $ \st yld sng stp ->
1135 let single = local f . sng
1136 yieldk a r = local f $ yld a (withLocal f r)
1137 in foldStream st yieldk single (local f stp) m
1139------------------------------------------------------------------------------
1141------------------------------------------------------------------------------
1144-- XXX handle and test cross thread state transfer
1147 => Stream m a -> (e -> Stream m a) -> Stream m a
1149 mkStream $ \_ stp sng yld ->
1150 let run x = unStream x Nothing stp sng yieldk
1151 handle r = r `catchError` \e -> run $ h e
1152 yieldk a r = yld a (withCatchError r h)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list