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
52 -- * Transformation Primitives
63 -- ** Specialized Generation
100 -- ** Specialized Folds
130 -- ** By folding (scans)
174 -- ** Transformation comprehensions
177 -- * Semigroup Style Composition
186 , Streaming -- deprecated
191import Control.Monad.Trans (MonadTrans(lift))
192import Control.Monad (void, join)
193import Control.Monad.Reader.Class (MonadReader(..))
194import Data.Function (fix)
196 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
197 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
198 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
199 foldr1, (!!), replicate, reverse, concatMap)
200import qualified Prelude
202import Streamly.Internal.Data.SVar
203import Streamly.Internal.Data.Stream.StreamK.Type
205-------------------------------------------------------------------------------
207-------------------------------------------------------------------------------
210uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
212 let stop = return Nothing
213 single a = return (Just (a, nil))
214 yieldk a r = return (Just (a, r))
215 in foldStream defState yieldk single stop m
217-------------------------------------------------------------------------------
219-------------------------------------------------------------------------------
221{-# INLINE unfoldr #-}
222unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
223unfoldr next s0 = build $ \yld stp ->
226 Just (a, b) -> yld a (go b)
230{-# INLINE unfoldrM #-}
231unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
234 go s = sharedM $ \yld _ stp -> do
237 Just (a, b) -> yld a (go b)
241-- Generalization of concurrent streams/SVar via unfoldr.
243-- Unfold a value into monadic actions and then run the resulting monadic
244-- actions to generate a stream. Since the step of generating the monadic
245-- action and running them are decoupled we can run the monadic actions
246-- cooncurrently. For example, the seed could be a list of monadic actions or a
247-- pure stream of monadic actions.
249-- We can have different flavors of this depending on the stream type t. The
250-- concurrent version could be async or ahead etc. Depending on how we queue
251-- back the feedback portion b, it could be DFS or BFS style.
253unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
257-------------------------------------------------------------------------------
259-------------------------------------------------------------------------------
264{-# DEPRECATED once "Please use yieldM instead." #-}
266once :: (Monad m, IsStream t) => m a -> t m a
271-- repeatM = fix . cons
272-- repeatM = cycle1 . yield
275-- Generate an infinite stream by repeating a monadic value.
278repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
280 where go m = m |: go m
282-- Generate an infinite stream by repeating a pure value.
286repeat :: IsStream t => a -> t m a
287repeat a = let x = cons a x in x
289{-# INLINE replicateM #-}
290replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
293 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
295{-# INLINE replicate #-}
296replicate :: IsStream t => Int -> a -> t m a
299 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
301{-# INLINE fromIndicesM #-}
302fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
303fromIndicesM gen = go 0
305 go i = mkStream $ \st stp sng yld -> do
306 foldStreamShared st stp sng yld (gen i |: go (i + 1))
308{-# INLINE fromIndices #-}
309fromIndices :: IsStream t => (Int -> a) -> t m a
310fromIndices gen = go 0
312 go n = (gen n) `cons` go (n + 1)
314-------------------------------------------------------------------------------
316-------------------------------------------------------------------------------
320-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
323-- Construct a stream from a 'Foldable' containing pure values:
326{-# INLINE fromFoldable #-}
327fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
328fromFoldable = Prelude.foldr cons nil
330{-# INLINE fromList #-}
331fromList :: IsStream t => [a] -> t m a
332fromList = fromFoldable
334{-# INLINE fromStreamK #-}
335fromStreamK :: IsStream t => Stream m a -> t m a
336fromStreamK = fromStream
338-------------------------------------------------------------------------------
339-- Elimination by Folding
340-------------------------------------------------------------------------------
342-- | Lazy right associative fold.
344foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
345foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
347-- | Right associative fold to an arbitrary transformer monad.
349foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
350 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
351foldrT step final m = go m
354 res <- lift $ uncons m1
356 Just (h, t) -> step h (go t)
360foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
364 Nothing -> return Nothing
365 Just (h, t) -> fmap Just (go h t)
369 single a = return $ step a p
370 yieldk a r = fmap (step p) (go a r)
371 in foldStream defState yieldk single stp m1
373-- | Strict left fold with an extraction function. Like the standard strict
374-- left fold, but applies a user supplied extraction function (the third
375-- argument) to the folded value at the end. This is designed to work with the
376-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
378-- Note that the accumulator is always evaluated including the initial value.
379{-# INLINE foldlx' #-}
380foldlx' :: forall t m a b x. (IsStream t, Monad m)
381 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
382foldlx' step begin done m = get $ go m begin
387 -- XXX we are not strictly evaluating the accumulator here. Is this
389 let single = return . done
390 -- XXX this is foldSingleton. why foldStreamShared?
391 in foldStreamShared undefined undefined single undefined m1
393 -- Note, this can be implemented by making a recursive call to "go",
394 -- however that is more expensive because of unnecessary recursion
395 -- that cannot be tail call optimized. Unfolding recursion explicitly via
396 -- continuations is much more efficient.
397 go :: t m a -> x -> t m x
398 go m1 !acc = mkStream $ \_ yld sng _ ->
400 single a = sng $ step acc a
401 -- XXX this is foldNonEmptyStream
402 yieldk a r = foldStream defState yld sng undefined $
404 in foldStream defState yieldk single stop m1
406-- | Strict left associative fold.
408foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
409foldl' step begin = foldlx' step begin id
411-- XXX replace the recursive "go" with explicit continuations.
412-- | Like 'foldx', but with a monadic step function.
413{-# INLINABLE foldlMx' #-}
414foldlMx' :: (IsStream t, Monad m)
415 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
416foldlMx' step begin done m = go begin m
419 let stop = acc >>= done
420 single a = acc >>= \b -> step b a >>= done
421 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
422 in foldStream defState yieldk single stop m1
424-- | Like 'foldl'' but with a monadic step function.
425{-# INLINE foldlM' #-}
426foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
427foldlM' step begin = foldlMx' step (return begin) return
429-- | Lazy left fold to a stream.
431foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
432foldlS step begin m = go begin m
434 go acc rest = mkStream $ \st yld sng stp ->
435 let run x = foldStream st yld sng stp x
437 single a = run $ step acc a
438 yieldk a r = run $ go (step acc a) r
439 in foldStream (adaptState st) yieldk single stop rest
441-- | Lazy left fold to an arbitrary transformer monad.
443foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
444 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
445foldlT step begin m = go begin m
448 res <- lift $ uncons m1
450 Just (h, t) -> go (step acc h) t
453------------------------------------------------------------------------------
455------------------------------------------------------------------------------
457-- XXX use foldrM to implement folds where possible
458-- XXX This (commented) definition of drain and mapM_ perform much better on
459-- some benchmarks but worse on others. Need to investigate why, may there is
460-- an optimization opportunity that we can exploit.
461-- drain = foldrM (\_ xs -> return () >> xs) (return ())
464-- > drain = foldl' (\_ _ -> ()) ()
465-- > drain = mapM_ (\_ -> return ())
467drain :: (Monad m, IsStream t) => t m a -> m ()
468drain = foldrM (\_ xs -> xs) (return ())
476 in foldStream defState yieldk single stop m1
480null :: (IsStream t, Monad m) => t m a -> m Bool
481-- null = foldrM (\_ _ -> return True) (return False)
483 let stop = return True
484 single _ = return False
485 yieldk _ _ = return False
486 in foldStream defState yieldk single stop m
489head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
490-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
492 let stop = return Nothing
493 single a = return (Just a)
494 yieldk a _ = return (Just a)
495 in foldStream defState yieldk single stop m
498tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
500 let stop = return Nothing
501 single _ = return $ Just nil
502 yieldk _ r = return $ Just r
503 in foldStream defState yieldk single stop m
505{-# INLINE headPartial #-}
506headPartial :: (IsStream t, Monad m) => t m a -> m a
507headPartial = foldrM (\x _ -> return x) (error "head of nil")
509{-# INLINE tailPartial #-}
510tailPartial :: IsStream t => t m a -> t m a
511tailPartial m = mkStream $ \st yld sng stp ->
512 let stop = error "tail of nil"
514 yieldk _ r = foldStream st yld sng stp r
515 in foldStream st yieldk single stop m
517-- | Iterate a lazy function `f` of the shape `m a -> t m a` until it gets
518-- fully defined i.e. becomes independent of its argument action, then return
519-- the resulting value of the function (`t m a`).
521-- It can be used to construct a stream that uses a cyclic definition. For
525-- import Streamly.Internal.Prelude as S
526-- import System.IO.Unsafe (unsafeInterleaveIO)
529-- S.mapM_ print $ S.mfix $ \x -> do
530-- a <- S.fromList [1,2]
531-- b <- S.fromListM [return 3, unsafeInterleaveIO (fmap fst x)]
535-- Note that the function `f` must be lazy in its argument, that's why we use
536-- 'unsafeInterleaveIO' because IO monad is strict.
538mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
539mfix f = mkStream $ \st yld sng stp ->
540 let single a = foldStream st yld sng stp $ a `cons` ys
541 yieldk a _ = foldStream st yld sng stp $ a `cons` ys
542 in foldStream st yieldk single stp xs
543 where xs = fix (f . headPartial)
544 ys = mfix (tailPartial . f)
547init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
553 Nothing -> return Nothing
554 Just (h, t) -> return . Just $ go h t
555 go p m1 = mkStream $ \_ yld sng stp ->
557 yieldk a x = yld p $ go a x
558 in foldStream defState yieldk single stp m1
561elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
565 let stop = return False
566 single a = return (a == e)
567 yieldk a r = if a == e then return True else go r
568 in foldStream defState yieldk single stop m1
570{-# INLINE notElem #-}
571notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
575 let stop = return True
576 single a = return (a /= e)
577 yieldk a r = if a == e then return False else go r
578 in foldStream defState yieldk single stop m1
581all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
585 let single a | p a = return True
586 | otherwise = return False
587 yieldk a r | p a = go r
588 | otherwise = return False
589 in foldStream defState yieldk single (return True) m1
592any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
596 let single a | p a = return True
597 | otherwise = return False
598 yieldk a r | p a = return True
600 in foldStream defState yieldk single (return False) m1
602-- | Extract the last element of the stream, if any.
604last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
605last = foldlx' (\_ y -> Just y) Nothing id
607{-# INLINE minimum #-}
608minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
609minimum m = go Nothing m
612 let stop = return Nothing
613 single a = return (Just a)
614 yieldk a r = go (Just a) r
615 in foldStream defState yieldk single stop m1
618 let stop = return (Just res)
621 then return (Just res)
627 in foldStream defState yieldk single stop m1
629{-# INLINE minimumBy #-}
631 :: (IsStream t, Monad m)
632 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
633minimumBy cmp m = go Nothing m
636 let stop = return Nothing
637 single a = return (Just a)
638 yieldk a r = go (Just a) r
639 in foldStream defState yieldk single stop m1
642 let stop = return (Just res)
643 single a = case cmp res a of
644 GT -> return (Just a)
645 _ -> return (Just res)
646 yieldk a r = case cmp res a of
649 in foldStream defState yieldk single stop m1
651{-# INLINE maximum #-}
652maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
653maximum m = go Nothing m
656 let stop = return Nothing
657 single a = return (Just a)
658 yieldk a r = go (Just a) r
659 in foldStream defState yieldk single stop m1
662 let stop = return (Just res)
666 else return (Just res)
671 in foldStream defState yieldk single stop m1
673{-# INLINE maximumBy #-}
674maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
675maximumBy cmp m = go Nothing m
678 let stop = return Nothing
679 single a = return (Just a)
680 yieldk a r = go (Just a) r
681 in foldStream defState yieldk single stop m1
684 let stop = return (Just res)
685 single a = case cmp res a of
686 GT -> return (Just res)
688 yieldk a r = case cmp res a of
689 GT -> go (Just res) r
691 in foldStream defState yieldk single stop m1
694(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
698 let single a | n == 0 = return $ Just a
699 | otherwise = return Nothing
700 yieldk a x | n < 0 = return Nothing
701 | n == 0 = return $ Just a
702 | otherwise = go (n - 1) x
703 in foldStream defState yieldk single (return Nothing) m1
706lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
710 let single (a, b) | a == e = return $ Just b
711 | otherwise = return Nothing
712 yieldk (a, b) x | a == e = return $ Just b
714 in foldStream defState yieldk single (return Nothing) m1
717findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
723 if b then return $ Just a else return Nothing
726 if b then return $ Just a else go x
727 in foldStream defState yieldk single (return Nothing) m1
730find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
731find p = findM (return . p)
733{-# INLINE findIndices #-}
734findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
737 go offset m1 = mkStream $ \st yld sng stp ->
738 let single a | p a = sng offset
740 yieldk a x | p a = yld offset $ go (offset + 1) x
741 | otherwise = foldStream (adaptState st) yld sng stp $
743 in foldStream (adaptState st) yieldk single stp m1
745------------------------------------------------------------------------------
747------------------------------------------------------------------------------
749-- | Apply a monadic action to each element of the stream and discard the
750-- output of the action.
752mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
757 single a = void (f a)
758 yieldk a r = f a >> go r
759 in foldStream defState yieldk single stop m1
761------------------------------------------------------------------------------
763------------------------------------------------------------------------------
765{-# INLINABLE toList #-}
766toList :: (IsStream t, Monad m) => t m a -> m [a]
769{-# INLINE toStreamK #-}
770toStreamK :: Stream m a -> Stream m a
773-- Based on suggestions by David Feuer and Pranay Sashank
775hoist :: (IsStream t, Monad m, Monad n)
776 => (forall x. m x -> n x) -> t m a -> t n a
778 mkStream $ \st yld sng stp ->
779 let single = return . sng
780 yieldk a s = return $ yld a (hoist f s)
782 state = adaptState st
783 in join . f $ foldStreamShared state yieldk single stop str
785-------------------------------------------------------------------------------
786-- Transformation by folding (Scans)
787-------------------------------------------------------------------------------
789{-# INLINE scanlx' #-}
790scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
791scanlx' step begin done m =
792 cons (done begin) $ go m begin
794 go m1 !acc = mkStream $ \st yld sng stp ->
795 let single a = sng (done $ step acc a)
798 in yld (done s) (go r s)
799 in foldStream (adaptState st) yieldk single stp m1
802scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
803scanl' step begin = scanlx' step begin id
805-------------------------------------------------------------------------------
807-------------------------------------------------------------------------------
810filter :: IsStream t => (a -> Bool) -> t m a -> t m a
813 go m1 = mkStream $ \st yld sng stp ->
814 let single a | p a = sng a
816 yieldk a r | p a = yld a (go r)
817 | otherwise = foldStream st yieldk single stp r
818 in foldStream st yieldk single stp m1
821take :: IsStream t => Int -> t m a -> t m a
824 go n1 m1 = mkStream $ \st yld sng stp ->
825 let yieldk a r = yld a (go (n1 - 1) r)
828 else foldStream st yieldk sng stp m1
830{-# INLINE takeWhile #-}
831takeWhile :: 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)
839 in foldStream st yieldk single stp m1
842drop :: IsStream t => Int -> t m a -> t m a
843drop n m = fromStream $ unShare (go n (toStream m))
845 go n1 m1 = mkStream $ \st yld sng stp ->
847 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
848 -- Somehow "<=" check performs better than a ">"
850 then foldStreamShared st yld sng stp m1
851 else foldStreamShared st yieldk single stp m1
853{-# INLINE dropWhile #-}
854dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
857 go m1 = mkStream $ \st yld sng stp ->
858 let single a | p a = stp
860 yieldk a r | p a = foldStream st yieldk single stp r
861 | otherwise = yld a r
862 in foldStream st yieldk single stp m1
864-------------------------------------------------------------------------------
866-------------------------------------------------------------------------------
868-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
869-- other stream types to overload it.
870{-# INLINE sequence #-}
871sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
874 go m1 = mkStream $ \st yld sng stp ->
875 let single ma = ma >>= sng
876 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
877 in foldStream (adaptState st) yieldk single stp m1
879-------------------------------------------------------------------------------
881-------------------------------------------------------------------------------
883{-# INLINE intersperseM #-}
884intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
885intersperseM a m = prependingStart m
887 prependingStart m1 = mkStream $ \st yld sng stp ->
888 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
889 in foldStream st yieldk sng stp m1
890 go m2 = mkStream $ \st yld sng stp ->
891 let single i = foldStreamShared st yld sng stp $ a |: yield i
892 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
893 in foldStream st yieldk single stp m2
895{-# INLINE intersperse #-}
896intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
897intersperse a = intersperseM (return a)
899{-# INLINE insertBy #-}
900insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
901insertBy cmp x m = go m
903 go m1 = mkStream $ \st yld _ _ ->
904 let single a = case cmp x a of
905 GT -> yld a (yield x)
908 yieldk a r = case cmp x a of
910 _ -> yld x (a `cons` r)
911 in foldStream st yieldk single stop m1
913------------------------------------------------------------------------------
915------------------------------------------------------------------------------
917{-# INLINE deleteBy #-}
918deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
919deleteBy eq x m = go m
921 go m1 = mkStream $ \st yld sng stp ->
922 let single a = if eq x a then stp else sng a
923 yieldk a r = if eq x a
924 then foldStream st yld sng stp r
926 in foldStream st yieldk single stp m1
928------------------------------------------------------------------------------
930------------------------------------------------------------------------------
932{-# INLINE reverse #-}
933reverse :: IsStream t => t m a -> t m a
934reverse = foldlS (flip cons) nil
936-------------------------------------------------------------------------------
938-------------------------------------------------------------------------------
940{-# INLINE mapMaybe #-}
941mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
944 go m1 = mkStream $ \st yld sng stp ->
945 let single a = case f a of
948 yieldk a r = case f a of
949 Just b -> yld b $ go r
950 Nothing -> foldStream (adaptState st) yieldk single stp r
951 in foldStream (adaptState st) yieldk single stp m1
953------------------------------------------------------------------------------
955------------------------------------------------------------------------------
957-- | Zip two streams serially using a pure zipping function.
960{-# INLINABLE zipWith #-}
961zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
964 go mx my = mkStream $ \st yld sng stp -> do
966 let single2 b = sng (f a b)
967 yield2 b rb = yld (f a b) (go ra rb)
968 in foldStream (adaptState st) yield2 single2 stp my
969 let single1 a = merge a nil
971 foldStream (adaptState st) yield1 single1 stp mx
973-- | Zip two streams serially using a monadic zipping function.
976{-# INLINABLE zipWithM #-}
977zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
978zipWithM f m1 m2 = go m1 m2
980 go mx my = mkStream $ \st yld sng stp -> do
982 let runIt x = foldStream st yld sng stp x
983 single2 b = f a b >>= sng
984 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
985 in foldStream (adaptState st) yield2 single2 stp my
986 let single1 a = merge a nil
988 foldStream (adaptState st) yield1 single1 stp mx
990------------------------------------------------------------------------------
992------------------------------------------------------------------------------
994{-# INLINE mergeByM #-}
996 :: (IsStream t, Monad m)
997 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1000 go mx my = mkStream $ \st yld sng stp -> do
1001 let mergeWithY a ra =
1002 let stop2 = foldStream st yld sng stp mx
1006 GT -> yld b (go (a `cons` ra) nil)
1007 _ -> yld a (go ra (b `cons` nil))
1011 GT -> yld b (go (a `cons` ra) rb)
1012 _ -> yld a (go ra (b `cons` rb))
1013 in foldStream st yield2 single2 stop2 my
1014 let stopX = foldStream st yld sng stp my
1015 singleX a = mergeWithY a nil
1017 foldStream st yieldX singleX stopX mx
1019{-# INLINABLE mergeBy #-}
1021 :: (IsStream t, Monad m)
1022 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1023mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1025------------------------------------------------------------------------------
1026-- Transformation comprehensions
1027------------------------------------------------------------------------------
1030the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
1034 Nothing -> return Nothing
1035 Just (h, t) -> go h t
1038 let single a | h == a = return $ Just h
1039 | otherwise = return Nothing
1040 yieldk a r | h == a = go h r
1041 | otherwise = return Nothing
1042 in foldStream defState yieldk single (return $ Just h) m1
1044------------------------------------------------------------------------------
1045-- Alternative & MonadPlus
1046------------------------------------------------------------------------------
1048_alt :: Stream m a -> Stream m a -> Stream m a
1049_alt m1 m2 = mkStream $ \st yld sng stp ->
1050 let stop = foldStream st yld sng stp m2
1051 in foldStream st yld sng stop m1
1053------------------------------------------------------------------------------
1055------------------------------------------------------------------------------
1057{-# INLINABLE withLocal #-}
1058withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1060 mkStream $ \st yld sng stp ->
1061 let single = local f . sng
1062 yieldk a r = local f $ yld a (withLocal f r)
1063 in foldStream st yieldk single (local f stp) m
1065------------------------------------------------------------------------------
1067------------------------------------------------------------------------------
1070-- XXX handle and test cross thread state transfer
1073 => Stream m a -> (e -> Stream m a) -> Stream m a
1075 mkStream $ \_ stp sng yld ->
1076 let run x = unStream x Nothing stp sng yieldk
1077 handle r = r `catchError` \e -> run $ h e
1078 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