1{-# LANGUAGE UndecidableInstances #-}
6-- Module : Streamly.Internal.Data.Stream.StreamK
7-- Copyright : (c) 2017 Composewell Technologies
10-- Maintainer : streamly@composewell.com
11-- Stability : experimental
15-- Continuation passing style (CPS) stream implementation. The symbol 'K' below
16-- denotes a function as well as a Kontinuation.
19-- import qualified Streamly.Internal.Data.Stream.StreamK as K
22module Streamly.Internal.Data.Stream.StreamK
24 -- * A class for streams
31 -- * Construction Primitives
38 -- * Elimination Primitives
42 -- * Transformation Primitives
53 -- ** Specialized Generation
93 -- ** Specialized Folds
123 -- ** By folding (scans)
171 -- ** Transformation comprehensions
174 -- * Semigroup Style Composition
183 , Streaming -- deprecated
188import Control.Monad.Trans.Class (MonadTrans(lift))
189import Control.Monad (void, join)
190import Control.Monad.Reader.Class (MonadReader(..))
191import Data.Function (fix)
193 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
194 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
195 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
196 foldr1, (!!), replicate, reverse, concatMap, iterate)
197import qualified Prelude
199import Streamly.Internal.Data.SVar
200import Streamly.Internal.Data.Stream.StreamK.Type
202import qualified Streamly.Internal.Data.Fold.Types as FL
204-------------------------------------------------------------------------------
206-------------------------------------------------------------------------------
209uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
211 let stop = return Nothing
212 single a = return (Just (a, nil))
213 yieldk a r = return (Just (a, r))
214 in foldStream defState yieldk single stop m
216-------------------------------------------------------------------------------
218-------------------------------------------------------------------------------
220{-# INLINE unfoldr #-}
221unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
222unfoldr next s0 = build $ \yld stp ->
225 Just (a, b) -> yld a (go b)
229{-# INLINE unfoldrM #-}
230unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
233 go s = sharedM $ \yld _ stp -> do
236 Just (a, b) -> yld a (go b)
240-- Generalization of concurrent streams/SVar via unfoldr.
242-- Unfold a value into monadic actions and then run the resulting monadic
243-- actions to generate a stream. Since the step of generating the monadic
244-- action and running them are decoupled we can run the monadic actions
245-- cooncurrently. For example, the seed could be a list of monadic actions or a
246-- pure stream of monadic actions.
248-- We can have different flavors of this depending on the stream type t. The
249-- concurrent version could be async or ahead etc. Depending on how we queue
250-- back the feedback portion b, it could be DFS or BFS style.
252unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
256-------------------------------------------------------------------------------
258-------------------------------------------------------------------------------
263{-# DEPRECATED once "Please use yieldM instead." #-}
265once :: (Monad m, IsStream t) => m a -> t m a
270-- repeatM = fix . cons
271-- repeatM = cycle1 . yield
274-- Generate an infinite stream by repeating a monadic value.
277repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
279 where go m = m |: go m
281-- Generate an infinite stream by repeating a pure value.
285repeat :: IsStream t => a -> t m a
286repeat a = let x = cons a x in x
288{-# INLINE replicateM #-}
289replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
292 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
294{-# INLINE replicate #-}
295replicate :: IsStream t => Int -> a -> t m a
298 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
300{-# INLINE fromIndicesM #-}
301fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
302fromIndicesM gen = go 0
304 go i = mkStream $ \st stp sng yld -> do
305 foldStreamShared st stp sng yld (gen i |: go (i + 1))
307{-# INLINE fromIndices #-}
308fromIndices :: IsStream t => (Int -> a) -> t m a
309fromIndices gen = go 0
311 go n = (gen n) `cons` go (n + 1)
313{-# INLINE iterate #-}
314iterate :: IsStream t => (a -> a) -> a -> t m a
315iterate step = fromStream . go
317 go s = cons s (go (step s))
319{-# INLINE iterateM #-}
320iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
323 go s = mkStream $ \st stp sng yld -> do
325 foldStreamShared st stp sng yld (return next |: go (step next))
327-------------------------------------------------------------------------------
329-------------------------------------------------------------------------------
333-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
336-- Construct a stream from a 'Foldable' containing pure values:
339{-# INLINE fromFoldable #-}
340fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
341fromFoldable = Prelude.foldr cons nil
343{-# INLINE fromList #-}
344fromList :: IsStream t => [a] -> t m a
345fromList = fromFoldable
347{-# INLINE fromStreamK #-}
348fromStreamK :: IsStream t => Stream m a -> t m a
349fromStreamK = fromStream
351-------------------------------------------------------------------------------
352-- Elimination by Folding
353-------------------------------------------------------------------------------
355-- | Lazy right associative fold.
357foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
358foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
360-- | Right associative fold to an arbitrary transformer monad.
362foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
363 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
364foldrT step final m = go m
367 res <- lift $ uncons m1
369 Just (h, t) -> step h (go t)
373foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
377 Nothing -> return Nothing
378 Just (h, t) -> fmap Just (go h t)
382 single a = return $ step a p
383 yieldk a r = fmap (step p) (go a r)
384 in foldStream defState yieldk single stp m1
386-- XXX replace the recursive "go" with explicit continuations.
387-- | Like 'foldx', but with a monadic step function.
388{-# INLINABLE foldlMx' #-}
389foldlMx' :: (IsStream t, Monad m)
390 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
391foldlMx' step begin done m = go begin m
394 let stop = acc >>= done
395 single a = acc >>= \b -> step b a >>= done
396 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
397 in foldStream defState yieldk single stop m1
399{-# INLINABLE foldOnce #-}
400foldOnce :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> m b
401foldOnce (FL.Fold step begin done) m = do
404 FL.Partial fs -> go fs m
405 FL.Done fb -> return fb
410 single a = step acc a
412 FL.Partial s -> done s
413 FL.Done b1 -> return b1
414 yieldk a r = step acc a
416 FL.Partial s -> go s r
417 FL.Done b1 -> return b1
418 in foldStream defState yieldk single stop m1
420-- | Like 'foldl'' but with a monadic step function.
421{-# INLINE foldlM' #-}
422foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> m b
423foldlM' step begin = foldlMx' step begin return
425-- | Lazy left fold to a stream.
427foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
428foldlS step begin m = go begin m
430 go acc rest = mkStream $ \st yld sng stp ->
431 let run x = foldStream st yld sng stp x
433 single a = run $ step acc a
434 yieldk a r = run $ go (step acc a) r
435 in foldStream (adaptState st) yieldk single stop rest
437-- | Lazy left fold to an arbitrary transformer monad.
439foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
440 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
441foldlT step begin m = go begin m
444 res <- lift $ uncons m1
446 Just (h, t) -> go (step acc h) t
449------------------------------------------------------------------------------
451------------------------------------------------------------------------------
453-- XXX use foldrM to implement folds where possible
454-- XXX This (commented) definition of drain and mapM_ perform much better on
455-- some benchmarks but worse on others. Need to investigate why, may there is
456-- an optimization opportunity that we can exploit.
457-- drain = foldrM (\_ xs -> return () >> xs) (return ())
460-- > drain = foldl' (\_ _ -> ()) ()
461-- > drain = mapM_ (\_ -> return ())
463drain :: (Monad m, IsStream t) => t m a -> m ()
464drain = foldrM (\_ xs -> xs) (return ())
472 in foldStream defState yieldk single stop m1
476null :: (IsStream t, Monad m) => t m a -> m Bool
477-- null = foldrM (\_ _ -> return True) (return False)
479 let stop = return True
480 single _ = return False
481 yieldk _ _ = return False
482 in foldStream defState yieldk single stop m
485head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
486-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
488 let stop = return Nothing
489 single a = return (Just a)
490 yieldk a _ = return (Just a)
491 in foldStream defState yieldk single stop m
494tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
496 let stop = return Nothing
497 single _ = return $ Just nil
498 yieldk _ r = return $ Just r
499 in foldStream defState yieldk single stop m
501{-# INLINE headPartial #-}
502headPartial :: (IsStream t, Monad m) => t m a -> m a
503headPartial = foldrM (\x _ -> return x) (error "head of nil")
505{-# INLINE tailPartial #-}
506tailPartial :: IsStream t => t m a -> t m a
507tailPartial m = mkStream $ \st yld sng stp ->
508 let stop = error "tail of nil"
510 yieldk _ r = foldStream st yld sng stp r
511 in foldStream st yieldk single stop m
513-- | We can define cyclic structures using @let@:
515-- >>> let (a, b) = ([1, b], head a) in (a, b)
518-- The function @fix@ defined as:
520-- > fix f = let x = f x in x
522-- ensures that the argument of a function and its output refer to the same
523-- lazy value @x@ i.e. the same location in memory. Thus @x@ can be defined
524-- in terms of itself, creating structures with cyclic references.
526-- >>> f ~(a, b) = ([1, b], head a)
530-- 'Control.Monad.mfix' is essentially the same as @fix@ but for monadic
533-- Using 'mfix' for streams we can construct a stream in which each element of
534-- the stream is defined in a cyclic fashion. The argument of the function
535-- being fixed represents the current element of the stream which is being
536-- returned by the stream monad. Thus, we can use the argument to construct
539-- In the following example, the argument @action@ of the function @f@
540-- represents the tuple @(x,y)@ returned by it in a given iteration. We define
541-- the first element of the tuple in terms of the second.
544-- import Streamly.Internal.Data.Stream.IsStream as Stream
545-- import System.IO.Unsafe (unsafeInterleaveIO)
548-- Stream.mapM_ print $ Stream.mfix f
553-- let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
554-- x <- Stream.fromListM [incr 1 action, incr 2 action]
555-- y <- Stream.fromList [4,5]
559-- Note: you cannot achieve this by just changing the order of the monad
560-- statements because that would change the order in which the stream elements
563-- Note that the function @f@ must be lazy in its argument, that's why we use
564-- 'unsafeInterleaveIO' on @action@ because IO monad is strict.
568mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
569mfix f = mkStream $ \st yld sng stp ->
570 let single a = foldStream st yld sng stp $ a `cons` ys
571 yieldk a _ = foldStream st yld sng stp $ a `cons` ys
572 in foldStream st yieldk single stp xs
576 -- fix the head element of the stream
577 xs = fix (f . headPartial)
579 -- now fix the tail recursively
580 ys = mfix (tailPartial . f)
583init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
589 Nothing -> return Nothing
590 Just (h, t) -> return . Just $ go h t
591 go p m1 = mkStream $ \_ yld sng stp ->
593 yieldk a x = yld p $ go a x
594 in foldStream defState yieldk single stp m1
597elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
601 let stop = return False
602 single a = return (a == e)
603 yieldk a r = if a == e then return True else go r
604 in foldStream defState yieldk single stop m1
606{-# INLINE notElem #-}
607notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
611 let stop = return True
612 single a = return (a /= e)
613 yieldk a r = if a == e then return False else go r
614 in foldStream defState yieldk single stop m1
617all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
621 let single a | p a = return True
622 | otherwise = return False
623 yieldk a r | p a = go r
624 | otherwise = return False
625 in foldStream defState yieldk single (return True) m1
628any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
632 let single a | p a = return True
633 | otherwise = return False
634 yieldk a r | p a = return True
636 in foldStream defState yieldk single (return False) m1
638-- | Extract the last element of the stream, if any.
640last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
641last = foldlx' (\_ y -> Just y) Nothing id
643{-# INLINE minimum #-}
644minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
645minimum 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)
657 then return (Just res)
663 in foldStream defState yieldk single stop m1
665{-# INLINE minimumBy #-}
667 :: (IsStream t, Monad m)
668 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
669minimumBy cmp m = go Nothing m
672 let stop = return Nothing
673 single a = return (Just a)
674 yieldk a r = go (Just a) r
675 in foldStream defState yieldk single stop m1
678 let stop = return (Just res)
679 single a = case cmp res a of
680 GT -> return (Just a)
681 _ -> return (Just res)
682 yieldk a r = case cmp res a of
685 in foldStream defState yieldk single stop m1
687{-# INLINE maximum #-}
688maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
689maximum m = go Nothing m
692 let stop = return Nothing
693 single a = return (Just a)
694 yieldk a r = go (Just a) r
695 in foldStream defState yieldk single stop m1
698 let stop = return (Just res)
702 else return (Just res)
707 in foldStream defState yieldk single stop m1
709{-# INLINE maximumBy #-}
710maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
711maximumBy cmp m = go Nothing m
714 let stop = return Nothing
715 single a = return (Just a)
716 yieldk a r = go (Just a) r
717 in foldStream defState yieldk single stop m1
720 let stop = return (Just res)
721 single a = case cmp res a of
722 GT -> return (Just res)
724 yieldk a r = case cmp res a of
725 GT -> go (Just res) r
727 in foldStream defState yieldk single stop m1
730(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
734 let single a | n == 0 = return $ Just a
735 | otherwise = return Nothing
736 yieldk a x | n < 0 = return Nothing
737 | n == 0 = return $ Just a
738 | otherwise = go (n - 1) x
739 in foldStream defState yieldk single (return Nothing) m1
742lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
746 let single (a, b) | a == e = return $ Just b
747 | otherwise = return Nothing
748 yieldk (a, b) x | a == e = return $ Just b
750 in foldStream defState yieldk single (return Nothing) m1
753findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
759 if b then return $ Just a else return Nothing
762 if b then return $ Just a else go x
763 in foldStream defState yieldk single (return Nothing) m1
766find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
767find p = findM (return . p)
769{-# INLINE findIndices #-}
770findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
773 go offset m1 = mkStream $ \st yld sng stp ->
774 let single a | p a = sng offset
776 yieldk a x | p a = yld offset $ go (offset + 1) x
777 | otherwise = foldStream (adaptState st) yld sng stp $
779 in foldStream (adaptState st) yieldk single stp m1
781------------------------------------------------------------------------------
783------------------------------------------------------------------------------
785-- | Apply a monadic action to each element of the stream and discard the
786-- output of the action.
788mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
793 single a = void (f a)
794 yieldk a r = f a >> go r
795 in foldStream defState yieldk single stop m1
797------------------------------------------------------------------------------
799------------------------------------------------------------------------------
801{-# INLINABLE toList #-}
802toList :: (IsStream t, Monad m) => t m a -> m [a]
805{-# INLINE toStreamK #-}
806toStreamK :: Stream m a -> Stream m a
809-- Based on suggestions by David Feuer and Pranay Sashank
811hoist :: (IsStream t, Monad m, Monad n)
812 => (forall x. m x -> n x) -> t m a -> t n a
814 mkStream $ \st yld sng stp ->
815 let single = return . sng
816 yieldk a s = return $ yld a (hoist f s)
818 state = adaptState st
819 in join . f $ foldStreamShared state yieldk single stop str
821-------------------------------------------------------------------------------
822-- Transformation by folding (Scans)
823-------------------------------------------------------------------------------
825{-# INLINE scanlx' #-}
826scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
827scanlx' step begin done m =
828 cons (done begin) $ go m begin
830 go m1 !acc = mkStream $ \st yld sng stp ->
831 let single a = sng (done $ step acc a)
834 in yld (done s) (go r s)
835 in foldStream (adaptState st) yieldk single stp m1
838scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
839scanl' step begin = scanlx' step begin id
841-------------------------------------------------------------------------------
843-------------------------------------------------------------------------------
846filter :: 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)
853 | otherwise = foldStream st yieldk single stp r
854 in foldStream st yieldk single stp m1
857take :: IsStream t => Int -> t m a -> t m a
860 go n1 m1 = mkStream $ \st yld sng stp ->
861 let yieldk a r = yld a (go (n1 - 1) r)
864 else foldStream st yieldk sng stp m1
866{-# INLINE takeWhile #-}
867takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
870 go m1 = mkStream $ \st yld sng stp ->
871 let single a | p a = sng a
873 yieldk a r | p a = yld a (go r)
875 in foldStream st yieldk single stp m1
878drop :: IsStream t => Int -> t m a -> t m a
879drop n m = fromStream $ unShare (go n (toStream m))
881 go n1 m1 = mkStream $ \st yld sng stp ->
883 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
884 -- Somehow "<=" check performs better than a ">"
886 then foldStreamShared st yld sng stp m1
887 else foldStreamShared st yieldk single stp m1
889{-# INLINE dropWhile #-}
890dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
893 go m1 = mkStream $ \st yld sng stp ->
894 let single a | p a = stp
896 yieldk a r | p a = foldStream st yieldk single stp r
897 | otherwise = yld a r
898 in foldStream st yieldk single stp m1
900-------------------------------------------------------------------------------
902-------------------------------------------------------------------------------
904-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
905-- other stream types to overload it.
906{-# INLINE sequence #-}
907sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
910 go m1 = mkStream $ \st yld sng stp ->
911 let single ma = ma >>= sng
912 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
913 in foldStream (adaptState st) yieldk single stp m1
915-------------------------------------------------------------------------------
917-------------------------------------------------------------------------------
919{-# INLINE intersperseM #-}
920intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
921intersperseM a m = prependingStart m
923 prependingStart m1 = mkStream $ \st yld sng stp ->
924 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
925 in foldStream st yieldk sng stp m1
926 go m2 = mkStream $ \st yld sng stp ->
927 let single i = foldStreamShared st yld sng stp $ a |: yield i
928 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
929 in foldStream st yieldk single stp m2
931{-# INLINE intersperse #-}
932intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
933intersperse a = intersperseM (return a)
935{-# INLINE insertBy #-}
936insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
937insertBy cmp x m = go m
939 go m1 = mkStream $ \st yld _ _ ->
940 let single a = case cmp x a of
941 GT -> yld a (yield x)
944 yieldk a r = case cmp x a of
946 _ -> yld x (a `cons` r)
947 in foldStream st yieldk single stop m1
949------------------------------------------------------------------------------
951------------------------------------------------------------------------------
953{-# INLINE deleteBy #-}
954deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
955deleteBy eq x m = go m
957 go m1 = mkStream $ \st yld sng stp ->
958 let single a = if eq x a then stp else sng a
959 yieldk a r = if eq x a
960 then foldStream st yld sng stp r
962 in foldStream st yieldk single stp m1
964------------------------------------------------------------------------------
966------------------------------------------------------------------------------
968{-# INLINE reverse #-}
969reverse :: IsStream t => t m a -> t m a
970reverse = foldlS (flip cons) nil
972-------------------------------------------------------------------------------
974-------------------------------------------------------------------------------
976{-# INLINE mapMaybe #-}
977mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
980 go m1 = mkStream $ \st yld sng stp ->
981 let single a = case f a of
984 yieldk a r = case f a of
985 Just b -> yld b $ go r
986 Nothing -> foldStream (adaptState st) yieldk single stp r
987 in foldStream (adaptState st) yieldk single stp m1
989------------------------------------------------------------------------------
991------------------------------------------------------------------------------
993-- | Zip two streams serially using a pure zipping function.
996{-# INLINABLE zipWith #-}
997zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
1000 go mx my = mkStream $ \st yld sng stp -> do
1002 let single2 b = sng (f a b)
1003 yield2 b rb = yld (f a b) (go ra rb)
1004 in foldStream (adaptState st) yield2 single2 stp my
1005 let single1 a = merge a nil
1007 foldStream (adaptState st) yield1 single1 stp mx
1009-- | Zip two streams serially using a monadic zipping function.
1012{-# INLINABLE zipWithM #-}
1013zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
1014zipWithM f m1 m2 = go m1 m2
1016 go mx my = mkStream $ \st yld sng stp -> do
1018 let runIt x = foldStream st yld sng stp x
1019 single2 b = f a b >>= sng
1020 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
1021 in foldStream (adaptState st) yield2 single2 stp my
1022 let single1 a = merge a nil
1024 foldStream (adaptState st) yield1 single1 stp mx
1026------------------------------------------------------------------------------
1028------------------------------------------------------------------------------
1030{-# INLINE mergeByM #-}
1032 :: (IsStream t, Monad m)
1033 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1036 go mx my = mkStream $ \st yld sng stp -> do
1037 let mergeWithY a ra =
1038 let stop2 = foldStream st yld sng stp mx
1042 GT -> yld b (go (a `cons` ra) nil)
1043 _ -> yld a (go ra (b `cons` nil))
1047 GT -> yld b (go (a `cons` ra) rb)
1048 _ -> yld a (go ra (b `cons` rb))
1049 in foldStream st yield2 single2 stop2 my
1050 let stopX = foldStream st yld sng stp my
1051 singleX a = mergeWithY a nil
1053 foldStream st yieldX singleX stopX mx
1055{-# INLINABLE mergeBy #-}
1057 :: (IsStream t, Monad m)
1058 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1059mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1061------------------------------------------------------------------------------
1062-- Transformation comprehensions
1063------------------------------------------------------------------------------
1066the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
1070 Nothing -> return Nothing
1071 Just (h, t) -> go h t
1074 let single a | h == a = return $ Just h
1075 | otherwise = return Nothing
1076 yieldk a r | h == a = go h r
1077 | otherwise = return Nothing
1078 in foldStream defState yieldk single (return $ Just h) m1
1080------------------------------------------------------------------------------
1081-- Alternative & MonadPlus
1082------------------------------------------------------------------------------
1084_alt :: Stream m a -> Stream m a -> Stream m a
1085_alt m1 m2 = mkStream $ \st yld sng stp ->
1086 let stop = foldStream st yld sng stp m2
1087 in foldStream st yld sng stop m1
1089------------------------------------------------------------------------------
1091------------------------------------------------------------------------------
1093{-# INLINABLE withLocal #-}
1094withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1096 mkStream $ \st yld sng stp ->
1097 let single = local f . sng
1098 yieldk a r = local f $ yld a (withLocal f r)
1099 in foldStream st yieldk single (local f stp) m
1101------------------------------------------------------------------------------
1103------------------------------------------------------------------------------
1106-- XXX handle and test cross thread state transfer
1109 => Stream m a -> (e -> Stream m a) -> Stream m a
1111 mkStream $ \_ stp sng yld ->
1112 let run x = unStream x Nothing stp sng yieldk
1113 handle r = r `catchError` \e -> run $ h e
1114 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