3-- Module : Streamly.Internal.Data.Stream.StreamK
4-- Copyright : (c) 2017 Composewell Technologies
7-- Maintainer : streamly@composewell.com
8-- Stability : experimental
11module Streamly.Internal.Data.Stream.StreamK
14 -- | To execute the code examples provided in this module in ghci, please
15 -- run the following commands first.
29 -- * Construction Primitives
36 -- * Elimination Primitives
40 -- * Transformation Primitives
51 -- ** Specialized Generation
93 -- ** Specialized Folds
122 -- ** By folding (scans)
173 , concatIterateLeftsWith
174 , concatIterateScanWith
179 -- ** Transformation comprehensions
182 -- * Semigroup Style Composition
192#include "ArrayMacros.h"
196import Control.Monad (void, join)
197import Data.Proxy (Proxy(..))
198import GHC.Types (SPEC(..))
199import Streamly.Internal.Data.Array.Type (Array(..))
200import Streamly.Internal.Data.Fold.Type (Fold(..))
201import Streamly.Internal.Data.Producer.Type (Producer(..))
202import Streamly.Internal.Data.SVar.Type (adaptState, defState)
203import Streamly.Internal.Data.Unboxed (sizeOf, Unbox)
204import Streamly.Internal.Data.Parser.ParserK.Type (ParserK)
206import qualified Streamly.Internal.Data.Array.Type as Array
207import qualified Streamly.Internal.Data.Fold.Type as FL
208import qualified Streamly.Internal.Data.Parser as Parser
209import qualified Streamly.Internal.Data.Parser.ParserD.Type as PR
210import qualified Streamly.Internal.Data.Parser.ParserK.Type as ParserK
211import qualified Streamly.Internal.Data.Stream.StreamD as Stream
212import qualified Prelude
215 hiding (foldl, foldr, last, map, mapM, mapM_, repeat, sequence,
216 take, filter, all, any, takeWhile, drop, dropWhile, minimum,
217 maximum, elem, notElem, null, head, tail, init, zipWith, lookup,
218 foldr1, (!!), replicate, reverse, concatMap, iterate, splitAt)
220import Streamly.Internal.Data.Stream.StreamK.Type
221import Streamly.Internal.Data.Parser.ParserD (ParseError(..))
223#include "DocTestDataStreamK.hs"
225{-# INLINE fromStream #-}
226fromStream :: Monad m => Stream.Stream m a -> StreamK m a
227fromStream = Stream.toStreamK
229{-# INLINE toStream #-}
230toStream :: Applicative m => StreamK m a -> Stream.Stream m a
231toStream = Stream.fromStreamK
233-------------------------------------------------------------------------------
235-------------------------------------------------------------------------------
238-- Generalization of concurrent streams/SVar via unfoldr.
240-- Unfold a value into monadic actions and then run the resulting monadic
241-- actions to generate a stream. Since the step of generating the monadic
242-- action and running them are decoupled we can run the monadic actions
243-- cooncurrently. For example, the seed could be a list of monadic actions or a
244-- pure stream of monadic actions.
246-- We can have different flavors of this depending on the stream type t. The
247-- concurrent version could be async or ahead etc. Depending on how we queue
248-- back the feedback portion b, it could be DFS or BFS style.
250unfoldrA :: (b -> Maybe (m a, b)) -> b -> StreamK m a
254-------------------------------------------------------------------------------
256-------------------------------------------------------------------------------
259-- >>> repeatM = StreamK.sequence . StreamK.repeat
260-- >>> repeatM = fix . StreamK.consM
261-- >>> repeatM = cycle1 . StreamK.fromEffect
263-- Generate a stream by repeatedly executing a monadic action forever.
267-- StreamK.repeatM (threadDelay 1000000 >> print 1)
269-- & StreamK.fold Fold.drain
272repeatM :: Monad m => m a -> StreamK m a
273repeatM = repeatMWith consM
275{-# INLINE replicateM #-}
276replicateM :: Monad m => Int -> m a -> StreamK m a
277replicateM = replicateMWith consM
278{-# INLINE replicate #-}
279replicate :: Int -> a -> StreamK m a
282 go cnt = if cnt <= 0 then nil else a `cons` go (cnt - 1)
284{-# INLINE fromIndicesM #-}
285fromIndicesM :: Monad m => (Int -> m a) -> StreamK m a
286fromIndicesM = fromIndicesMWith consM
287{-# INLINE fromIndices #-}
288fromIndices :: (Int -> a) -> StreamK m a
289fromIndices gen = go 0
291 go n = gen n `cons` go (n + 1)
294-- >>> iterate f x = x `StreamK.cons` iterate f x
296-- Generate an infinite stream with @x@ as the first element and each
297-- successive element derived by applying the function @f@ on the previous
300-- >>> StreamK.toList $ StreamK.take 5 $ StreamK.iterate (+1) 1
303{-# INLINE iterate #-}
304iterate :: (a -> a) -> a -> StreamK m a
307 go !s = cons s (go (step s))
310-- >>> iterateM f m = m >>= \a -> return a `StreamK.consM` iterateM f (f a)
312-- Generate an infinite stream with the first element generated by the action
313-- @m@ and each successive element derived by applying the monadic function
314-- @f@ on the previous element.
317-- StreamK.iterateM (\x -> print x >> return (x + 1)) (return 0)
325{-# INLINE iterateM #-}
326iterateM :: Monad m => (a -> m a) -> m a -> StreamK m a
327iterateM = iterateMWith consM
329-------------------------------------------------------------------------------
331-------------------------------------------------------------------------------
333{-# INLINE fromList #-}
334fromList :: [a] -> StreamK m a
335fromList = fromFoldable
337-------------------------------------------------------------------------------
338-- Elimination by Folding
339-------------------------------------------------------------------------------
342foldr1 :: Monad m => (a -> a -> a) -> StreamK m a -> m (Maybe a)
346 Nothing -> return Nothing
347 Just (h, t) -> fmap Just (go h t)
351 single a = return $ step a p
352 yieldk a r = fmap (step p) (go a r)
353 in foldStream defState yieldk single stp m1
355-- XXX replace the recursive "go" with explicit continuations.
356-- | Like 'foldx', but with a monadic step function.
357{-# INLINABLE foldlMx' #-}
359 => (x -> a -> m x) -> m x -> (x -> m b) -> StreamK m a -> m b
360foldlMx' step begin done = go begin
363 let stop = acc >>= done
364 single a = acc >>= \b -> step b a >>= done
365 yieldk a r = acc >>= \b -> step b a >>= \x -> go (return x) r
366 in foldStream defState yieldk single stop m1
368-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
369-- expression strictly at each step. The behavior is similar to 'foldl''. A
370-- 'Fold' can terminate early without consuming the full stream. See the
371-- documentation of individual 'Fold's for termination behavior.
375-- >>> fold f = fmap fst . StreamK.foldBreak f
376-- >>> fold f = StreamK.parseD (Parser.fromFold f)
380-- >>> StreamK.fold Fold.sum $ StreamK.fromStream $ Stream.enumerateFromTo 1 100
383{-# INLINABLE fold #-}
384fold :: Monad m => FL.Fold m a b -> StreamK m a -> m b
385fold (FL.Fold step begin done) m = do
388 FL.Partial fs -> go fs m
389 FL.Done fb -> return fb
394 single a = step acc a
396 FL.Partial s -> done s
397 FL.Done b1 -> return b1
398 yieldk a r = step acc a
400 FL.Partial s -> go s r
401 FL.Done b1 -> return b1
402 in foldStream defState yieldk single stop m1
404-- | Fold resulting in either breaking the stream or continuation of the fold.
405-- Instead of supplying the input stream in one go we can run the fold multiple
406-- times, each time supplying the next segment of the input stream. If the fold
407-- has not yet finished it returns a fold that can be run again otherwise it
408-- returns the fold result and the residual stream.
411{-# INLINE foldEither #-}
412foldEither :: Monad m =>
413 Fold m a b -> StreamK m a -> m (Either (Fold m a b) (b, StreamK m a))
414foldEither (FL.Fold step begin done) m = do
417 FL.Partial fs -> go fs m
418 FL.Done fb -> return $ Right (fb, m)
423 let stop = return $ Left (Fold step (return $ FL.Partial acc) done)
428 return $ Left (Fold step (return $ FL.Partial s) done)
429 FL.Done b1 -> return $ Right (b1, nil)
433 FL.Partial s -> go s r
434 FL.Done b1 -> return $ Right (b1, r)
435 in foldStream defState yieldk single stop m1
437-- | Like 'fold' but also returns the remaining stream. The resulting stream
438-- would be 'StreamK.nil' if the stream finished before the fold.
440{-# INLINE foldBreak #-}
441foldBreak :: Monad m => Fold m a b -> StreamK m a -> m (b, StreamK m a)
442foldBreak fld strm = do
443 r <- foldEither fld strm
445 Right res -> return res
446 Left (Fold _ initial extract) -> do
449 FL.Done _ -> error "foldBreak: unreachable state"
454-- XXX Array folds can be implemented using this.
455-- foldContainers? Specialized to foldArrays.
457-- | Generate streams from individual elements of a stream and fold the
458-- concatenation of those streams using the supplied fold. Return the result of
459-- the fold and residual stream.
461-- For example, this can be used to efficiently fold an Array Word8 stream
465{-# INLINE foldConcat #-}
466foldConcat :: Monad m =>
467 Producer m a b -> Fold m b c -> StreamK m a -> m (c, StreamK m a)
469 (Producer pstep pinject pextract)
470 (Fold fstep begin done)
475 FL.Partial fs -> go fs stream
476 FL.Done fb -> return (fb, stream)
486 res <- go1 SPEC acc st
493 return (b, fromPure x)
496 res <- go1 SPEC acc st
501 return (b, x `cons` r)
502 in foldStream defState yieldk single stop m1
508 Stream.Yield x s -> do
511 FL.Done b -> return $ Right (b, s)
512 FL.Partial fs1 -> go1 SPEC fs1 s
513 Stream.Skip s -> go1 SPEC fs s
514 Stream.Stop -> return $ Left fs
516-- | Like 'foldl'' but with a monadic step function.
517{-# INLINE foldlM' #-}
518foldlM' :: Monad m => (b -> a -> m b) -> m b -> StreamK m a -> m b
519foldlM' step begin = foldlMx' step begin return
521------------------------------------------------------------------------------
523------------------------------------------------------------------------------
526head :: Monad m => StreamK m a -> m (Maybe a)
527-- head = foldrM (\x _ -> return $ Just x) (return Nothing)
529 let stop = return Nothing
530 single a = return (Just a)
531 yieldk a _ = return (Just a)
532 in foldStream defState yieldk single stop m
535elem :: (Monad m, Eq a) => a -> StreamK m a -> m Bool
539 let stop = return False
540 single a = return (a == e)
541 yieldk a r = if a == e then return True else go r
542 in foldStream defState yieldk single stop m1
544{-# INLINE notElem #-}
545notElem :: (Monad m, Eq a) => a -> StreamK m a -> m Bool
549 let stop = return True
550 single a = return (a /= e)
551 yieldk a r = if a == e then return False else go r
552 in foldStream defState yieldk single stop m1
555all :: Monad m => (a -> Bool) -> StreamK m a -> m Bool
559 let single a | p a = return True
560 | otherwise = return False
561 yieldk a r | p a = go r
562 | otherwise = return False
563 in foldStream defState yieldk single (return True) m1
566any :: Monad m => (a -> Bool) -> StreamK m a -> m Bool
570 let single a | p a = return True
571 | otherwise = return False
572 yieldk a r | p a = return True
574 in foldStream defState yieldk single (return False) m1
576-- | Extract the last element of the stream, if any.
578last :: Monad m => StreamK m a -> m (Maybe a)
579last = foldlx' (\_ y -> Just y) Nothing id
581{-# INLINE minimum #-}
582minimum :: (Monad m, Ord a) => StreamK m a -> m (Maybe a)
586 let stop = return Nothing
587 single a = return (Just a)
588 yieldk a r = go (Just a) r
589 in foldStream defState yieldk single stop m1
592 let stop = return (Just res)
595 then return (Just res)
601 in foldStream defState yieldk single stop m1
603{-# INLINE minimumBy #-}
606 => (a -> a -> Ordering) -> StreamK m a -> m (Maybe a)
607minimumBy cmp = go Nothing
610 let stop = return Nothing
611 single a = return (Just a)
612 yieldk a r = go (Just a) r
613 in foldStream defState yieldk single stop m1
616 let stop = return (Just res)
617 single a = case cmp res a of
618 GT -> return (Just a)
619 _ -> return (Just res)
620 yieldk a r = case cmp res a of
623 in foldStream defState yieldk single stop m1
625{-# INLINE maximum #-}
626maximum :: (Monad m, Ord a) => StreamK m a -> m (Maybe a)
630 let stop = return Nothing
631 single a = return (Just a)
632 yieldk a r = go (Just a) r
633 in foldStream defState yieldk single stop m1
636 let stop = return (Just res)
640 else return (Just res)
645 in foldStream defState yieldk single stop m1
647{-# INLINE maximumBy #-}
648maximumBy :: Monad m => (a -> a -> Ordering) -> StreamK m a -> m (Maybe a)
649maximumBy cmp = go Nothing
652 let stop = return Nothing
653 single a = return (Just a)
654 yieldk a r = go (Just a) r
655 in foldStream defState yieldk single stop m1
658 let stop = return (Just res)
659 single a = case cmp res a of
660 GT -> return (Just res)
662 yieldk a r = case cmp res a of
663 GT -> go (Just res) r
665 in foldStream defState yieldk single stop m1
668(!!) :: Monad m => StreamK m a -> Int -> m (Maybe a)
672 let single a | n == 0 = return $ Just a
673 | otherwise = return Nothing
674 yieldk a x | n < 0 = return Nothing
675 | n == 0 = return $ Just a
676 | otherwise = go (n - 1) x
677 in foldStream defState yieldk single (return Nothing) m1
680lookup :: (Monad m, Eq a) => a -> StreamK m (a, b) -> m (Maybe b)
684 let single (a, b) | a == e = return $ Just b
685 | otherwise = return Nothing
686 yieldk (a, b) x | a == e = return $ Just b
688 in foldStream defState yieldk single (return Nothing) m1
691findM :: Monad m => (a -> m Bool) -> StreamK m a -> m (Maybe a)
697 if b then return $ Just a else return Nothing
700 if b then return $ Just a else go x
701 in foldStream defState yieldk single (return Nothing) m1
704find :: Monad m => (a -> Bool) -> StreamK m a -> m (Maybe a)
705find p = findM (return . p)
707{-# INLINE findIndices #-}
708findIndices :: (a -> Bool) -> StreamK m a -> StreamK m Int
711 go offset m1 = mkStream $ \st yld sng stp ->
712 let single a | p a = sng offset
714 yieldk a x | p a = yld offset $ go (offset + 1) x
715 | otherwise = foldStream (adaptState st) yld sng stp $
717 in foldStream (adaptState st) yieldk single stp m1
719------------------------------------------------------------------------------
721------------------------------------------------------------------------------
723-- | Apply a monadic action to each element of the stream and discard the
724-- output of the action.
726mapM_ :: Monad m => (a -> m b) -> StreamK m a -> m ()
731 single a = void (f a)
732 yieldk a r = f a >> go r
733 in foldStream defState yieldk single stop m1
736mapM :: Monad m => (a -> m b) -> StreamK m a -> StreamK m b
739------------------------------------------------------------------------------
741------------------------------------------------------------------------------
743{-# INLINABLE toList #-}
744toList :: Monad m => StreamK m a -> m [a]
747-- Based on suggestions by David Feuer and Pranay Sashank
749hoist :: (Monad m, Monad n)
750 => (forall x. m x -> n x) -> StreamK m a -> StreamK n a
752 mkStream $ \st yld sng stp ->
753 let single = return . sng
754 yieldk a s = return $ yld a (hoist f s)
756 state = adaptState st
757 in join . f $ foldStreamShared state yieldk single stop str
759-------------------------------------------------------------------------------
760-- Transformation by folding (Scans)
761-------------------------------------------------------------------------------
763{-# INLINE scanlx' #-}
764scanlx' :: (x -> a -> x) -> x -> (x -> b) -> StreamK m a -> StreamK m b
765scanlx' step begin done m =
766 cons (done begin) $ go m begin
768 go m1 !acc = mkStream $ \st yld sng stp ->
769 let single a = sng (done $ step acc a)
772 in yld (done s) (go r s)
773 in foldStream (adaptState st) yieldk single stp m1
776scanl' :: (b -> a -> b) -> b -> StreamK m a -> StreamK m b
777scanl' step begin = scanlx' step begin id
779-------------------------------------------------------------------------------
781-------------------------------------------------------------------------------
784filter :: (a -> Bool) -> StreamK m a -> StreamK m a
787 go m1 = mkStream $ \st yld sng stp ->
788 let single a | p a = sng a
790 yieldk a r | p a = yld a (go r)
791 | otherwise = foldStream st yieldk single stp r
792 in foldStream st yieldk single stp m1
795take :: Int -> StreamK m a -> StreamK m a
798 go n1 m1 = mkStream $ \st yld sng stp ->
799 let yieldk a r = yld a (go (n1 - 1) r)
802 else foldStream st yieldk sng stp m1
804{-# INLINE takeWhile #-}
805takeWhile :: (a -> Bool) -> StreamK m a -> StreamK m a
808 go m1 = mkStream $ \st yld sng stp ->
809 let single a | p a = sng a
811 yieldk a r | p a = yld a (go r)
813 in foldStream st yieldk single stp m1
816drop :: Int -> StreamK m a -> StreamK m a
817drop n m = unShare (go n m)
819 go n1 m1 = mkStream $ \st yld sng stp ->
821 yieldk _ r = foldStreamShared st yld sng stp $ go (n1 - 1) r
822 -- Somehow "<=" check performs better than a ">"
824 then foldStreamShared st yld sng stp m1
825 else foldStreamShared st yieldk single stp m1
827{-# INLINE dropWhile #-}
828dropWhile :: (a -> Bool) -> StreamK m a -> StreamK m a
831 go m1 = mkStream $ \st yld sng stp ->
832 let single a | p a = stp
834 yieldk a r | p a = foldStream st yieldk single stp r
835 | otherwise = yld a r
836 in foldStream st yieldk single stp m1
838-------------------------------------------------------------------------------
840-------------------------------------------------------------------------------
842-- Be careful when modifying this, this uses a consM (|:) deliberately to allow
843-- other stream types to overload it.
844{-# INLINE sequence #-}
845sequence :: Monad m => StreamK m (m a) -> StreamK m a
848 go m1 = mkStream $ \st yld sng stp ->
849 let single ma = ma >>= sng
850 yieldk ma r = foldStreamShared st yld sng stp $ ma `consM` go r
851 in foldStream (adaptState st) yieldk single stp m1
853-------------------------------------------------------------------------------
855-------------------------------------------------------------------------------
857{-# INLINE intersperseM #-}
858intersperseM :: Monad m => m a -> StreamK m a -> StreamK m a
859intersperseM a = prependingStart
861 prependingStart m1 = mkStream $ \st yld sng stp ->
863 foldStreamShared st yld sng stp $ return i `consM` go x
864 in foldStream st yieldk sng stp m1
865 go m2 = mkStream $ \st yld sng stp ->
866 let single i = foldStreamShared st yld sng stp $ a `consM` fromPure i
869 st yld sng stp $ a `consM` return i `consM` go x
870 in foldStream st yieldk single stp m2
872{-# INLINE intersperse #-}
873intersperse :: Monad m => a -> StreamK m a -> StreamK m a
874intersperse a = intersperseM (return a)
876{-# INLINE insertBy #-}
877insertBy :: (a -> a -> Ordering) -> a -> StreamK m a -> StreamK m a
880 go m1 = mkStream $ \st yld _ _ ->
881 let single a = case cmp x a of
882 GT -> yld a (fromPure x)
883 _ -> yld x (fromPure a)
885 yieldk a r = case cmp x a of
887 _ -> yld x (a `cons` r)
888 in foldStream st yieldk single stop m1
890------------------------------------------------------------------------------
892------------------------------------------------------------------------------
894{-# INLINE deleteBy #-}
895deleteBy :: (a -> a -> Bool) -> a -> StreamK m a -> StreamK m a
898 go m1 = mkStream $ \st yld sng stp ->
899 let single a = if eq x a then stp else sng a
900 yieldk a r = if eq x a
901 then foldStream st yld sng stp r
903 in foldStream st yieldk single stp m1
905-------------------------------------------------------------------------------
907-------------------------------------------------------------------------------
909{-# INLINE mapMaybe #-}
910mapMaybe :: (a -> Maybe b) -> StreamK m a -> StreamK m b
913 go m1 = mkStream $ \st yld sng stp ->
914 let single a = maybe stp sng (f a)
915 yieldk a r = case f a of
916 Just b -> yld b $ go r
917 Nothing -> foldStream (adaptState st) yieldk single stp r
918 in foldStream (adaptState st) yieldk single stp m1
920------------------------------------------------------------------------------
922------------------------------------------------------------------------------
924-- | Zip two streams serially using a pure zipping function.
926{-# INLINE zipWith #-}
927zipWith :: Monad m => (a -> b -> c) -> StreamK m a -> StreamK m b -> StreamK m c
928zipWith f = zipWithM (\a b -> return (f a b))
930-- | Zip two streams serially using a monadic zipping function.
932{-# INLINE zipWithM #-}
933zipWithM :: Monad m =>
934 (a -> b -> m c) -> StreamK m a -> StreamK m b -> StreamK m c
939 go mx my = mkStream $ \st yld sng stp -> do
941 let single2 b = f a b >>= sng
942 yield2 b rb = f a b >>= \x -> yld x (go ra rb)
943 in foldStream (adaptState st) yield2 single2 stp my
944 let single1 a = merge a nil
946 foldStream (adaptState st) yield1 single1 stp mx
948------------------------------------------------------------------------------
950------------------------------------------------------------------------------
952{-# INLINE mergeByM #-}
953mergeByM :: Monad m =>
954 (a -> a -> m Ordering) -> StreamK m a -> StreamK m a -> StreamK m a
959 go mx my = mkStream $ \st yld sng stp -> do
960 let stop = foldStream st yld sng stp my
961 single x = foldStream st yld sng stp (goX0 x my)
962 yield x rx = foldStream st yld sng stp (goX x rx my)
963 foldStream st yield single stop mx
965 goX0 x my = mkStream $ \st yld sng _ -> do
970 GT -> yld y (fromPure x)
971 _ -> yld x (fromPure y)
975 GT -> yld y (goX0 x ry)
976 _ -> yld x (y `cons` ry)
977 in foldStream st yield single stop my
979 goX x mx my = mkStream $ \st yld _ _ -> do
984 GT -> yld y (x `cons` mx)
985 _ -> yld x (goY0 mx y)
989 GT -> yld y (goX x mx ry)
990 _ -> yld x (goY mx y ry)
991 in foldStream st yield single stop my
993 goY0 mx y = mkStream $ \st yld sng _ -> do
998 GT -> yld y (fromPure x)
999 _ -> yld x (fromPure y)
1003 GT -> yld y (x `cons` rx)
1004 _ -> yld x (goY0 rx y)
1005 in foldStream st yield single stop mx
1007 goY mx y my = mkStream $ \st yld _ _ -> do
1012 GT -> yld y (goX0 x my)
1013 _ -> yld x (y `cons` my)
1017 GT -> yld y (goX x rx my)
1018 _ -> yld x (goY rx y my)
1019 in foldStream st yield single stop mx
1021{-# INLINE mergeBy #-}
1022mergeBy :: (a -> a -> Ordering) -> StreamK m a -> StreamK m a -> StreamK m a
1023-- XXX GHC: This has slightly worse performance than replacing "r <- cmp x y"
1024-- with "let r = cmp x y" in the monadic version. The definition below is
1025-- exactly the same as mergeByM except this change.
1026-- mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
1031 go mx my = mkStream $ \st yld sng stp -> do
1032 let stop = foldStream st yld sng stp my
1033 single x = foldStream st yld sng stp (goX0 x my)
1034 yield x rx = foldStream st yld sng stp (goX x rx my)
1035 foldStream st yield single stop mx
1037 goX0 x my = mkStream $ \st yld sng _ -> do
1041 GT -> yld y (fromPure x)
1042 _ -> yld x (fromPure y)
1045 GT -> yld y (goX0 x ry)
1046 _ -> yld x (y `cons` ry)
1047 in foldStream st yield single stop my
1049 goX x mx my = mkStream $ \st yld _ _ -> do
1053 GT -> yld y (x `cons` mx)
1054 _ -> yld x (goY0 mx y)
1057 GT -> yld y (goX x mx ry)
1058 _ -> yld x (goY mx y ry)
1059 in foldStream st yield single stop my
1061 goY0 mx y = mkStream $ \st yld sng _ -> do
1065 GT -> yld y (fromPure x)
1066 _ -> yld x (fromPure y)
1069 GT -> yld y (x `cons` rx)
1070 _ -> yld x (goY0 rx y)
1071 in foldStream st yield single stop mx
1073 goY mx y my = mkStream $ \st yld _ _ -> do
1077 GT -> yld y (goX0 x my)
1078 _ -> yld x (y `cons` my)
1081 GT -> yld y (goX x rx my)
1082 _ -> yld x (goY rx y my)
1083 in foldStream st yield single stop mx
1085------------------------------------------------------------------------------
1086-- Transformation comprehensions
1087------------------------------------------------------------------------------
1090the :: (Eq a, Monad m) => StreamK m a -> m (Maybe a)
1094 Nothing -> return Nothing
1095 Just (h, t) -> go h t
1098 let single a | h == a = return $ Just h
1099 | otherwise = return Nothing
1100 yieldk a r | h == a = go h r
1101 | otherwise = return Nothing
1102 in foldStream defState yieldk single (return $ Just h) m1
1104------------------------------------------------------------------------------
1105-- Alternative & MonadPlus
1106------------------------------------------------------------------------------
1108_alt :: StreamK m a -> StreamK m a -> StreamK m a
1109_alt m1 m2 = mkStream $ \st yld sng stp ->
1110 let stop = foldStream st yld sng stp m2
1111 in foldStream st yld sng stop m1
1113------------------------------------------------------------------------------
1115------------------------------------------------------------------------------
1118-- XXX handle and test cross thread state transfer
1121 => StreamK m a -> (e -> StreamK m a) -> StreamK m a
1123 mkStream $ \_ stp sng yld ->
1124 let run x = unStream x Nothing stp sng yieldk
1125 handle r = r `catchError` \e -> run $ h e
1126 yieldk a r = yld a (withCatchError r h)
1130-------------------------------------------------------------------------------
1132-------------------------------------------------------------------------------
1134-- Inlined definition.
1135{-# INLINE splitAt #-}
1136splitAt :: Int -> [a] -> ([a],[a])
1139 | otherwise = splitAt' n ls
1141 splitAt' :: Int -> [a] -> ([a], [a])
1142 splitAt' _ [] = ([], [])
1143 splitAt' 1 (x:xs) = ([x], xs)
1144 splitAt' m (x:xs) = (x:xs', xs'')
1146 (xs', xs'') = splitAt' (m - 1) xs
1148-- | Run a 'Parser' over a stream and return rest of the Stream.
1149{-# INLINE_NORMAL parseDBreak #-}
1154 -> m (Either ParseError b, StreamK m a)
1155parseDBreak (PR.Parser pstep initial extract) stream = do
1158 PR.IPartial s -> goStream stream [] s
1159 PR.IDone b -> return (Right b, stream)
1160 PR.IError err -> return (Left (ParseError err), stream)
1164 -- "buf" contains last few items in the stream that we may have to
1167 -- XXX currently we are using a dumb list based approach for backtracking
1168 -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
1169 -- That will allow us more efficient random back and forth movement.
1170 goStream st buf !pst =
1174 PR.Error err -> return (Left (ParseError err), nil)
1176 assertM(n <= length buf)
1177 let src0 = Prelude.take n buf
1178 src = Prelude.reverse src0
1179 return (Right b, fromList src)
1180 PR.Partial _ _ -> error "Bug: parseBreak: Partial in extract"
1181 PR.Continue 0 s -> goStream nil buf s
1182 PR.Continue n s -> do
1183 assertM(n <= length buf)
1184 let (src0, buf1) = splitAt n buf
1185 src = Prelude.reverse src0
1186 goBuf nil buf1 src s
1187 single x = yieldk x nil
1191 PR.Partial 0 s -> goStream r [] s
1192 PR.Partial n s -> do
1193 assertM(n <= length (x:buf))
1194 let src0 = Prelude.take n (x:buf)
1195 src = Prelude.reverse src0
1197 PR.Continue 0 s -> goStream r (x:buf) s
1198 PR.Continue n s -> do
1199 assertM(n <= length (x:buf))
1200 let (src0, buf1) = splitAt n (x:buf)
1201 src = Prelude.reverse src0
1203 PR.Done 0 b -> return (Right b, r)
1205 assertM(n <= length (x:buf))
1206 let src0 = Prelude.take n (x:buf)
1207 src = Prelude.reverse src0
1208 return (Right b, append (fromList src) r)
1209 PR.Error err -> return (Left (ParseError err), r)
1210 in foldStream defState yieldk single stop st
1212 goBuf st buf [] !pst = goStream st buf pst
1213 goBuf st buf (x:xs) !pst = do
1216 PR.Partial 0 s -> goBuf st [] xs s
1217 PR.Partial n s -> do
1218 assert (n <= length (x:buf)) (return ())
1219 let src0 = Prelude.take n (x:buf)
1220 src = Prelude.reverse src0 ++ xs
1222 PR.Continue 0 s -> goBuf st (x:buf) xs s
1223 PR.Continue n s -> do
1224 assert (n <= length (x:buf)) (return ())
1225 let (src0, buf1) = splitAt n (x:buf)
1226 src = Prelude.reverse src0 ++ xs
1229 assert (n <= length (x:buf)) (return ())
1230 let src0 = Prelude.take n (x:buf)
1231 src = Prelude.reverse src0
1232 return (Right b, append (fromList src) st)
1233 PR.Error err -> return (Left (ParseError err), nil)
1235-- Using ParserD or ParserK on StreamK may not make much difference. We should
1236-- perhaps use only chunked parsing on StreamK. We can always convert a stream
1237-- to chunks before parsing. Or just have a ParserK element parser for StreamK
1238-- and convert ParserD to ParserK for element parsing using StreamK.
1239{-# INLINE parseD #-}
1241 Parser.Parser a m b -> StreamK m a -> m (Either ParseError b)
1242parseD f = fmap fst . parseDBreak f
1244-------------------------------------------------------------------------------
1245-- Chunked parsing using ParserK
1246-------------------------------------------------------------------------------
1248-- The backracking buffer consists of arrays in the most-recent-first order. We
1249-- want to take a total of n array elements from this buffer. Note: when we
1250-- have to take an array partially, we must take the last part of the array.
1251{-# INLINE backTrack #-}
1252backTrack :: forall m a. Unbox a =>
1255 -> StreamK m (Array a)
1256 -> (StreamK m (Array a), [Array a])
1261 go _ [] stream = (stream, [])
1262 go n xs stream | n <= 0 = (stream, xs)
1263 go n (x:xs) stream =
1264 let len = Array.length x
1266 then go (n - len) xs (cons x stream)
1268 then (cons x stream, xs)
1269 else let !(Array contents start end) = x
1270 !start1 = end - (n * SIZE_OF(a))
1271 arr1 = Array contents start1 end
1272 arr2 = Array contents start start1
1273 in (cons arr1 stream, arr2:xs)
1275-- | A continuation to extract the result when a CPS parser is done.
1276{-# INLINE parserDone #-}
1277parserDone :: Applicative m =>
1278 ParserK.ParseResult b -> Int -> ParserK.Input a -> m (ParserK.Step a m b)
1279parserDone (ParserK.Success n b) _ _ = pure $ ParserK.Done n b
1280parserDone (ParserK.Failure n e) _ _ = pure $ ParserK.Error n e
1282-- XXX parseDBreakChunks may be faster than converting parserD to parserK and
1283-- using parseBreakChunks. We can also use parseBreak as an alternative to the
1284-- monad instance of ParserD.
1286-- | Run a 'ParserK' over a chunked 'StreamK' and return the rest of the Stream.
1287{-# INLINE_NORMAL parseBreakChunks #-}
1289 :: (Monad m, Unbox a)
1291 -> StreamK m (Array a)
1292 -> m (Either ParseError b, StreamK m (Array a))
1293parseBreakChunks parser input = do
1294 let parserk = ParserK.runParser parser parserDone 0 0
1295 in go [] parserk input
1299 {-# INLINE goStop #-}
1300 goStop backBuf parserk = do
1301 pRes <- parserk ParserK.None
1303 -- If we stop in an alternative, it will try calling the next
1304 -- parser, the next parser may call initial returning Partial and
1305 -- then immediately we have to call extract on it.
1306 ParserK.Partial 0 cont1 ->
1308 ParserK.Partial n cont1 -> do
1310 assertM(n1 >= 0 && n1 <= sum (Prelude.map Array.length backBuf))
1311 let (s1, backBuf1) = backTrack n1 backBuf nil
1312 in go backBuf1 cont1 s1
1313 ParserK.Continue 0 cont1 ->
1314 go backBuf cont1 nil
1315 ParserK.Continue n cont1 -> do
1317 assertM(n1 >= 0 && n1 <= sum (Prelude.map Array.length backBuf))
1318 let (s1, backBuf1) = backTrack n1 backBuf nil
1319 in go backBuf1 cont1 s1
1321 return (Right b, nil)
1322 ParserK.Done n b -> do
1324 assertM(n1 >= 0 && n1 <= sum (Prelude.map Array.length backBuf))
1325 let (s1, _) = backTrack n1 backBuf nil
1326 in return (Right b, s1)
1327 ParserK.Error _ err -> return (Left (ParseError err), nil)
1330 error $ "parseBreak: Partial: forward seek not implemented n = "
1331 ++ show n ++ " len = " ++ show len
1333 yieldk backBuf parserk arr stream = do
1334 pRes <- parserk (ParserK.Chunk arr)
1335 let len = Array.length arr
1337 ParserK.Partial n cont1 ->
1338 case compare n len of
1339 EQ -> go [] cont1 stream
1342 then yieldk [] cont1 arr stream
1345 bufLen = sum (Prelude.map Array.length backBuf)
1347 assertM(n1 >= 0 && n1 <= bufLen)
1348 let (s1, _) = backTrack n1 backBuf s
1351 ParserK.Continue n cont1 ->
1352 case compare n len of
1353 EQ -> go (arr:backBuf) cont1 stream
1356 then yieldk backBuf cont1 arr stream
1359 bufLen = sum (Prelude.map Array.length backBuf)
1361 assertM(n1 >= 0 && n1 <= bufLen)
1362 let (s1, backBuf1) = backTrack n1 backBuf s
1363 go backBuf1 cont1 s1
1365 ParserK.Done n b -> do
1367 assertM(n1 <= sum (Prelude.map Array.length (arr:backBuf)))
1368 let (s1, _) = backTrack n1 (arr:backBuf) stream
1369 in return (Right b, s1)
1370 ParserK.Error _ err -> return (Left (ParseError err), nil)
1372 go backBuf parserk stream = do
1373 let stop = goStop backBuf parserk
1374 single a = yieldk backBuf parserk a nil
1376 defState (yieldk backBuf parserk) single stop stream
1378{-# INLINE parseChunks #-}
1379parseChunks :: (Monad m, Unbox a) =>
1380 ParserK a m b -> StreamK m (Array a) -> m (Either ParseError b)
1381parseChunks f = fmap fst . parseBreakChunks f
1383-------------------------------------------------------------------------------
1385-------------------------------------------------------------------------------
1387-- | Sort the input stream using a supplied comparison function.
1389-- Sorting can be achieved by simply:
1391-- >>> sortBy cmp = StreamK.mergeMapWith (StreamK.mergeBy cmp) StreamK.fromPure
1393-- However, this combinator uses a parser to first split the input stream into
1394-- down and up sorted segments and then merges them to optimize sorting when
1395-- pre-sorted sequences exist in the input stream.
1399{-# INLINE sortBy #-}
1400sortBy :: Monad m => (a -> a -> Ordering) -> StreamK m a -> StreamK m a
1401-- sortBy f = Stream.concatPairsWith (Stream.mergeBy f) Stream.fromPure
1404 Parser.groupByRollingEither
1405 (\x -> (< GT) . cmp x)
1408 in mergeMapWith (mergeBy cmp) id
1410 . Stream.catRights -- its a non-failing backtracking parser
1411 . Stream.parseMany (fmap (either id id) p)
1412 . 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