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
51 -- * Transformation Primitives
62 -- ** Specialized Generation
101 -- ** Specialized Folds
131 -- ** By folding (scans)
179 -- ** Transformation comprehensions
182 -- * Semigroup Style Composition
191 , Streaming -- deprecated
196import Control.Monad.Trans.Class (MonadTrans(lift))
197import Control.Monad (void, join)
198import Control.Monad.Reader.Class (MonadReader(..))
199import Data.Function (fix)
201 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
202 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
203 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
204 foldr1, (!!), replicate, reverse, concatMap, iterate)
205import qualified Prelude
207import Streamly.Internal.Data.SVar
208import 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-------------------------------------------------------------------------------
269{-# DEPRECATED once "Please use yieldM instead." #-}
271once :: (Monad m, IsStream t) => m a -> t m a
276-- repeatM = fix . cons
277-- repeatM = cycle1 . yield
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
321iterate step = fromStream . go
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-- | Strict left fold with an extraction function. Like the standard strict
393-- left fold, but applies a user supplied extraction function (the third
394-- argument) to the folded value at the end. This is designed to work with the
395-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
397-- Note that the accumulator is always evaluated including the initial value.
398{-# INLINE foldlx' #-}
399foldlx' :: forall t m a b x. (IsStream t, Monad m)
400 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
401foldlx' step begin done m = get $ go m begin
406 -- XXX we are not strictly evaluating the accumulator here. Is this
408 let single = return . done
409 -- XXX this is foldSingleton. why foldStreamShared?
410 in foldStreamShared undefined undefined single undefined m1
412 -- Note, this can be implemented by making a recursive call to "go",
413 -- however that is more expensive because of unnecessary recursion
414 -- that cannot be tail call optimized. Unfolding recursion explicitly via
415 -- continuations is much more efficient.
416 go :: t m a -> x -> t m x
417 go m1 !acc = mkStream $ \_ yld sng _ ->
419 single a = sng $ step acc a
420 -- XXX this is foldNonEmptyStream
421 yieldk a r = foldStream defState yld sng undefined $
423 in foldStream defState yieldk single stop m1
425-- | Strict left associative fold.
427foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
428foldl' step begin = foldlx' step begin id
430-- XXX replace the recursive "go" with explicit continuations.
431-- | Like 'foldx', but with a monadic step function.
432{-# INLINABLE foldlMx' #-}
433foldlMx' :: (IsStream t, Monad m)
434 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
435foldlMx' step begin done m = go begin m
438 let stop = acc >>= done
439 single a = acc >>= \b -> step b a >>= done
440 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
441 in foldStream defState yieldk single stop m1
443-- | Like 'foldl'' but with a monadic step function.
444{-# INLINE foldlM' #-}
445foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
446foldlM' step begin = foldlMx' step (return begin) return
448-- | Lazy left fold to a stream.
450foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
451foldlS step begin m = go begin m
453 go acc rest = mkStream $ \st yld sng stp ->
454 let run x = foldStream st yld sng stp x
456 single a = run $ step acc a
457 yieldk a r = run $ go (step acc a) r
458 in foldStream (adaptState st) yieldk single stop rest
460-- | Lazy left fold to an arbitrary transformer monad.
462foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
463 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
464foldlT step begin m = go begin m
467 res <- lift $ uncons m1
469 Just (h, t) -> go (step acc h) t
472------------------------------------------------------------------------------
474------------------------------------------------------------------------------
476-- XXX use foldrM to implement folds where possible
477-- XXX This (commented) definition of drain and mapM_ perform much better on
478-- some benchmarks but worse on others. Need to investigate why, may there is
479-- an optimization opportunity that we can exploit.
480-- drain = foldrM (\_ xs -> return () >> xs) (return ())
483-- > drain = foldl' (\_ _ -> ()) ()
484-- > drain = mapM_ (\_ -> return ())
486drain :: (Monad m, IsStream t) => t m a -> m ()
487drain = foldrM (\_ xs -> xs) (return ())
495 in foldStream defState yieldk single stop m1
499null :: (IsStream t, Monad m) => t m a -> m Bool
500-- null = foldrM (\_ _ -> return True) (return False)
502 let stop = return True
503 single _ = return False
504 yieldk _ _ = return False
505 in foldStream defState yieldk single stop m
508head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
509-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
511 let stop = return Nothing
512 single a = return (Just a)
513 yieldk a _ = return (Just a)
514 in foldStream defState yieldk single stop m
517tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
519 let stop = return Nothing
520 single _ = return $ Just nil
521 yieldk _ r = return $ Just r
522 in foldStream defState yieldk single stop m
524{-# INLINE headPartial #-}
525headPartial :: (IsStream t, Monad m) => t m a -> m a
526headPartial = foldrM (\x _ -> return x) (error "head of nil")
528{-# INLINE tailPartial #-}
529tailPartial :: IsStream t => t m a -> t m a
530tailPartial m = mkStream $ \st yld sng stp ->
531 let stop = error "tail of nil"
533 yieldk _ r = foldStream st yld sng stp r
534 in foldStream st yieldk single stop m
536-- | Iterate a lazy function `f` of the shape `m a -> t m a` until it gets
537-- fully defined i.e. becomes independent of its argument action, then return
538-- the resulting value of the function (`t m a`).
540-- It can be used to construct a stream that uses a cyclic definition. For
544-- import Streamly.Internal.Prelude as S
545-- import System.IO.Unsafe (unsafeInterleaveIO)
548-- S.mapM_ print $ S.mfix $ \x -> do
549-- a <- S.fromList [1,2]
550-- b <- S.fromListM [return 3, unsafeInterleaveIO (fmap fst x)]
554-- Note that the function `f` must be lazy in its argument, that's why we use
555-- 'unsafeInterleaveIO' because IO monad is strict.
559mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
560mfix f = mkStream $ \st yld sng stp ->
561 let single a = foldStream st yld sng stp $ a `cons` ys
562 yieldk a _ = foldStream st yld sng stp $ a `cons` ys
563 in foldStream st yieldk single stp xs
564 where xs = fix (f . headPartial)
565 ys = mfix (tailPartial . f)
568init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
574 Nothing -> return Nothing
575 Just (h, t) -> return . Just $ go h t
576 go p m1 = mkStream $ \_ yld sng stp ->
578 yieldk a x = yld p $ go a x
579 in foldStream defState yieldk single stp m1
582elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
586 let stop = return False
587 single a = return (a == e)
588 yieldk a r = if a == e then return True else go r
589 in foldStream defState yieldk single stop m1
591{-# INLINE notElem #-}
592notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
596 let stop = return True
597 single a = return (a /= e)
598 yieldk a r = if a == e then return False else go r
599 in foldStream defState yieldk single stop m1
602all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
606 let single a | p a = return True
607 | otherwise = return False
608 yieldk a r | p a = go r
609 | otherwise = return False
610 in foldStream defState yieldk single (return True) m1
613any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
617 let single a | p a = return True
618 | otherwise = return False
619 yieldk a r | p a = return True
621 in foldStream defState yieldk single (return False) m1
623-- | Extract the last element of the stream, if any.
625last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
626last = foldlx' (\_ y -> Just y) Nothing id
628{-# INLINE minimum #-}
629minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
630minimum m = go Nothing m
633 let stop = return Nothing
634 single a = return (Just a)
635 yieldk a r = go (Just a) r
636 in foldStream defState yieldk single stop m1
639 let stop = return (Just res)
642 then return (Just res)
648 in foldStream defState yieldk single stop m1
650{-# INLINE minimumBy #-}
652 :: (IsStream t, Monad m)
653 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
654minimumBy cmp m = go Nothing m
657 let stop = return Nothing
658 single a = return (Just a)
659 yieldk a r = go (Just a) r
660 in foldStream defState yieldk single stop m1
663 let stop = return (Just res)
664 single a = case cmp res a of
665 GT -> return (Just a)
666 _ -> return (Just res)
667 yieldk a r = case cmp res a of
670 in foldStream defState yieldk single stop m1
672{-# INLINE maximum #-}
673maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
674maximum 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)
687 else return (Just res)
692 in foldStream defState yieldk single stop m1
694{-# INLINE maximumBy #-}
695maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
696maximumBy cmp 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)
706 single a = case cmp res a of
707 GT -> return (Just res)
709 yieldk a r = case cmp res a of
710 GT -> go (Just res) r
712 in foldStream defState yieldk single stop m1
715(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
719 let single a | n == 0 = return $ Just a
720 | otherwise = return Nothing
721 yieldk a x | n < 0 = return Nothing
722 | n == 0 = return $ Just a
723 | otherwise = go (n - 1) x
724 in foldStream defState yieldk single (return Nothing) m1
727lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
731 let single (a, b) | a == e = return $ Just b
732 | otherwise = return Nothing
733 yieldk (a, b) x | a == e = return $ Just b
735 in foldStream defState yieldk single (return Nothing) m1
738findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
744 if b then return $ Just a else return Nothing
747 if b then return $ Just a else go x
748 in foldStream defState yieldk single (return Nothing) m1
751find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
752find p = findM (return . p)
754{-# INLINE findIndices #-}
755findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
758 go offset m1 = mkStream $ \st yld sng stp ->
759 let single a | p a = sng offset
761 yieldk a x | p a = yld offset $ go (offset + 1) x
762 | otherwise = foldStream (adaptState st) yld sng stp $
764 in foldStream (adaptState st) yieldk single stp m1
766------------------------------------------------------------------------------
768------------------------------------------------------------------------------
770-- | Apply a monadic action to each element of the stream and discard the
771-- output of the action.
773mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
778 single a = void (f a)
779 yieldk a r = f a >> go r
780 in foldStream defState yieldk single stop m1
782------------------------------------------------------------------------------
784------------------------------------------------------------------------------
786{-# INLINABLE toList #-}
787toList :: (IsStream t, Monad m) => t m a -> m [a]
790{-# INLINE toStreamK #-}
791toStreamK :: Stream m a -> Stream m a
794-- Based on suggestions by David Feuer and Pranay Sashank
796hoist :: (IsStream t, Monad m, Monad n)
797 => (forall x. m x -> n x) -> t m a -> t n a
799 mkStream $ \st yld sng stp ->
800 let single = return . sng
801 yieldk a s = return $ yld a (hoist f s)
803 state = adaptState st
804 in join . f $ foldStreamShared state yieldk single stop str
806-------------------------------------------------------------------------------
807-- Transformation by folding (Scans)
808-------------------------------------------------------------------------------
810{-# INLINE scanlx' #-}
811scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
812scanlx' step begin done m =
813 cons (done begin) $ go m begin
815 go m1 !acc = mkStream $ \st yld sng stp ->
816 let single a = sng (done $ step acc a)
819 in yld (done s) (go r s)
820 in foldStream (adaptState st) yieldk single stp m1
823scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
824scanl' step begin = scanlx' step begin id
826-------------------------------------------------------------------------------
828-------------------------------------------------------------------------------
831filter :: IsStream t => (a -> Bool) -> t m a -> t m a
834 go m1 = mkStream $ \st yld sng stp ->
835 let single a | p a = sng a
837 yieldk a r | p a = yld a (go r)
838 | otherwise = foldStream st yieldk single stp r
839 in foldStream st yieldk single stp m1
842take :: IsStream t => Int -> t m a -> t m a
845 go n1 m1 = mkStream $ \st yld sng stp ->
846 let yieldk a r = yld a (go (n1 - 1) r)
849 else foldStream st yieldk sng stp m1
851{-# INLINE takeWhile #-}
852takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
855 go m1 = mkStream $ \st yld sng stp ->
856 let single a | p a = sng a
858 yieldk a r | p a = yld a (go r)
860 in foldStream st yieldk single stp m1
863drop :: IsStream t => Int -> t m a -> t m a
864drop n m = fromStream $ unShare (go n (toStream m))
866 go n1 m1 = mkStream $ \st yld sng stp ->
868 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
869 -- Somehow "<=" check performs better than a ">"
871 then foldStreamShared st yld sng stp m1
872 else foldStreamShared st yieldk single stp m1
874{-# INLINE dropWhile #-}
875dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
878 go m1 = mkStream $ \st yld sng stp ->
879 let single a | p a = stp
881 yieldk a r | p a = foldStream st yieldk single stp r
882 | otherwise = yld a r
883 in foldStream st yieldk single stp m1
885-------------------------------------------------------------------------------
887-------------------------------------------------------------------------------
889-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
890-- other stream types to overload it.
891{-# INLINE sequence #-}
892sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
895 go m1 = mkStream $ \st yld sng stp ->
896 let single ma = ma >>= sng
897 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
898 in foldStream (adaptState st) yieldk single stp m1
900-------------------------------------------------------------------------------
902-------------------------------------------------------------------------------
904{-# INLINE intersperseM #-}
905intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
906intersperseM a m = prependingStart m
908 prependingStart m1 = mkStream $ \st yld sng stp ->
909 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
910 in foldStream st yieldk sng stp m1
911 go m2 = mkStream $ \st yld sng stp ->
912 let single i = foldStreamShared st yld sng stp $ a |: yield i
913 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
914 in foldStream st yieldk single stp m2
916{-# INLINE intersperse #-}
917intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
918intersperse a = intersperseM (return a)
920{-# INLINE insertBy #-}
921insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
922insertBy cmp x m = go m
924 go m1 = mkStream $ \st yld _ _ ->
925 let single a = case cmp x a of
926 GT -> yld a (yield x)
929 yieldk a r = case cmp x a of
931 _ -> yld x (a `cons` r)
932 in foldStream st yieldk single stop m1
934------------------------------------------------------------------------------
936------------------------------------------------------------------------------
938{-# INLINE deleteBy #-}
939deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
940deleteBy eq x m = go m
942 go m1 = mkStream $ \st yld sng stp ->
943 let single a = if eq x a then stp else sng a
944 yieldk a r = if eq x a
945 then foldStream st yld sng stp r
947 in foldStream st yieldk single stp m1
949------------------------------------------------------------------------------
951------------------------------------------------------------------------------
953{-# INLINE reverse #-}
954reverse :: IsStream t => t m a -> t m a
955reverse = foldlS (flip cons) nil
957-------------------------------------------------------------------------------
959-------------------------------------------------------------------------------
961{-# INLINE mapMaybe #-}
962mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
965 go m1 = mkStream $ \st yld sng stp ->
966 let single a = case f a of
969 yieldk a r = case f a of
970 Just b -> yld b $ go r
971 Nothing -> foldStream (adaptState st) yieldk single stp r
972 in foldStream (adaptState st) yieldk single stp m1
974------------------------------------------------------------------------------
976------------------------------------------------------------------------------
978-- | Zip two streams serially using a pure zipping function.
981{-# INLINABLE zipWith #-}
982zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
985 go mx my = mkStream $ \st yld sng stp -> do
987 let single2 b = sng (f a b)
988 yield2 b rb = yld (f a b) (go ra rb)
989 in foldStream (adaptState st) yield2 single2 stp my
990 let single1 a = merge a nil
992 foldStream (adaptState st) yield1 single1 stp mx
994-- | Zip two streams serially using a monadic zipping function.
997{-# INLINABLE zipWithM #-}
998zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
999zipWithM f m1 m2 = go m1 m2
1001 go mx my = mkStream $ \st yld sng stp -> do
1003 let runIt x = foldStream st yld sng stp x
1004 single2 b = f a b >>= sng
1005 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
1006 in foldStream (adaptState st) yield2 single2 stp my
1007 let single1 a = merge a nil
1009 foldStream (adaptState st) yield1 single1 stp mx
1011------------------------------------------------------------------------------
1013------------------------------------------------------------------------------
1015{-# INLINE mergeByM #-}
1017 :: (IsStream t, Monad m)
1018 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1021 go mx my = mkStream $ \st yld sng stp -> do
1022 let mergeWithY a ra =
1023 let stop2 = foldStream st yld sng stp mx
1027 GT -> yld b (go (a `cons` ra) nil)
1028 _ -> yld a (go ra (b `cons` nil))
1032 GT -> yld b (go (a `cons` ra) rb)
1033 _ -> yld a (go ra (b `cons` rb))
1034 in foldStream st yield2 single2 stop2 my
1035 let stopX = foldStream st yld sng stp my
1036 singleX a = mergeWithY a nil
1038 foldStream st yieldX singleX stopX mx
1040{-# INLINABLE mergeBy #-}
1042 :: (IsStream t, Monad m)
1043 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1044mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1046------------------------------------------------------------------------------
1047-- Transformation comprehensions
1048------------------------------------------------------------------------------
1051the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
1055 Nothing -> return Nothing
1056 Just (h, t) -> go h t
1059 let single a | h == a = return $ Just h
1060 | otherwise = return Nothing
1061 yieldk a r | h == a = go h r
1062 | otherwise = return Nothing
1063 in foldStream defState yieldk single (return $ Just h) m1
1065------------------------------------------------------------------------------
1066-- Alternative & MonadPlus
1067------------------------------------------------------------------------------
1069_alt :: Stream m a -> Stream m a -> Stream m a
1070_alt m1 m2 = mkStream $ \st yld sng stp ->
1071 let stop = foldStream st yld sng stp m2
1072 in foldStream st yld sng stop m1
1074------------------------------------------------------------------------------
1076------------------------------------------------------------------------------
1078{-# INLINABLE withLocal #-}
1079withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1081 mkStream $ \st yld sng stp ->
1082 let single = local f . sng
1083 yieldk a r = local f $ yld a (withLocal f r)
1084 in foldStream st yieldk single (local f stp) m
1086------------------------------------------------------------------------------
1088------------------------------------------------------------------------------
1091-- XXX handle and test cross thread state transfer
1094 => Stream m a -> (e -> Stream m a) -> Stream m a
1096 mkStream $ \_ stp sng yld ->
1097 let run x = unStream x Nothing stp sng yieldk
1098 handle r = r `catchError` \e -> run $ h e
1099 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