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)
175 -- ** Transformation comprehensions
178 -- * Semigroup Style Composition
187 , Streaming -- deprecated
192import Control.Monad.Trans (MonadTrans(lift))
193import Control.Monad (void, join)
194import Control.Monad.Reader.Class (MonadReader(..))
195import Data.Function (fix)
197 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
198 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
199 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
200 foldr1, (!!), replicate, reverse, concatMap, iterate)
201import qualified Prelude
203import Streamly.Internal.Data.SVar
204import Streamly.Internal.Data.Stream.StreamK.Type
206-------------------------------------------------------------------------------
208-------------------------------------------------------------------------------
211uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
213 let stop = return Nothing
214 single a = return (Just (a, nil))
215 yieldk a r = return (Just (a, r))
216 in foldStream defState yieldk single stop m
218-------------------------------------------------------------------------------
220-------------------------------------------------------------------------------
222{-# INLINE unfoldr #-}
223unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
224unfoldr next s0 = build $ \yld stp ->
227 Just (a, b) -> yld a (go b)
231{-# INLINE unfoldrM #-}
232unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
235 go s = sharedM $ \yld _ stp -> do
238 Just (a, b) -> yld a (go b)
242-- Generalization of concurrent streams/SVar via unfoldr.
244-- Unfold a value into monadic actions and then run the resulting monadic
245-- actions to generate a stream. Since the step of generating the monadic
246-- action and running them are decoupled we can run the monadic actions
247-- cooncurrently. For example, the seed could be a list of monadic actions or a
248-- pure stream of monadic actions.
250-- We can have different flavors of this depending on the stream type t. The
251-- concurrent version could be async or ahead etc. Depending on how we queue
252-- back the feedback portion b, it could be DFS or BFS style.
254unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
258-------------------------------------------------------------------------------
260-------------------------------------------------------------------------------
265{-# DEPRECATED once "Please use yieldM instead." #-}
267once :: (Monad m, IsStream t) => m a -> t m a
272-- repeatM = fix . cons
273-- repeatM = cycle1 . yield
276-- Generate an infinite stream by repeating a monadic value.
279repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
281 where go m = m |: go m
283-- Generate an infinite stream by repeating a pure value.
287repeat :: IsStream t => a -> t m a
288repeat a = let x = cons a x in x
290{-# INLINE replicateM #-}
291replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
294 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
296{-# INLINE replicate #-}
297replicate :: IsStream t => Int -> a -> t m a
300 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
302{-# INLINE fromIndicesM #-}
303fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
304fromIndicesM gen = go 0
306 go i = mkStream $ \st stp sng yld -> do
307 foldStreamShared st stp sng yld (gen i |: go (i + 1))
309{-# INLINE fromIndices #-}
310fromIndices :: IsStream t => (Int -> a) -> t m a
311fromIndices gen = go 0
313 go n = (gen n) `cons` go (n + 1)
315{-# INLINE iterate #-}
316iterate :: IsStream t => (a -> a) -> a -> t m a
317iterate step = fromStream . go
319 go s = cons s (go (step s))
321{-# INLINE iterateM #-}
322iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
325 go s = mkStream $ \st stp sng yld -> do
327 foldStreamShared st stp sng yld (return next |: go (step next))
329-------------------------------------------------------------------------------
331-------------------------------------------------------------------------------
335-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
338-- Construct a stream from a 'Foldable' containing pure values:
341{-# INLINE fromFoldable #-}
342fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
343fromFoldable = Prelude.foldr cons nil
345{-# INLINE fromList #-}
346fromList :: IsStream t => [a] -> t m a
347fromList = fromFoldable
349{-# INLINE fromStreamK #-}
350fromStreamK :: IsStream t => Stream m a -> t m a
351fromStreamK = fromStream
353-------------------------------------------------------------------------------
354-- Elimination by Folding
355-------------------------------------------------------------------------------
357-- | Lazy right associative fold.
359foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
360foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
362-- | Right associative fold to an arbitrary transformer monad.
364foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
365 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
366foldrT step final m = go m
369 res <- lift $ uncons m1
371 Just (h, t) -> step h (go t)
375foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
379 Nothing -> return Nothing
380 Just (h, t) -> fmap Just (go h t)
384 single a = return $ step a p
385 yieldk a r = fmap (step p) (go a r)
386 in foldStream defState yieldk single stp m1
388-- | Strict left fold with an extraction function. Like the standard strict
389-- left fold, but applies a user supplied extraction function (the third
390-- argument) to the folded value at the end. This is designed to work with the
391-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
393-- Note that the accumulator is always evaluated including the initial value.
394{-# INLINE foldlx' #-}
395foldlx' :: forall t m a b x. (IsStream t, Monad m)
396 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
397foldlx' step begin done m = get $ go m begin
402 -- XXX we are not strictly evaluating the accumulator here. Is this
404 let single = return . done
405 -- XXX this is foldSingleton. why foldStreamShared?
406 in foldStreamShared undefined undefined single undefined m1
408 -- Note, this can be implemented by making a recursive call to "go",
409 -- however that is more expensive because of unnecessary recursion
410 -- that cannot be tail call optimized. Unfolding recursion explicitly via
411 -- continuations is much more efficient.
412 go :: t m a -> x -> t m x
413 go m1 !acc = mkStream $ \_ yld sng _ ->
415 single a = sng $ step acc a
416 -- XXX this is foldNonEmptyStream
417 yieldk a r = foldStream defState yld sng undefined $
419 in foldStream defState yieldk single stop m1
421-- | Strict left associative fold.
423foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
424foldl' step begin = foldlx' step begin id
426-- XXX replace the recursive "go" with explicit continuations.
427-- | Like 'foldx', but with a monadic step function.
428{-# INLINABLE foldlMx' #-}
429foldlMx' :: (IsStream t, Monad m)
430 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
431foldlMx' step begin done m = go begin m
434 let stop = acc >>= done
435 single a = acc >>= \b -> step b a >>= done
436 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
437 in foldStream defState yieldk single stop m1
439-- | Like 'foldl'' but with a monadic step function.
440{-# INLINE foldlM' #-}
441foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
442foldlM' step begin = foldlMx' step (return begin) return
444-- | Lazy left fold to a stream.
446foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
447foldlS step begin m = go begin m
449 go acc rest = mkStream $ \st yld sng stp ->
450 let run x = foldStream st yld sng stp x
452 single a = run $ step acc a
453 yieldk a r = run $ go (step acc a) r
454 in foldStream (adaptState st) yieldk single stop rest
456-- | Lazy left fold to an arbitrary transformer monad.
458foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
459 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
460foldlT step begin m = go begin m
463 res <- lift $ uncons m1
465 Just (h, t) -> go (step acc h) t
468------------------------------------------------------------------------------
470------------------------------------------------------------------------------
472-- XXX use foldrM to implement folds where possible
473-- XXX This (commented) definition of drain and mapM_ perform much better on
474-- some benchmarks but worse on others. Need to investigate why, may there is
475-- an optimization opportunity that we can exploit.
476-- drain = foldrM (\_ xs -> return () >> xs) (return ())
479-- > drain = foldl' (\_ _ -> ()) ()
480-- > drain = mapM_ (\_ -> return ())
482drain :: (Monad m, IsStream t) => t m a -> m ()
483drain = foldrM (\_ xs -> xs) (return ())
491 in foldStream defState yieldk single stop m1
495null :: (IsStream t, Monad m) => t m a -> m Bool
496-- null = foldrM (\_ _ -> return True) (return False)
498 let stop = return True
499 single _ = return False
500 yieldk _ _ = return False
501 in foldStream defState yieldk single stop m
504head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
505-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
507 let stop = return Nothing
508 single a = return (Just a)
509 yieldk a _ = return (Just a)
510 in foldStream defState yieldk single stop m
513tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
515 let stop = return Nothing
516 single _ = return $ Just nil
517 yieldk _ r = return $ Just r
518 in foldStream defState yieldk single stop m
520{-# INLINE headPartial #-}
521headPartial :: (IsStream t, Monad m) => t m a -> m a
522headPartial = foldrM (\x _ -> return x) (error "head of nil")
524{-# INLINE tailPartial #-}
525tailPartial :: IsStream t => t m a -> t m a
526tailPartial m = mkStream $ \st yld sng stp ->
527 let stop = error "tail of nil"
529 yieldk _ r = foldStream st yld sng stp r
530 in foldStream st yieldk single stop m
532-- | Iterate a lazy function `f` of the shape `m a -> t m a` until it gets
533-- fully defined i.e. becomes independent of its argument action, then return
534-- the resulting value of the function (`t m a`).
536-- It can be used to construct a stream that uses a cyclic definition. For
540-- import Streamly.Internal.Prelude as S
541-- import System.IO.Unsafe (unsafeInterleaveIO)
544-- S.mapM_ print $ S.mfix $ \x -> do
545-- a <- S.fromList [1,2]
546-- b <- S.fromListM [return 3, unsafeInterleaveIO (fmap fst x)]
550-- Note that the function `f` must be lazy in its argument, that's why we use
551-- 'unsafeInterleaveIO' because IO monad is strict.
553mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
554mfix f = mkStream $ \st yld sng stp ->
555 let single a = foldStream st yld sng stp $ a `cons` ys
556 yieldk a _ = foldStream st yld sng stp $ a `cons` ys
557 in foldStream st yieldk single stp xs
558 where xs = fix (f . headPartial)
559 ys = mfix (tailPartial . f)
562init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
568 Nothing -> return Nothing
569 Just (h, t) -> return . Just $ go h t
570 go p m1 = mkStream $ \_ yld sng stp ->
572 yieldk a x = yld p $ go a x
573 in foldStream defState yieldk single stp m1
576elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
580 let stop = return False
581 single a = return (a == e)
582 yieldk a r = if a == e then return True else go r
583 in foldStream defState yieldk single stop m1
585{-# INLINE notElem #-}
586notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
590 let stop = return True
591 single a = return (a /= e)
592 yieldk a r = if a == e then return False else go r
593 in foldStream defState yieldk single stop m1
596all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
600 let single a | p a = return True
601 | otherwise = return False
602 yieldk a r | p a = go r
603 | otherwise = return False
604 in foldStream defState yieldk single (return True) m1
607any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
611 let single a | p a = return True
612 | otherwise = return False
613 yieldk a r | p a = return True
615 in foldStream defState yieldk single (return False) m1
617-- | Extract the last element of the stream, if any.
619last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
620last = foldlx' (\_ y -> Just y) Nothing id
622{-# INLINE minimum #-}
623minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
624minimum m = go Nothing m
627 let stop = return Nothing
628 single a = return (Just a)
629 yieldk a r = go (Just a) r
630 in foldStream defState yieldk single stop m1
633 let stop = return (Just res)
636 then return (Just res)
642 in foldStream defState yieldk single stop m1
644{-# INLINE minimumBy #-}
646 :: (IsStream t, Monad m)
647 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
648minimumBy cmp m = go Nothing m
651 let stop = return Nothing
652 single a = return (Just a)
653 yieldk a r = go (Just a) r
654 in foldStream defState yieldk single stop m1
657 let stop = return (Just res)
658 single a = case cmp res a of
659 GT -> return (Just a)
660 _ -> return (Just res)
661 yieldk a r = case cmp res a of
664 in foldStream defState yieldk single stop m1
666{-# INLINE maximum #-}
667maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
668maximum m = go Nothing m
671 let stop = return Nothing
672 single a = return (Just a)
673 yieldk a r = go (Just a) r
674 in foldStream defState yieldk single stop m1
677 let stop = return (Just res)
681 else return (Just res)
686 in foldStream defState yieldk single stop m1
688{-# INLINE maximumBy #-}
689maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
690maximumBy cmp m = go Nothing m
693 let stop = return Nothing
694 single a = return (Just a)
695 yieldk a r = go (Just a) r
696 in foldStream defState yieldk single stop m1
699 let stop = return (Just res)
700 single a = case cmp res a of
701 GT -> return (Just res)
703 yieldk a r = case cmp res a of
704 GT -> go (Just res) r
706 in foldStream defState yieldk single stop m1
709(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
713 let single a | n == 0 = return $ Just a
714 | otherwise = return Nothing
715 yieldk a x | n < 0 = return Nothing
716 | n == 0 = return $ Just a
717 | otherwise = go (n - 1) x
718 in foldStream defState yieldk single (return Nothing) m1
721lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
725 let single (a, b) | a == e = return $ Just b
726 | otherwise = return Nothing
727 yieldk (a, b) x | a == e = return $ Just b
729 in foldStream defState yieldk single (return Nothing) m1
732findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
738 if b then return $ Just a else return Nothing
741 if b then return $ Just a else go x
742 in foldStream defState yieldk single (return Nothing) m1
745find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
746find p = findM (return . p)
748{-# INLINE findIndices #-}
749findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
752 go offset m1 = mkStream $ \st yld sng stp ->
753 let single a | p a = sng offset
755 yieldk a x | p a = yld offset $ go (offset + 1) x
756 | otherwise = foldStream (adaptState st) yld sng stp $
758 in foldStream (adaptState st) yieldk single stp m1
760------------------------------------------------------------------------------
762------------------------------------------------------------------------------
764-- | Apply a monadic action to each element of the stream and discard the
765-- output of the action.
767mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
772 single a = void (f a)
773 yieldk a r = f a >> go r
774 in foldStream defState yieldk single stop m1
776------------------------------------------------------------------------------
778------------------------------------------------------------------------------
780{-# INLINABLE toList #-}
781toList :: (IsStream t, Monad m) => t m a -> m [a]
784{-# INLINE toStreamK #-}
785toStreamK :: Stream m a -> Stream m a
788-- Based on suggestions by David Feuer and Pranay Sashank
790hoist :: (IsStream t, Monad m, Monad n)
791 => (forall x. m x -> n x) -> t m a -> t n a
793 mkStream $ \st yld sng stp ->
794 let single = return . sng
795 yieldk a s = return $ yld a (hoist f s)
797 state = adaptState st
798 in join . f $ foldStreamShared state yieldk single stop str
800-------------------------------------------------------------------------------
801-- Transformation by folding (Scans)
802-------------------------------------------------------------------------------
804{-# INLINE scanlx' #-}
805scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
806scanlx' step begin done m =
807 cons (done begin) $ go m begin
809 go m1 !acc = mkStream $ \st yld sng stp ->
810 let single a = sng (done $ step acc a)
813 in yld (done s) (go r s)
814 in foldStream (adaptState st) yieldk single stp m1
817scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
818scanl' step begin = scanlx' step begin id
820-------------------------------------------------------------------------------
822-------------------------------------------------------------------------------
825filter :: IsStream t => (a -> Bool) -> t m a -> t m a
828 go m1 = mkStream $ \st yld sng stp ->
829 let single a | p a = sng a
831 yieldk a r | p a = yld a (go r)
832 | otherwise = foldStream st yieldk single stp r
833 in foldStream st yieldk single stp m1
836take :: IsStream t => Int -> t m a -> t m a
839 go n1 m1 = mkStream $ \st yld sng stp ->
840 let yieldk a r = yld a (go (n1 - 1) r)
843 else foldStream st yieldk sng stp m1
845{-# INLINE takeWhile #-}
846takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
849 go m1 = mkStream $ \st yld sng stp ->
850 let single a | p a = sng a
852 yieldk a r | p a = yld a (go r)
854 in foldStream st yieldk single stp m1
857drop :: IsStream t => Int -> t m a -> t m a
858drop n m = fromStream $ unShare (go n (toStream m))
860 go n1 m1 = mkStream $ \st yld sng stp ->
862 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
863 -- Somehow "<=" check performs better than a ">"
865 then foldStreamShared st yld sng stp m1
866 else foldStreamShared st yieldk single stp m1
868{-# INLINE dropWhile #-}
869dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
872 go m1 = mkStream $ \st yld sng stp ->
873 let single a | p a = stp
875 yieldk a r | p a = foldStream st yieldk single stp r
876 | otherwise = yld a r
877 in foldStream st yieldk single stp m1
879-------------------------------------------------------------------------------
881-------------------------------------------------------------------------------
883-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
884-- other stream types to overload it.
885{-# INLINE sequence #-}
886sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
889 go m1 = mkStream $ \st yld sng stp ->
890 let single ma = ma >>= sng
891 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
892 in foldStream (adaptState st) yieldk single stp m1
894-------------------------------------------------------------------------------
896-------------------------------------------------------------------------------
898{-# INLINE intersperseM #-}
899intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
900intersperseM a m = prependingStart m
902 prependingStart m1 = mkStream $ \st yld sng stp ->
903 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
904 in foldStream st yieldk sng stp m1
905 go m2 = mkStream $ \st yld sng stp ->
906 let single i = foldStreamShared st yld sng stp $ a |: yield i
907 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
908 in foldStream st yieldk single stp m2
910{-# INLINE intersperse #-}
911intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
912intersperse a = intersperseM (return a)
914{-# INLINE insertBy #-}
915insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
916insertBy cmp x m = go m
918 go m1 = mkStream $ \st yld _ _ ->
919 let single a = case cmp x a of
920 GT -> yld a (yield x)
923 yieldk a r = case cmp x a of
925 _ -> yld x (a `cons` r)
926 in foldStream st yieldk single stop m1
928------------------------------------------------------------------------------
930------------------------------------------------------------------------------
932{-# INLINE deleteBy #-}
933deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
934deleteBy eq x m = go m
936 go m1 = mkStream $ \st yld sng stp ->
937 let single a = if eq x a then stp else sng a
938 yieldk a r = if eq x a
939 then foldStream st yld sng stp r
941 in foldStream st yieldk single stp m1
943------------------------------------------------------------------------------
945------------------------------------------------------------------------------
947{-# INLINE reverse #-}
948reverse :: IsStream t => t m a -> t m a
949reverse = foldlS (flip cons) nil
951-------------------------------------------------------------------------------
953-------------------------------------------------------------------------------
955{-# INLINE mapMaybe #-}
956mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
959 go m1 = mkStream $ \st yld sng stp ->
960 let single a = case f a of
963 yieldk a r = case f a of
964 Just b -> yld b $ go r
965 Nothing -> foldStream (adaptState st) yieldk single stp r
966 in foldStream (adaptState st) yieldk single stp m1
968------------------------------------------------------------------------------
970------------------------------------------------------------------------------
972-- | Zip two streams serially using a pure zipping function.
975{-# INLINABLE zipWith #-}
976zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
979 go mx my = mkStream $ \st yld sng stp -> do
981 let single2 b = sng (f a b)
982 yield2 b rb = yld (f a b) (go ra rb)
983 in foldStream (adaptState st) yield2 single2 stp my
984 let single1 a = merge a nil
986 foldStream (adaptState st) yield1 single1 stp mx
988-- | Zip two streams serially using a monadic zipping function.
991{-# INLINABLE zipWithM #-}
992zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
993zipWithM f m1 m2 = go m1 m2
995 go mx my = mkStream $ \st yld sng stp -> do
997 let runIt x = foldStream st yld sng stp x
998 single2 b = f a b >>= sng
999 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
1000 in foldStream (adaptState st) yield2 single2 stp my
1001 let single1 a = merge a nil
1003 foldStream (adaptState st) yield1 single1 stp mx
1005------------------------------------------------------------------------------
1007------------------------------------------------------------------------------
1009{-# INLINE mergeByM #-}
1011 :: (IsStream t, Monad m)
1012 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1015 go mx my = mkStream $ \st yld sng stp -> do
1016 let mergeWithY a ra =
1017 let stop2 = foldStream st yld sng stp mx
1021 GT -> yld b (go (a `cons` ra) nil)
1022 _ -> yld a (go ra (b `cons` nil))
1026 GT -> yld b (go (a `cons` ra) rb)
1027 _ -> yld a (go ra (b `cons` rb))
1028 in foldStream st yield2 single2 stop2 my
1029 let stopX = foldStream st yld sng stp my
1030 singleX a = mergeWithY a nil
1032 foldStream st yieldX singleX stopX mx
1034{-# INLINABLE mergeBy #-}
1036 :: (IsStream t, Monad m)
1037 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1038mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1040------------------------------------------------------------------------------
1041-- Transformation comprehensions
1042------------------------------------------------------------------------------
1045the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
1049 Nothing -> return Nothing
1050 Just (h, t) -> go h t
1053 let single a | h == a = return $ Just h
1054 | otherwise = return Nothing
1055 yieldk a r | h == a = go h r
1056 | otherwise = return Nothing
1057 in foldStream defState yieldk single (return $ Just h) m1
1059------------------------------------------------------------------------------
1060-- Alternative & MonadPlus
1061------------------------------------------------------------------------------
1063_alt :: Stream m a -> Stream m a -> Stream m a
1064_alt m1 m2 = mkStream $ \st yld sng stp ->
1065 let stop = foldStream st yld sng stp m2
1066 in foldStream st yld sng stop m1
1068------------------------------------------------------------------------------
1070------------------------------------------------------------------------------
1072{-# INLINABLE withLocal #-}
1073withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1075 mkStream $ \st yld sng stp ->
1076 let single = local f . sng
1077 yieldk a r = local f $ yld a (withLocal f r)
1078 in foldStream st yieldk single (local f stp) m
1080------------------------------------------------------------------------------
1082------------------------------------------------------------------------------
1085-- XXX handle and test cross thread state transfer
1088 => Stream m a -> (e -> Stream m a) -> Stream m a
1090 mkStream $ \_ stp sng yld ->
1091 let run x = unStream x Nothing stp sng yieldk
1092 handle r = r `catchError` \e -> run $ h e
1093 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