1{-# LANGUAGE BangPatterns #-}
3{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE InstanceSigs #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE RankNTypes #-}
9{-# LANGUAGE ScopedTypeVariables #-}
10{-# LANGUAGE UndecidableInstances #-} -- XXX
15-- Module : Streamly.Internal.Data.Stream.StreamK
16-- Copyright : (c) 2017 Harendra Kumar
19-- Maintainer : streamly@composewell.com
20-- Stability : experimental
24-- Continuation passing style (CPS) stream implementation. The symbol 'K' below
25-- denotes a function as well as a Kontinuation.
28-- import qualified Streamly.Internal.Data.Stream.StreamK as K
31module Streamly.Internal.Data.Stream.StreamK
33 -- * A class for streams
40 -- * Construction Primitives
47 -- * Elimination Primitives
52 -- * Transformation Primitives
63 -- ** Specialized Generation
102 -- ** Specialized Folds
132 -- ** By folding (scans)
176 -- ** Transformation comprehensions
179 -- * Semigroup Style Composition
188 , Streaming -- deprecated
193import Control.Monad.Trans (MonadTrans(lift))
194import Control.Monad (void, join)
195import Control.Monad.Reader.Class (MonadReader(..))
196import Data.Function (fix)
198 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
199 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
200 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
201 foldr1, (!!), replicate, reverse, concatMap, iterate)
202import qualified Prelude
204import Streamly.Internal.Data.SVar
205import Streamly.Internal.Data.Stream.StreamK.Type
207-------------------------------------------------------------------------------
209-------------------------------------------------------------------------------
212uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
214 let stop = return Nothing
215 single a = return (Just (a, nil))
216 yieldk a r = return (Just (a, r))
217 in foldStream defState yieldk single stop m
219-------------------------------------------------------------------------------
221-------------------------------------------------------------------------------
223{-# INLINE unfoldr #-}
224unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
225unfoldr next s0 = build $ \yld stp ->
228 Just (a, b) -> yld a (go b)
232{-# INLINE unfoldrM #-}
233unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
236 go s = sharedM $ \yld _ stp -> do
239 Just (a, b) -> yld a (go b)
243-- Generalization of concurrent streams/SVar via unfoldr.
245-- Unfold a value into monadic actions and then run the resulting monadic
246-- actions to generate a stream. Since the step of generating the monadic
247-- action and running them are decoupled we can run the monadic actions
248-- cooncurrently. For example, the seed could be a list of monadic actions or a
249-- pure stream of monadic actions.
251-- We can have different flavors of this depending on the stream type t. The
252-- concurrent version could be async or ahead etc. Depending on how we queue
253-- back the feedback portion b, it could be DFS or BFS style.
255unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
259-------------------------------------------------------------------------------
261-------------------------------------------------------------------------------
266{-# DEPRECATED once "Please use yieldM instead." #-}
268once :: (Monad m, IsStream t) => m a -> t m a
273-- repeatM = fix . cons
274-- repeatM = cycle1 . yield
277-- Generate an infinite stream by repeating a monadic value.
280repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
282 where go m = m |: go m
284-- Generate an infinite stream by repeating a pure value.
288repeat :: IsStream t => a -> t m a
289repeat a = let x = cons a x in x
291{-# INLINE replicateM #-}
292replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
295 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
297{-# INLINE replicate #-}
298replicate :: IsStream t => Int -> a -> t m a
301 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
303{-# INLINE fromIndicesM #-}
304fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
305fromIndicesM gen = go 0
307 go i = mkStream $ \st stp sng yld -> do
308 foldStreamShared st stp sng yld (gen i |: go (i + 1))
310{-# INLINE fromIndices #-}
311fromIndices :: IsStream t => (Int -> a) -> t m a
312fromIndices gen = go 0
314 go n = (gen n) `cons` go (n + 1)
316{-# INLINE iterate #-}
317iterate :: IsStream t => (a -> a) -> a -> t m a
318iterate step = fromStream . go
320 go s = cons s (go (step s))
322{-# INLINE iterateM #-}
323iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
326 go s = mkStream $ \st stp sng yld -> do
328 foldStreamShared st stp sng yld (return next |: go (step next))
330-------------------------------------------------------------------------------
332-------------------------------------------------------------------------------
336-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
339-- Construct a stream from a 'Foldable' containing pure values:
342{-# INLINE fromFoldable #-}
343fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
344fromFoldable = Prelude.foldr cons nil
346{-# INLINE fromList #-}
347fromList :: IsStream t => [a] -> t m a
348fromList = fromFoldable
350{-# INLINE fromStreamK #-}
351fromStreamK :: IsStream t => Stream m a -> t m a
352fromStreamK = fromStream
354-------------------------------------------------------------------------------
355-- Elimination by Folding
356-------------------------------------------------------------------------------
358-- | Lazy right associative fold.
360foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
361foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
363-- | Right associative fold to an arbitrary transformer monad.
365foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
366 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
367foldrT step final m = go m
370 res <- lift $ uncons m1
372 Just (h, t) -> step h (go t)
376foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
380 Nothing -> return Nothing
381 Just (h, t) -> fmap Just (go h t)
385 single a = return $ step a p
386 yieldk a r = fmap (step p) (go a r)
387 in foldStream defState yieldk single stp m1
389-- | Strict left fold with an extraction function. Like the standard strict
390-- left fold, but applies a user supplied extraction function (the third
391-- argument) to the folded value at the end. This is designed to work with the
392-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
394-- Note that the accumulator is always evaluated including the initial value.
395{-# INLINE foldlx' #-}
396foldlx' :: forall t m a b x. (IsStream t, Monad m)
397 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
398foldlx' step begin done m = get $ go m begin
403 -- XXX we are not strictly evaluating the accumulator here. Is this
405 let single = return . done
406 -- XXX this is foldSingleton. why foldStreamShared?
407 in foldStreamShared undefined undefined single undefined m1
409 -- Note, this can be implemented by making a recursive call to "go",
410 -- however that is more expensive because of unnecessary recursion
411 -- that cannot be tail call optimized. Unfolding recursion explicitly via
412 -- continuations is much more efficient.
413 go :: t m a -> x -> t m x
414 go m1 !acc = mkStream $ \_ yld sng _ ->
416 single a = sng $ step acc a
417 -- XXX this is foldNonEmptyStream
418 yieldk a r = foldStream defState yld sng undefined $
420 in foldStream defState yieldk single stop m1
422-- | Strict left associative fold.
424foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
425foldl' step begin = foldlx' step begin id
427-- XXX replace the recursive "go" with explicit continuations.
428-- | Like 'foldx', but with a monadic step function.
429{-# INLINABLE foldlMx' #-}
430foldlMx' :: (IsStream t, Monad m)
431 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
432foldlMx' step begin done m = go begin m
435 let stop = acc >>= done
436 single a = acc >>= \b -> step b a >>= done
437 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
438 in foldStream defState yieldk single stop m1
440-- | Like 'foldl'' but with a monadic step function.
441{-# INLINE foldlM' #-}
442foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
443foldlM' step begin = foldlMx' step (return begin) return
445-- | Lazy left fold to a stream.
447foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
448foldlS step begin m = go begin m
450 go acc rest = mkStream $ \st yld sng stp ->
451 let run x = foldStream st yld sng stp x
453 single a = run $ step acc a
454 yieldk a r = run $ go (step acc a) r
455 in foldStream (adaptState st) yieldk single stop rest
457-- | Lazy left fold to an arbitrary transformer monad.
459foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
460 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
461foldlT step begin m = go begin m
464 res <- lift $ uncons m1
466 Just (h, t) -> go (step acc h) t
469------------------------------------------------------------------------------
471------------------------------------------------------------------------------
473-- XXX use foldrM to implement folds where possible
474-- XXX This (commented) definition of drain and mapM_ perform much better on
475-- some benchmarks but worse on others. Need to investigate why, may there is
476-- an optimization opportunity that we can exploit.
477-- drain = foldrM (\_ xs -> return () >> xs) (return ())
480-- > drain = foldl' (\_ _ -> ()) ()
481-- > drain = mapM_ (\_ -> return ())
483drain :: (Monad m, IsStream t) => t m a -> m ()
484drain = foldrM (\_ xs -> xs) (return ())
492 in foldStream defState yieldk single stop m1
496null :: (IsStream t, Monad m) => t m a -> m Bool
497-- null = foldrM (\_ _ -> return True) (return False)
499 let stop = return True
500 single _ = return False
501 yieldk _ _ = return False
502 in foldStream defState yieldk single stop m
505head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
506-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
508 let stop = return Nothing
509 single a = return (Just a)
510 yieldk a _ = return (Just a)
511 in foldStream defState yieldk single stop m
514tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
516 let stop = return Nothing
517 single _ = return $ Just nil
518 yieldk _ r = return $ Just r
519 in foldStream defState yieldk single stop m
521{-# INLINE headPartial #-}
522headPartial :: (IsStream t, Monad m) => t m a -> m a
523headPartial = foldrM (\x _ -> return x) (error "head of nil")
525{-# INLINE tailPartial #-}
526tailPartial :: IsStream t => t m a -> t m a
527tailPartial m = mkStream $ \st yld sng stp ->
528 let stop = error "tail of nil"
530 yieldk _ r = foldStream st yld sng stp r
531 in foldStream st yieldk single stop m
533-- | Iterate a lazy function `f` of the shape `m a -> t m a` until it gets
534-- fully defined i.e. becomes independent of its argument action, then return
535-- the resulting value of the function (`t m a`).
537-- It can be used to construct a stream that uses a cyclic definition. For
541-- import Streamly.Internal.Prelude as S
542-- import System.IO.Unsafe (unsafeInterleaveIO)
545-- S.mapM_ print $ S.mfix $ \x -> do
546-- a <- S.fromList [1,2]
547-- b <- S.fromListM [return 3, unsafeInterleaveIO (fmap fst x)]
551-- Note that the function `f` must be lazy in its argument, that's why we use
552-- 'unsafeInterleaveIO' because IO monad is strict.
554mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
555mfix f = mkStream $ \st yld sng stp ->
556 let single a = foldStream st yld sng stp $ a `cons` ys
557 yieldk a _ = foldStream st yld sng stp $ a `cons` ys
558 in foldStream st yieldk single stp xs
559 where xs = fix (f . headPartial)
560 ys = mfix (tailPartial . f)
563init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
569 Nothing -> return Nothing
570 Just (h, t) -> return . Just $ go h t
571 go p m1 = mkStream $ \_ yld sng stp ->
573 yieldk a x = yld p $ go a x
574 in foldStream defState yieldk single stp m1
577elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
581 let stop = return False
582 single a = return (a == e)
583 yieldk a r = if a == e then return True else go r
584 in foldStream defState yieldk single stop m1
586{-# INLINE notElem #-}
587notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
591 let stop = return True
592 single a = return (a /= e)
593 yieldk a r = if a == e then return False else go r
594 in foldStream defState yieldk single stop m1
597all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
601 let single a | p a = return True
602 | otherwise = return False
603 yieldk a r | p a = go r
604 | otherwise = return False
605 in foldStream defState yieldk single (return True) m1
608any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
612 let single a | p a = return True
613 | otherwise = return False
614 yieldk a r | p a = return True
616 in foldStream defState yieldk single (return False) m1
618-- | Extract the last element of the stream, if any.
620last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
621last = foldlx' (\_ y -> Just y) Nothing id
623{-# INLINE minimum #-}
624minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
625minimum m = go Nothing m
628 let stop = return Nothing
629 single a = return (Just a)
630 yieldk a r = go (Just a) r
631 in foldStream defState yieldk single stop m1
634 let stop = return (Just res)
637 then return (Just res)
643 in foldStream defState yieldk single stop m1
645{-# INLINE minimumBy #-}
647 :: (IsStream t, Monad m)
648 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
649minimumBy cmp m = go Nothing m
652 let stop = return Nothing
653 single a = return (Just a)
654 yieldk a r = go (Just a) r
655 in foldStream defState yieldk single stop m1
658 let stop = return (Just res)
659 single a = case cmp res a of
660 GT -> return (Just a)
661 _ -> return (Just res)
662 yieldk a r = case cmp res a of
665 in foldStream defState yieldk single stop m1
667{-# INLINE maximum #-}
668maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
669maximum m = go Nothing m
672 let stop = return Nothing
673 single a = return (Just a)
674 yieldk a r = go (Just a) r
675 in foldStream defState yieldk single stop m1
678 let stop = return (Just res)
682 else return (Just res)
687 in foldStream defState yieldk single stop m1
689{-# INLINE maximumBy #-}
690maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
691maximumBy cmp m = go Nothing m
694 let stop = return Nothing
695 single a = return (Just a)
696 yieldk a r = go (Just a) r
697 in foldStream defState yieldk single stop m1
700 let stop = return (Just res)
701 single a = case cmp res a of
702 GT -> return (Just res)
704 yieldk a r = case cmp res a of
705 GT -> go (Just res) r
707 in foldStream defState yieldk single stop m1
710(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
714 let single a | n == 0 = return $ Just a
715 | otherwise = return Nothing
716 yieldk a x | n < 0 = return Nothing
717 | n == 0 = return $ Just a
718 | otherwise = go (n - 1) x
719 in foldStream defState yieldk single (return Nothing) m1
722lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
726 let single (a, b) | a == e = return $ Just b
727 | otherwise = return Nothing
728 yieldk (a, b) x | a == e = return $ Just b
730 in foldStream defState yieldk single (return Nothing) m1
733findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
739 if b then return $ Just a else return Nothing
742 if b then return $ Just a else go x
743 in foldStream defState yieldk single (return Nothing) m1
746find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
747find p = findM (return . p)
749{-# INLINE findIndices #-}
750findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
753 go offset m1 = mkStream $ \st yld sng stp ->
754 let single a | p a = sng offset
756 yieldk a x | p a = yld offset $ go (offset + 1) x
757 | otherwise = foldStream (adaptState st) yld sng stp $
759 in foldStream (adaptState st) yieldk single stp m1
761------------------------------------------------------------------------------
763------------------------------------------------------------------------------
765-- | Apply a monadic action to each element of the stream and discard the
766-- output of the action.
768mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
773 single a = void (f a)
774 yieldk a r = f a >> go r
775 in foldStream defState yieldk single stop m1
777------------------------------------------------------------------------------
779------------------------------------------------------------------------------
781{-# INLINABLE toList #-}
782toList :: (IsStream t, Monad m) => t m a -> m [a]
785{-# INLINE toStreamK #-}
786toStreamK :: Stream m a -> Stream m a
789-- Based on suggestions by David Feuer and Pranay Sashank
791hoist :: (IsStream t, Monad m, Monad n)
792 => (forall x. m x -> n x) -> t m a -> t n a
794 mkStream $ \st yld sng stp ->
795 let single = return . sng
796 yieldk a s = return $ yld a (hoist f s)
798 state = adaptState st
799 in join . f $ foldStreamShared state yieldk single stop str
801-------------------------------------------------------------------------------
802-- Transformation by folding (Scans)
803-------------------------------------------------------------------------------
805{-# INLINE scanlx' #-}
806scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
807scanlx' step begin done m =
808 cons (done begin) $ go m begin
810 go m1 !acc = mkStream $ \st yld sng stp ->
811 let single a = sng (done $ step acc a)
814 in yld (done s) (go r s)
815 in foldStream (adaptState st) yieldk single stp m1
818scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
819scanl' step begin = scanlx' step begin id
821-------------------------------------------------------------------------------
823-------------------------------------------------------------------------------
826filter :: IsStream t => (a -> Bool) -> t m a -> t m a
829 go m1 = mkStream $ \st yld sng stp ->
830 let single a | p a = sng a
832 yieldk a r | p a = yld a (go r)
833 | otherwise = foldStream st yieldk single stp r
834 in foldStream st yieldk single stp m1
837take :: IsStream t => Int -> t m a -> t m a
840 go n1 m1 = mkStream $ \st yld sng stp ->
841 let yieldk a r = yld a (go (n1 - 1) r)
844 else foldStream st yieldk sng stp m1
846{-# INLINE takeWhile #-}
847takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
850 go m1 = mkStream $ \st yld sng stp ->
851 let single a | p a = sng a
853 yieldk a r | p a = yld a (go r)
855 in foldStream st yieldk single stp m1
858drop :: IsStream t => Int -> t m a -> t m a
859drop n m = fromStream $ unShare (go n (toStream m))
861 go n1 m1 = mkStream $ \st yld sng stp ->
863 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
864 -- Somehow "<=" check performs better than a ">"
866 then foldStreamShared st yld sng stp m1
867 else foldStreamShared st yieldk single stp m1
869{-# INLINE dropWhile #-}
870dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
873 go m1 = mkStream $ \st yld sng stp ->
874 let single a | p a = stp
876 yieldk a r | p a = foldStream st yieldk single stp r
877 | otherwise = yld a r
878 in foldStream st yieldk single stp m1
880-------------------------------------------------------------------------------
882-------------------------------------------------------------------------------
884-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
885-- other stream types to overload it.
886{-# INLINE sequence #-}
887sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
890 go m1 = mkStream $ \st yld sng stp ->
891 let single ma = ma >>= sng
892 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
893 in foldStream (adaptState st) yieldk single stp m1
895-------------------------------------------------------------------------------
897-------------------------------------------------------------------------------
899{-# INLINE intersperseM #-}
900intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
901intersperseM a m = prependingStart m
903 prependingStart m1 = mkStream $ \st yld sng stp ->
904 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
905 in foldStream st yieldk sng stp m1
906 go m2 = mkStream $ \st yld sng stp ->
907 let single i = foldStreamShared st yld sng stp $ a |: yield i
908 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
909 in foldStream st yieldk single stp m2
911{-# INLINE intersperse #-}
912intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
913intersperse a = intersperseM (return a)
915{-# INLINE insertBy #-}
916insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
917insertBy cmp x m = go m
919 go m1 = mkStream $ \st yld _ _ ->
920 let single a = case cmp x a of
921 GT -> yld a (yield x)
924 yieldk a r = case cmp x a of
926 _ -> yld x (a `cons` r)
927 in foldStream st yieldk single stop m1
929------------------------------------------------------------------------------
931------------------------------------------------------------------------------
933{-# INLINE deleteBy #-}
934deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
935deleteBy eq x m = go m
937 go m1 = mkStream $ \st yld sng stp ->
938 let single a = if eq x a then stp else sng a
939 yieldk a r = if eq x a
940 then foldStream st yld sng stp r
942 in foldStream st yieldk single stp m1
944------------------------------------------------------------------------------
946------------------------------------------------------------------------------
948{-# INLINE reverse #-}
949reverse :: IsStream t => t m a -> t m a
950reverse = foldlS (flip cons) nil
952-------------------------------------------------------------------------------
954-------------------------------------------------------------------------------
956{-# INLINE mapMaybe #-}
957mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
960 go m1 = mkStream $ \st yld sng stp ->
961 let single a = case f a of
964 yieldk a r = case f a of
965 Just b -> yld b $ go r
966 Nothing -> foldStream (adaptState st) yieldk single stp r
967 in foldStream (adaptState st) yieldk single stp m1
969------------------------------------------------------------------------------
971------------------------------------------------------------------------------
973-- | Zip two streams serially using a pure zipping function.
976{-# INLINABLE zipWith #-}
977zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
980 go mx my = mkStream $ \st yld sng stp -> do
982 let single2 b = sng (f a b)
983 yield2 b rb = yld (f a b) (go ra rb)
984 in foldStream (adaptState st) yield2 single2 stp my
985 let single1 a = merge a nil
987 foldStream (adaptState st) yield1 single1 stp mx
989-- | Zip two streams serially using a monadic zipping function.
992{-# INLINABLE zipWithM #-}
993zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
994zipWithM f m1 m2 = go m1 m2
996 go mx my = mkStream $ \st yld sng stp -> do
998 let runIt x = foldStream st yld sng stp x
999 single2 b = f a b >>= sng
1000 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
1001 in foldStream (adaptState st) yield2 single2 stp my
1002 let single1 a = merge a nil
1004 foldStream (adaptState st) yield1 single1 stp mx
1006------------------------------------------------------------------------------
1008------------------------------------------------------------------------------
1010{-# INLINE mergeByM #-}
1012 :: (IsStream t, Monad m)
1013 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1016 go mx my = mkStream $ \st yld sng stp -> do
1017 let mergeWithY a ra =
1018 let stop2 = foldStream st yld sng stp mx
1022 GT -> yld b (go (a `cons` ra) nil)
1023 _ -> yld a (go ra (b `cons` nil))
1027 GT -> yld b (go (a `cons` ra) rb)
1028 _ -> yld a (go ra (b `cons` rb))
1029 in foldStream st yield2 single2 stop2 my
1030 let stopX = foldStream st yld sng stp my
1031 singleX a = mergeWithY a nil
1033 foldStream st yieldX singleX stopX mx
1035{-# INLINABLE mergeBy #-}
1037 :: (IsStream t, Monad m)
1038 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1039mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1041------------------------------------------------------------------------------
1042-- Transformation comprehensions
1043------------------------------------------------------------------------------
1046the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
1050 Nothing -> return Nothing
1051 Just (h, t) -> go h t
1054 let single a | h == a = return $ Just h
1055 | otherwise = return Nothing
1056 yieldk a r | h == a = go h r
1057 | otherwise = return Nothing
1058 in foldStream defState yieldk single (return $ Just h) m1
1060------------------------------------------------------------------------------
1061-- Alternative & MonadPlus
1062------------------------------------------------------------------------------
1064_alt :: Stream m a -> Stream m a -> Stream m a
1065_alt m1 m2 = mkStream $ \st yld sng stp ->
1066 let stop = foldStream st yld sng stp m2
1067 in foldStream st yld sng stop m1
1069------------------------------------------------------------------------------
1071------------------------------------------------------------------------------
1073{-# INLINABLE withLocal #-}
1074withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1076 mkStream $ \st yld sng stp ->
1077 let single = local f . sng
1078 yieldk a r = local f $ yld a (withLocal f r)
1079 in foldStream st yieldk single (local f stp) m
1081------------------------------------------------------------------------------
1083------------------------------------------------------------------------------
1086-- XXX handle and test cross thread state transfer
1089 => Stream m a -> (e -> Stream m a) -> Stream m a
1091 mkStream $ \_ stp sng yld ->
1092 let run x = unStream x Nothing stp sng yieldk
1093 handle r = r `catchError` \e -> run $ h e
1094 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