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
46 -- * Elimination Primitives
51 -- * Transformation Primitives
62 -- ** Specialized Generation
98 -- ** Specialized Folds
127 -- ** By folding (scans)
171 -- ** Transformation comprehensions
174 -- * Semigroup Style Composition
182 , Streaming -- deprecated
187import Control.Monad.Trans (MonadTrans(lift))
188import Control.Monad (void)
189import Control.Monad.Reader.Class (MonadReader(..))
191 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
192 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
193 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
194 foldr1, (!!), replicate, reverse, concatMap)
195import qualified Prelude
198import Streamly.Streams.StreamK.Type
200-------------------------------------------------------------------------------
202-------------------------------------------------------------------------------
205uncons :: (IsStream t, Monad m) => t m a -> m (Maybe (a, t m a))
207 let stop = return Nothing
208 single a = return (Just (a, nil))
209 yieldk a r = return (Just (a, r))
210 in foldStream defState yieldk single stop m
212-------------------------------------------------------------------------------
214-------------------------------------------------------------------------------
216{-# INLINE unfoldr #-}
217unfoldr :: IsStream t => (b -> Maybe (a, b)) -> b -> t m a
220 go s = buildS $ \yld stp ->
222 Just (a, b) -> yld a (go b)
225{-# INLINE unfoldrM #-}
226unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
229 go s = sharedM $ \yld _ stp -> do
232 Just (a, b) -> yld a (go b)
236-- Generalization of concurrent streams/SVar via unfoldr.
238-- Unfold a value into monadic actions and then run the resulting monadic
239-- actions to generate a stream. Since the step of generating the monadic
240-- action and running them are decoupled we can run the monadic actions
241-- cooncurrently. For example, the seed could be a list of monadic actions or a
242-- pure stream of monadic actions.
244-- We can have different flavors of this depending on the stream type t. The
245-- concurrent version could be async or ahead etc. Depending on how we queue
246-- back the feedback portion b, it could be DFS or BFS style.
248unfoldrA :: (IsStream t, MonadAsync m) => (b -> Maybe (m a, b)) -> b -> t m a
252-------------------------------------------------------------------------------
254-------------------------------------------------------------------------------
259{-# DEPRECATED once "Please use yieldM instead." #-}
261once :: (Monad m, IsStream t) => m a -> t m a
266-- repeatM = fix . cons
267-- repeatM = cycle1 . yield
270-- Generate an infinite stream by repeating a pure value.
274repeat :: IsStream t => a -> t m a
275repeat a = let x = cons a x in x
277{-# INLINE replicateM #-}
278replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
281 go cnt = if cnt <= 0 then nil else m |: go (cnt - 1)
283{-# INLINE replicate #-}
284replicate :: IsStream t => Int -> a -> t m a
287 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
289{-# INLINE fromIndicesM #-}
290fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
291fromIndicesM gen = go 0
293 go i = mkStream $ \st stp sng yld -> do
294 foldStreamShared st stp sng yld (gen i |: go (i + 1))
296{-# INLINE fromIndices #-}
297fromIndices :: IsStream t => (Int -> a) -> t m a
298fromIndices gen = go 0
300 go n = (gen n) `cons` go (n + 1)
302-------------------------------------------------------------------------------
304-------------------------------------------------------------------------------
308-- fromFoldable = 'Prelude.foldr' 'cons' 'nil'
311-- Construct a stream from a 'Foldable' containing pure values:
314{-# INLINE fromFoldable #-}
315fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
316fromFoldable = Prelude.foldr cons nil
318{-# INLINE fromList #-}
319fromList :: IsStream t => [a] -> t m a
320fromList = fromFoldable
322{-# INLINE fromStreamK #-}
323fromStreamK :: IsStream t => Stream m a -> t m a
324fromStreamK = fromStream
326-------------------------------------------------------------------------------
327-- Elimination by Folding
328-------------------------------------------------------------------------------
330-- | Lazy right associative fold.
332foldr :: (IsStream t, Monad m) => (a -> b -> b) -> b -> t m a -> m b
333foldr step acc = foldrM (\x xs -> xs >>= \b -> return (step x b)) (return acc)
335-- | Right associative fold to an arbitrary transformer monad.
337foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
338 => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
339foldrT step final m = go m
342 res <- lift $ uncons m1
344 Just (h, t) -> step h (go t)
348foldr1 :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> m (Maybe a)
352 Nothing -> return Nothing
353 Just (h, t) -> fmap Just (go h t)
357 single a = return $ step a p
358 yieldk a r = fmap (step p) (go a r)
359 in foldStream defState yieldk single stp m1
361-- | Strict left fold with an extraction function. Like the standard strict
362-- left fold, but applies a user supplied extraction function (the third
363-- argument) to the folded value at the end. This is designed to work with the
364-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
366-- Note that the accumulator is always evaluated including the initial value.
367{-# INLINE foldlx' #-}
368foldlx' :: forall t m a b x. (IsStream t, Monad m)
369 => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b
370foldlx' step begin done m = get $ go m begin
375 -- XXX we are not strictly evaluating the accumulator here. Is this
377 let single = return . done
378 -- XXX this is foldSingleton. why foldStreamShared?
379 in foldStreamShared undefined undefined single undefined m1
381 -- Note, this can be implemented by making a recursive call to "go",
382 -- however that is more expensive because of unnecessary recursion
383 -- that cannot be tail call optimized. Unfolding recursion explicitly via
384 -- continuations is much more efficient.
385 go :: t m a -> x -> t m x
386 go m1 !acc = mkStream $ \_ yld sng _ ->
388 single a = sng $ step acc a
389 -- XXX this is foldNonEmptyStream
390 yieldk a r = foldStream defState yld sng undefined $
392 in foldStream defState yieldk single stop m1
394-- | Strict left associative fold.
396foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b
397foldl' step begin = foldlx' step begin id
399-- XXX replace the recursive "go" with explicit continuations.
400-- | Like 'foldx', but with a monadic step function.
401{-# INLINABLE foldlMx' #-}
402foldlMx' :: (IsStream t, Monad m)
403 => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b
404foldlMx' step begin done m = go begin m
407 let stop = acc >>= done
408 single a = acc >>= \b -> step b a >>= done
409 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
410 in foldStream defState yieldk single stop m1
412-- | Like 'foldl'' but with a monadic step function.
413{-# INLINE foldlM' #-}
414foldlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> m b
415foldlM' step begin = foldlMx' step (return begin) return
417-- | Lazy left fold to a stream.
419foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b
420foldlS step begin m = go begin m
422 go acc rest = mkStream $ \st yld sng stp ->
423 let run x = foldStream st yld sng stp x
425 single a = run $ step acc a
426 yieldk a r = run $ go (step acc a) r
427 in foldStream (adaptState st) yieldk single stop rest
429-- | Lazy left fold to an arbitrary transformer monad.
431foldlT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
432 => (s m b -> a -> s m b) -> s m b -> t m a -> s m b
433foldlT step begin m = go begin m
436 res <- lift $ uncons m1
438 Just (h, t) -> go (step acc h) t
441------------------------------------------------------------------------------
443------------------------------------------------------------------------------
445-- XXX use foldrM to implement folds where possible
446-- XXX This (commented) definition of drain and mapM_ perform much better on
447-- some benchmarks but worse on others. Need to investigate why, may there is
448-- an optimization opportunity that we can exploit.
449-- drain = foldrM (\_ xs -> return () >> xs) (return ())
452-- > drain = foldl' (\_ _ -> ()) ()
453-- > drain = mapM_ (\_ -> return ())
455drain :: (Monad m, IsStream t) => t m a -> m ()
456drain = foldrM (\_ xs -> xs) (return ())
464 in foldStream defState yieldk single stop m1
468null :: (IsStream t, Monad m) => t m a -> m Bool
469-- null = foldrM (\_ _ -> return True) (return False)
471 let stop = return True
472 single _ = return False
473 yieldk _ _ = return False
474 in foldStream defState yieldk single stop m
477head :: (IsStream t, Monad m) => t m a -> m (Maybe a)
478-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
480 let stop = return Nothing
481 single a = return (Just a)
482 yieldk a _ = return (Just a)
483 in foldStream defState yieldk single stop m
486tail :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
488 let stop = return Nothing
489 single _ = return $ Just nil
490 yieldk _ r = return $ Just r
491 in foldStream defState yieldk single stop m
494init :: (IsStream t, Monad m) => t m a -> m (Maybe (t m a))
500 Nothing -> return Nothing
501 Just (h, t) -> return . Just $ go h t
502 go p m1 = mkStream $ \_ yld sng stp ->
504 yieldk a x = yld p $ go a x
505 in foldStream defState yieldk single stp m1
508elem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
512 let stop = return False
513 single a = return (a == e)
514 yieldk a r = if a == e then return True else go r
515 in foldStream defState yieldk single stop m1
517{-# INLINE notElem #-}
518notElem :: (IsStream t, Monad m, Eq a) => a -> t m a -> m Bool
522 let stop = return True
523 single a = return (a /= e)
524 yieldk a r = if a == e then return False else go r
525 in foldStream defState yieldk single stop m1
528all :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
532 let single a | p a = return True
533 | otherwise = return False
534 yieldk a r | p a = go r
535 | otherwise = return False
536 in foldStream defState yieldk single (return True) m1
539any :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m Bool
543 let single a | p a = return True
544 | otherwise = return False
545 yieldk a r | p a = return True
547 in foldStream defState yieldk single (return False) m1
549-- | Extract the last element of the stream, if any.
551last :: (IsStream t, Monad m) => t m a -> m (Maybe a)
552last = foldlx' (\_ y -> Just y) Nothing id
554{-# INLINE minimum #-}
555minimum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
556minimum m = go Nothing m
559 let stop = return Nothing
560 single a = return (Just a)
561 yieldk a r = go (Just a) r
562 in foldStream defState yieldk single stop m1
565 let stop = return (Just res)
568 then return (Just res)
574 in foldStream defState yieldk single stop m1
576{-# INLINE minimumBy #-}
578 :: (IsStream t, Monad m)
579 => (a -> a -> Ordering) -> t m a -> m (Maybe a)
580minimumBy cmp m = go Nothing m
583 let stop = return Nothing
584 single a = return (Just a)
585 yieldk a r = go (Just a) r
586 in foldStream defState yieldk single stop m1
589 let stop = return (Just res)
590 single a = case cmp res a of
591 GT -> return (Just a)
592 _ -> return (Just res)
593 yieldk a r = case cmp res a of
596 in foldStream defState yieldk single stop m1
598{-# INLINE maximum #-}
599maximum :: (IsStream t, Monad m, Ord a) => t m a -> m (Maybe a)
600maximum m = go Nothing m
603 let stop = return Nothing
604 single a = return (Just a)
605 yieldk a r = go (Just a) r
606 in foldStream defState yieldk single stop m1
609 let stop = return (Just res)
613 else return (Just res)
618 in foldStream defState yieldk single stop m1
620{-# INLINE maximumBy #-}
621maximumBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> m (Maybe a)
622maximumBy cmp m = go Nothing m
625 let stop = return Nothing
626 single a = return (Just a)
627 yieldk a r = go (Just a) r
628 in foldStream defState yieldk single stop m1
631 let stop = return (Just res)
632 single a = case cmp res a of
633 GT -> return (Just res)
635 yieldk a r = case cmp res a of
636 GT -> go (Just res) r
638 in foldStream defState yieldk single stop m1
641(!!) :: (IsStream t, Monad m) => t m a -> Int -> m (Maybe a)
645 let single a | n == 0 = return $ Just a
646 | otherwise = return Nothing
647 yieldk a x | n < 0 = return Nothing
648 | n == 0 = return $ Just a
649 | otherwise = go (n - 1) x
650 in foldStream defState yieldk single (return Nothing) m1
653lookup :: (IsStream t, Monad m, Eq a) => a -> t m (a, b) -> m (Maybe b)
657 let single (a, b) | a == e = return $ Just b
658 | otherwise = return Nothing
659 yieldk (a, b) x | a == e = return $ Just b
661 in foldStream defState yieldk single (return Nothing) m1
664findM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> m (Maybe a)
670 if b then return $ Just a else return Nothing
673 if b then return $ Just a else go x
674 in foldStream defState yieldk single (return Nothing) m1
677find :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> m (Maybe a)
678find p = findM (return . p)
680{-# INLINE findIndices #-}
681findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
684 go offset m1 = mkStream $ \st yld sng stp ->
685 let single a | p a = sng offset
687 yieldk a x | p a = yld offset $ go (offset + 1) x
688 | otherwise = foldStream (adaptState st) yld sng stp $
690 in foldStream (adaptState st) yieldk single stp m1
692------------------------------------------------------------------------------
694------------------------------------------------------------------------------
696-- | Apply a monadic action to each element of the stream and discard the
697-- output of the action.
699mapM_ :: (IsStream t, Monad m) => (a -> m b) -> t m a -> m ()
704 single a = void (f a)
705 yieldk a r = f a >> go r
706 in foldStream defState yieldk single stop m1
708------------------------------------------------------------------------------
710------------------------------------------------------------------------------
712{-# INLINABLE toList #-}
713toList :: (IsStream t, Monad m) => t m a -> m [a]
716{-# INLINE toStreamK #-}
717toStreamK :: Stream m a -> Stream m a
720-------------------------------------------------------------------------------
721-- Transformation by folding (Scans)
722-------------------------------------------------------------------------------
724{-# INLINE scanlx' #-}
725scanlx' :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
726scanlx' step begin done m =
727 cons (done begin) $ go m begin
729 go m1 !acc = mkStream $ \st yld sng stp ->
730 let single a = sng (done $ step acc a)
733 in yld (done s) (go r s)
734 in foldStream (adaptState st) yieldk single stp m1
737scanl' :: IsStream t => (b -> a -> b) -> b -> t m a -> t m b
738scanl' step begin = scanlx' step begin id
740-------------------------------------------------------------------------------
742-------------------------------------------------------------------------------
745filter :: IsStream t => (a -> Bool) -> t m a -> t m a
748 go m1 = mkStream $ \st yld sng stp ->
749 let single a | p a = sng a
751 yieldk a r | p a = yld a (go r)
752 | otherwise = foldStream st yieldk single stp r
753 in foldStream st yieldk single stp m1
756take :: IsStream t => Int -> t m a -> t m a
759 go n1 m1 = mkStream $ \st yld sng stp ->
760 let yieldk a r = yld a (go (n1 - 1) r)
763 else foldStream st yieldk sng stp m1
765{-# INLINE takeWhile #-}
766takeWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
769 go m1 = mkStream $ \st yld sng stp ->
770 let single a | p a = sng a
772 yieldk a r | p a = yld a (go r)
774 in foldStream st yieldk single stp m1
777drop :: IsStream t => Int -> t m a -> t m a
778drop n m = fromStream $ unShare (go n (toStream m))
780 go n1 m1 = mkStream $ \st yld sng stp ->
782 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
783 -- Somehow "<=" check performs better than a ">"
785 then foldStreamShared st yld sng stp m1
786 else foldStreamShared st yieldk single stp m1
788{-# INLINE dropWhile #-}
789dropWhile :: IsStream t => (a -> Bool) -> t m a -> t m a
792 go m1 = mkStream $ \st yld sng stp ->
793 let single a | p a = stp
795 yieldk a r | p a = foldStream st yieldk single stp r
796 | otherwise = yld a r
797 in foldStream st yieldk single stp m1
799-------------------------------------------------------------------------------
801-------------------------------------------------------------------------------
803-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
804-- other stream types to overload it.
805{-# INLINE sequence #-}
806sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
809 go m1 = mkStream $ \st yld sng stp ->
810 let single ma = ma >>= sng
811 yieldk ma r = foldStreamShared st yld sng stp $ ma |: go r
812 in foldStream (adaptState st) yieldk single stp m1
814-------------------------------------------------------------------------------
816-------------------------------------------------------------------------------
818{-# INLINE intersperseM #-}
819intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
820intersperseM a m = prependingStart m
822 prependingStart m1 = mkStream $ \st yld sng stp ->
823 let yieldk i x = foldStreamShared st yld sng stp $ return i |: go x
824 in foldStream st yieldk sng stp m1
825 go m2 = mkStream $ \st yld sng stp ->
826 let single i = foldStreamShared st yld sng stp $ a |: yield i
827 yieldk i x = foldStreamShared st yld sng stp $ a |: return i |: go x
828 in foldStream st yieldk single stp m2
830{-# INLINE intersperse #-}
831intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
832intersperse a = intersperseM (return a)
834{-# INLINE insertBy #-}
835insertBy :: IsStream t => (a -> a -> Ordering) -> a -> t m a -> t m a
836insertBy cmp x m = go m
838 go m1 = mkStream $ \st yld _ _ ->
839 let single a = case cmp x a of
840 GT -> yld a (yield x)
843 yieldk a r = case cmp x a of
845 _ -> yld x (a `cons` r)
846 in foldStream st yieldk single stop m1
848------------------------------------------------------------------------------
850------------------------------------------------------------------------------
852{-# INLINE deleteBy #-}
853deleteBy :: IsStream t => (a -> a -> Bool) -> a -> t m a -> t m a
854deleteBy eq x m = go m
856 go m1 = mkStream $ \st yld sng stp ->
857 let single a = if eq x a then stp else sng a
858 yieldk a r = if eq x a
859 then foldStream st yld sng stp r
861 in foldStream st yieldk single stp m1
863------------------------------------------------------------------------------
865------------------------------------------------------------------------------
867{-# INLINE reverse #-}
868reverse :: IsStream t => t m a -> t m a
869reverse = foldlS (flip cons) nil
871-------------------------------------------------------------------------------
873-------------------------------------------------------------------------------
875{-# INLINE mapMaybe #-}
876mapMaybe :: IsStream t => (a -> Maybe b) -> t m a -> t m b
879 go m1 = mkStream $ \st yld sng stp ->
880 let single a = case f a of
883 yieldk a r = case f a of
884 Just b -> yld b $ go r
885 Nothing -> foldStream (adaptState st) yieldk single stp r
886 in foldStream (adaptState st) yieldk single stp m1
888------------------------------------------------------------------------------
890------------------------------------------------------------------------------
892-- | Zip two streams serially using a pure zipping function.
895{-# INLINABLE zipWith #-}
896zipWith :: IsStream t => (a -> b -> c) -> t m a -> t m b -> t m c
899 go mx my = mkStream $ \st yld sng stp -> do
901 let single2 b = sng (f a b)
902 yield2 b rb = yld (f a b) (go ra rb)
903 in foldStream (adaptState st) yield2 single2 stp my
904 let single1 a = merge a nil
906 foldStream (adaptState st) yield1 single1 stp mx
908-- | Zip two streams serially using a monadic zipping function.
911{-# INLINABLE zipWithM #-}
912zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
913zipWithM f m1 m2 = go m1 m2
915 go mx my = mkStream $ \st yld sng stp -> do
917 let runIt x = foldStream st yld sng stp x
918 single2 b = f a b >>= sng
919 yield2 b rb = f a b >>= \x -> runIt (x `cons` go ra rb)
920 in foldStream (adaptState st) yield2 single2 stp my
921 let single1 a = merge a nil
923 foldStream (adaptState st) yield1 single1 stp mx
925------------------------------------------------------------------------------
927------------------------------------------------------------------------------
929{-# INLINE mergeByM #-}
931 :: (IsStream t, Monad m)
932 => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
935 go mx my = mkStream $ \st yld sng stp -> do
936 let mergeWithY a ra =
937 let stop2 = foldStream st yld sng stp mx
941 GT -> yld b (go (a `cons` ra) nil)
942 _ -> yld a (go ra (b `cons` nil))
946 GT -> yld b (go (a `cons` ra) rb)
947 _ -> yld a (go ra (b `cons` rb))
948 in foldStream st yield2 single2 stop2 my
949 let stopX = foldStream st yld sng stp my
950 singleX a = mergeWithY a nil
952 foldStream st yieldX singleX stopX mx
954{-# INLINABLE mergeBy #-}
956 :: (IsStream t, Monad m)
957 => (a -> a -> Ordering) -> t m a -> t m a -> t m a
958mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
960------------------------------------------------------------------------------
961-- Transformation comprehensions
962------------------------------------------------------------------------------
965the :: (Eq a, IsStream t, Monad m) => t m a -> m (Maybe a)
969 Nothing -> return Nothing
970 Just (h, t) -> go h t
973 let single a | h == a = return $ Just h
974 | otherwise = return Nothing
975 yieldk a r | h == a = go h r
976 | otherwise = return Nothing
977 in foldStream defState yieldk single (return $ Just h) m1
979------------------------------------------------------------------------------
980-- Alternative & MonadPlus
981------------------------------------------------------------------------------
983_alt :: Stream m a -> Stream m a -> Stream m a
984_alt m1 m2 = mkStream $ \st yld sng stp ->
985 let stop = foldStream st yld sng stp m2
986 in foldStream st yld sng stop m1
988------------------------------------------------------------------------------
990------------------------------------------------------------------------------
992{-# INLINABLE withLocal #-}
993withLocal :: MonadReader r m => (r -> r) -> Stream m a -> Stream m a
995 mkStream $ \st yld sng stp ->
996 let single = local f . sng
997 yieldk a r = local f $ yld a (withLocal f r)
998 in foldStream st yieldk single (local f stp) m
1000------------------------------------------------------------------------------
1002------------------------------------------------------------------------------
1005-- XXX handle and test cross thread state transfer
1008 => Stream m a -> (e -> Stream m a) -> Stream m a
1010 mkStream $ \_ stp sng yld ->
1011 let run x = unStream x Nothing stp sng yieldk
1012 handle r = r `catchError` \e -> run $ h e
1013 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