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)
172 -- ** Transformation comprehensions
175 -- * Semigroup Style Composition
184 , Streaming -- deprecated
189import Control.Monad.Trans.Class (MonadTrans(lift))
190import Control.Monad (void, join)
191import Control.Monad.Reader.Class (MonadReader(..))
192import Data.Function (fix)
194 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
195 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
196 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
197 foldr1, (!!), replicate, reverse, concatMap, iterate)
198import qualified Prelude
200import Streamly.Internal.Data.SVar
201import Streamly.Internal.Data.Stream.StreamK.Type
203import qualified Streamly.Internal.Data.Fold.Type as FL
208-------------------------------------------------------------------------------
210-------------------------------------------------------------------------------
213uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
215 let stop = return Nothing
216 single a = return (Just (a, nil))
217 yieldk a r = return (Just (a, r))
218 in foldStream defState yieldk single stop m
220-------------------------------------------------------------------------------
222-------------------------------------------------------------------------------
224{-# INLINE unfoldr #-}
225unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
226unfoldr next s0 = build $ \yld stp ->
229 Just (a, b) -> yld a (go b)
233{-# INLINE unfoldrM #-}
234unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
237 go s = sharedM $ \yld _ stp -> do
240 Just (a, b) -> yld a (go b)
244-- Generalization of concurrent streams/SVar via unfoldr.
246-- Unfold a value into monadic actions and then run the resulting monadic
247-- actions to generate a stream. Since the step of generating the monadic
248-- action and running them are decoupled we can run the monadic actions
249-- cooncurrently. For example, the seed could be a list of monadic actions or a
250-- pure stream of monadic actions.
252-- We can have different flavors of this depending on the stream type t. The
253-- concurrent version could be async or ahead etc. Depending on how we queue
254-- back the feedback portion b, it could be DFS or BFS style.
256unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
260-------------------------------------------------------------------------------
262-------------------------------------------------------------------------------
267{-# DEPRECATED once "Please use yieldM instead." #-}
269once :: (Monad m, IsStream t) => m a -> t m a
274-- repeatM = fix . cons
275-- repeatM = cycle1 . yield
278-- Generate an infinite stream by repeating a monadic value.
281repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
283 where go m = m |: go m
285-- Generate an infinite stream by repeating a pure value.
289repeat :: IsStream t => a -> t m a
290repeat a = let x = cons a x in x
292{-# INLINE replicateM #-}
293replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
296 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
298{-# INLINE replicate #-}
299replicate :: IsStream t => Int -> a -> t m a
302 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
304{-# INLINE fromIndicesM #-}
305fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
306fromIndicesM gen = go 0
308 go i = mkStream $ \st stp sng yld -> do
309 foldStreamShared st stp sng yld (gen i |: go (i + 1))
311{-# INLINE fromIndices #-}
312fromIndices :: IsStream t => (Int -> a) -> t m a
313fromIndices gen = go 0
315 go n = (gen n) `cons` go (n + 1)
317{-# INLINE iterate #-}
318iterate :: IsStream t => (a -> a) -> a -> t m a
319iterate step = fromStream . go
321 go s = cons s (go (step s))
323{-# INLINE iterateM #-}
324iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
327 go s = mkStream $ \st stp sng yld -> do
329 foldStreamShared st stp sng yld (return next |: go (step next))
331-------------------------------------------------------------------------------
333-------------------------------------------------------------------------------
337-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
340-- Construct a stream from a 'Foldable' containing pure values:
343{-# INLINE fromFoldable #-}
344fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
345fromFoldable = Prelude.foldr cons nil
347{-# INLINE fromList #-}
348fromList :: IsStream t => [a] -> t m a
349fromList = fromFoldable
351{-# INLINE fromStreamK #-}
352fromStreamK :: IsStream t => Stream m a -> t m a
353fromStreamK = fromStream
355-------------------------------------------------------------------------------
356-- Elimination by Folding
357-------------------------------------------------------------------------------
359-- | Lazy right associative fold.
361foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
362foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
364-- | Right associative fold to an arbitrary transformer monad.
366foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
367 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
368foldrT step final m = go m
371 res <- lift $ uncons m1
373 Just (h, t) -> step h (go t)
377foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
381 Nothing -> return Nothing
382 Just (h, t) -> fmap Just (go h t)
386 single a = return $ step a p
387 yieldk a r = fmap (step p) (go a r)
388 in foldStream defState yieldk single stp m1
390-- XXX replace the recursive "go" with explicit continuations.
391-- | Like 'foldx', but with a monadic step function.
392{-# INLINABLE foldlMx' #-}
393foldlMx' :: (IsStream t, Monad m)
394 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
395foldlMx' step begin done m = go begin m
398 let stop = acc >>= done
399 single a = acc >>= \b -> step b a >>= done
400 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
401 in foldStream defState yieldk single stop m1
403{-# INLINABLE fold #-}
404fold :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> m b
405fold (FL.Fold step begin done) m = do
408 FL.Partial fs -> go fs m
409 FL.Done fb -> return fb
414 single a = step acc a
416 FL.Partial s -> done s
417 FL.Done b1 -> return b1
418 yieldk a r = step acc a
420 FL.Partial s -> go s r
421 FL.Done b1 -> return b1
422 in foldStream defState yieldk single stop m1
424-- | Like 'foldl'' but with a monadic step function.
425{-# INLINE foldlM' #-}
426foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> m b
427foldlM' step begin = foldlMx' step begin return
429-- | Lazy left fold to a stream.
431foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
432foldlS step begin m = go begin m
434 go acc rest = mkStream $ \st yld sng stp ->
435 let run x = foldStream st yld sng stp x
437 single a = run $ step acc a
438 yieldk a r = run $ go (step acc a) r
439 in foldStream (adaptState st) yieldk single stop rest
441-- | Lazy left fold to an arbitrary transformer monad.
443foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
444 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
445foldlT step begin m = go begin m
448 res <- lift $ uncons m1
450 Just (h, t) -> go (step acc h) t
453------------------------------------------------------------------------------
455------------------------------------------------------------------------------
457-- XXX use foldrM to implement folds where possible
458-- XXX This (commented) definition of drain and mapM_ perform much better on
459-- some benchmarks but worse on others. Need to investigate why, may there is
460-- an optimization opportunity that we can exploit.
461-- drain = foldrM (\_ xs -> return () >> xs) (return ())
464-- > drain = foldl' (\_ _ -> ()) ()
465-- > drain = mapM_ (\_ -> return ())
467drain :: (Monad m, IsStream t) => t m a -> m ()
468drain = foldrM (\_ xs -> xs) (return ())
476 in foldStream defState yieldk single stop m1
480null :: (IsStream t, Monad m) => t m a -> m Bool
481-- null = foldrM (\_ _ -> return True) (return False)
483 let stop = return True
484 single _ = return False
485 yieldk _ _ = return False
486 in foldStream defState yieldk single stop m
489head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
490-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
492 let stop = return Nothing
493 single a = return (Just a)
494 yieldk a _ = return (Just a)
495 in foldStream defState yieldk single stop m
498tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
500 let stop = return Nothing
501 single _ = return $ Just nil
502 yieldk _ r = return $ Just r
503 in foldStream defState yieldk single stop m
505{-# INLINE headPartial #-}
506headPartial :: (IsStream t, Monad m) => t m a -> m a
507headPartial = foldrM (\x _ -> return x) (error "head of nil")
509{-# INLINE tailPartial #-}
510tailPartial :: IsStream t => t m a -> t m a
511tailPartial m = mkStream $ \st yld sng stp ->
512 let stop = error "tail of nil"
514 yieldk _ r = foldStream st yld sng stp r
515 in foldStream st yieldk single stop m
517-- | We can define cyclic structures using @let@:
519-- >>> let (a, b) = ([1, b], head a) in (a, b)
522-- The function @fix@ defined as:
524-- > fix f = let x = f x in x
526-- ensures that the argument of a function and its output refer to the same
527-- lazy value @x@ i.e. the same location in memory. Thus @x@ can be defined
528-- in terms of itself, creating structures with cyclic references.
530-- >>> import Data.Function (fix)
531-- >>> f ~(a, b) = ([1, b], head a)
535-- 'Control.Monad.mfix' is essentially the same as @fix@ but for monadic
538-- Using 'mfix' for streams we can construct a stream in which each element of
539-- the stream is defined in a cyclic fashion. The argument of the function
540-- being fixed represents the current element of the stream which is being
541-- returned by the stream monad. Thus, we can use the argument to construct
544-- In the following example, the argument @action@ of the function @f@
545-- represents the tuple @(x,y)@ returned by it in a given iteration. We define
546-- the first element of the tuple in terms of the second.
549-- import Streamly.Internal.Data.Stream.IsStream as Stream
550-- import System.IO.Unsafe (unsafeInterleaveIO)
553-- Stream.mapM_ print $ Stream.mfix f
558-- let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
559-- x <- Stream.fromListM [incr 1 action, incr 2 action]
560-- y <- Stream.fromList [4,5]
564-- Note: you cannot achieve this by just changing the order of the monad
565-- statements because that would change the order in which the stream elements
568-- Note that the function @f@ must be lazy in its argument, that's why we use
569-- 'unsafeInterleaveIO' on @action@ because IO monad is strict.
573mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
574mfix f = mkStream $ \st yld sng stp ->
575 let single a = foldStream st yld sng stp $ a `cons` ys
576 yieldk a _ = foldStream st yld sng stp $ a `cons` ys
577 in foldStream st yieldk single stp xs
581 -- fix the head element of the stream
582 xs = fix (f . headPartial)
584 -- now fix the tail recursively
585 ys = mfix (tailPartial . f)
588init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
594 Nothing -> return Nothing
595 Just (h, t) -> return . Just $ go h t
596 go p m1 = mkStream $ \_ yld sng stp ->
598 yieldk a x = yld p $ go a x
599 in foldStream defState yieldk single stp m1
602elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
606 let stop = return False
607 single a = return (a == e)
608 yieldk a r = if a == e then return True else go r
609 in foldStream defState yieldk single stop m1
611{-# INLINE notElem #-}
612notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
616 let stop = return True
617 single a = return (a /= e)
618 yieldk a r = if a == e then return False else go r
619 in foldStream defState yieldk single stop m1
622all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
626 let single a | p a = return True
627 | otherwise = return False
628 yieldk a r | p a = go r
629 | otherwise = return False
630 in foldStream defState yieldk single (return True) m1
633any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
637 let single a | p a = return True
638 | otherwise = return False
639 yieldk a r | p a = return True
641 in foldStream defState yieldk single (return False) m1
643-- | Extract the last element of the stream, if any.
645last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
646last = foldlx' (\_ y -> Just y) Nothing id
648{-# INLINE minimum #-}
649minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
650minimum m = go Nothing m
653 let stop = return Nothing
654 single a = return (Just a)
655 yieldk a r = go (Just a) r
656 in foldStream defState yieldk single stop m1
659 let stop = return (Just res)
662 then return (Just res)
668 in foldStream defState yieldk single stop m1
670{-# INLINE minimumBy #-}
672 :: (IsStream t, Monad m)
673 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
674minimumBy cmp m = go Nothing m
677 let stop = return Nothing
678 single a = return (Just a)
679 yieldk a r = go (Just a) r
680 in foldStream defState yieldk single stop m1
683 let stop = return (Just res)
684 single a = case cmp res a of
685 GT -> return (Just a)
686 _ -> return (Just res)
687 yieldk a r = case cmp res a of
690 in foldStream defState yieldk single stop m1
692{-# INLINE maximum #-}
693maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
694maximum m = go Nothing m
697 let stop = return Nothing
698 single a = return (Just a)
699 yieldk a r = go (Just a) r
700 in foldStream defState yieldk single stop m1
703 let stop = return (Just res)
707 else return (Just res)
712 in foldStream defState yieldk single stop m1
714{-# INLINE maximumBy #-}
715maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
716maximumBy cmp m = go Nothing m
719 let stop = return Nothing
720 single a = return (Just a)
721 yieldk a r = go (Just a) r
722 in foldStream defState yieldk single stop m1
725 let stop = return (Just res)
726 single a = case cmp res a of
727 GT -> return (Just res)
729 yieldk a r = case cmp res a of
730 GT -> go (Just res) r
732 in foldStream defState yieldk single stop m1
735(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
739 let single a | n == 0 = return $ Just a
740 | otherwise = return Nothing
741 yieldk a x | n < 0 = return Nothing
742 | n == 0 = return $ Just a
743 | otherwise = go (n - 1) x
744 in foldStream defState yieldk single (return Nothing) m1
747lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
751 let single (a, b) | a == e = return $ Just b
752 | otherwise = return Nothing
753 yieldk (a, b) x | a == e = return $ Just b
755 in foldStream defState yieldk single (return Nothing) m1
758findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
764 if b then return $ Just a else return Nothing
767 if b then return $ Just a else go x
768 in foldStream defState yieldk single (return Nothing) m1
771find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
772find p = findM (return . p)
774{-# INLINE findIndices #-}
775findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
778 go offset m1 = mkStream $ \st yld sng stp ->
779 let single a | p a = sng offset
781 yieldk a x | p a = yld offset $ go (offset + 1) x
782 | otherwise = foldStream (adaptState st) yld sng stp $
784 in foldStream (adaptState st) yieldk single stp m1
786------------------------------------------------------------------------------
788------------------------------------------------------------------------------
790-- | Apply a monadic action to each element of the stream and discard the
791-- output of the action.
793mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
798 single a = void (f a)
799 yieldk a r = f a >> go r
800 in foldStream defState yieldk single stop m1
802------------------------------------------------------------------------------
804------------------------------------------------------------------------------
806{-# INLINABLE toList #-}
807toList :: (IsStream t, Monad m) => t m a -> m [a]
810{-# INLINE toStreamK #-}
811toStreamK :: Stream m a -> Stream m a
814-- Based on suggestions by David Feuer and Pranay Sashank
816hoist :: (IsStream t, Monad m, Monad n)
817 => (forall x. m x -> n x) -> t m a -> t n a
819 mkStream $ \st yld sng stp ->
820 let single = return . sng
821 yieldk a s = return $ yld a (hoist f s)
823 state = adaptState st
824 in join . f $ foldStreamShared state yieldk single stop str
826-------------------------------------------------------------------------------
827-- Transformation by folding (Scans)
828-------------------------------------------------------------------------------
830{-# INLINE scanlx' #-}
831scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
832scanlx' step begin done m =
833 cons (done begin) $ go m begin
835 go m1 !acc = mkStream $ \st yld sng stp ->
836 let single a = sng (done $ step acc a)
839 in yld (done s) (go r s)
840 in foldStream (adaptState st) yieldk single stp m1
843scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
844scanl' step begin = scanlx' step begin id
846-------------------------------------------------------------------------------
848-------------------------------------------------------------------------------
851filter :: IsStream t => (a -> Bool) -> t m a -> t m a
854 go m1 = mkStream $ \st yld sng stp ->
855 let single a | p a = sng a
857 yieldk a r | p a = yld a (go r)
858 | otherwise = foldStream st yieldk single stp r
859 in foldStream st yieldk single stp m1
862take :: IsStream t => Int -> t m a -> t m a
865 go n1 m1 = mkStream $ \st yld sng stp ->
866 let yieldk a r = yld a (go (n1 - 1) r)
869 else foldStream st yieldk sng stp m1
871{-# INLINE takeWhile #-}
872takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
875 go m1 = mkStream $ \st yld sng stp ->
876 let single a | p a = sng a
878 yieldk a r | p a = yld a (go r)
880 in foldStream st yieldk single stp m1
883drop :: IsStream t => Int -> t m a -> t m a
884drop n m = fromStream $ unShare (go n (toStream m))
886 go n1 m1 = mkStream $ \st yld sng stp ->
888 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
889 -- Somehow "<=" check performs better than a ">"
891 then foldStreamShared st yld sng stp m1
892 else foldStreamShared st yieldk single stp m1
894{-# INLINE dropWhile #-}
895dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
898 go m1 = mkStream $ \st yld sng stp ->
899 let single a | p a = stp
901 yieldk a r | p a = foldStream st yieldk single stp r
902 | otherwise = yld a r
903 in foldStream st yieldk single stp m1
905-------------------------------------------------------------------------------
907-------------------------------------------------------------------------------
909-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
910-- other stream types to overload it.
911{-# INLINE sequence #-}
912sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
915 go m1 = mkStream $ \st yld sng stp ->
916 let single ma = ma >>= sng
917 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
918 in foldStream (adaptState st) yieldk single stp m1
920-------------------------------------------------------------------------------
922-------------------------------------------------------------------------------
924{-# INLINE intersperseM #-}
925intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
926intersperseM a m = prependingStart m
928 prependingStart m1 = mkStream $ \st yld sng stp ->
929 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
930 in foldStream st yieldk sng stp m1
931 go m2 = mkStream $ \st yld sng stp ->
932 let single i = foldStreamShared st yld sng stp $ a |: yield i
933 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
934 in foldStream st yieldk single stp m2
936{-# INLINE intersperse #-}
937intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
938intersperse a = intersperseM (return a)
940{-# INLINE insertBy #-}
941insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
942insertBy cmp x m = go m
944 go m1 = mkStream $ \st yld _ _ ->
945 let single a = case cmp x a of
946 GT -> yld a (yield x)
949 yieldk a r = case cmp x a of
951 _ -> yld x (a `cons` r)
952 in foldStream st yieldk single stop m1
954------------------------------------------------------------------------------
956------------------------------------------------------------------------------
958{-# INLINE deleteBy #-}
959deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
960deleteBy eq x m = go m
962 go m1 = mkStream $ \st yld sng stp ->
963 let single a = if eq x a then stp else sng a
964 yieldk a r = if eq x a
965 then foldStream st yld sng stp r
967 in foldStream st yieldk single stp m1
969------------------------------------------------------------------------------
971------------------------------------------------------------------------------
973{-# INLINE reverse #-}
974reverse :: IsStream t => t m a -> t m a
975reverse = foldlS (flip cons) nil
977-------------------------------------------------------------------------------
979-------------------------------------------------------------------------------
981{-# INLINE mapMaybe #-}
982mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
985 go m1 = mkStream $ \st yld sng stp ->
986 let single a = case f a of
989 yieldk a r = case f a of
990 Just b -> yld b $ go r
991 Nothing -> foldStream (adaptState st) yieldk single stp r
992 in foldStream (adaptState st) yieldk single stp m1
994------------------------------------------------------------------------------
996------------------------------------------------------------------------------
998-- XXX We can probably implement zipWith in terms of zipWithM
999-- | Zip two streams serially using a pure zipping function. The zipping
1000-- function is applied concurrently for concurrent streams.
1003{-# INLINABLE zipWith #-}
1005 (IsStream t, MonadAsync m) => (a -> b -> c) -> t m a -> t m b -> t m c
1008 go mx my = mkStream $ \st yld sng stp -> do
1010 let single2 b = sng (f a b)
1011 runIt x = foldStream st yld sng stp x
1012 yield2 b rb = runIt (return (f a b) `consM` go ra rb)
1013 in foldStream (adaptState st) yield2 single2 stp my
1014 let single1 a = merge a nil
1016 foldStream (adaptState st) yield1 single1 stp mx
1018-- | Zip two streams serially using a monadic zipping function. The zipping
1019-- function is applied concurrently for concurrent streams.
1022{-# INLINABLE zipWithM #-}
1024 (IsStream t, MonadAsync m) => (a -> b -> m c) -> t m a -> t m b -> t m c
1025zipWithM f m1 m2 = go m1 m2
1027 go mx my = mkStream $ \st yld sng stp -> do
1029 let runIt x = foldStream st yld sng stp x
1030 single2 b = f a b >>= sng
1031 yield2 b rb = runIt (f a b `consM` go ra rb)
1032 in foldStream (adaptState st) yield2 single2 stp my
1033 let single1 a = merge a nil
1035 foldStream (adaptState st) yield1 single1 stp mx
1037------------------------------------------------------------------------------
1039------------------------------------------------------------------------------
1041{-# INLINE mergeByM #-}
1043 :: (IsStream t, Monad m)
1044 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1047 go mx my = mkStream $ \st yld sng stp -> do
1048 let mergeWithY a ra =
1049 let stop2 = foldStream st yld sng stp mx
1053 GT -> yld b (go (a `cons` ra) nil)
1054 _ -> yld a (go ra (b `cons` nil))
1058 GT -> yld b (go (a `cons` ra) rb)
1059 _ -> yld a (go ra (b `cons` rb))
1060 in foldStream st yield2 single2 stop2 my
1061 let stopX = foldStream st yld sng stp my
1062 singleX a = mergeWithY a nil
1064 foldStream st yieldX singleX stopX mx
1066{-# INLINABLE mergeBy #-}
1068 :: (IsStream t, Monad m)
1069 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1070mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1072------------------------------------------------------------------------------
1073-- Transformation comprehensions
1074------------------------------------------------------------------------------
1077the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
1081 Nothing -> return Nothing
1082 Just (h, t) -> go h t
1085 let single a | h == a = return $ Just h
1086 | otherwise = return Nothing
1087 yieldk a r | h == a = go h r
1088 | otherwise = return Nothing
1089 in foldStream defState yieldk single (return $ Just h) m1
1091------------------------------------------------------------------------------
1092-- Alternative & MonadPlus
1093------------------------------------------------------------------------------
1095_alt :: Stream m a -> Stream m a -> Stream m a
1096_alt m1 m2 = mkStream $ \st yld sng stp ->
1097 let stop = foldStream st yld sng stp m2
1098 in foldStream st yld sng stop m1
1100------------------------------------------------------------------------------
1102------------------------------------------------------------------------------
1104{-# INLINABLE withLocal #-}
1105withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1107 mkStream $ \st yld sng stp ->
1108 let single = local f . sng
1109 yieldk a r = local f $ yld a (withLocal f r)
1110 in foldStream st yieldk single (local f stp) m
1112------------------------------------------------------------------------------
1114------------------------------------------------------------------------------
1117-- XXX handle and test cross thread state transfer
1120 => Stream m a -> (e -> Stream m a) -> Stream m a
1122 mkStream $ \_ stp sng yld ->
1123 let run x = unStream x Nothing stp sng yieldk
1124 handle r = r `catchError` \e -> run $ h e
1125 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