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.Streams.StreamK
16-- Copyright : (c) 2017 Harendra Kumar
19-- Maintainer : harendra.kumar@gmail.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.Streams.StreamK as K
31module Streamly.Streams.StreamK
33 -- * A class for streams
40 -- * Construction Primitives
47 -- * Elimination Primitives
52 -- * Transformation Primitives
63 -- ** Specialized Generation
100 -- ** Specialized Folds
129 -- ** By folding (scans)
173 -- ** Transformation comprehensions
176 -- * Semigroup Style Composition
184 , Streaming -- deprecated
189import Control.Monad.Trans (MonadTrans(lift))
190import Control.Monad (void)
191import Control.Monad.Reader.Class (MonadReader(..))
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)
197import qualified Prelude
199import Streamly.Internal.Data.SVar
200import Streamly.Streams.StreamK.Type
202-------------------------------------------------------------------------------
204-------------------------------------------------------------------------------
207uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
209 let stop = return Nothing
210 single a = return (Just (a, nil))
211 yieldk a r = return (Just (a, r))
212 in foldStream defState yieldk single stop m
214-------------------------------------------------------------------------------
216-------------------------------------------------------------------------------
218{-# INLINE unfoldr #-}
219unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
220unfoldr next s0 = build $ \yld stp ->
223 Just (a, b) -> yld a (go b)
227{-# INLINE unfoldrM #-}
228unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
231 go s = sharedM $ \yld _ stp -> do
234 Just (a, b) -> yld a (go b)
238-- Generalization of concurrent streams/SVar via unfoldr.
240-- Unfold a value into monadic actions and then run the resulting monadic
241-- actions to generate a stream. Since the step of generating the monadic
242-- action and running them are decoupled we can run the monadic actions
243-- cooncurrently. For example, the seed could be a list of monadic actions or a
244-- pure stream of monadic actions.
246-- We can have different flavors of this depending on the stream type t. The
247-- concurrent version could be async or ahead etc. Depending on how we queue
248-- back the feedback portion b, it could be DFS or BFS style.
250unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
254-------------------------------------------------------------------------------
256-------------------------------------------------------------------------------
261{-# DEPRECATED once "Please use yieldM instead." #-}
263once :: (Monad m, IsStream t) => m a -> t m a
268-- repeatM = fix . cons
269-- repeatM = cycle1 . yield
272-- Generate an infinite stream by repeating a monadic value.
275repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
277 where go m = m |: go m
279-- Generate an infinite stream by repeating a pure value.
283repeat :: IsStream t => a -> t m a
284repeat a = let x = cons a x in x
286{-# INLINE replicateM #-}
287replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
290 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
292{-# INLINE replicate #-}
293replicate :: IsStream t => Int -> a -> t m a
296 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
298{-# INLINE fromIndicesM #-}
299fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
300fromIndicesM gen = go 0
302 go i = mkStream $ \st stp sng yld -> do
303 foldStreamShared st stp sng yld (gen i |: go (i + 1))
305{-# INLINE fromIndices #-}
306fromIndices :: IsStream t => (Int -> a) -> t m a
307fromIndices gen = go 0
309 go n = (gen n) `cons` go (n + 1)
311-------------------------------------------------------------------------------
313-------------------------------------------------------------------------------
317-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
320-- Construct a stream from a 'Foldable' containing pure values:
323{-# INLINE fromFoldable #-}
324fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
325fromFoldable = Prelude.foldr cons nil
327{-# INLINE fromList #-}
328fromList :: IsStream t => [a] -> t m a
329fromList = fromFoldable
331{-# INLINE fromStreamK #-}
332fromStreamK :: IsStream t => Stream m a -> t m a
333fromStreamK = fromStream
335-------------------------------------------------------------------------------
336-- Elimination by Folding
337-------------------------------------------------------------------------------
339-- | Lazy right associative fold.
341foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
342foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
344-- | Right associative fold to an arbitrary transformer monad.
346foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
347 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
348foldrT step final m = go m
351 res <- lift $ uncons m1
353 Just (h, t) -> step h (go t)
357foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
361 Nothing -> return Nothing
362 Just (h, t) -> fmap Just (go h t)
366 single a = return $ step a p
367 yieldk a r = fmap (step p) (go a r)
368 in foldStream defState yieldk single stp m1
370-- | Strict left fold with an extraction function. Like the standard strict
371-- left fold, but applies a user supplied extraction function (the third
372-- argument) to the folded value at the end. This is designed to work with the
373-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
375-- Note that the accumulator is always evaluated including the initial value.
376{-# INLINE foldlx' #-}
377foldlx' :: forall t m a b x. (IsStream t, Monad m)
378 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
379foldlx' step begin done m = get $ go m begin
384 -- XXX we are not strictly evaluating the accumulator here. Is this
386 let single = return . done
387 -- XXX this is foldSingleton. why foldStreamShared?
388 in foldStreamShared undefined undefined single undefined m1
390 -- Note, this can be implemented by making a recursive call to "go",
391 -- however that is more expensive because of unnecessary recursion
392 -- that cannot be tail call optimized. Unfolding recursion explicitly via
393 -- continuations is much more efficient.
394 go :: t m a -> x -> t m x
395 go m1 !acc = mkStream $ \_ yld sng _ ->
397 single a = sng $ step acc a
398 -- XXX this is foldNonEmptyStream
399 yieldk a r = foldStream defState yld sng undefined $
401 in foldStream defState yieldk single stop m1
403-- | Strict left associative fold.
405foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
406foldl' step begin = foldlx' step begin id
408-- XXX replace the recursive "go" with explicit continuations.
409-- | Like 'foldx', but with a monadic step function.
410{-# INLINABLE foldlMx' #-}
411foldlMx' :: (IsStream t, Monad m)
412 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
413foldlMx' step begin done m = go begin m
416 let stop = acc >>= done
417 single a = acc >>= \b -> step b a >>= done
418 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
419 in foldStream defState yieldk single stop m1
421-- | Like 'foldl'' but with a monadic step function.
422{-# INLINE foldlM' #-}
423foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
424foldlM' step begin = foldlMx' step (return begin) return
426-- | Lazy left fold to a stream.
428foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
429foldlS step begin m = go begin m
431 go acc rest = mkStream $ \st yld sng stp ->
432 let run x = foldStream st yld sng stp x
434 single a = run $ step acc a
435 yieldk a r = run $ go (step acc a) r
436 in foldStream (adaptState st) yieldk single stop rest
438-- | Lazy left fold to an arbitrary transformer monad.
440foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
441 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
442foldlT step begin m = go begin m
445 res <- lift $ uncons m1
447 Just (h, t) -> go (step acc h) t
450------------------------------------------------------------------------------
452------------------------------------------------------------------------------
454-- XXX use foldrM to implement folds where possible
455-- XXX This (commented) definition of drain and mapM_ perform much better on
456-- some benchmarks but worse on others. Need to investigate why, may there is
457-- an optimization opportunity that we can exploit.
458-- drain = foldrM (\_ xs -> return () >> xs) (return ())
461-- > drain = foldl' (\_ _ -> ()) ()
462-- > drain = mapM_ (\_ -> return ())
464drain :: (Monad m, IsStream t) => t m a -> m ()
465drain = foldrM (\_ xs -> xs) (return ())
473 in foldStream defState yieldk single stop m1
477null :: (IsStream t, Monad m) => t m a -> m Bool
478-- null = foldrM (\_ _ -> return True) (return False)
480 let stop = return True
481 single _ = return False
482 yieldk _ _ = return False
483 in foldStream defState yieldk single stop m
486head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
487-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
489 let stop = return Nothing
490 single a = return (Just a)
491 yieldk a _ = return (Just a)
492 in foldStream defState yieldk single stop m
495tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
497 let stop = return Nothing
498 single _ = return $ Just nil
499 yieldk _ r = return $ Just r
500 in foldStream defState yieldk single stop m
503init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
509 Nothing -> return Nothing
510 Just (h, t) -> return . Just $ go h t
511 go p m1 = mkStream $ \_ yld sng stp ->
513 yieldk a x = yld p $ go a x
514 in foldStream defState yieldk single stp m1
517elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
521 let stop = return False
522 single a = return (a == e)
523 yieldk a r = if a == e then return True else go r
524 in foldStream defState yieldk single stop m1
526{-# INLINE notElem #-}
527notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
531 let stop = return True
532 single a = return (a /= e)
533 yieldk a r = if a == e then return False else go r
534 in foldStream defState yieldk single stop m1
537all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
541 let single a | p a = return True
542 | otherwise = return False
543 yieldk a r | p a = go r
544 | otherwise = return False
545 in foldStream defState yieldk single (return True) m1
548any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
552 let single a | p a = return True
553 | otherwise = return False
554 yieldk a r | p a = return True
556 in foldStream defState yieldk single (return False) m1
558-- | Extract the last element of the stream, if any.
560last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
561last = foldlx' (\_ y -> Just y) Nothing id
563{-# INLINE minimum #-}
564minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
565minimum m = go Nothing m
568 let stop = return Nothing
569 single a = return (Just a)
570 yieldk a r = go (Just a) r
571 in foldStream defState yieldk single stop m1
574 let stop = return (Just res)
577 then return (Just res)
583 in foldStream defState yieldk single stop m1
585{-# INLINE minimumBy #-}
587 :: (IsStream t, Monad m)
588 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
589minimumBy cmp m = go Nothing m
592 let stop = return Nothing
593 single a = return (Just a)
594 yieldk a r = go (Just a) r
595 in foldStream defState yieldk single stop m1
598 let stop = return (Just res)
599 single a = case cmp res a of
600 GT -> return (Just a)
601 _ -> return (Just res)
602 yieldk a r = case cmp res a of
605 in foldStream defState yieldk single stop m1
607{-# INLINE maximum #-}
608maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
609maximum 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)
622 else return (Just res)
627 in foldStream defState yieldk single stop m1
629{-# INLINE maximumBy #-}
630maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
631maximumBy cmp m = go Nothing m
634 let stop = return Nothing
635 single a = return (Just a)
636 yieldk a r = go (Just a) r
637 in foldStream defState yieldk single stop m1
640 let stop = return (Just res)
641 single a = case cmp res a of
642 GT -> return (Just res)
644 yieldk a r = case cmp res a of
645 GT -> go (Just res) r
647 in foldStream defState yieldk single stop m1
650(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
654 let single a | n == 0 = return $ Just a
655 | otherwise = return Nothing
656 yieldk a x | n < 0 = return Nothing
657 | n == 0 = return $ Just a
658 | otherwise = go (n - 1) x
659 in foldStream defState yieldk single (return Nothing) m1
662lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
666 let single (a, b) | a == e = return $ Just b
667 | otherwise = return Nothing
668 yieldk (a, b) x | a == e = return $ Just b
670 in foldStream defState yieldk single (return Nothing) m1
673findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
679 if b then return $ Just a else return Nothing
682 if b then return $ Just a else go x
683 in foldStream defState yieldk single (return Nothing) m1
686find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
687find p = findM (return . p)
689{-# INLINE findIndices #-}
690findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
693 go offset m1 = mkStream $ \st yld sng stp ->
694 let single a | p a = sng offset
696 yieldk a x | p a = yld offset $ go (offset + 1) x
697 | otherwise = foldStream (adaptState st) yld sng stp $
699 in foldStream (adaptState st) yieldk single stp m1
701------------------------------------------------------------------------------
703------------------------------------------------------------------------------
705-- | Apply a monadic action to each element of the stream and discard the
706-- output of the action.
708mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
713 single a = void (f a)
714 yieldk a r = f a >> go r
715 in foldStream defState yieldk single stop m1
717------------------------------------------------------------------------------
719------------------------------------------------------------------------------
721{-# INLINABLE toList #-}
722toList :: (IsStream t, Monad m) => t m a -> m [a]
725{-# INLINE toStreamK #-}
726toStreamK :: Stream m a -> Stream m a
729-------------------------------------------------------------------------------
730-- Transformation by folding (Scans)
731-------------------------------------------------------------------------------
733{-# INLINE scanlx' #-}
734scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
735scanlx' step begin done m =
736 cons (done begin) $ go m begin
738 go m1 !acc = mkStream $ \st yld sng stp ->
739 let single a = sng (done $ step acc a)
742 in yld (done s) (go r s)
743 in foldStream (adaptState st) yieldk single stp m1
746scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
747scanl' step begin = scanlx' step begin id
749-------------------------------------------------------------------------------
751-------------------------------------------------------------------------------
754filter :: IsStream t => (a -> Bool) -> t m a -> t m a
757 go m1 = mkStream $ \st yld sng stp ->
758 let single a | p a = sng a
760 yieldk a r | p a = yld a (go r)
761 | otherwise = foldStream st yieldk single stp r
762 in foldStream st yieldk single stp m1
765take :: IsStream t => Int -> t m a -> t m a
768 go n1 m1 = mkStream $ \st yld sng stp ->
769 let yieldk a r = yld a (go (n1 - 1) r)
772 else foldStream st yieldk sng stp m1
774{-# INLINE takeWhile #-}
775takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
778 go m1 = mkStream $ \st yld sng stp ->
779 let single a | p a = sng a
781 yieldk a r | p a = yld a (go r)
783 in foldStream st yieldk single stp m1
786drop :: IsStream t => Int -> t m a -> t m a
787drop n m = fromStream $ unShare (go n (toStream m))
789 go n1 m1 = mkStream $ \st yld sng stp ->
791 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
792 -- Somehow "<=" check performs better than a ">"
794 then foldStreamShared st yld sng stp m1
795 else foldStreamShared st yieldk single stp m1
797{-# INLINE dropWhile #-}
798dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
801 go m1 = mkStream $ \st yld sng stp ->
802 let single a | p a = stp
804 yieldk a r | p a = foldStream st yieldk single stp r
805 | otherwise = yld a r
806 in foldStream st yieldk single stp m1
808-------------------------------------------------------------------------------
810-------------------------------------------------------------------------------
812-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
813-- other stream types to overload it.
814{-# INLINE sequence #-}
815sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
818 go m1 = mkStream $ \st yld sng stp ->
819 let single ma = ma >>= sng
820 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
821 in foldStream (adaptState st) yieldk single stp m1
823-------------------------------------------------------------------------------
825-------------------------------------------------------------------------------
827{-# INLINE intersperseM #-}
828intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
829intersperseM a m = prependingStart m
831 prependingStart m1 = mkStream $ \st yld sng stp ->
832 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
833 in foldStream st yieldk sng stp m1
834 go m2 = mkStream $ \st yld sng stp ->
835 let single i = foldStreamShared st yld sng stp $ a |: yield i
836 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
837 in foldStream st yieldk single stp m2
839{-# INLINE intersperse #-}
840intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
841intersperse a = intersperseM (return a)
843{-# INLINE insertBy #-}
844insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
845insertBy cmp x m = go m
847 go m1 = mkStream $ \st yld _ _ ->
848 let single a = case cmp x a of
849 GT -> yld a (yield x)
852 yieldk a r = case cmp x a of
854 _ -> yld x (a `cons` r)
855 in foldStream st yieldk single stop m1
857------------------------------------------------------------------------------
859------------------------------------------------------------------------------
861{-# INLINE deleteBy #-}
862deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
863deleteBy eq x m = go m
865 go m1 = mkStream $ \st yld sng stp ->
866 let single a = if eq x a then stp else sng a
867 yieldk a r = if eq x a
868 then foldStream st yld sng stp r
870 in foldStream st yieldk single stp m1
872------------------------------------------------------------------------------
874------------------------------------------------------------------------------
876{-# INLINE reverse #-}
877reverse :: IsStream t => t m a -> t m a
878reverse = foldlS (flip cons) nil
880-------------------------------------------------------------------------------
882-------------------------------------------------------------------------------
884{-# INLINE mapMaybe #-}
885mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
888 go m1 = mkStream $ \st yld sng stp ->
889 let single a = case f a of
892 yieldk a r = case f a of
893 Just b -> yld b $ go r
894 Nothing -> foldStream (adaptState st) yieldk single stp r
895 in foldStream (adaptState st) yieldk single stp m1
897------------------------------------------------------------------------------
899------------------------------------------------------------------------------
901-- | Zip two streams serially using a pure zipping function.
904{-# INLINABLE zipWith #-}
905zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
908 go mx my = mkStream $ \st yld sng stp -> do
910 let single2 b = sng (f a b)
911 yield2 b rb = yld (f a b) (go ra rb)
912 in foldStream (adaptState st) yield2 single2 stp my
913 let single1 a = merge a nil
915 foldStream (adaptState st) yield1 single1 stp mx
917-- | Zip two streams serially using a monadic zipping function.
920{-# INLINABLE zipWithM #-}
921zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
922zipWithM f m1 m2 = go m1 m2
924 go mx my = mkStream $ \st yld sng stp -> do
926 let runIt x = foldStream st yld sng stp x
927 single2 b = f a b >>= sng
928 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
929 in foldStream (adaptState st) yield2 single2 stp my
930 let single1 a = merge a nil
932 foldStream (adaptState st) yield1 single1 stp mx
934------------------------------------------------------------------------------
936------------------------------------------------------------------------------
938{-# INLINE mergeByM #-}
940 :: (IsStream t, Monad m)
941 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
944 go mx my = mkStream $ \st yld sng stp -> do
945 let mergeWithY a ra =
946 let stop2 = foldStream st yld sng stp mx
950 GT -> yld b (go (a `cons` ra) nil)
951 _ -> yld a (go ra (b `cons` nil))
955 GT -> yld b (go (a `cons` ra) rb)
956 _ -> yld a (go ra (b `cons` rb))
957 in foldStream st yield2 single2 stop2 my
958 let stopX = foldStream st yld sng stp my
959 singleX a = mergeWithY a nil
961 foldStream st yieldX singleX stopX mx
963{-# INLINABLE mergeBy #-}
965 :: (IsStream t, Monad m)
966 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
967mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
969------------------------------------------------------------------------------
970-- Transformation comprehensions
971------------------------------------------------------------------------------
974the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
978 Nothing -> return Nothing
979 Just (h, t) -> go h t
982 let single a | h == a = return $ Just h
983 | otherwise = return Nothing
984 yieldk a r | h == a = go h r
985 | otherwise = return Nothing
986 in foldStream defState yieldk single (return $ Just h) m1
988------------------------------------------------------------------------------
989-- Alternative & MonadPlus
990------------------------------------------------------------------------------
992_alt :: Stream m a -> Stream m a -> Stream m a
993_alt m1 m2 = mkStream $ \st yld sng stp ->
994 let stop = foldStream st yld sng stp m2
995 in foldStream st yld sng stop m1
997------------------------------------------------------------------------------
999------------------------------------------------------------------------------
1001{-# INLINABLE withLocal #-}
1002withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
1004 mkStream $ \st yld sng stp ->
1005 let single = local f . sng
1006 yieldk a r = local f $ yld a (withLocal f r)
1007 in foldStream st yieldk single (local f stp) m
1009------------------------------------------------------------------------------
1011------------------------------------------------------------------------------
1014-- XXX handle and test cross thread state transfer
1017 => Stream m a -> (e -> Stream m a) -> Stream m a
1019 mkStream $ \_ stp sng yld ->
1020 let run x = unStream x Nothing stp sng yieldk
1021 handle r = r `catchError` \e -> run $ h e
1022 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