3-- Module : Streamly.Internal.Data.StreamK
4-- Copyright : (c) 2017 Composewell Technologies
7-- Maintainer : streamly@composewell.com
8-- Stability : experimental
11module Streamly.Internal.Data.StreamK
14 -- | To execute the code examples provided in this module in ghci, please
15 -- run the following commands first.
20 module Streamly.Internal.Data.StreamK.Type
21 , module Streamly.Internal.Data.StreamK.Transformer
28 -- ** Specialized Generation
52 , parseBreakChunksGeneric
55 -- ** Specialized Folds
80 -- ** By folding (scans)
117 -- ** Transformation comprehensions
123 -- * Resource Management
128#include "ArrayMacros.h"
132import Control.Exception (mask_, Exception)
133import Control.Monad (void, join)
134import Control.Monad.Catch (MonadCatch)
135import Control.Monad.IO.Class (MonadIO(..))
136import Data.Proxy (Proxy(..))
137import GHC.Types (SPEC(..))
138import Streamly.Internal.Data.Array.Type (Array(..))
139import Streamly.Internal.Data.Fold.Type (Fold(..))
140import Streamly.Internal.Data.IOFinalizer (newIOFinalizer, runIOFinalizer)
141import Streamly.Internal.Data.ParserK.Type (ParserK)
142import Streamly.Internal.Data.Producer.Type (Producer(..))
143import Streamly.Internal.Data.SVar.Type (adaptState, defState)
144import Streamly.Internal.Data.Unbox (sizeOf, Unbox)
146import qualified Control.Monad.Catch as MC
147import qualified Streamly.Internal.Data.Array.Type as Array
148import qualified Streamly.Internal.Data.Array.Generic as GenArr
149import qualified Streamly.Internal.Data.Fold.Type as FL
150import qualified Streamly.Internal.Data.Parser as Parser
151import qualified Streamly.Internal.Data.Parser.Type as PR
152import qualified Streamly.Internal.Data.ParserK.Type as ParserK
153import qualified Streamly.Internal.Data.Stream as Stream
154import qualified Prelude
157 hiding (Foldable(..), last, map, mapM, mapM_, repeat, sequence,
158 take, filter, all, any, takeWhile, drop, dropWhile,
159 notElem, head, tail, init, zipWith, lookup,
160 (!!), replicate, reverse, concatMap, iterate, splitAt)
161import Data.Foldable (sum, length)
162import Streamly.Internal.Data.StreamK.Type
163import Streamly.Internal.Data.StreamK.Transformer
164import Streamly.Internal.Data.Parser (ParseError(..))
166#include "DocTestDataStreamK.hs"
168-- | Convert a fused 'Stream' to 'StreamK'.
172-- >>> s1 = StreamK.fromStream $ Stream.fromList [1,2]
173-- >>> s2 = StreamK.fromStream $ Stream.fromList [3,4]
174-- >>> Stream.fold Fold.toList $ StreamK.toStream $ s1 `StreamK.append` s2
177{-# INLINE fromStream #-}
178fromStream :: Monad m => Stream.Stream m a -> StreamK m a
179fromStream = Stream.toStreamK
181-- | Convert a 'StreamK' to a fused 'Stream'.
183{-# INLINE toStream #-}
184toStream :: Applicative m => StreamK m a -> Stream.Stream m a
185toStream = Stream.fromStreamK
187-------------------------------------------------------------------------------
189-------------------------------------------------------------------------------
192-- Generalization of concurrent streams/SVar via unfoldr.
194-- Unfold a value into monadic actions and then run the resulting monadic
195-- actions to generate a stream. Since the step of generating the monadic
196-- action and running them are decoupled we can run the monadic actions
197-- cooncurrently. For example, the seed could be a list of monadic actions or a
198-- pure stream of monadic actions.
200-- We can have different flavors of this depending on the stream type t. The
201-- concurrent version could be async or ahead etc. Depending on how we queue
202-- back the feedback portion b, it could be DFS or BFS style.
204unfoldrA :: (b -> Maybe (m a, b)) -> b -> StreamK m a
208-------------------------------------------------------------------------------
210-------------------------------------------------------------------------------
213-- >>> repeatM = StreamK.sequence . StreamK.repeat
214-- >>> repeatM = fix . StreamK.consM
215-- >>> repeatM = cycle1 . StreamK.fromEffect
217-- Generate a stream by repeatedly executing a monadic action forever.
221-- StreamK.repeatM (threadDelay 1000000 >> print 1)
223-- & StreamK.fold Fold.drain
226repeatM :: Monad m => m a -> StreamK m a
227repeatM = repeatMWith consM
229{-# INLINE replicateM #-}
230replicateM :: Monad m => Int -> m a -> StreamK m a
231replicateM = replicateMWith consM
232{-# INLINE replicate #-}
233replicate :: Int -> a -> StreamK m a
236 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
238{-# INLINE fromIndicesM #-}
239fromIndicesM :: Monad m => (Int -> m a) -> StreamK m a
240fromIndicesM = fromIndicesMWith consM
241{-# INLINE fromIndices #-}
242fromIndices :: (Int -> a) -> StreamK m a
243fromIndices gen = go 0
245 go n = gen n `cons` go (n + 1)
248-- >>> iterate f x = x `StreamK.cons` iterate f x
250-- Generate an infinite stream with @x@ as the first element and each
251-- successive element derived by applying the function @f@ on the previous
254-- >>> StreamK.toList $ StreamK.take 5 $ StreamK.iterate (+1) 1
257{-# INLINE iterate #-}
258iterate :: (a -> a) -> a -> StreamK m a
261 go !s = cons s (go (step s))
264-- >>> iterateM f m = m >>= \a -> return a `StreamK.consM` iterateM f (f a)
266-- Generate an infinite stream with the first element generated by the action
267-- @m@ and each successive element derived by applying the monadic function
268-- @f@ on the previous element.
271-- StreamK.iterateM (\x -> print x >> return (x + 1)) (return 0)
279{-# INLINE iterateM #-}
280iterateM :: Monad m => (a -> m a) -> m a -> StreamK m a
281iterateM = iterateMWith consM
283-------------------------------------------------------------------------------
285-------------------------------------------------------------------------------
287{-# INLINE fromList #-}
288fromList :: [a] -> StreamK m a
289fromList = fromFoldable
291-------------------------------------------------------------------------------
292-- Elimination by Folding
293-------------------------------------------------------------------------------
296foldr1 :: Monad m => (a -> a -> a) -> StreamK m a -> m (Maybe a)
300 Nothing -> return Nothing
301 Just (h, t) -> fmap Just (go h t)
305 single a = return $ step a p
306 yieldk a r = fmap (step p) (go a r)
307 in foldStream defState yieldk single stp m1
309-- XXX replace the recursive "go" with explicit continuations.
310-- | Like 'foldx', but with a monadic step function.
311{-# INLINABLE foldlMx' #-}
313 => (x -> a -> m x) -> m x -> (x -> m b) -> StreamK m a -> m b
314foldlMx' step begin done = go begin
317 let stop = acc >>= done
318 single a = acc >>= \b -> step b a >>= done
319 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
320 in foldStream defState yieldk single stop m1
322-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
323-- expression strictly at each step. The behavior is similar to 'foldl''. A
324-- 'Fold' can terminate early without consuming the full stream. See the
325-- documentation of individual 'Fold's for termination behavior.
329-- >>> fold f = fmap fst . StreamK.foldBreak f
330-- >>> fold f = StreamK.parseD (Parser.fromFold f)
334-- >>> StreamK.fold Fold.sum $ StreamK.fromStream $ Stream.enumerateFromTo 1 100
337{-# INLINABLE fold #-}
338fold :: Monad m => FL.Fold m a b -> StreamK m a -> m b
339fold (FL.Fold step begin done) m = do
342 FL.Partial fs -> go fs m
343 FL.Done fb -> return fb
348 single a = step acc a
350 FL.Partial s -> done s
351 FL.Done b1 -> return b1
352 yieldk a r = step acc a
354 FL.Partial s -> go s r
355 FL.Done b1 -> return b1
356 in foldStream defState yieldk single stop m1
358-- | Fold resulting in either breaking the stream or continuation of the fold.
359-- Instead of supplying the input stream in one go we can run the fold multiple
360-- times, each time supplying the next segment of the input stream. If the fold
361-- has not yet finished it returns a fold that can be run again otherwise it
362-- returns the fold result and the residual stream.
365{-# INLINE foldEither #-}
366foldEither :: Monad m =>
367 Fold m a b -> StreamK m a -> m (Either (Fold m a b) (b, StreamK m a))
368foldEither (FL.Fold step begin done) m = do
371 FL.Partial fs -> go fs m
372 FL.Done fb -> return $ Right (fb, m)
377 let stop = return $ Left (Fold step (return $ FL.Partial acc) done)
382 return $ Left (Fold step (return $ FL.Partial s) done)
383 FL.Done b1 -> return $ Right (b1, nil)
387 FL.Partial s -> go s r
388 FL.Done b1 -> return $ Right (b1, r)
389 in foldStream defState yieldk single stop m1
391-- | Like 'fold' but also returns the remaining stream. The resulting stream
392-- would be 'StreamK.nil' if the stream finished before the fold.
394{-# INLINE foldBreak #-}
395foldBreak :: Monad m => Fold m a b -> StreamK m a -> m (b, StreamK m a)
396foldBreak fld strm = do
397 r <- foldEither fld strm
399 Right res -> return res
400 Left (Fold _ initial extract) -> do
403 FL.Done _ -> error "foldBreak: unreachable state"
408-- XXX Array folds can be implemented using this.
409-- foldContainers? Specialized to foldArrays.
411-- | Generate streams from individual elements of a stream and fold the
412-- concatenation of those streams using the supplied fold. Return the result of
413-- the fold and residual stream.
415-- For example, this can be used to efficiently fold an Array Word8 stream
419{-# INLINE foldConcat #-}
420foldConcat :: Monad m =>
421 Producer m a b -> Fold m b c -> StreamK m a -> m (c, StreamK m a)
423 (Producer pstep pinject pextract)
424 (Fold fstep begin done)
429 FL.Partial fs -> go fs stream
430 FL.Done fb -> return (fb, stream)
440 res <- go1 SPEC acc st
447 return (b, fromPure x)
450 res <- go1 SPEC acc st
455 return (b, x `cons` r)
456 in foldStream defState yieldk single stop m1
462 Stream.Yield x s -> do
465 FL.Done b -> return $ Right (b, s)
466 FL.Partial fs1 -> go1 SPEC fs1 s
467 Stream.Skip s -> go1 SPEC fs s
468 Stream.Stop -> return $ Left fs
470-- | Like 'foldl'' but with a monadic step function.
471{-# INLINE foldlM' #-}
472foldlM' :: Monad m => (b -> a -> m b) -> m b -> StreamK m a -> m b
473foldlM' step begin = foldlMx' step begin return
475------------------------------------------------------------------------------
477------------------------------------------------------------------------------
480head :: Monad m => StreamK m a -> m (Maybe a)
481-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
483 let stop = return Nothing
484 single a = return (Just a)
485 yieldk a _ = return (Just a)
486 in foldStream defState yieldk single stop m
489elem :: (Monad m, Eq a) => a -> StreamK m a -> m Bool
493 let stop = return False
494 single a = return (a == e)
495 yieldk a r = if a == e then return True else go r
496 in foldStream defState yieldk single stop m1
498{-# INLINE notElem #-}
499notElem :: (Monad m, Eq a) => a -> StreamK m a -> m Bool
503 let stop = return True
504 single a = return (a /= e)
505 yieldk a r = if a == e then return False else go r
506 in foldStream defState yieldk single stop m1
509all :: Monad m => (a -> Bool) -> StreamK m a -> m Bool
513 let single a | p a = return True
514 | otherwise = return False
515 yieldk a r | p a = go r
516 | otherwise = return False
517 in foldStream defState yieldk single (return True) m1
520any :: Monad m => (a -> Bool) -> StreamK m a -> m Bool
524 let single a | p a = return True
525 | otherwise = return False
526 yieldk a r | p a = return True
528 in foldStream defState yieldk single (return False) m1
530-- | Extract the last element of the stream, if any.
532last :: Monad m => StreamK m a -> m (Maybe a)
533last = foldlx' (\_ y -> Just y) Nothing id
535{-# INLINE minimum #-}
536minimum :: (Monad m, Ord a) => StreamK m a -> m (Maybe a)
540 let stop = return Nothing
541 single a = return (Just a)
542 yieldk a r = go (Just a) r
543 in foldStream defState yieldk single stop m1
546 let stop = return (Just res)
549 then return (Just res)
555 in foldStream defState yieldk single stop m1
557{-# INLINE minimumBy #-}
560 => (a -> a -> Ordering) -> StreamK m a -> m (Maybe a)
561minimumBy cmp = go Nothing
564 let stop = return Nothing
565 single a = return (Just a)
566 yieldk a r = go (Just a) r
567 in foldStream defState yieldk single stop m1
570 let stop = return (Just res)
571 single a = case cmp res a of
572 GT -> return (Just a)
573 _ -> return (Just res)
574 yieldk a r = case cmp res a of
577 in foldStream defState yieldk single stop m1
579{-# INLINE maximum #-}
580maximum :: (Monad m, Ord a) => StreamK m a -> m (Maybe a)
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)
594 else return (Just res)
599 in foldStream defState yieldk single stop m1
601{-# INLINE maximumBy #-}
602maximumBy :: Monad m => (a -> a -> Ordering) -> StreamK m a -> m (Maybe a)
603maximumBy cmp = go Nothing
606 let stop = return Nothing
607 single a = return (Just a)
608 yieldk a r = go (Just a) r
609 in foldStream defState yieldk single stop m1
612 let stop = return (Just res)
613 single a = case cmp res a of
614 GT -> return (Just res)
616 yieldk a r = case cmp res a of
617 GT -> go (Just res) r
619 in foldStream defState yieldk single stop m1
622(!!) :: Monad m => StreamK m a -> Int -> m (Maybe a)
626 let single a | n == 0 = return $ Just a
627 | otherwise = return Nothing
628 yieldk a x | n < 0 = return Nothing
629 | n == 0 = return $ Just a
630 | otherwise = go (n - 1) x
631 in foldStream defState yieldk single (return Nothing) m1
634lookup :: (Monad m, Eq a) => a -> StreamK m (a, b) -> m (Maybe b)
638 let single (a, b) | a == e = return $ Just b
639 | otherwise = return Nothing
640 yieldk (a, b) x | a == e = return $ Just b
642 in foldStream defState yieldk single (return Nothing) m1
645findM :: Monad m => (a -> m Bool) -> StreamK m a -> m (Maybe a)
651 if b then return $ Just a else return Nothing
654 if b then return $ Just a else go x
655 in foldStream defState yieldk single (return Nothing) m1
658find :: Monad m => (a -> Bool) -> StreamK m a -> m (Maybe a)
659find p = findM (return . p)
661{-# INLINE findIndices #-}
662findIndices :: (a -> Bool) -> StreamK m a -> StreamK m Int
665 go offset m1 = mkStream $ \st yld sng stp ->
666 let single a | p a = sng offset
668 yieldk a x | p a = yld offset $ go (offset + 1) x
669 | otherwise = foldStream (adaptState st) yld sng stp $
671 in foldStream (adaptState st) yieldk single stp m1
673------------------------------------------------------------------------------
675------------------------------------------------------------------------------
677-- | Apply a monadic action to each element of the stream and discard the
678-- output of the action.
680mapM_ :: Monad m => (a -> m b) -> StreamK m a -> m ()
685 single a = void (f a)
686 yieldk a r = f a >> go r
687 in foldStream defState yieldk single stop m1
690mapM :: Monad m => (a -> m b) -> StreamK m a -> StreamK m b
693------------------------------------------------------------------------------
695------------------------------------------------------------------------------
697{-# INLINABLE toList #-}
698toList :: Monad m => StreamK m a -> m [a]
701-- Based on suggestions by David Feuer and Pranay Sashank
703hoist :: (Monad m, Monad n)
704 => (forall x. m x -> n x) -> StreamK m a -> StreamK n a
706 mkStream $ \st yld sng stp ->
707 let single = return . sng
708 yieldk a s = return $ yld a (hoist f s)
710 state = adaptState st
711 in join . f $ foldStreamShared state yieldk single stop str
713-------------------------------------------------------------------------------
714-- Transformation by folding (Scans)
715-------------------------------------------------------------------------------
717{-# INLINE scanlx' #-}
718scanlx' :: (x -> a -> x) -> x -> (x -> b) -> StreamK m a -> StreamK m b
719scanlx' step begin done m =
720 cons (done begin) $ go m begin
722 go m1 !acc = mkStream $ \st yld sng stp ->
723 let single a = sng (done $ step acc a)
726 in yld (done s) (go r s)
727 in foldStream (adaptState st) yieldk single stp m1
730scanl' :: (b -> a -> b) -> b -> StreamK m a -> StreamK m b
731scanl' step begin = scanlx' step begin id
733-------------------------------------------------------------------------------
735-------------------------------------------------------------------------------
738filter :: (a -> Bool) -> StreamK m a -> StreamK m a
741 go m1 = mkStream $ \st yld sng stp ->
742 let single a | p a = sng a
744 yieldk a r | p a = yld a (go r)
745 | otherwise = foldStream st yieldk single stp r
746 in foldStream st yieldk single stp m1
749take :: Int -> StreamK m a -> StreamK m a
752 go n1 m1 = mkStream $ \st yld sng stp ->
753 let yieldk a r = yld a (go (n1 - 1) r)
756 else foldStream st yieldk sng stp m1
758{-# INLINE takeWhile #-}
759takeWhile :: (a -> Bool) -> StreamK m a -> StreamK m a
762 go m1 = mkStream $ \st yld sng stp ->
763 let single a | p a = sng a
765 yieldk a r | p a = yld a (go r)
767 in foldStream st yieldk single stp m1
770drop :: Int -> StreamK m a -> StreamK m a
771drop n m = unShare (go n m)
773 go n1 m1 = mkStream $ \st yld sng stp ->
775 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
776 -- Somehow "<=" check performs better than a ">"
778 then foldStreamShared st yld sng stp m1
779 else foldStreamShared st yieldk single stp m1
781{-# INLINE dropWhile #-}
782dropWhile :: (a -> Bool) -> StreamK m a -> StreamK m a
785 go m1 = mkStream $ \st yld sng stp ->
786 let single a | p a = stp
788 yieldk a r | p a = foldStream st yieldk single stp r
789 | otherwise = yld a r
790 in foldStream st yieldk single stp m1
792-------------------------------------------------------------------------------
794-------------------------------------------------------------------------------
796-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
797-- other stream types to overload it.
798{-# INLINE sequence #-}
799sequence :: Monad m => StreamK m (m a) -> StreamK m a
802 go m1 = mkStream $ \st yld sng stp ->
803 let single ma = ma >>= sng
804 yieldk ma r = foldStreamShared st yld sng stp $ ma `consM` go r
805 in foldStream (adaptState st) yieldk single stp m1
807-------------------------------------------------------------------------------
809-------------------------------------------------------------------------------
811{-# INLINE intersperseM #-}
812intersperseM :: Monad m => m a -> StreamK m a -> StreamK m a
813intersperseM a = prependingStart
815 prependingStart m1 = mkStream $ \st yld sng stp ->
817 foldStreamShared st yld sng stp $ return i `consM` go x
818 in foldStream st yieldk sng stp m1
819 go m2 = mkStream $ \st yld sng stp ->
820 let single i = foldStreamShared st yld sng stp $ a `consM` fromPure i
823 st yld sng stp $ a `consM` return i `consM` go x
824 in foldStream st yieldk single stp m2
826{-# INLINE intersperse #-}
827intersperse :: Monad m => a -> StreamK m a -> StreamK m a
828intersperse a = intersperseM (return a)
830{-# INLINE insertBy #-}
831insertBy :: (a -> a -> Ordering) -> a -> StreamK m a -> StreamK m a
834 go m1 = mkStream $ \st yld _ _ ->
835 let single a = case cmp x a of
836 GT -> yld a (fromPure x)
837 _ -> yld x (fromPure a)
839 yieldk a r = case cmp x a of
841 _ -> yld x (a `cons` r)
842 in foldStream st yieldk single stop m1
844------------------------------------------------------------------------------
846------------------------------------------------------------------------------
848{-# INLINE deleteBy #-}
849deleteBy :: (a -> a -> Bool) -> a -> StreamK m a -> StreamK m a
852 go m1 = mkStream $ \st yld sng stp ->
853 let single a = if eq x a then stp else sng a
854 yieldk a r = if eq x a
855 then foldStream st yld sng stp r
857 in foldStream st yieldk single stp m1
859-------------------------------------------------------------------------------
861-------------------------------------------------------------------------------
863{-# INLINE mapMaybe #-}
864mapMaybe :: (a -> Maybe b) -> StreamK m a -> StreamK m b
867 go m1 = mkStream $ \st yld sng stp ->
868 let single a = maybe stp sng (f a)
869 yieldk a r = case f a of
870 Just b -> yld b $ go r
871 Nothing -> foldStream (adaptState st) yieldk single stp r
872 in foldStream (adaptState st) yieldk single stp m1
874-------------------------------------------------------------------------------
876-------------------------------------------------------------------------------
878-- | Like Streamly.Data.Stream.'Streamly.Data.Stream.handle' but with one
879-- significant difference, this function observes exceptions from the consumer
880-- of the stream as well.
882-- You can also convert 'StreamK' to 'Stream' and use exception handling from
885-- >>> handle f s = StreamK.fromStream $ Stream.handle (\e -> StreamK.toStream (f e)) (StreamK.toStream s)
887{-# INLINABLE handle #-}
888handle :: (MonadCatch m, Exception e)
889 => (e -> m (StreamK m a)) -> StreamK m a -> StreamK m a
890handle f stream = go stream
894 go m1 = mkStream $ \st yld sng stp ->
895 let yieldk a r = yld a $ go r
897 res <- MC.try (foldStream (adaptState st) yieldk sng stp m1)
902 foldStream (adaptState st) yld sng stp r
904-------------------------------------------------------------------------------
905-- Resource Management
906-------------------------------------------------------------------------------
908-- If we are folding the stream and we do not drain the entire stream (e.g. if
909-- the fold terminates before the stream) then the finalizer will run on GC.
911-- XXX To implement a prompt cleanup, we will have to yield a cleanup function
912-- via the yield continuation. A chain of cleanup functions can be built and
913-- the entire chain can be invoked when the stream ends voluntarily or if
914-- someone decides to abandon the stream.
916-- | Like Streamly.Data.Stream.'Streamly.Data.Stream.bracketIO' but with one
917-- significant difference, this function observes exceptions from the consumer
918-- of the stream as well. Therefore, it cleans up the resource promptly when
919-- the consumer encounters an exception.
921-- You can also convert 'StreamK' to 'Stream' and use resource handling from
924-- >>> bracketIO bef aft bet = StreamK.fromStream $ Stream.bracketIO bef aft (StreamK.toStream . bet)
926{-# INLINABLE bracketIO #-}
927bracketIO :: (MonadIO m, MonadCatch m)
928 => IO b -> (b -> IO c) -> (b -> StreamK m a) -> StreamK m a
929bracketIO bef aft bet =
931 (r, ref) <- liftIO $ mask_ $ do
933 ref <- newIOFinalizer (aft r)
935 return $ go ref (bet r)
939 go ref m1 = mkStream $ \st yld sng stp ->
941 -- We can discard exceptions on continuations to make it equivalent
942 -- to StreamD, but it seems like a desirable behavior.
943 stop = liftIO (runIOFinalizer ref) >> stp
944 single a = liftIO (runIOFinalizer ref) >> sng a
945 yieldk a r = yld a $ go ref r
947 -- Do not call the finalizer twice if it has already been
948 -- called via stop continuation and stop continuation itself
949 -- generated an exception. runIOFinalizer takes care of that.
950 res <- MC.try (foldStream (adaptState st) yieldk single stop m1)
953 Left (e :: MC.SomeException) ->
954 liftIO (runIOFinalizer ref) >> MC.throwM e
956------------------------------------------------------------------------------
958------------------------------------------------------------------------------
960-- | Zipping of @n@ streams can be performed by combining the streams pair
961-- wise using 'mergeMapWith' with O(n * log n) time complexity. If used
962-- with 'concatMapWith' it will have O(n^2) performance.
963{-# INLINE zipWith #-}
964zipWith :: Monad m => (a -> b -> c) -> StreamK m a -> StreamK m b -> StreamK m c
965zipWith f = zipWithM (\a b -> return (f a b))
967{-# INLINE zipWithM #-}
968zipWithM :: Monad m =>
969 (a -> b -> m c) -> StreamK m a -> StreamK m b -> StreamK m c
974 go mx my = mkStream $ \st yld sng stp -> do
976 let single2 b = f a b >>= sng
977 yield2 b rb = f a b >>= \x -> yld x (go ra rb)
978 in foldStream (adaptState st) yield2 single2 stp my
979 let single1 a = merge a nil
981 foldStream (adaptState st) yield1 single1 stp mx
983------------------------------------------------------------------------------
985------------------------------------------------------------------------------
987{-# INLINE mergeByM #-}
988mergeByM :: Monad m =>
989 (a -> a -> m Ordering) -> StreamK m a -> StreamK m a -> StreamK m a
994 go mx my = mkStream $ \st yld sng stp -> do
995 let stop = foldStream st yld sng stp my
996 single x = foldStream st yld sng stp (goX0 x my)
997 yield x rx = foldStream st yld sng stp (goX x rx my)
998 foldStream st yield single stop mx
1000 goX0 x my = mkStream $ \st yld sng _ -> do
1005 GT -> yld y (fromPure x)
1006 _ -> yld x (fromPure y)
1010 GT -> yld y (goX0 x ry)
1011 _ -> yld x (y `cons` ry)
1012 in foldStream st yield single stop my
1014 goX x mx my = mkStream $ \st yld _ _ -> do
1019 GT -> yld y (x `cons` mx)
1020 _ -> yld x (goY0 mx y)
1024 GT -> yld y (goX x mx ry)
1025 _ -> yld x (goY mx y ry)
1026 in foldStream st yield single stop my
1028 goY0 mx y = mkStream $ \st yld sng _ -> do
1033 GT -> yld y (fromPure x)
1034 _ -> yld x (fromPure y)
1038 GT -> yld y (x `cons` rx)
1039 _ -> yld x (goY0 rx y)
1040 in foldStream st yield single stop mx
1042 goY mx y my = mkStream $ \st yld _ _ -> do
1047 GT -> yld y (goX0 x my)
1048 _ -> yld x (y `cons` my)
1052 GT -> yld y (goX x rx my)
1053 _ -> yld x (goY rx y my)
1054 in foldStream st yield single stop mx
1056-- | Merging of @n@ streams can be performed by combining the streams pair
1057-- wise using 'mergeMapWith' to give O(n * log n) time complexity. If used
1058-- with 'concatMapWith' it will have O(n^2) performance.
1060{-# INLINE mergeBy #-}
1061mergeBy :: (a -> a -> Ordering) -> StreamK m a -> StreamK m a -> StreamK m a
1062-- XXX GHC: This has slightly worse performance than replacing "r <- cmp x y"
1063-- with "let r = cmp x y" in the monadic version. The definition below is
1064-- exactly the same as mergeByM except this change.
1065-- mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1070 go mx my = mkStream $ \st yld sng stp -> do
1071 let stop = foldStream st yld sng stp my
1072 single x = foldStream st yld sng stp (goX0 x my)
1073 yield x rx = foldStream st yld sng stp (goX x rx my)
1074 foldStream st yield single stop mx
1076 goX0 x my = mkStream $ \st yld sng _ -> do
1080 GT -> yld y (fromPure x)
1081 _ -> yld x (fromPure y)
1084 GT -> yld y (goX0 x ry)
1085 _ -> yld x (y `cons` ry)
1086 in foldStream st yield single stop my
1088 goX x mx my = mkStream $ \st yld _ _ -> do
1092 GT -> yld y (x `cons` mx)
1093 _ -> yld x (goY0 mx y)
1096 GT -> yld y (goX x mx ry)
1097 _ -> yld x (goY mx y ry)
1098 in foldStream st yield single stop my
1100 goY0 mx y = mkStream $ \st yld sng _ -> do
1104 GT -> yld y (fromPure x)
1105 _ -> yld x (fromPure y)
1108 GT -> yld y (x `cons` rx)
1109 _ -> yld x (goY0 rx y)
1110 in foldStream st yield single stop mx
1112 goY mx y my = mkStream $ \st yld _ _ -> do
1116 GT -> yld y (goX0 x my)
1117 _ -> yld x (y `cons` my)
1120 GT -> yld y (goX x rx my)
1121 _ -> yld x (goY rx y my)
1122 in foldStream st yield single stop mx
1124------------------------------------------------------------------------------
1125-- Transformation comprehensions
1126------------------------------------------------------------------------------
1129the :: (Eq a, Monad m) => StreamK m a -> m (Maybe a)
1133 Nothing -> return Nothing
1134 Just (h, t) -> go h t
1137 let single a | h == a = return $ Just h
1138 | otherwise = return Nothing
1139 yieldk a r | h == a = go h r
1140 | otherwise = return Nothing
1141 in foldStream defState yieldk single (return $ Just h) m1
1143------------------------------------------------------------------------------
1144-- Alternative & MonadPlus
1145------------------------------------------------------------------------------
1147_alt :: StreamK m a -> StreamK m a -> StreamK m a
1148_alt m1 m2 = mkStream $ \st yld sng stp ->
1149 let stop = foldStream st yld sng stp m2
1150 in foldStream st yld sng stop m1
1152------------------------------------------------------------------------------
1154------------------------------------------------------------------------------
1157-- XXX handle and test cross thread state transfer
1160 => StreamK m a -> (e -> StreamK m a) -> StreamK m a
1162 mkStream $ \_ stp sng yld ->
1163 let run x = unStream x Nothing stp sng yieldk
1164 handle r = r `catchError` \e -> run $ h e
1165 yieldk a r = yld a (withCatchError r h)
1169-------------------------------------------------------------------------------
1171-------------------------------------------------------------------------------
1173-- Inlined definition.
1174{-# INLINE splitAt #-}
1175splitAt :: Int -> [a] -> ([a],[a])
1178 | otherwise = splitAt' n ls
1180 splitAt' :: Int -> [a] -> ([a], [a])
1181 splitAt' _ [] = ([], [])
1182 splitAt' 1 (x:xs) = ([x], xs)
1183 splitAt' m (x:xs) = (x:xs', xs'')
1185 (xs', xs'') = splitAt' (m - 1) xs
1187-- | Run a 'Parser' over a stream and return rest of the Stream.
1188{-# INLINE_NORMAL parseDBreak #-}
1193 -> m (Either ParseError b, StreamK m a)
1194parseDBreak (PR.Parser pstep initial extract) stream = do
1197 PR.IPartial s -> goStream stream [] s
1198 PR.IDone b -> return (Right b, stream)
1199 PR.IError err -> return (Left (ParseError err), stream)
1203 -- "buf" contains last few items in the stream that we may have to
1206 -- XXX currently we are using a dumb list based approach for backtracking
1207 -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
1208 -- That will allow us more efficient random back and forth movement.
1209 goStream st buf !pst =
1214 let src = Prelude.reverse buf
1215 return (Left (ParseError err), fromList src)
1217 assertM(n <= length buf)
1218 let src0 = Prelude.take n buf
1219 src = Prelude.reverse src0
1220 return (Right b, fromList src)
1221 PR.Partial _ _ -> error "Bug: parseBreak: Partial in extract"
1222 PR.Continue 0 s -> goStream nil buf s
1223 PR.Continue n s -> do
1224 assertM(n <= length buf)
1225 let (src0, buf1) = splitAt n buf
1226 src = Prelude.reverse src0
1227 goBuf nil buf1 src s
1228 single x = yieldk x nil
1232 PR.Partial 0 s -> goStream r [] s
1233 PR.Partial n s -> do
1234 assertM(n <= length (x:buf))
1235 let src0 = Prelude.take n (x:buf)
1236 src = Prelude.reverse src0
1238 PR.Continue 0 s -> goStream r (x:buf) s
1239 PR.Continue n s -> do
1240 assertM(n <= length (x:buf))
1241 let (src0, buf1) = splitAt n (x:buf)
1242 src = Prelude.reverse src0
1244 PR.Done 0 b -> return (Right b, r)
1246 assertM(n <= length (x:buf))
1247 let src0 = Prelude.take n (x:buf)
1248 src = Prelude.reverse src0
1249 return (Right b, append (fromList src) r)
1251 let src = Prelude.reverse (x:buf)
1252 return (Left (ParseError err), append (fromList src) r)
1253 in foldStream defState yieldk single stop st
1255 goBuf st buf [] !pst = goStream st buf pst
1256 goBuf st buf (x:xs) !pst = do
1259 PR.Partial 0 s -> goBuf st [] xs s
1260 PR.Partial n s -> do
1261 assert (n <= length (x:buf)) (return ())
1262 let src0 = Prelude.take n (x:buf)
1263 src = Prelude.reverse src0 ++ xs
1265 PR.Continue 0 s -> goBuf st (x:buf) xs s
1266 PR.Continue n s -> do
1267 assert (n <= length (x:buf)) (return ())
1268 let (src0, buf1) = splitAt n (x:buf)
1269 src = Prelude.reverse src0 ++ xs
1272 assert (n <= length (x:buf)) (return ())
1273 let src0 = Prelude.take n (x:buf)
1274 src = Prelude.reverse src0
1275 return (Right b, append (fromList src) st)
1277 let src = Prelude.reverse buf ++ x:xs
1278 return (Left (ParseError err), append (fromList src) st)
1280-- Using ParserD or ParserK on StreamK may not make much difference. We should
1281-- perhaps use only chunked parsing on StreamK. We can always convert a stream
1282-- to chunks before parsing. Or just have a ParserK element parser for StreamK
1283-- and convert ParserD to ParserK for element parsing using StreamK.
1284{-# INLINE parseD #-}
1286 Parser.Parser a m b -> StreamK m a -> m (Either ParseError b)
1287parseD f = fmap fst . parseDBreak f
1289-------------------------------------------------------------------------------
1291-------------------------------------------------------------------------------
1293-- The backracking buffer consists of arrays in the most-recent-first order. We
1294-- want to take a total of n array elements from this buffer. Note: when we
1295-- have to take an array partially, we must take the last part of the array.
1296{-# INLINE backTrack #-}
1297backTrack :: forall m a. Unbox a =>
1300 -> StreamK m (Array a)
1301 -> (StreamK m (Array a), [Array a])
1306 go _ [] stream = (stream, [])
1307 go n xs stream | n <= 0 = (stream, xs)
1308 go n (x:xs) stream =
1309 let len = Array.length x
1311 then go (n - len) xs (cons x stream)
1313 then (cons x stream, xs)
1314 else let !(Array contents start end) = x
1315 !start1 = end - (n * SIZE_OF(a))
1316 arr1 = Array contents start1 end
1317 arr2 = Array contents start start1
1318 in (cons arr1 stream, arr2:xs)
1320-- | A continuation to extract the result when a CPS parser is done.
1321{-# INLINE parserDone #-}
1322parserDone :: Applicative m =>
1323 ParserK.ParseResult b -> Int -> ParserK.Input a -> m (ParserK.Step a m b)
1324parserDone (ParserK.Success n b) _ _ = pure $ ParserK.Done n b
1325parserDone (ParserK.Failure n e) _ _ = pure $ ParserK.Error n e
1327-- XXX parseDBreakChunks may be faster than converting parserD to parserK and
1328-- using parseBreakChunks. We can also use parseBreak as an alternative to the
1329-- monad instance of ParserD.
1331-- | Run a 'ParserK' over a chunked 'StreamK' and return the rest of the Stream.
1332{-# INLINE_NORMAL parseBreakChunks #-}
1334 :: (Monad m, Unbox a)
1335 => ParserK (Array a) m b
1336 -> StreamK m (Array a)
1337 -> m (Either ParseError b, StreamK m (Array a))
1338parseBreakChunks parser input = do
1339 let parserk = ParserK.runParser parser parserDone 0 0
1340 in go [] parserk input
1344 {-# INLINE goStop #-}
1345 goStop backBuf parserk = do
1346 pRes <- parserk ParserK.None
1348 -- If we stop in an alternative, it will try calling the next
1349 -- parser, the next parser may call initial returning Partial and
1350 -- then immediately we have to call extract on it.
1351 ParserK.Partial 0 cont1 ->
1353 ParserK.Partial n cont1 -> do
1355 assertM(n1 >= 0 && n1 <= sum (Prelude.map Array.length backBuf))
1356 let (s1, backBuf1) = backTrack n1 backBuf nil
1357 in go backBuf1 cont1 s1
1358 ParserK.Continue 0 cont1 ->
1359 go backBuf cont1 nil
1360 ParserK.Continue n cont1 -> do
1362 assertM(n1 >= 0 && n1 <= sum (Prelude.map Array.length backBuf))
1363 let (s1, backBuf1) = backTrack n1 backBuf nil
1364 in go backBuf1 cont1 s1
1366 return (Right b, nil)
1367 ParserK.Done n b -> do
1369 assertM(n1 >= 0 && n1 <= sum (Prelude.map Array.length backBuf))
1370 let (s1, _) = backTrack n1 backBuf nil
1371 in return (Right b, s1)
1372 ParserK.Error _ err -> do
1373 let (s1, _) = backTrack maxBound backBuf nil
1374 return (Left (ParseError err), s1)
1377 error $ "parseBreak: Partial: forward seek not implemented n = "
1378 ++ show n ++ " len = " ++ show len
1380 yieldk backBuf parserk arr stream = do
1381 pRes <- parserk (ParserK.Chunk arr)
1382 let len = Array.length arr
1384 ParserK.Partial n cont1 ->
1385 case compare n len of
1386 EQ -> go [] cont1 stream
1389 then yieldk [] cont1 arr stream
1392 bufLen = sum (Prelude.map Array.length backBuf)
1394 assertM(n1 >= 0 && n1 <= bufLen)
1395 let (s1, _) = backTrack n1 backBuf s
1398 ParserK.Continue n cont1 ->
1399 case compare n len of
1400 EQ -> go (arr:backBuf) cont1 stream
1403 then yieldk backBuf cont1 arr stream
1406 bufLen = sum (Prelude.map Array.length backBuf)
1408 assertM(n1 >= 0 && n1 <= bufLen)
1409 let (s1, backBuf1) = backTrack n1 backBuf s
1410 go backBuf1 cont1 s1
1412 ParserK.Done n b -> do
1414 assertM(n1 <= sum (Prelude.map Array.length (arr:backBuf)))
1415 let (s1, _) = backTrack n1 (arr:backBuf) stream
1416 in return (Right b, s1)
1417 ParserK.Error _ err -> do
1418 let (s1, _) = backTrack maxBound (arr:backBuf) stream
1419 return (Left (ParseError err), s1)
1421 go backBuf parserk stream = do
1422 let stop = goStop backBuf parserk
1423 single a = yieldk backBuf parserk a nil
1425 defState (yieldk backBuf parserk) single stop stream
1427{-# INLINE parseChunks #-}
1428parseChunks :: (Monad m, Unbox a) =>
1429 ParserK (Array a) m b -> StreamK m (Array a) -> m (Either ParseError b)
1430parseChunks f = fmap fst . parseBreakChunks f
1432-------------------------------------------------------------------------------
1434-------------------------------------------------------------------------------
1436{-# INLINE backTrackSingular #-}
1437backTrackSingular :: Int -> [a] -> StreamK m a -> (StreamK m a, [a])
1438backTrackSingular = go
1442 go _ [] stream = (stream, [])
1443 go n xs stream | n <= 0 = (stream, xs)
1445 let (appendBuf, newBTBuf) = splitAt n xs
1446 in (append (fromList (Prelude.reverse appendBuf)) stream, newBTBuf)
1449-- | Similar to 'parseBreak' but works on singular elements.
1451{-# INLINE_NORMAL parseBreak #-}
1453 :: forall m a b. Monad m
1454 => ParserK.ParserK a m b
1456 -> m (Either ParseError b, StreamK m a)
1457parseBreak parser input = do
1458 let parserk = ParserK.runParser parser parserDone 0 0
1459 in go [] parserk input
1463 {-# INLINE goStop #-}
1466 -> (ParserK.Input a -> m (ParserK.Step a m b))
1467 -> m (Either ParseError b, StreamK m a)
1468 goStop backBuf parserk = do
1469 pRes <- parserk ParserK.None
1471 -- If we stop in an alternative, it will try calling the next
1472 -- parser, the next parser may call initial returning Partial and
1473 -- then immediately we have to call extract on it.
1474 ParserK.Partial 0 cont1 ->
1476 ParserK.Partial n cont1 -> do
1478 assertM(n1 >= 0 && n1 <= length backBuf)
1479 let (s1, backBuf1) = backTrackSingular n1 backBuf nil
1480 in go backBuf1 cont1 s1
1481 ParserK.Continue 0 cont1 ->
1482 go backBuf cont1 nil
1483 ParserK.Continue n cont1 -> do
1485 assertM(n1 >= 0 && n1 <= length backBuf)
1486 let (s1, backBuf1) = backTrackSingular n1 backBuf nil
1487 in go backBuf1 cont1 s1
1489 return (Right b, nil)
1490 ParserK.Done n b -> do
1492 assertM(n1 >= 0 && n1 <= length backBuf)
1493 let (s1, _) = backTrackSingular n1 backBuf nil
1494 in return (Right b, s1)
1495 ParserK.Error _ err -> return (Left (ParseError err), nil)
1498 error $ "parseBreak: Partial: forward seek not implemented n = "
1503 -> (ParserK.Input a -> m (ParserK.Step a m b))
1506 -> m (Either ParseError b, StreamK m a)
1507 yieldk backBuf parserk arr stream = do
1508 pRes <- parserk (ParserK.Chunk arr)
1510 ParserK.Partial 1 cont1 -> go [] cont1 stream
1511 ParserK.Partial 0 cont1 -> go [] cont1 (cons arr stream)
1512 ParserK.Partial n _ | n > 1 -> seekErr n
1513 ParserK.Partial n cont1 -> do
1515 bufLen = length backBuf
1517 assertM(n1 >= 0 && n1 <= bufLen)
1518 let (s1, _) = backTrackSingular n1 backBuf s
1520 ParserK.Continue 1 cont1 -> go (arr:backBuf) cont1 stream
1521 ParserK.Continue 0 cont1 ->
1522 go backBuf cont1 (cons arr stream)
1523 ParserK.Continue n _ | n > 1 -> seekErr n
1524 ParserK.Continue n cont1 -> do
1526 bufLen = length backBuf
1528 assertM(n1 >= 0 && n1 <= bufLen)
1529 let (s1, backBuf1) = backTrackSingular n1 backBuf s
1530 go backBuf1 cont1 s1
1531 ParserK.Done 1 b -> pure (Right b, stream)
1532 ParserK.Done 0 b -> pure (Right b, cons arr stream)
1533 ParserK.Done n _ | n > 1 -> seekErr n
1534 ParserK.Done n b -> do
1536 bufLen = length backBuf
1538 assertM(n1 >= 0 && n1 <= bufLen)
1539 let (s1, _) = backTrackSingular n1 backBuf s
1541 ParserK.Error _ err -> return (Left (ParseError err), nil)
1545 -> (ParserK.Input a -> m (ParserK.Step a m b))
1547 -> m (Either ParseError b, StreamK m a)
1548 go backBuf parserk stream = do
1549 let stop = goStop backBuf parserk
1550 single a = yieldk backBuf parserk a nil
1552 defState (yieldk backBuf parserk) single stop stream
1554-- | Run a 'ParserK' over a 'StreamK'. Please use 'parseChunks' where possible,
1555-- for better performance.
1558 ParserK.ParserK a m b -> StreamK m a -> m (Either ParseError b)
1559parse f = fmap fst . parseBreak f
1561-------------------------------------------------------------------------------
1562-- ParserK Chunked Generic
1563-------------------------------------------------------------------------------
1565{-# INLINE backTrackGenericChunks #-}
1566backTrackGenericChunks ::
1569 -> StreamK m (GenArr.Array a)
1570 -> (StreamK m (GenArr.Array a), [GenArr.Array a])
1571backTrackGenericChunks = go
1575 go _ [] stream = (stream, [])
1576 go n xs stream | n <= 0 = (stream, xs)
1577 go n (x:xs) stream =
1578 let len = GenArr.length x
1580 then go (n - len) xs (cons x stream)
1582 then (cons x stream, xs)
1583 else let arr1 = GenArr.getSliceUnsafe (len - n) n x
1584 arr2 = GenArr.getSliceUnsafe 0 (len - n) x
1585 in (cons arr1 stream, arr2:xs)
1587-- | Similar to 'parseBreak' but works on generic arrays
1589{-# INLINE_NORMAL parseBreakChunksGeneric #-}
1590parseBreakChunksGeneric
1591 :: forall m a b. Monad m
1592 => ParserK.ParserK (GenArr.Array a) m b
1593 -> StreamK m (GenArr.Array a)
1594 -> m (Either ParseError b, StreamK m (GenArr.Array a))
1595parseBreakChunksGeneric parser input = do
1596 let parserk = ParserK.runParser parser parserDone 0 0
1597 in go [] parserk input
1601 {-# INLINE goStop #-}
1604 -> (ParserK.Input (GenArr.Array a)
1605 -> m (ParserK.Step (GenArr.Array a) m b))
1606 -> m (Either ParseError b, StreamK m (GenArr.Array a))
1607 goStop backBuf parserk = do
1608 pRes <- parserk ParserK.None
1610 -- If we stop in an alternative, it will try calling the next
1611 -- parser, the next parser may call initial returning Partial and
1612 -- then immediately we have to call extract on it.
1613 ParserK.Partial 0 cont1 ->
1615 ParserK.Partial n cont1 -> do
1617 assertM(n1 >= 0 && n1 <= sum (Prelude.map GenArr.length backBuf))
1618 let (s1, backBuf1) = backTrackGenericChunks n1 backBuf nil
1619 in go backBuf1 cont1 s1
1620 ParserK.Continue 0 cont1 ->
1621 go backBuf cont1 nil
1622 ParserK.Continue n cont1 -> do
1624 assertM(n1 >= 0 && n1 <= sum (Prelude.map GenArr.length backBuf))
1625 let (s1, backBuf1) = backTrackGenericChunks n1 backBuf nil
1626 in go backBuf1 cont1 s1
1628 return (Right b, nil)
1629 ParserK.Done n b -> do
1631 assertM(n1 >= 0 && n1 <= sum (Prelude.map GenArr.length backBuf))
1632 let (s1, _) = backTrackGenericChunks n1 backBuf nil
1633 in return (Right b, s1)
1634 ParserK.Error _ err -> return (Left (ParseError err), nil)
1637 error $ "parseBreak: Partial: forward seek not implemented n = "
1638 ++ show n ++ " len = " ++ show len
1642 -> (ParserK.Input (GenArr.Array a)
1643 -> m (ParserK.Step (GenArr.Array a) m b))
1645 -> StreamK m (GenArr.Array a)
1646 -> m (Either ParseError b, StreamK m (GenArr.Array a))
1647 yieldk backBuf parserk arr stream = do
1648 pRes <- parserk (ParserK.Chunk arr)
1649 let len = GenArr.length arr
1651 ParserK.Partial n cont1 ->
1652 case compare n len of
1653 EQ -> go [] cont1 stream
1656 then yieldk [] cont1 arr stream
1659 bufLen = sum (Prelude.map GenArr.length backBuf)
1661 assertM(n1 >= 0 && n1 <= bufLen)
1662 let (s1, _) = backTrackGenericChunks n1 backBuf s
1665 ParserK.Continue n cont1 ->
1666 case compare n len of
1667 EQ -> go (arr:backBuf) cont1 stream
1670 then yieldk backBuf cont1 arr stream
1673 bufLen = sum (Prelude.map GenArr.length backBuf)
1675 assertM(n1 >= 0 && n1 <= bufLen)
1676 let (s1, backBuf1) = backTrackGenericChunks n1 backBuf s
1677 go backBuf1 cont1 s1
1679 ParserK.Done n b -> do
1681 assertM(n1 <= sum (Prelude.map GenArr.length (arr:backBuf)))
1682 let (s1, _) = backTrackGenericChunks n1 (arr:backBuf) stream
1683 in return (Right b, s1)
1684 ParserK.Error _ err -> return (Left (ParseError err), nil)
1688 -> (ParserK.Input (GenArr.Array a)
1689 -> m (ParserK.Step (GenArr.Array a) m b))
1690 -> StreamK m (GenArr.Array a)
1691 -> m (Either ParseError b, StreamK m (GenArr.Array a))
1692 go backBuf parserk stream = do
1693 let stop = goStop backBuf parserk
1694 single a = yieldk backBuf parserk a nil
1696 defState (yieldk backBuf parserk) single stop stream
1698{-# INLINE parseChunksGeneric #-}
1699parseChunksGeneric ::
1701 => ParserK.ParserK (GenArr.Array a) m b
1702 -> StreamK m (GenArr.Array a)
1703 -> m (Either ParseError b)
1704parseChunksGeneric f = fmap fst . parseBreakChunksGeneric f
1706-------------------------------------------------------------------------------
1708-------------------------------------------------------------------------------
1710-- | Sort the input stream using a supplied comparison function.
1712-- Sorting can be achieved by simply:
1714-- >>> sortBy cmp = StreamK.mergeMapWith (StreamK.mergeBy cmp) StreamK.fromPure
1716-- However, this combinator uses a parser to first split the input stream into
1717-- down and up sorted segments and then merges them to optimize sorting when
1718-- pre-sorted sequences exist in the input stream.
1722{-# INLINE sortBy #-}
1723sortBy :: Monad m => (a -> a -> Ordering) -> StreamK m a -> StreamK m a
1724-- sortBy f = Stream.concatPairsWith (Stream.mergeBy f) Stream.fromPure
1727 Parser.groupByRollingEither
1728 (\x -> (< GT) . cmp x)
1731 in mergeMapWith (mergeBy cmp) id
1733 . Stream.catRights -- its a non-failing backtracking parser
1734 . Stream.parseMany (fmap (either id id) p)
1735 . Stream.fromStreamK
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