on master help sign in
Implement stream split ops in terms of folds

Added only doctest definitions and commented code as of now for implementing: * splitWithSuffixSeq in terms of takeEndBySeq fold * splitOnSuffixSeq in terms of takeEndBySeq_ * splitOnSeq in terms of takeEndBySeq_

commita5a941937e0d4e2c7d1f99664e9dd3e06c056fc9 authorHarendra Kumar <harendra@composewell.com> dateSat 21 May 2022, 18:55 (4 years ago) parentd5b3e37
2 files changed+41−21
src/Streamly/Internal/Data/Stream/IsStream/Common.hs+29 src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs+12−21
src/Streamly/Internal/Data/Stream/IsStream/Common.hs+29
@@ -32,6 +32,7 @@ module Streamly.Internal.Data.Stream.IsStream.Common
3232 , postscanlMAfter'
3333 , postscanlM'
3434 , smapM
35+ , foldManyPost
3536 -- $smapM_Notes
3637 , take
3738 , takeWhile
@@ -641,6 +642,27 @@ concatMap f m = fromStreamD $ D.concatMap (toStreamD . f) (toStreamD m)
641642concatM :: (IsStream t, Monad m) => m (t m a) -> t m a
642643concatM generator = concatMapM (\() -> generator) (fromPure ())
643644
645+-- | Like 'foldMany' but appends empty fold output if the fold and stream
646+-- termination aligns:
647+--
648+-- >>> f = Fold.take 2 Fold.sum
649+-- >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList []
650+-- [0]
651+-- >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList [1..9]
652+-- [3,7,11,15,9]
653+-- >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList [1..10]
654+-- [3,7,11,15,19,0]
655+--
656+-- /Pre-release/
657+--
658+{-# INLINE foldManyPost #-}
659+foldManyPost
660+ :: (IsStream t, Monad m)
661+ => Fold m a b
662+ -> t m a
663+ -> t m b
664+foldManyPost f m = fromStreamD $ D.foldManyPost f (toStreamD m)
665+
644666------------------------------------------------------------------------------
645667-- Split stream and fold
646668------------------------------------------------------------------------------
@@ -692,6 +714,8 @@ concatM generator = concatMapM (\() -> generator) (fromPure ())
692714--
693715-- > splitOnSeq . intercalate == id
694716--
717+-- >>> splitOnSeq pat f = Stream.foldManyPost (Fold.takeEndBySeq_ pat f)
718+--
695719-- /Pre-release/
696720
697721-- XXX We can use a polymorphic vector implemented by Array# to represent the
@@ -705,6 +729,11 @@ splitOnSeq
705729 => Array a -> Fold m a b -> t m a -> t m b
706730splitOnSeq patt f m =
707731 IsStream.fromStreamD $ D.splitOnSeq patt f (IsStream.toStreamD m)
732+-- XXX This may have a problem if the stream terminates and we start extracting
733+-- the fold and then the fold terminates before consuming all the buffered
734+-- input. We have no way to supply the buffered input back to the driver.
735+-- splitOnSeq patt f =
736+ -- foldManyPost (Fold.takeEndBySeq_ patt f)
708737
709738------------------------------------------------------------------------------
710739-- Zipping
src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs+12−21
@@ -170,6 +170,7 @@ import Streamly.Internal.Data.Stream.IsStream.Common
170170 , intersperseM
171171 , map
172172 , scanlMAfter'
173+ , foldManyPost
173174 , splitOnSeq
174175 , fromPure)
175176import Streamly.Internal.Data.Stream.IsStream.Type
@@ -251,27 +252,6 @@ dropSuffix = error "Not implemented yet!"
251252--
252253-- XXX We need takeGE/takeBetween to implement "some" using "many".
253254
254−-- | Like 'foldMany' but appends empty fold output if the fold and stream
255−-- termination aligns:
256−--
257−-- >>> f = Fold.take 2 Fold.sum
258−-- >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList []
259−-- [0]
260−-- >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList [1..9]
261−-- [3,7,11,15,9]
262−-- >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList [1..10]
263−-- [3,7,11,15,19,0]
264−--
265−-- /Pre-release/
266−--
267−{-# INLINE foldManyPost #-}
268−foldManyPost
269− :: (IsStream t, Monad m)
270− => Fold m a b
271− -> t m a
272− -> t m b
273−foldManyPost f m = fromStreamD $ D.foldManyPost f (toStreamD m)
274−
275255-- | Apply a 'Fold' repeatedly on a stream and emit the fold outputs in the
276256-- output stream.
277257--
@@ -889,6 +869,8 @@ splitBySeq patt f m =
889869--
890870-- > splitSuffixOn . intercalateSuffix == id
891871--
872+-- >>> splitOnSuffixSeq pat f = Stream.foldMany (Fold.takeEndBySeq_ pat f)
873+--
892874-- /Pre-release/
893875{-# INLINE splitOnSuffixSeq #-}
894876splitOnSuffixSeq
@@ -896,6 +878,11 @@ splitOnSuffixSeq
896878 => Array a -> Fold m a b -> t m a -> t m b
897879splitOnSuffixSeq patt f m =
898880 fromStreamD $ D.splitOnSuffixSeq False patt f (toStreamD m)
881+-- XXX This may have a problem if the stream terminates and we start extracting
882+-- the fold and then the fold terminates before consuming all the buffered
883+-- input. We have no way to supply the buffered input back to the driver.
884+-- splitOnSuffixSeq patt f =
885+-- foldMany (FL.takeEndBySeq_ patt f)
899886
900887-- | Like 'splitOn' but drops any empty splits.
901888--
@@ -934,6 +921,8 @@ wordsOn _subseq _f _m =
934921-- >>> splitWithSuffixSeq' "." "a..b.."
935922-- ["a.",".","b.","."]
936923--
924+-- >>> splitWithSuffixSeq pat f = Stream.foldMany (Fold.takeEndBySeq pat f)
925+--
937926-- /Pre-release/
938927{-# INLINE splitWithSuffixSeq #-}
939928splitWithSuffixSeq
@@ -941,6 +930,8 @@ splitWithSuffixSeq
941930 => Array a -> Fold m a b -> t m a -> t m b
942931splitWithSuffixSeq patt f m =
943932 fromStreamD $ D.splitOnSuffixSeq True patt f (toStreamD m)
933+-- splitWithSuffixSeq patt f =
934+-- foldMany (FL.takeEndBySeq patt f)
944935
945936-- This can be implemented easily using Rabin Karp
946937-- | Split post any one of the given patterns.