1{-# LANGUAGE UndecidableInstances #-}
6-- Module : Streamly.Internal.Data.Stream.StreamK
7-- Copyright : (c) 2017 Harendra Kumar
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
92 -- ** Specialized Folds
122 -- ** By folding (scans)
170 -- ** Transformation comprehensions
173 -- * Semigroup Style Composition
182 , Streaming -- deprecated
187import Control.Monad.Trans.Class (MonadTrans(lift))
188import Control.Monad (void, join)
189import Control.Monad.Reader.Class (MonadReader(..))
190import Data.Function (fix)
192 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
193 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
194 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
195 foldr1, (!!), replicate, reverse, concatMap, iterate)
196import qualified Prelude
198import Streamly.Internal.Data.SVar
199import Streamly.Internal.Data.Stream.StreamK.Type
201-------------------------------------------------------------------------------
203-------------------------------------------------------------------------------
206uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
208 let stop = return Nothing
209 single a = return (Just (a, nil))
210 yieldk a r = return (Just (a, r))
211 in foldStream defState yieldk single stop m
213-------------------------------------------------------------------------------
215-------------------------------------------------------------------------------
217{-# INLINE unfoldr #-}
218unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
219unfoldr next s0 = build $ \yld stp ->
222 Just (a, b) -> yld a (go b)
226{-# INLINE unfoldrM #-}
227unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
230 go s = sharedM $ \yld _ stp -> do
233 Just (a, b) -> yld a (go b)
237-- Generalization of concurrent streams/SVar via unfoldr.
239-- Unfold a value into monadic actions and then run the resulting monadic
240-- actions to generate a stream. Since the step of generating the monadic
241-- action and running them are decoupled we can run the monadic actions
242-- cooncurrently. For example, the seed could be a list of monadic actions or a
243-- pure stream of monadic actions.
245-- We can have different flavors of this depending on the stream type t. The
246-- concurrent version could be async or ahead etc. Depending on how we queue
247-- back the feedback portion b, it could be DFS or BFS style.
249unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
253-------------------------------------------------------------------------------
255-------------------------------------------------------------------------------
260{-# DEPRECATED once "Please use yieldM instead." #-}
262once :: (Monad m, IsStream t) => m a -> t m a
267-- repeatM = fix . cons
268-- repeatM = cycle1 . yield
271-- Generate an infinite stream by repeating a monadic value.
274repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
276 where go m = m |: go m
278-- Generate an infinite stream by repeating a pure value.
282repeat :: IsStream t => a -> t m a
283repeat a = let x = cons a x in x
285{-# INLINE replicateM #-}
286replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
289 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
291{-# INLINE replicate #-}
292replicate :: IsStream t => Int -> a -> t m a
295 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
297{-# INLINE fromIndicesM #-}
298fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
299fromIndicesM gen = go 0
301 go i = mkStream $ \st stp sng yld -> do
302 foldStreamShared st stp sng yld (gen i |: go (i + 1))
304{-# INLINE fromIndices #-}
305fromIndices :: IsStream t => (Int -> a) -> t m a
306fromIndices gen = go 0
308 go n = (gen n) `cons` go (n + 1)
310{-# INLINE iterate #-}
311iterate :: IsStream t => (a -> a) -> a -> t m a
312iterate step = fromStream . go
314 go s = cons s (go (step s))
316{-# INLINE iterateM #-}
317iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
320 go s = mkStream $ \st stp sng yld -> do
322 foldStreamShared st stp sng yld (return next |: go (step next))
324-------------------------------------------------------------------------------
326-------------------------------------------------------------------------------
330-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
333-- Construct a stream from a 'Foldable' containing pure values:
336{-# INLINE fromFoldable #-}
337fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
338fromFoldable = Prelude.foldr cons nil
340{-# INLINE fromList #-}
341fromList :: IsStream t => [a] -> t m a
342fromList = fromFoldable
344{-# INLINE fromStreamK #-}
345fromStreamK :: IsStream t => Stream m a -> t m a
346fromStreamK = fromStream
348-------------------------------------------------------------------------------
349-- Elimination by Folding
350-------------------------------------------------------------------------------
352-- | Lazy right associative fold.
354foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
355foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
357-- | Right associative fold to an arbitrary transformer monad.
359foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
360 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
361foldrT step final m = go m
364 res <- lift $ uncons m1
366 Just (h, t) -> step h (go t)
370foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
374 Nothing -> return Nothing
375 Just (h, t) -> fmap Just (go h t)
379 single a = return $ step a p
380 yieldk a r = fmap (step p) (go a r)
381 in foldStream defState yieldk single stp m1
383-- | Strict left fold with an extraction function. Like the standard strict
384-- left fold, but applies a user supplied extraction function (the third
385-- argument) to the folded value at the end. This is designed to work with the
386-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
388-- Note that the accumulator is always evaluated including the initial value.
389{-# INLINE foldlx' #-}
390foldlx' :: forall t m a b x. (IsStream t, Monad m)
391 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
392foldlx' step begin done m = get $ go m begin
397 -- XXX we are not strictly evaluating the accumulator here. Is this
399 let single = return . done
400 -- XXX this is foldSingleton. why foldStreamShared?
401 in foldStreamShared undefined undefined single undefined m1
403 -- Note, this can be implemented by making a recursive call to "go",
404 -- however that is more expensive because of unnecessary recursion
405 -- that cannot be tail call optimized. Unfolding recursion explicitly via
406 -- continuations is much more efficient.
407 go :: t m a -> x -> t m x
408 go m1 !acc = mkStream $ \_ yld sng _ ->
410 single a = sng $ step acc a
411 -- XXX this is foldNonEmptyStream
412 yieldk a r = foldStream defState yld sng undefined $
414 in foldStream defState yieldk single stop m1
416-- | Strict left associative fold.
418foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
419foldl' step begin = foldlx' step begin id
421-- XXX replace the recursive "go" with explicit continuations.
422-- | Like 'foldx', but with a monadic step function.
423{-# INLINABLE foldlMx' #-}
424foldlMx' :: (IsStream t, Monad m)
425 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
426foldlMx' step begin done m = go begin m
429 let stop = acc >>= done
430 single a = acc >>= \b -> step b a >>= done
431 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
432 in foldStream defState yieldk single stop m1
434-- | Like 'foldl'' but with a monadic step function.
435{-# INLINE foldlM' #-}
436foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> m b
437foldlM' step begin = foldlMx' step begin return
439-- | Lazy left fold to a stream.
441foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
442foldlS step begin m = go begin m
444 go acc rest = mkStream $ \st yld sng stp ->
445 let run x = foldStream st yld sng stp x
447 single a = run $ step acc a
448 yieldk a r = run $ go (step acc a) r
449 in foldStream (adaptState st) yieldk single stop rest
451-- | Lazy left fold to an arbitrary transformer monad.
453foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
454 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
455foldlT step begin m = go begin m
458 res <- lift $ uncons m1
460 Just (h, t) -> go (step acc h) t
463------------------------------------------------------------------------------
465------------------------------------------------------------------------------
467-- XXX use foldrM to implement folds where possible
468-- XXX This (commented) definition of drain and mapM_ perform much better on
469-- some benchmarks but worse on others. Need to investigate why, may there is
470-- an optimization opportunity that we can exploit.
471-- drain = foldrM (\_ xs -> return () >> xs) (return ())
474-- > drain = foldl' (\_ _ -> ()) ()
475-- > drain = mapM_ (\_ -> return ())
477drain :: (Monad m, IsStream t) => t m a -> m ()
478drain = foldrM (\_ xs -> xs) (return ())
486 in foldStream defState yieldk single stop m1
490null :: (IsStream t, Monad m) => t m a -> m Bool
491-- null = foldrM (\_ _ -> return True) (return False)
493 let stop = return True
494 single _ = return False
495 yieldk _ _ = return False
496 in foldStream defState yieldk single stop m
499head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
500-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
502 let stop = return Nothing
503 single a = return (Just a)
504 yieldk a _ = return (Just a)
505 in foldStream defState yieldk single stop m
508tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
510 let stop = return Nothing
511 single _ = return $ Just nil
512 yieldk _ r = return $ Just r
513 in foldStream defState yieldk single stop m
515{-# INLINE headPartial #-}
516headPartial :: (IsStream t, Monad m) => t m a -> m a
517headPartial = foldrM (\x _ -> return x) (error "head of nil")
519{-# INLINE tailPartial #-}
520tailPartial :: IsStream t => t m a -> t m a
521tailPartial m = mkStream $ \st yld sng stp ->
522 let stop = error "tail of nil"
524 yieldk _ r = foldStream st yld sng stp r
525 in foldStream st yieldk single stop m
527-- | Iterate a lazy function `f` of the shape `m a -> t m a` until it gets
528-- fully defined i.e. becomes independent of its argument action, then return
529-- the resulting value of the function (`t m a`).
531-- It can be used to construct a stream that uses a cyclic definition. For
535-- import Streamly.Internal.Data.Stream.IsStream as S
536-- import System.IO.Unsafe (unsafeInterleaveIO)
539-- S.mapM_ print $ S.mfix $ \x -> do
540-- a <- S.fromList [1,2]
541-- b <- S.fromListM [return 3, unsafeInterleaveIO (fmap fst x)]
545-- Note that the function `f` must be lazy in its argument, that's why we use
546-- 'unsafeInterleaveIO' because IO monad is strict.
550mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
551mfix f = mkStream $ \st yld sng stp ->
552 let single a = foldStream st yld sng stp $ a `cons` ys
553 yieldk a _ = foldStream st yld sng stp $ a `cons` ys
554 in foldStream st yieldk single stp xs
555 where xs = fix (f . headPartial)
556 ys = mfix (tailPartial . f)
559init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
565 Nothing -> return Nothing
566 Just (h, t) -> return . Just $ go h t
567 go p m1 = mkStream $ \_ yld sng stp ->
569 yieldk a x = yld p $ go a x
570 in foldStream defState yieldk single stp m1
573elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
577 let stop = return False
578 single a = return (a == e)
579 yieldk a r = if a == e then return True else go r
580 in foldStream defState yieldk single stop m1
582{-# INLINE notElem #-}
583notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
587 let stop = return True
588 single a = return (a /= e)
589 yieldk a r = if a == e then return False else go r
590 in foldStream defState yieldk single stop m1
593all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
597 let single a | p a = return True
598 | otherwise = return False
599 yieldk a r | p a = go r
600 | otherwise = return False
601 in foldStream defState yieldk single (return True) m1
604any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
608 let single a | p a = return True
609 | otherwise = return False
610 yieldk a r | p a = return True
612 in foldStream defState yieldk single (return False) m1
614-- | Extract the last element of the stream, if any.
616last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
617last = foldlx' (\_ y -> Just y) Nothing id
619{-# INLINE minimum #-}
620minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
621minimum m = go Nothing m
624 let stop = return Nothing
625 single a = return (Just a)
626 yieldk a r = go (Just a) r
627 in foldStream defState yieldk single stop m1
630 let stop = return (Just res)
633 then return (Just res)
639 in foldStream defState yieldk single stop m1
641{-# INLINE minimumBy #-}
643 :: (IsStream t, Monad m)
644 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
645minimumBy cmp m = go Nothing m
648 let stop = return Nothing
649 single a = return (Just a)
650 yieldk a r = go (Just a) r
651 in foldStream defState yieldk single stop m1
654 let stop = return (Just res)
655 single a = case cmp res a of
656 GT -> return (Just a)
657 _ -> return (Just res)
658 yieldk a r = case cmp res a of
661 in foldStream defState yieldk single stop m1
663{-# INLINE maximum #-}
664maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
665maximum m = go Nothing m
668 let stop = return Nothing
669 single a = return (Just a)
670 yieldk a r = go (Just a) r
671 in foldStream defState yieldk single stop m1
674 let stop = return (Just res)
678 else return (Just res)
683 in foldStream defState yieldk single stop m1
685{-# INLINE maximumBy #-}
686maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
687maximumBy cmp m = go Nothing m
690 let stop = return Nothing
691 single a = return (Just a)
692 yieldk a r = go (Just a) r
693 in foldStream defState yieldk single stop m1
696 let stop = return (Just res)
697 single a = case cmp res a of
698 GT -> return (Just res)
700 yieldk a r = case cmp res a of
701 GT -> go (Just res) r
703 in foldStream defState yieldk single stop m1
706(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
710 let single a | n == 0 = return $ Just a
711 | otherwise = return Nothing
712 yieldk a x | n < 0 = return Nothing
713 | n == 0 = return $ Just a
714 | otherwise = go (n - 1) x
715 in foldStream defState yieldk single (return Nothing) m1
718lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
722 let single (a, b) | a == e = return $ Just b
723 | otherwise = return Nothing
724 yieldk (a, b) x | a == e = return $ Just b
726 in foldStream defState yieldk single (return Nothing) m1
729findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
735 if b then return $ Just a else return Nothing
738 if b then return $ Just a else go x
739 in foldStream defState yieldk single (return Nothing) m1
742find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
743find p = findM (return . p)
745{-# INLINE findIndices #-}
746findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
749 go offset m1 = mkStream $ \st yld sng stp ->
750 let single a | p a = sng offset
752 yieldk a x | p a = yld offset $ go (offset + 1) x
753 | otherwise = foldStream (adaptState st) yld sng stp $
755 in foldStream (adaptState st) yieldk single stp m1
757------------------------------------------------------------------------------
759------------------------------------------------------------------------------
761-- | Apply a monadic action to each element of the stream and discard the
762-- output of the action.
764mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
769 single a = void (f a)
770 yieldk a r = f a >> go r
771 in foldStream defState yieldk single stop m1
773------------------------------------------------------------------------------
775------------------------------------------------------------------------------
777{-# INLINABLE toList #-}
778toList :: (IsStream t, Monad m) => t m a -> m [a]
781{-# INLINE toStreamK #-}
782toStreamK :: Stream m a -> Stream m a
785-- Based on suggestions by David Feuer and Pranay Sashank
787hoist :: (IsStream t, Monad m, Monad n)
788 => (forall x. m x -> n x) -> t m a -> t n a
790 mkStream $ \st yld sng stp ->
791 let single = return . sng
792 yieldk a s = return $ yld a (hoist f s)
794 state = adaptState st
795 in join . f $ foldStreamShared state yieldk single stop str
797-------------------------------------------------------------------------------
798-- Transformation by folding (Scans)
799-------------------------------------------------------------------------------
801{-# INLINE scanlx' #-}
802scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
803scanlx' step begin done m =
804 cons (done begin) $ go m begin
806 go m1 !acc = mkStream $ \st yld sng stp ->
807 let single a = sng (done $ step acc a)
810 in yld (done s) (go r s)
811 in foldStream (adaptState st) yieldk single stp m1
814scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
815scanl' step begin = scanlx' step begin id
817-------------------------------------------------------------------------------
819-------------------------------------------------------------------------------
822filter :: IsStream t => (a -> Bool) -> t m a -> t m a
825 go m1 = mkStream $ \st yld sng stp ->
826 let single a | p a = sng a
828 yieldk a r | p a = yld a (go r)
829 | otherwise = foldStream st yieldk single stp r
830 in foldStream st yieldk single stp m1
833take :: IsStream t => Int -> t m a -> t m a
836 go n1 m1 = mkStream $ \st yld sng stp ->
837 let yieldk a r = yld a (go (n1 - 1) r)
840 else foldStream st yieldk sng stp m1
842{-# INLINE takeWhile #-}
843takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
846 go m1 = mkStream $ \st yld sng stp ->
847 let single a | p a = sng a
849 yieldk a r | p a = yld a (go r)
851 in foldStream st yieldk single stp m1
854drop :: IsStream t => Int -> t m a -> t m a
855drop n m = fromStream $ unShare (go n (toStream m))
857 go n1 m1 = mkStream $ \st yld sng stp ->
859 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
860 -- Somehow "<=" check performs better than a ">"
862 then foldStreamShared st yld sng stp m1
863 else foldStreamShared st yieldk single stp m1
865{-# INLINE dropWhile #-}
866dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
869 go m1 = mkStream $ \st yld sng stp ->
870 let single a | p a = stp
872 yieldk a r | p a = foldStream st yieldk single stp r
873 | otherwise = yld a r
874 in foldStream st yieldk single stp m1
876-------------------------------------------------------------------------------
878-------------------------------------------------------------------------------
880-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
881-- other stream types to overload it.
882{-# INLINE sequence #-}
883sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
886 go m1 = mkStream $ \st yld sng stp ->
887 let single ma = ma >>= sng
888 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
889 in foldStream (adaptState st) yieldk single stp m1
891-------------------------------------------------------------------------------
893-------------------------------------------------------------------------------
895{-# INLINE intersperseM #-}
896intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
897intersperseM a m = prependingStart m
899 prependingStart m1 = mkStream $ \st yld sng stp ->
900 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
901 in foldStream st yieldk sng stp m1
902 go m2 = mkStream $ \st yld sng stp ->
903 let single i = foldStreamShared st yld sng stp $ a |: yield i
904 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
905 in foldStream st yieldk single stp m2
907{-# INLINE intersperse #-}
908intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
909intersperse a = intersperseM (return a)
911{-# INLINE insertBy #-}
912insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
913insertBy cmp x m = go m
915 go m1 = mkStream $ \st yld _ _ ->
916 let single a = case cmp x a of
917 GT -> yld a (yield x)
920 yieldk a r = case cmp x a of
922 _ -> yld x (a `cons` r)
923 in foldStream st yieldk single stop m1
925------------------------------------------------------------------------------
927------------------------------------------------------------------------------
929{-# INLINE deleteBy #-}
930deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
931deleteBy eq x m = go m
933 go m1 = mkStream $ \st yld sng stp ->
934 let single a = if eq x a then stp else sng a
935 yieldk a r = if eq x a
936 then foldStream st yld sng stp r
938 in foldStream st yieldk single stp m1
940------------------------------------------------------------------------------
942------------------------------------------------------------------------------
944{-# INLINE reverse #-}
945reverse :: IsStream t => t m a -> t m a
946reverse = foldlS (flip cons) nil
948-------------------------------------------------------------------------------
950-------------------------------------------------------------------------------
952{-# INLINE mapMaybe #-}
953mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
956 go m1 = mkStream $ \st yld sng stp ->
957 let single a = case f a of
960 yieldk a r = case f a of
961 Just b -> yld b $ go r
962 Nothing -> foldStream (adaptState st) yieldk single stp r
963 in foldStream (adaptState st) yieldk single stp m1
965------------------------------------------------------------------------------
967------------------------------------------------------------------------------
969-- | Zip two streams serially using a pure zipping function.
972{-# INLINABLE zipWith #-}
973zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
976 go mx my = mkStream $ \st yld sng stp -> do
978 let single2 b = sng (f a b)
979 yield2 b rb = yld (f a b) (go ra rb)
980 in foldStream (adaptState st) yield2 single2 stp my
981 let single1 a = merge a nil
983 foldStream (adaptState st) yield1 single1 stp mx
985-- | Zip two streams serially using a monadic zipping function.
988{-# INLINABLE zipWithM #-}
989zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
990zipWithM f m1 m2 = go m1 m2
992 go mx my = mkStream $ \st yld sng stp -> do
994 let runIt x = foldStream st yld sng stp x
995 single2 b = f a b >>= sng
996 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
997 in foldStream (adaptState st) yield2 single2 stp my
998 let single1 a = merge a nil
1000 foldStream (adaptState st) yield1 single1 stp mx
1002------------------------------------------------------------------------------
1004------------------------------------------------------------------------------
1006{-# INLINE mergeByM #-}
1008 :: (IsStream t, Monad m)
1009 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1012 go mx my = mkStream $ \st yld sng stp -> do
1013 let mergeWithY a ra =
1014 let stop2 = foldStream st yld sng stp mx
1018 GT -> yld b (go (a `cons` ra) nil)
1019 _ -> yld a (go ra (b `cons` nil))
1023 GT -> yld b (go (a `cons` ra) rb)
1024 _ -> yld a (go ra (b `cons` rb))
1025 in foldStream st yield2 single2 stop2 my
1026 let stopX = foldStream st yld sng stp my
1027 singleX a = mergeWithY a nil
1029 foldStream st yieldX singleX stopX mx
1031{-# INLINABLE mergeBy #-}
1033 :: (IsStream t, Monad m)
1034 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1035mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1037------------------------------------------------------------------------------
1038-- Transformation comprehensions
1039------------------------------------------------------------------------------
1042the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
1046 Nothing -> return Nothing
1047 Just (h, t) -> go h t
1050 let single a | h == a = return $ Just h
1051 | otherwise = return Nothing
1052 yieldk a r | h == a = go h r
1053 | otherwise = return Nothing
1054 in foldStream defState yieldk single (return $ Just h) m1
1056------------------------------------------------------------------------------
1057-- Alternative & MonadPlus
1058------------------------------------------------------------------------------
1060_alt :: Stream m a -> Stream m a -> Stream m a
1061_alt m1 m2 = mkStream $ \st yld sng stp ->
1062 let stop = foldStream st yld sng stp m2
1063 in foldStream st yld sng stop m1
1065------------------------------------------------------------------------------
1067------------------------------------------------------------------------------
1069{-# INLINABLE withLocal #-}
1070withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1072 mkStream $ \st yld sng stp ->
1073 let single = local f . sng
1074 yieldk a r = local f $ yld a (withLocal f r)
1075 in foldStream st yieldk single (local f stp) m
1077------------------------------------------------------------------------------
1079------------------------------------------------------------------------------
1082-- XXX handle and test cross thread state transfer
1085 => Stream m a -> (e -> Stream m a) -> Stream m a
1087 mkStream $ \_ stp sng yld ->
1088 let run x = unStream x Nothing stp sng yieldk
1089 handle r = r `catchError` \e -> run $ h e
1090 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