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
99 -- ** Specialized Folds
128 -- ** By folding (scans)
172 -- ** Transformation comprehensions
175 -- * Semigroup Style Composition
183 , Streaming -- deprecated
188import Control.Monad.Trans (MonadTrans(lift))
189import Control.Monad (void)
190import Control.Monad.Reader.Class (MonadReader(..))
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)
196import qualified Prelude
198import Streamly.Internal.Data.SVar
199import Streamly.Streams.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 pure value.
275repeat :: IsStream t => a -> t m a
276repeat a = let x = cons a x in x
278{-# INLINE replicateM #-}
279replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
282 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
284{-# INLINE replicate #-}
285replicate :: IsStream t => Int -> a -> t m a
288 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
290{-# INLINE fromIndicesM #-}
291fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
292fromIndicesM gen = go 0
294 go i = mkStream $ \st stp sng yld -> do
295 foldStreamShared st stp sng yld (gen i |: go (i + 1))
297{-# INLINE fromIndices #-}
298fromIndices :: IsStream t => (Int -> a) -> t m a
299fromIndices gen = go 0
301 go n = (gen n) `cons` go (n + 1)
303-------------------------------------------------------------------------------
305-------------------------------------------------------------------------------
309-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
312-- Construct a stream from a 'Foldable' containing pure values:
315{-# INLINE fromFoldable #-}
316fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
317fromFoldable = Prelude.foldr cons nil
319{-# INLINE fromList #-}
320fromList :: IsStream t => [a] -> t m a
321fromList = fromFoldable
323{-# INLINE fromStreamK #-}
324fromStreamK :: IsStream t => Stream m a -> t m a
325fromStreamK = fromStream
327-------------------------------------------------------------------------------
328-- Elimination by Folding
329-------------------------------------------------------------------------------
331-- | Lazy right associative fold.
333foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
334foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
336-- | Right associative fold to an arbitrary transformer monad.
338foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
339 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
340foldrT step final m = go m
343 res <- lift $ uncons m1
345 Just (h, t) -> step h (go t)
349foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
353 Nothing -> return Nothing
354 Just (h, t) -> fmap Just (go h t)
358 single a = return $ step a p
359 yieldk a r = fmap (step p) (go a r)
360 in foldStream defState yieldk single stp m1
362-- | Strict left fold with an extraction function. Like the standard strict
363-- left fold, but applies a user supplied extraction function (the third
364-- argument) to the folded value at the end. This is designed to work with the
365-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
367-- Note that the accumulator is always evaluated including the initial value.
368{-# INLINE foldlx' #-}
369foldlx' :: forall t m a b x. (IsStream t, Monad m)
370 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
371foldlx' step begin done m = get $ go m begin
376 -- XXX we are not strictly evaluating the accumulator here. Is this
378 let single = return . done
379 -- XXX this is foldSingleton. why foldStreamShared?
380 in foldStreamShared undefined undefined single undefined m1
382 -- Note, this can be implemented by making a recursive call to "go",
383 -- however that is more expensive because of unnecessary recursion
384 -- that cannot be tail call optimized. Unfolding recursion explicitly via
385 -- continuations is much more efficient.
386 go :: t m a -> x -> t m x
387 go m1 !acc = mkStream $ \_ yld sng _ ->
389 single a = sng $ step acc a
390 -- XXX this is foldNonEmptyStream
391 yieldk a r = foldStream defState yld sng undefined $
393 in foldStream defState yieldk single stop m1
395-- | Strict left associative fold.
397foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
398foldl' step begin = foldlx' step begin id
400-- XXX replace the recursive "go" with explicit continuations.
401-- | Like 'foldx', but with a monadic step function.
402{-# INLINABLE foldlMx' #-}
403foldlMx' :: (IsStream t, Monad m)
404 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
405foldlMx' step begin done m = go begin m
408 let stop = acc >>= done
409 single a = acc >>= \b -> step b a >>= done
410 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
411 in foldStream defState yieldk single stop m1
413-- | Like 'foldl'' but with a monadic step function.
414{-# INLINE foldlM' #-}
415foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
416foldlM' step begin = foldlMx' step (return begin) return
418-- | Lazy left fold to a stream.
420foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
421foldlS step begin m = go begin m
423 go acc rest = mkStream $ \st yld sng stp ->
424 let run x = foldStream st yld sng stp x
426 single a = run $ step acc a
427 yieldk a r = run $ go (step acc a) r
428 in foldStream (adaptState st) yieldk single stop rest
430-- | Lazy left fold to an arbitrary transformer monad.
432foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
433 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
434foldlT step begin m = go begin m
437 res <- lift $ uncons m1
439 Just (h, t) -> go (step acc h) t
442------------------------------------------------------------------------------
444------------------------------------------------------------------------------
446-- XXX use foldrM to implement folds where possible
447-- XXX This (commented) definition of drain and mapM_ perform much better on
448-- some benchmarks but worse on others. Need to investigate why, may there is
449-- an optimization opportunity that we can exploit.
450-- drain = foldrM (\_ xs -> return () >> xs) (return ())
453-- > drain = foldl' (\_ _ -> ()) ()
454-- > drain = mapM_ (\_ -> return ())
456drain :: (Monad m, IsStream t) => t m a -> m ()
457drain = foldrM (\_ xs -> xs) (return ())
465 in foldStream defState yieldk single stop m1
469null :: (IsStream t, Monad m) => t m a -> m Bool
470-- null = foldrM (\_ _ -> return True) (return False)
472 let stop = return True
473 single _ = return False
474 yieldk _ _ = return False
475 in foldStream defState yieldk single stop m
478head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
479-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
481 let stop = return Nothing
482 single a = return (Just a)
483 yieldk a _ = return (Just a)
484 in foldStream defState yieldk single stop m
487tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
489 let stop = return Nothing
490 single _ = return $ Just nil
491 yieldk _ r = return $ Just r
492 in foldStream defState yieldk single stop m
495init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
501 Nothing -> return Nothing
502 Just (h, t) -> return . Just $ go h t
503 go p m1 = mkStream $ \_ yld sng stp ->
505 yieldk a x = yld p $ go a x
506 in foldStream defState yieldk single stp m1
509elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
513 let stop = return False
514 single a = return (a == e)
515 yieldk a r = if a == e then return True else go r
516 in foldStream defState yieldk single stop m1
518{-# INLINE notElem #-}
519notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
523 let stop = return True
524 single a = return (a /= e)
525 yieldk a r = if a == e then return False else go r
526 in foldStream defState yieldk single stop m1
529all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
533 let single a | p a = return True
534 | otherwise = return False
535 yieldk a r | p a = go r
536 | otherwise = return False
537 in foldStream defState yieldk single (return True) m1
540any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
544 let single a | p a = return True
545 | otherwise = return False
546 yieldk a r | p a = return True
548 in foldStream defState yieldk single (return False) m1
550-- | Extract the last element of the stream, if any.
552last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
553last = foldlx' (\_ y -> Just y) Nothing id
555{-# INLINE minimum #-}
556minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
557minimum m = go Nothing m
560 let stop = return Nothing
561 single a = return (Just a)
562 yieldk a r = go (Just a) r
563 in foldStream defState yieldk single stop m1
566 let stop = return (Just res)
569 then return (Just res)
575 in foldStream defState yieldk single stop m1
577{-# INLINE minimumBy #-}
579 :: (IsStream t, Monad m)
580 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
581minimumBy cmp m = go Nothing m
584 let stop = return Nothing
585 single a = return (Just a)
586 yieldk a r = go (Just a) r
587 in foldStream defState yieldk single stop m1
590 let stop = return (Just res)
591 single a = case cmp res a of
592 GT -> return (Just a)
593 _ -> return (Just res)
594 yieldk a r = case cmp res a of
597 in foldStream defState yieldk single stop m1
599{-# INLINE maximum #-}
600maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
601maximum m = go Nothing m
604 let stop = return Nothing
605 single a = return (Just a)
606 yieldk a r = go (Just a) r
607 in foldStream defState yieldk single stop m1
610 let stop = return (Just res)
614 else return (Just res)
619 in foldStream defState yieldk single stop m1
621{-# INLINE maximumBy #-}
622maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
623maximumBy cmp m = go Nothing m
626 let stop = return Nothing
627 single a = return (Just a)
628 yieldk a r = go (Just a) r
629 in foldStream defState yieldk single stop m1
632 let stop = return (Just res)
633 single a = case cmp res a of
634 GT -> return (Just res)
636 yieldk a r = case cmp res a of
637 GT -> go (Just res) r
639 in foldStream defState yieldk single stop m1
642(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
646 let single a | n == 0 = return $ Just a
647 | otherwise = return Nothing
648 yieldk a x | n < 0 = return Nothing
649 | n == 0 = return $ Just a
650 | otherwise = go (n - 1) x
651 in foldStream defState yieldk single (return Nothing) m1
654lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
658 let single (a, b) | a == e = return $ Just b
659 | otherwise = return Nothing
660 yieldk (a, b) x | a == e = return $ Just b
662 in foldStream defState yieldk single (return Nothing) m1
665findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
671 if b then return $ Just a else return Nothing
674 if b then return $ Just a else go x
675 in foldStream defState yieldk single (return Nothing) m1
678find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
679find p = findM (return . p)
681{-# INLINE findIndices #-}
682findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
685 go offset m1 = mkStream $ \st yld sng stp ->
686 let single a | p a = sng offset
688 yieldk a x | p a = yld offset $ go (offset + 1) x
689 | otherwise = foldStream (adaptState st) yld sng stp $
691 in foldStream (adaptState st) yieldk single stp m1
693------------------------------------------------------------------------------
695------------------------------------------------------------------------------
697-- | Apply a monadic action to each element of the stream and discard the
698-- output of the action.
700mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
705 single a = void (f a)
706 yieldk a r = f a >> go r
707 in foldStream defState yieldk single stop m1
709------------------------------------------------------------------------------
711------------------------------------------------------------------------------
713{-# INLINABLE toList #-}
714toList :: (IsStream t, Monad m) => t m a -> m [a]
717{-# INLINE toStreamK #-}
718toStreamK :: Stream m a -> Stream m a
721-------------------------------------------------------------------------------
722-- Transformation by folding (Scans)
723-------------------------------------------------------------------------------
725{-# INLINE scanlx' #-}
726scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
727scanlx' step begin done m =
728 cons (done begin) $ go m begin
730 go m1 !acc = mkStream $ \st yld sng stp ->
731 let single a = sng (done $ step acc a)
734 in yld (done s) (go r s)
735 in foldStream (adaptState st) yieldk single stp m1
738scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
739scanl' step begin = scanlx' step begin id
741-------------------------------------------------------------------------------
743-------------------------------------------------------------------------------
746filter :: IsStream t => (a -> Bool) -> t m a -> t m a
749 go m1 = mkStream $ \st yld sng stp ->
750 let single a | p a = sng a
752 yieldk a r | p a = yld a (go r)
753 | otherwise = foldStream st yieldk single stp r
754 in foldStream st yieldk single stp m1
757take :: IsStream t => Int -> t m a -> t m a
760 go n1 m1 = mkStream $ \st yld sng stp ->
761 let yieldk a r = yld a (go (n1 - 1) r)
764 else foldStream st yieldk sng stp m1
766{-# INLINE takeWhile #-}
767takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
770 go m1 = mkStream $ \st yld sng stp ->
771 let single a | p a = sng a
773 yieldk a r | p a = yld a (go r)
775 in foldStream st yieldk single stp m1
778drop :: IsStream t => Int -> t m a -> t m a
779drop n m = fromStream $ unShare (go n (toStream m))
781 go n1 m1 = mkStream $ \st yld sng stp ->
783 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
784 -- Somehow "<=" check performs better than a ">"
786 then foldStreamShared st yld sng stp m1
787 else foldStreamShared st yieldk single stp m1
789{-# INLINE dropWhile #-}
790dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
793 go m1 = mkStream $ \st yld sng stp ->
794 let single a | p a = stp
796 yieldk a r | p a = foldStream st yieldk single stp r
797 | otherwise = yld a r
798 in foldStream st yieldk single stp m1
800-------------------------------------------------------------------------------
802-------------------------------------------------------------------------------
804-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
805-- other stream types to overload it.
806{-# INLINE sequence #-}
807sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
810 go m1 = mkStream $ \st yld sng stp ->
811 let single ma = ma >>= sng
812 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
813 in foldStream (adaptState st) yieldk single stp m1
815-------------------------------------------------------------------------------
817-------------------------------------------------------------------------------
819{-# INLINE intersperseM #-}
820intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
821intersperseM a m = prependingStart m
823 prependingStart m1 = mkStream $ \st yld sng stp ->
824 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
825 in foldStream st yieldk sng stp m1
826 go m2 = mkStream $ \st yld sng stp ->
827 let single i = foldStreamShared st yld sng stp $ a |: yield i
828 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
829 in foldStream st yieldk single stp m2
831{-# INLINE intersperse #-}
832intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
833intersperse a = intersperseM (return a)
835{-# INLINE insertBy #-}
836insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
837insertBy cmp x m = go m
839 go m1 = mkStream $ \st yld _ _ ->
840 let single a = case cmp x a of
841 GT -> yld a (yield x)
844 yieldk a r = case cmp x a of
846 _ -> yld x (a `cons` r)
847 in foldStream st yieldk single stop m1
849------------------------------------------------------------------------------
851------------------------------------------------------------------------------
853{-# INLINE deleteBy #-}
854deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
855deleteBy eq x m = go m
857 go m1 = mkStream $ \st yld sng stp ->
858 let single a = if eq x a then stp else sng a
859 yieldk a r = if eq x a
860 then foldStream st yld sng stp r
862 in foldStream st yieldk single stp m1
864------------------------------------------------------------------------------
866------------------------------------------------------------------------------
868{-# INLINE reverse #-}
869reverse :: IsStream t => t m a -> t m a
870reverse = foldlS (flip cons) nil
872-------------------------------------------------------------------------------
874-------------------------------------------------------------------------------
876{-# INLINE mapMaybe #-}
877mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
880 go m1 = mkStream $ \st yld sng stp ->
881 let single a = case f a of
884 yieldk a r = case f a of
885 Just b -> yld b $ go r
886 Nothing -> foldStream (adaptState st) yieldk single stp r
887 in foldStream (adaptState st) yieldk single stp m1
889------------------------------------------------------------------------------
891------------------------------------------------------------------------------
893-- | Zip two streams serially using a pure zipping function.
896{-# INLINABLE zipWith #-}
897zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
900 go mx my = mkStream $ \st yld sng stp -> do
902 let single2 b = sng (f a b)
903 yield2 b rb = yld (f a b) (go ra rb)
904 in foldStream (adaptState st) yield2 single2 stp my
905 let single1 a = merge a nil
907 foldStream (adaptState st) yield1 single1 stp mx
909-- | Zip two streams serially using a monadic zipping function.
912{-# INLINABLE zipWithM #-}
913zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
914zipWithM f m1 m2 = go m1 m2
916 go mx my = mkStream $ \st yld sng stp -> do
918 let runIt x = foldStream st yld sng stp x
919 single2 b = f a b >>= sng
920 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
921 in foldStream (adaptState st) yield2 single2 stp my
922 let single1 a = merge a nil
924 foldStream (adaptState st) yield1 single1 stp mx
926------------------------------------------------------------------------------
928------------------------------------------------------------------------------
930{-# INLINE mergeByM #-}
932 :: (IsStream t, Monad m)
933 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
936 go mx my = mkStream $ \st yld sng stp -> do
937 let mergeWithY a ra =
938 let stop2 = foldStream st yld sng stp mx
942 GT -> yld b (go (a `cons` ra) nil)
943 _ -> yld a (go ra (b `cons` nil))
947 GT -> yld b (go (a `cons` ra) rb)
948 _ -> yld a (go ra (b `cons` rb))
949 in foldStream st yield2 single2 stop2 my
950 let stopX = foldStream st yld sng stp my
951 singleX a = mergeWithY a nil
953 foldStream st yieldX singleX stopX mx
955{-# INLINABLE mergeBy #-}
957 :: (IsStream t, Monad m)
958 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
959mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
961------------------------------------------------------------------------------
962-- Transformation comprehensions
963------------------------------------------------------------------------------
966the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
970 Nothing -> return Nothing
971 Just (h, t) -> go h t
974 let single a | h == a = return $ Just h
975 | otherwise = return Nothing
976 yieldk a r | h == a = go h r
977 | otherwise = return Nothing
978 in foldStream defState yieldk single (return $ Just h) m1
980------------------------------------------------------------------------------
981-- Alternative & MonadPlus
982------------------------------------------------------------------------------
984_alt :: Stream m a -> Stream m a -> Stream m a
985_alt m1 m2 = mkStream $ \st yld sng stp ->
986 let stop = foldStream st yld sng stp m2
987 in foldStream st yld sng stop m1
989------------------------------------------------------------------------------
991------------------------------------------------------------------------------
993{-# INLINABLE withLocal #-}
994withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
996 mkStream $ \st yld sng stp ->
997 let single = local f . sng
998 yieldk a r = local f $ yld a (withLocal f r)
999 in foldStream st yieldk single (local f stp) m
1001------------------------------------------------------------------------------
1003------------------------------------------------------------------------------
1006-- XXX handle and test cross thread state transfer
1009 => Stream m a -> (e -> Stream m a) -> Stream m a
1011 mkStream $ \_ stp sng yld ->
1012 let run x = unStream x Nothing stp sng yieldk
1013 handle r = r `catchError` \e -> run $ h e
1014 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