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)
193import Streamly.Internal.Control.Concurrent (MonadAsync)
194import Streamly.Internal.Data.SVar.Type (adaptState, defState)
196import qualified Prelude
197import qualified Streamly.Internal.Data.Fold.Type as FL
200 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
201 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
202 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
203 foldr1, (!!), replicate, reverse, concatMap, iterate)
205import Streamly.Internal.Data.Stream.StreamK.Type
210-------------------------------------------------------------------------------
212-------------------------------------------------------------------------------
215uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
217 let stop = return Nothing
218 single a = return (Just (a, nil))
219 yieldk a r = return (Just (a, r))
220 in foldStream defState yieldk single stop m
222-------------------------------------------------------------------------------
224-------------------------------------------------------------------------------
226{-# INLINE unfoldr #-}
227unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
228unfoldr next s0 = build $ \yld stp ->
231 Just (a, b) -> yld a (go b)
235{-# INLINE unfoldrM #-}
236unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
239 go s = sharedM $ \yld _ stp -> do
242 Just (a, b) -> yld a (go b)
246-- Generalization of concurrent streams/SVar via unfoldr.
248-- Unfold a value into monadic actions and then run the resulting monadic
249-- actions to generate a stream. Since the step of generating the monadic
250-- action and running them are decoupled we can run the monadic actions
251-- cooncurrently. For example, the seed could be a list of monadic actions or a
252-- pure stream of monadic actions.
254-- We can have different flavors of this depending on the stream type t. The
255-- concurrent version could be async or ahead etc. Depending on how we queue
256-- back the feedback portion b, it could be DFS or BFS style.
258unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
262-------------------------------------------------------------------------------
264-------------------------------------------------------------------------------
266-- | Same as fromEffect
269{-# DEPRECATED once "Please use fromEffect instead." #-}
271once :: (Monad m, IsStream t) => m a -> t m a
276-- repeatM = fix . cons
277-- repeatM = cycle1 . fromPure
280-- Generate an infinite stream by repeating a monadic value.
283repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
285 where go m = m |: go m
287-- Generate an infinite stream by repeating a pure value.
291repeat :: IsStream t => a -> t m a
292repeat a = let x = cons a x in x
294{-# INLINE replicateM #-}
295replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
298 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
300{-# INLINE replicate #-}
301replicate :: IsStream t => Int -> a -> t m a
304 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
306{-# INLINE fromIndicesM #-}
307fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
308fromIndicesM gen = go 0
310 go i = mkStream $ \st stp sng yld -> do
311 foldStreamShared st stp sng yld (gen i |: go (i + 1))
313{-# INLINE fromIndices #-}
314fromIndices :: IsStream t => (Int -> a) -> t m a
315fromIndices gen = go 0
317 go n = (gen n) `cons` go (n + 1)
319{-# INLINE iterate #-}
320iterate :: IsStream t => (a -> a) -> a -> t m a
323 go !s = cons s (go (step s))
325{-# INLINE iterateM #-}
326iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
329 go s = mkStream $ \st stp sng yld -> do
331 foldStreamShared st stp sng yld (return next |: go (step next))
333-------------------------------------------------------------------------------
335-------------------------------------------------------------------------------
339-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
342-- Construct a stream from a 'Foldable' containing pure values:
345{-# INLINE fromFoldable #-}
346fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
347fromFoldable = Prelude.foldr cons nil
349{-# INLINE fromList #-}
350fromList :: IsStream t => [a] -> t m a
351fromList = fromFoldable
353{-# INLINE fromStreamK #-}
354fromStreamK :: IsStream t => Stream m a -> t m a
355fromStreamK = fromStream
357-------------------------------------------------------------------------------
358-- Elimination by Folding
359-------------------------------------------------------------------------------
361-- | Lazy right associative fold.
363foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
364foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
366-- | Right associative fold to an arbitrary transformer monad.
368foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
369 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
370foldrT step final m = go m
373 res <- lift $ uncons m1
375 Just (h, t) -> step h (go t)
379foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
383 Nothing -> return Nothing
384 Just (h, t) -> fmap Just (go h t)
388 single a = return $ step a p
389 yieldk a r = fmap (step p) (go a r)
390 in foldStream defState yieldk single stp m1
392-- XXX replace the recursive "go" with explicit continuations.
393-- | Like 'foldx', but with a monadic step function.
394{-# INLINABLE foldlMx' #-}
395foldlMx' :: (IsStream t, Monad m)
396 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
397foldlMx' step begin done m = go begin m
400 let stop = acc >>= done
401 single a = acc >>= \b -> step b a >>= done
402 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
403 in foldStream defState yieldk single stop m1
405{-# INLINABLE fold #-}
406fold :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> m b
407fold (FL.Fold step begin done) m = do
410 FL.Partial fs -> go fs m
411 FL.Done fb -> return fb
416 single a = step acc a
418 FL.Partial s -> done s
419 FL.Done b1 -> return b1
420 yieldk a r = step acc a
422 FL.Partial s -> go s r
423 FL.Done b1 -> return b1
424 in foldStream defState yieldk single stop m1
426-- | Like 'foldl'' but with a monadic step function.
427{-# INLINE foldlM' #-}
428foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> m b
429foldlM' step begin = foldlMx' step begin return
431-- | Lazy left fold to a stream.
433foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
434foldlS step begin m = go begin m
436 go acc rest = mkStream $ \st yld sng stp ->
437 let run x = foldStream st yld sng stp x
439 single a = run $ step acc a
440 yieldk a r = run $ go (step acc a) r
441 in foldStream (adaptState st) yieldk single stop rest
443-- | Lazy left fold to an arbitrary transformer monad.
445foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
446 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
447foldlT step begin m = go begin m
450 res <- lift $ uncons m1
452 Just (h, t) -> go (step acc h) t
455------------------------------------------------------------------------------
457------------------------------------------------------------------------------
459-- XXX use foldrM to implement folds where possible
460-- XXX This (commented) definition of drain and mapM_ perform much better on
461-- some benchmarks but worse on others. Need to investigate why, may there is
462-- an optimization opportunity that we can exploit.
463-- drain = foldrM (\_ xs -> return () >> xs) (return ())
466-- > drain = foldl' (\_ _ -> ()) ()
467-- > drain = mapM_ (\_ -> return ())
469drain :: (Monad m, IsStream t) => t m a -> m ()
470drain = foldrM (\_ xs -> xs) (return ())
478 in foldStream defState yieldk single stop m1
482null :: (IsStream t, Monad m) => t m a -> m Bool
483-- null = foldrM (\_ _ -> return True) (return False)
485 let stop = return True
486 single _ = return False
487 yieldk _ _ = return False
488 in foldStream defState yieldk single stop m
491head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
492-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
494 let stop = return Nothing
495 single a = return (Just a)
496 yieldk a _ = return (Just a)
497 in foldStream defState yieldk single stop m
500tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
502 let stop = return Nothing
503 single _ = return $ Just nil
504 yieldk _ r = return $ Just r
505 in foldStream defState yieldk single stop m
507{-# INLINE headPartial #-}
508headPartial :: (IsStream t, Monad m) => t m a -> m a
509headPartial = foldrM (\x _ -> return x) (error "head of nil")
511{-# INLINE tailPartial #-}
512tailPartial :: IsStream t => t m a -> t m a
513tailPartial m = mkStream $ \st yld sng stp ->
514 let stop = error "tail of nil"
516 yieldk _ r = foldStream st yld sng stp r
517 in foldStream st yieldk single stop m
519-- | We can define cyclic structures using @let@:
521-- >>> let (a, b) = ([1, b], head a) in (a, b)
524-- The function @fix@ defined as:
526-- > fix f = let x = f x in x
528-- ensures that the argument of a function and its output refer to the same
529-- lazy value @x@ i.e. the same location in memory. Thus @x@ can be defined
530-- in terms of itself, creating structures with cyclic references.
532-- >>> import Data.Function (fix)
533-- >>> f ~(a, b) = ([1, b], head a)
537-- 'Control.Monad.mfix' is essentially the same as @fix@ but for monadic
540-- Using 'mfix' for streams we can construct a stream in which each element of
541-- the stream is defined in a cyclic fashion. The argument of the function
542-- being fixed represents the current element of the stream which is being
543-- returned by the stream monad. Thus, we can use the argument to construct
546-- In the following example, the argument @action@ of the function @f@
547-- represents the tuple @(x,y)@ returned by it in a given iteration. We define
548-- the first element of the tuple in terms of the second.
551-- import Streamly.Internal.Data.Stream.IsStream as Stream
552-- import System.IO.Unsafe (unsafeInterleaveIO)
555-- Stream.mapM_ print $ Stream.mfix f
560-- let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
561-- x <- Stream.fromListM [incr 1 action, incr 2 action]
562-- y <- Stream.fromList [4,5]
566-- Note: you cannot achieve this by just changing the order of the monad
567-- statements because that would change the order in which the stream elements
570-- Note that the function @f@ must be lazy in its argument, that's why we use
571-- 'unsafeInterleaveIO' on @action@ because IO monad is strict.
575mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
576mfix f = mkStream $ \st yld sng stp ->
577 let single a = foldStream st yld sng stp $ a `cons` ys
578 yieldk a _ = foldStream st yld sng stp $ a `cons` ys
579 in foldStream st yieldk single stp xs
583 -- fix the head element of the stream
584 xs = fix (f . headPartial)
586 -- now fix the tail recursively
587 ys = mfix (tailPartial . f)
590init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
596 Nothing -> return Nothing
597 Just (h, t) -> return . Just $ go h t
598 go p m1 = mkStream $ \_ yld sng stp ->
600 yieldk a x = yld p $ go a x
601 in foldStream defState yieldk single stp m1
604elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
608 let stop = return False
609 single a = return (a == e)
610 yieldk a r = if a == e then return True else go r
611 in foldStream defState yieldk single stop m1
613{-# INLINE notElem #-}
614notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
618 let stop = return True
619 single a = return (a /= e)
620 yieldk a r = if a == e then return False else go r
621 in foldStream defState yieldk single stop m1
624all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
628 let single a | p a = return True
629 | otherwise = return False
630 yieldk a r | p a = go r
631 | otherwise = return False
632 in foldStream defState yieldk single (return True) m1
635any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
639 let single a | p a = return True
640 | otherwise = return False
641 yieldk a r | p a = return True
643 in foldStream defState yieldk single (return False) m1
645-- | Extract the last element of the stream, if any.
647last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
648last = foldlx' (\_ y -> Just y) Nothing id
650{-# INLINE minimum #-}
651minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
652minimum m = go Nothing m
655 let stop = return Nothing
656 single a = return (Just a)
657 yieldk a r = go (Just a) r
658 in foldStream defState yieldk single stop m1
661 let stop = return (Just res)
664 then return (Just res)
670 in foldStream defState yieldk single stop m1
672{-# INLINE minimumBy #-}
674 :: (IsStream t, Monad m)
675 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
676minimumBy cmp m = go Nothing m
679 let stop = return Nothing
680 single a = return (Just a)
681 yieldk a r = go (Just a) r
682 in foldStream defState yieldk single stop m1
685 let stop = return (Just res)
686 single a = case cmp res a of
687 GT -> return (Just a)
688 _ -> return (Just res)
689 yieldk a r = case cmp res a of
692 in foldStream defState yieldk single stop m1
694{-# INLINE maximum #-}
695maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
696maximum m = go Nothing m
699 let stop = return Nothing
700 single a = return (Just a)
701 yieldk a r = go (Just a) r
702 in foldStream defState yieldk single stop m1
705 let stop = return (Just res)
709 else return (Just res)
714 in foldStream defState yieldk single stop m1
716{-# INLINE maximumBy #-}
717maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
718maximumBy cmp m = go Nothing m
721 let stop = return Nothing
722 single a = return (Just a)
723 yieldk a r = go (Just a) r
724 in foldStream defState yieldk single stop m1
727 let stop = return (Just res)
728 single a = case cmp res a of
729 GT -> return (Just res)
731 yieldk a r = case cmp res a of
732 GT -> go (Just res) r
734 in foldStream defState yieldk single stop m1
737(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
741 let single a | n == 0 = return $ Just a
742 | otherwise = return Nothing
743 yieldk a x | n < 0 = return Nothing
744 | n == 0 = return $ Just a
745 | otherwise = go (n - 1) x
746 in foldStream defState yieldk single (return Nothing) m1
749lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
753 let single (a, b) | a == e = return $ Just b
754 | otherwise = return Nothing
755 yieldk (a, b) x | a == e = return $ Just b
757 in foldStream defState yieldk single (return Nothing) m1
760findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
766 if b then return $ Just a else return Nothing
769 if b then return $ Just a else go x
770 in foldStream defState yieldk single (return Nothing) m1
773find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
774find p = findM (return . p)
776{-# INLINE findIndices #-}
777findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
780 go offset m1 = mkStream $ \st yld sng stp ->
781 let single a | p a = sng offset
783 yieldk a x | p a = yld offset $ go (offset + 1) x
784 | otherwise = foldStream (adaptState st) yld sng stp $
786 in foldStream (adaptState st) yieldk single stp m1
788------------------------------------------------------------------------------
790------------------------------------------------------------------------------
792-- | Apply a monadic action to each element of the stream and discard the
793-- output of the action.
795mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
800 single a = void (f a)
801 yieldk a r = f a >> go r
802 in foldStream defState yieldk single stop m1
804------------------------------------------------------------------------------
806------------------------------------------------------------------------------
808{-# INLINABLE toList #-}
809toList :: (IsStream t, Monad m) => t m a -> m [a]
812{-# INLINE toStreamK #-}
813toStreamK :: Stream m a -> Stream m a
816-- Based on suggestions by David Feuer and Pranay Sashank
818hoist :: (IsStream t, Monad m, Monad n)
819 => (forall x. m x -> n x) -> t m a -> t n a
821 mkStream $ \st yld sng stp ->
822 let single = return . sng
823 yieldk a s = return $ yld a (hoist f s)
825 state = adaptState st
826 in join . f $ foldStreamShared state yieldk single stop str
828-------------------------------------------------------------------------------
829-- Transformation by folding (Scans)
830-------------------------------------------------------------------------------
832{-# INLINE scanlx' #-}
833scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
834scanlx' step begin done m =
835 cons (done begin) $ go m begin
837 go m1 !acc = mkStream $ \st yld sng stp ->
838 let single a = sng (done $ step acc a)
841 in yld (done s) (go r s)
842 in foldStream (adaptState st) yieldk single stp m1
845scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
846scanl' step begin = scanlx' step begin id
848-------------------------------------------------------------------------------
850-------------------------------------------------------------------------------
853filter :: IsStream t => (a -> Bool) -> t m a -> t m a
856 go m1 = mkStream $ \st yld sng stp ->
857 let single a | p a = sng a
859 yieldk a r | p a = yld a (go r)
860 | otherwise = foldStream st yieldk single stp r
861 in foldStream st yieldk single stp m1
864take :: IsStream t => Int -> t m a -> t m a
867 go n1 m1 = mkStream $ \st yld sng stp ->
868 let yieldk a r = yld a (go (n1 - 1) r)
871 else foldStream st yieldk sng stp m1
873{-# INLINE takeWhile #-}
874takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
877 go m1 = mkStream $ \st yld sng stp ->
878 let single a | p a = sng a
880 yieldk a r | p a = yld a (go r)
882 in foldStream st yieldk single stp m1
885drop :: IsStream t => Int -> t m a -> t m a
886drop n m = fromStream $ unShare (go n (toStream m))
888 go n1 m1 = mkStream $ \st yld sng stp ->
890 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
891 -- Somehow "<=" check performs better than a ">"
893 then foldStreamShared st yld sng stp m1
894 else foldStreamShared st yieldk single stp m1
896{-# INLINE dropWhile #-}
897dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
900 go m1 = mkStream $ \st yld sng stp ->
901 let single a | p a = stp
903 yieldk a r | p a = foldStream st yieldk single stp r
904 | otherwise = yld a r
905 in foldStream st yieldk single stp m1
907-------------------------------------------------------------------------------
909-------------------------------------------------------------------------------
911-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
912-- other stream types to overload it.
913{-# INLINE sequence #-}
914sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
917 go m1 = mkStream $ \st yld sng stp ->
918 let single ma = ma >>= sng
919 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
920 in foldStream (adaptState st) yieldk single stp m1
922-------------------------------------------------------------------------------
924-------------------------------------------------------------------------------
926{-# INLINE intersperseM #-}
927intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
928intersperseM a m = prependingStart m
930 prependingStart m1 = mkStream $ \st yld sng stp ->
931 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
932 in foldStream st yieldk sng stp m1
933 go m2 = mkStream $ \st yld sng stp ->
934 let single i = foldStreamShared st yld sng stp $ a |: fromPure i
935 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
936 in foldStream st yieldk single stp m2
938{-# INLINE intersperse #-}
939intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
940intersperse a = intersperseM (return a)
942{-# INLINE insertBy #-}
943insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
944insertBy cmp x m = go m
946 go m1 = mkStream $ \st yld _ _ ->
947 let single a = case cmp x a of
948 GT -> yld a (fromPure x)
949 _ -> yld x (fromPure a)
951 yieldk a r = case cmp x a of
953 _ -> yld x (a `cons` r)
954 in foldStream st yieldk single stop m1
956------------------------------------------------------------------------------
958------------------------------------------------------------------------------
960{-# INLINE deleteBy #-}
961deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
962deleteBy eq x m = go m
964 go m1 = mkStream $ \st yld sng stp ->
965 let single a = if eq x a then stp else sng a
966 yieldk a r = if eq x a
967 then foldStream st yld sng stp r
969 in foldStream st yieldk single stp m1
971------------------------------------------------------------------------------
973------------------------------------------------------------------------------
975{-# INLINE reverse #-}
976reverse :: IsStream t => t m a -> t m a
977reverse = foldlS (flip cons) nil
979-------------------------------------------------------------------------------
981-------------------------------------------------------------------------------
983{-# INLINE mapMaybe #-}
984mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
987 go m1 = mkStream $ \st yld sng stp ->
988 let single a = case f a of
991 yieldk a r = case f a of
992 Just b -> yld b $ go r
993 Nothing -> foldStream (adaptState st) yieldk single stp r
994 in foldStream (adaptState st) yieldk single stp m1
996------------------------------------------------------------------------------
998------------------------------------------------------------------------------
1000-- | Zip two streams serially using a pure zipping function.
1003{-# INLINABLE zipWith #-}
1004zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
1007 go mx my = mkStream $ \st yld sng stp -> do
1009 let single2 b = sng (f a b)
1010 yield2 b rb = yld (f a b) (go ra rb)
1011 in foldStream (adaptState st) yield2 single2 stp my
1012 let single1 a = merge a nil
1014 foldStream (adaptState st) yield1 single1 stp mx
1016-- | Zip two streams serially using a monadic zipping function.
1019{-# INLINABLE zipWithM #-}
1020zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
1021zipWithM f m1 m2 = go m1 m2
1023 go mx my = mkStream $ \st yld sng stp -> do
1025 let runIt x = foldStream st yld sng stp x
1026 single2 b = f a b >>= sng
1027 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
1028 in foldStream (adaptState st) yield2 single2 stp my
1029 let single1 a = merge a nil
1031 foldStream (adaptState st) yield1 single1 stp mx
1033------------------------------------------------------------------------------
1035------------------------------------------------------------------------------
1037{-# INLINE mergeByM #-}
1039 :: (IsStream t, Monad m)
1040 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1043 go mx my = mkStream $ \st yld sng stp -> do
1044 let mergeWithY a ra =
1045 let stop2 = foldStream st yld sng stp mx
1049 GT -> yld b (go (a `cons` ra) nil)
1050 _ -> yld a (go ra (b `cons` nil))
1054 GT -> yld b (go (a `cons` ra) rb)
1055 _ -> yld a (go ra (b `cons` rb))
1056 in foldStream st yield2 single2 stop2 my
1057 let stopX = foldStream st yld sng stp my
1058 singleX a = mergeWithY a nil
1060 foldStream st yieldX singleX stopX mx
1062{-# INLINABLE mergeBy #-}
1064 :: (IsStream t, Monad m)
1065 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1066mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1068------------------------------------------------------------------------------
1069-- Transformation comprehensions
1070------------------------------------------------------------------------------
1073the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
1077 Nothing -> return Nothing
1078 Just (h, t) -> go h t
1081 let single a | h == a = return $ Just h
1082 | otherwise = return Nothing
1083 yieldk a r | h == a = go h r
1084 | otherwise = return Nothing
1085 in foldStream defState yieldk single (return $ Just h) m1
1087------------------------------------------------------------------------------
1088-- Alternative & MonadPlus
1089------------------------------------------------------------------------------
1091_alt :: Stream m a -> Stream m a -> Stream m a
1092_alt m1 m2 = mkStream $ \st yld sng stp ->
1093 let stop = foldStream st yld sng stp m2
1094 in foldStream st yld sng stop m1
1096------------------------------------------------------------------------------
1098------------------------------------------------------------------------------
1100{-# INLINABLE withLocal #-}
1101withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1103 mkStream $ \st yld sng stp ->
1104 let single = local f . sng
1105 yieldk a r = local f $ yld a (withLocal f r)
1106 in foldStream st yieldk single (local f stp) m
1108------------------------------------------------------------------------------
1110------------------------------------------------------------------------------
1113-- XXX handle and test cross thread state transfer
1116 => Stream m a -> (e -> Stream m a) -> Stream m a
1118 mkStream $ \_ stp sng yld ->
1119 let run x = unStream x Nothing stp sng yieldk
1120 handle r = r `catchError` \e -> run $ h e
1121 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