on master help sign in
Break IsStream module into smaller modules.

- IsStream.Generate - IsStream.Eliminate - IsStream.Transform - IsStream.Exceptions

commit3e53339d50687e59afc52b1d80e451e430a8ccac authorPranay Sashank <pranaysashank@composewell.com> dateTue 15 Dec 2020, 07:58 (6 years ago) parentc671f2e
6 files changed+4816−4149
src/Streamly/Internal/Data/Stream/IsStream.hs+289−4149 src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs+932 src/Streamly/Internal/Data/Stream/IsStream/Exceptions.hs+228 src/Streamly/Internal/Data/Stream/IsStream/Generate.hs+644 src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+2719 streamly.cabal+4
src/Streamly/Internal/Data/Stream/IsStream.hs+289−4149
@@ -599,55 +599,42 @@ module Streamly.Internal.Data.Stream.IsStream
599599where
600600
601601import Control.Concurrent (threadDelay)
602−import Control.Exception (Exception, assert)
603−import Control.Monad (void)
604−import Control.Monad.Catch (MonadCatch, MonadThrow)
602+import Control.Exception (assert)
605603import Control.Monad.IO.Class (MonadIO(..))
606−import Control.Monad.Trans.Reader (ReaderT)
607−import Control.Monad.Trans.State.Strict (StateT)
608−import Control.Monad.Trans.Class (MonadTrans(..))
609−import Control.Monad.Trans.Control (MonadBaseControl)
610−import Data.Either (isLeft, isRight)
611−import Data.Functor.Identity (Identity (..))
612604import Data.Kind (Type)
613605import Data.Heap (Entry(..))
614−import Data.Maybe (isJust, fromJust, isNothing)
615−import Data.Void (Void)
606+import Data.Maybe (isNothing)
616607import Foreign.Storable (Storable)
617−import Streamly.Internal.BaseCompat (fromLeft, fromRight)
618608import Streamly.Internal.Data.Stream.Enumeration
619609 (Enumerable(..), enumerate, enumerateTo)
620−import Streamly.Internal.Data.Fold.Types (Fold (..), Fold2 (..))
621−import Streamly.Internal.Data.Parser (Parser (..))
622−import Streamly.Internal.Data.Unfold.Types (Unfold)
623−import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array, writeNUnsafe)
624−import Streamly.Internal.Data.SVar (MonadAsync, defState, Rate (..))
625−import Streamly.Internal.Data.Stream.Ahead (AheadT, Ahead, ahead, aheadly)
610+import Streamly.Internal.Data.Fold.Types (Fold (..))
611+import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array)
612+import Streamly.Internal.Data.SVar (MonadAsync, Rate (..))
613+import Streamly.Internal.Data.Stream.Ahead (AheadT, Ahead, aheadly)
626614import Streamly.Internal.Data.Stream.Async
627− ( AsyncT, Async, WAsyncT, WAsync, mkAsync, async, asyncly, wAsync
615+ ( AsyncT, Async, WAsyncT, WAsync, mkAsync, asyncly
628616 , wAsyncly)
629617import Streamly.Internal.Data.Stream.Combinators
630− ( inspectMode, maxBuffer, maxThreads, maxYields, rate, avgRate, minRate
618+ ( inspectMode, maxBuffer, maxThreads, rate, avgRate, minRate
631619 , maxRate, constRate)
632620import Streamly.Internal.Data.Stream.Parallel
633− ( ParallelT, Parallel, parallel, parallely)
634−import Streamly.Internal.Data.Stream.Prelude
635− (fromStreamS, toStreamS, concatFoldableWith, concatMapFoldableWith
636− , concatForFoldableWith)
637−import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
621+ ( ParallelT, Parallel, parallely)
638622import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM), adapt)
639623import Streamly.Internal.Data.Stream.Serial
640− ( SerialT, WSerialT, Serial, WSerial, serial, wSerial, serially
624+ ( SerialT, WSerialT, Serial, WSerial, serially
641625 , wSerially)
642626import Streamly.Internal.Data.Stream.Zip
643627 ( ZipSerialM, ZipSerial, ZipAsyncM, ZipAsync, zipSerially, zipAsyncly)
644−import Streamly.Internal.Data.Pipe.Types (Pipe (..))
645628import Streamly.Internal.Data.Time.Units
646629 ( AbsTime, MilliSecond64(..), addToAbsTime, toRelTime
647− , toAbsTime, TimeUnit64, RelTime64, addToAbsTime64)
648−import Streamly.Internal.Data.IORef.Prim (Prim, IORef)
630+ , toAbsTime, RelTime64)
649631import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
650632
633+import Streamly.Internal.Data.Stream.IsStream.Generate
634+import Streamly.Internal.Data.Stream.IsStream.Eliminate
635+import Streamly.Internal.Data.Stream.IsStream.Transform
636+import Streamly.Internal.Data.Stream.IsStream.Exceptions
637+
651638import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
652639import qualified Streamly.Internal.Data.Fold as FL
653640import qualified Streamly.Internal.Data.Stream.Prelude as P
@@ -656,17 +643,8 @@ import qualified Streamly.Internal.Data.Stream.StreamD as D
656643import qualified Streamly.Internal.Data.Stream.Serial as Serial
657644import qualified Streamly.Internal.Data.Stream.Parallel as Par
658645import qualified Streamly.Internal.Data.Stream.Zip as Z
659−import qualified Streamly.Internal.Data.Parser.ParserK.Types as PRK
660−import qualified Streamly.Internal.Data.Parser.ParserD as PRD
661646import qualified Data.Heap as H
662647import qualified Data.Map.Strict as Map
663−import qualified Prelude
664−import qualified System.IO as IO
665−#ifdef USE_STREAMK_ONLY
666−import qualified Streamly.Internal.Data.Stream.StreamK as S
667−#else
668−import qualified Streamly.Internal.Data.Stream.StreamD as S
669−#endif
670648
671649import Prelude hiding
672650 ( filter, drop, dropWhile, take, takeWhile, zipWith, foldr
@@ -676,407 +654,10 @@ import Prelude hiding
676654 , scanl, scanl1, replicate, concatMap, span, splitAt, break
677655 , repeat, concat, mconcat)
678656
679−------------------------------------------------------------------------------
680−-- Deconstruction
681−------------------------------------------------------------------------------
682−
683−-- | Decompose a stream into its head and tail. If the stream is empty, returns
684−-- 'Nothing'. If the stream is non-empty, returns @Just (a, ma)@, where @a@ is
685−-- the head of the stream and @ma@ its tail.
686−--
687−-- This is a brute force primitive. Avoid using it as long as possible, use it
688−-- when no other combinator can do the job. This can be used to do pretty much
689−-- anything in an imperative manner, as it just breaks down the stream into
690−-- individual elements and we can loop over them as we deem fit. For example,
691−-- this can be used to convert a streamly stream into other stream types.
692−--
693−-- @since 0.1.0
694−{-# INLINE uncons #-}
695−uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a))
696−uncons m = K.uncons (K.adapt m)
697−
698−------------------------------------------------------------------------------
699−-- Generation by Unfolding
700−------------------------------------------------------------------------------
701−
702−-- |
703−-- @
704−-- unfoldr step s =
705−-- case step s of
706−-- Nothing -> 'K.nil'
707−-- Just (a, b) -> a \`cons` unfoldr step b
708−-- @
709−--
710−-- Build a stream by unfolding a /pure/ step function @step@ starting from a
711−-- seed @s@. The step function returns the next element in the stream and the
712−-- next seed value. When it is done it returns 'Nothing' and the stream ends.
713−-- For example,
714−--
715−-- @
716−-- let f b =
717−-- if b > 3
718−-- then Nothing
719−-- else Just (b, b + 1)
720−-- in toList $ unfoldr f 0
721−-- @
722−-- @
723−-- [0,1,2,3]
724−-- @
725−--
726−-- @since 0.1.0
727−{-# INLINE_EARLY unfoldr #-}
728−unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a
729−unfoldr step seed = fromStreamS (S.unfoldr step seed)
730−{-# RULES "unfoldr fallback to StreamK" [1]
731− forall a b. S.toStreamK (S.unfoldr a b) = K.unfoldr a b #-}
732−
733−-- | Build a stream by unfolding a /monadic/ step function starting from a
734−-- seed. The step function returns the next element in the stream and the next
735−-- seed value. When it is done it returns 'Nothing' and the stream ends. For
736−-- example,
737−--
738−-- @
739−-- let f b =
740−-- if b > 3
741−-- then return Nothing
742−-- else print b >> return (Just (b, b + 1))
743−-- in drain $ unfoldrM f 0
744−-- @
745−-- @
746−-- 0
747−-- 1
748−-- 2
749−-- 3
750−-- @
751−-- When run concurrently, the next unfold step can run concurrently with the
752−-- processing of the output of the previous step. Note that more than one step
753−-- cannot run concurrently as the next step depends on the output of the
754−-- previous step.
755−--
756−-- @
757−-- (asyncly $ S.unfoldrM (\\n -> liftIO (threadDelay 1000000) >> return (Just (n, n + 1))) 0)
758−-- & S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
759−-- @
760−--
761−-- /Concurrent/
762−--
763−-- /Since: 0.1.0/
764−{-# INLINE_EARLY unfoldrM #-}
765−unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
766−unfoldrM = K.unfoldrM
767−
768−{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
769−{-# INLINE_EARLY unfoldrMSerial #-}
770−unfoldrMSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
771−unfoldrMSerial = Serial.unfoldrM
772−
773−{-# RULES "unfoldrM wSerial" unfoldrM = unfoldrMWSerial #-}
774−{-# INLINE_EARLY unfoldrMWSerial #-}
775−unfoldrMWSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> WSerialT m a
776−unfoldrMWSerial = Serial.unfoldrM
777−
778−{-# RULES "unfoldrM zipSerial" unfoldrM = unfoldrMZipSerial #-}
779−{-# INLINE_EARLY unfoldrMZipSerial #-}
780−unfoldrMZipSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> ZipSerialM m a
781−unfoldrMZipSerial = Serial.unfoldrM
782−
783−-- | Convert an 'Unfold' into a stream by supplying it an input seed.
784−--
785−-- >>> unfold (UF.replicateM 10) (putStrLn "hello")
786−--
787−-- /Since: 0.7.0/
788−{-# INLINE unfold #-}
789−unfold :: (IsStream t, Monad m) => Unfold m a b -> a -> t m b
790−unfold unf x = fromStreamD $ D.unfold unf x
791−
792−-- | Convert an 'Unfold' with a closed input end into a stream.
793−--
794−-- /Internal/
795−{-# INLINE unfold0 #-}
796−unfold0 :: (IsStream t, Monad m) => Unfold m Void b -> t m b
797−unfold0 unf = unfold unf (error "unfold0: unexpected void evaluation")
798−
799−------------------------------------------------------------------------------
800−-- Specialized Generation
801−------------------------------------------------------------------------------
802−
803−-- Faster than yieldM because there is no bind.
804−--
805−-- |
806−-- @
807−-- yield a = a \`cons` nil
808−-- @
809−--
810−-- Create a singleton stream from a pure value.
811−--
812−-- The following holds in monadic streams, but not in Zip streams:
813−--
814−-- @
815−-- yield = pure
816−-- yield = yieldM . pure
817−-- @
818−--
819−-- In Zip applicative streams 'yield' is not the same as 'pure' because in that
820−-- case 'pure' is equivalent to 'repeat' instead. 'yield' and 'pure' are
821−-- equally efficient, in other cases 'yield' may be slightly more efficient
822−-- than the other equivalent definitions.
823−--
824−-- @since 0.4.0
825−{-# INLINE yield #-}
826−yield :: IsStream t => a -> t m a
827−yield = K.yield
828−
829−-- |
830−-- @
831−-- yieldM m = m \`consM` nil
832−-- @
833−--
834−-- Create a singleton stream from a monadic action.
835−--
836−-- @
837−-- > toList $ yieldM getLine
838−-- hello
839−-- ["hello"]
840−-- @
841−--
842−-- @since 0.4.0
843−{-# INLINE yieldM #-}
844−yieldM :: (Monad m, IsStream t) => m a -> t m a
845−yieldM = K.yieldM
846−
847−-- |
848−-- @
849−-- fromIndices f = let g i = f i \`cons` g (i + 1) in g 0
850−-- @
851−--
852−-- Generate an infinite stream, whose values are the output of a function @f@
853−-- applied on the corresponding index. Index starts at 0.
854−--
855−-- @
856−-- > S.toList $ S.take 5 $ S.fromIndices id
857−-- [0,1,2,3,4]
858−-- @
859−--
860−-- @since 0.6.0
861−{-# INLINE fromIndices #-}
862−fromIndices :: (IsStream t, Monad m) => (Int -> a) -> t m a
863−fromIndices = fromStreamS . S.fromIndices
864−
865−--
866−-- |
867−-- @
868−-- fromIndicesM f = let g i = f i \`consM` g (i + 1) in g 0
869−-- @
870−--
871−-- Generate an infinite stream, whose values are the output of a monadic
872−-- function @f@ applied on the corresponding index. Index starts at 0.
873−--
874−-- /Concurrent/
875−--
876−-- @since 0.6.0
877−{-# INLINE_EARLY fromIndicesM #-}
878−fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
879−fromIndicesM = K.fromIndicesM
880−
881−{-# RULES "fromIndicesM serial" fromIndicesM = fromIndicesMSerial #-}
882−{-# INLINE fromIndicesMSerial #-}
883−fromIndicesMSerial :: MonadAsync m => (Int -> m a) -> SerialT m a
884−fromIndicesMSerial = fromStreamS . S.fromIndicesM
885−
886−-- |
887−-- @
888−-- replicateM = take n . repeatM
889−-- @
890−--
891−-- Generate a stream by performing a monadic action @n@ times. Same as:
892−--
893−-- @
894−-- drain $ serially $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
895−-- drain $ asyncly $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
896−-- @
897−--
898−-- /Concurrent/
899−--
900−-- @since 0.1.1
901−{-# INLINE_EARLY replicateM #-}
902−replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
903−replicateM = K.replicateM
904−
905−{-# RULES "replicateM serial" replicateM = replicateMSerial #-}
906−{-# INLINE replicateMSerial #-}
907−replicateMSerial :: MonadAsync m => Int -> m a -> SerialT m a
908−replicateMSerial n = fromStreamS . S.replicateM n
909−
910−-- |
911−-- @
912−-- replicate = take n . repeat
913−-- @
914−--
915−-- Generate a stream of length @n@ by repeating a value @n@ times.
916−--
917−-- @since 0.6.0
918−{-# INLINE_NORMAL replicate #-}
919−replicate :: (IsStream t, Monad m) => Int -> a -> t m a
920−replicate n = fromStreamS . S.replicate n
921−
922−-- |
923−-- Generate an infinite stream by repeating a pure value.
924−--
925−-- @since 0.4.0
926−{-# INLINE_NORMAL repeat #-}
927−repeat :: (IsStream t, Monad m) => a -> t m a
928−repeat = fromStreamS . S.repeat
929−
930−-- |
931−-- @
932−-- repeatM = fix . consM
933−-- repeatM = cycle1 . yieldM
934−-- @
935−--
936−-- Generate a stream by repeatedly executing a monadic action forever.
937−--
938−-- @
939−-- drain $ serially $ S.take 10 $ S.repeatM $ (threadDelay 1000000 >> print 1)
940−-- drain $ asyncly $ S.take 10 $ S.repeatM $ (threadDelay 1000000 >> print 1)
941−-- @
942−--
943−-- /Concurrent, infinite (do not use with 'parallely')/
944−--
945−-- @since 0.2.0
946−{-# INLINE_EARLY repeatM #-}
947−repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
948−repeatM = K.repeatM
949−
950−{-# RULES "repeatM serial" repeatM = repeatMSerial #-}
951−{-# INLINE repeatMSerial #-}
952−repeatMSerial :: MonadAsync m => m a -> SerialT m a
953−repeatMSerial = fromStreamS . S.repeatM
954−
955−-- |
956−-- @
957−-- iterate f x = x \`cons` iterate f x
958−-- @
959−--
960−-- Generate an infinite stream with @x@ as the first element and each
961−-- successive element derived by applying the function @f@ on the previous
962−-- element.
963−--
964−-- @
965−-- > S.toList $ S.take 5 $ S.iterate (+1) 1
966−-- [1,2,3,4,5]
967−-- @
968−--
969−-- @since 0.1.2
970−{-# INLINE_NORMAL iterate #-}
971−iterate :: (IsStream t, Monad m) => (a -> a) -> a -> t m a
972−iterate step = fromStreamS . S.iterate step
973−
974−-- |
975−-- @
976−-- iterateM f m = m >>= \a -> return a \`consM` iterateM f (f a)
977−-- @
978−--
979−-- Generate an infinite stream with the first element generated by the action
980−-- @m@ and each successive element derived by applying the monadic function
981−-- @f@ on the previous element.
982−--
983−-- When run concurrently, the next iteration can run concurrently with the
984−-- processing of the previous iteration. Note that more than one iteration
985−-- cannot run concurrently as the next iteration depends on the output of the
986−-- previous iteration.
987−--
988−-- @
989−-- drain $ serially $ S.take 10 $ S.iterateM
990−-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) (return 0)
991−--
992−-- drain $ asyncly $ S.take 10 $ S.iterateM
993−-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) (return 0)
994−-- @
995−--
996−-- /Concurrent/
997−--
998−-- /Since: 0.1.2/
999−--
1000−-- /Since: 0.7.0 (signature change)/
1001−{-# INLINE_EARLY iterateM #-}
1002−iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
1003−iterateM = K.iterateM
1004−
1005−{-# RULES "iterateM serial" iterateM = iterateMSerial #-}
1006−{-# INLINE iterateMSerial #-}
1007−iterateMSerial :: MonadAsync m => (a -> m a) -> m a -> SerialT m a
1008−iterateMSerial step = fromStreamS . S.iterateM step
1009−
1010657------------------------------------------------------------------------------
1011658-- Conversions
1012659------------------------------------------------------------------------------
1013660
1014−-- |
1015−-- @
1016−-- fromListM = 'Prelude.foldr' 'K.consM' 'K.nil'
1017−-- @
1018−--
1019−-- Construct a stream from a list of monadic actions. This is more efficient
1020−-- than 'fromFoldableM' for serial streams.
1021−--
1022−-- @since 0.4.0
1023−{-# INLINE_EARLY fromListM #-}
1024−fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a
1025−fromListM = fromStreamD . D.fromListM
1026−{-# RULES "fromListM fallback to StreamK" [1]
1027− forall a. D.toStreamK (D.fromListM a) = fromFoldableM a #-}
1028−
1029−-- |
1030−-- @
1031−-- fromFoldableM = 'Prelude.foldr' 'consM' 'K.nil'
1032−-- @
1033−--
1034−-- Construct a stream from a 'Foldable' containing monadic actions.
1035−--
1036−-- @
1037−-- drain $ serially $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
1038−-- drain $ asyncly $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
1039−-- @
1040−--
1041−-- /Concurrent (do not use with 'parallely' on infinite containers)/
1042−--
1043−-- @since 0.3.0
1044−{-# INLINE fromFoldableM #-}
1045−fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a
1046−fromFoldableM = Prelude.foldr consM K.nil
1047−
1048−-- | Same as 'fromFoldable'.
1049−--
1050−-- @since 0.1.0
1051−{-# DEPRECATED each "Please use fromFoldable instead." #-}
1052−{-# INLINE each #-}
1053−each :: (IsStream t, Foldable f) => f a -> t m a
1054−each = K.fromFoldable
1055−
1056−-- | Read lines from an IO Handle into a stream of Strings.
1057−--
1058−-- @since 0.1.0
1059−{-# DEPRECATED fromHandle
1060− "Please use Streamly.FileSystem.Handle module (see the changelog)" #-}
1061−fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
1062−fromHandle h = go
1063− where
1064− go = K.mkStream $ \_ yld _ stp -> do
1065− eof <- liftIO $ IO.hIsEOF h
1066− if eof
1067− then stp
1068− else do
1069− str <- liftIO $ IO.hGetLine h
1070− yld str go
1071−
1072−-- | Construct a stream by reading a 'Prim' 'IORef' repeatedly.
1073−--
1074−-- /Internal/
1075−--
1076−{-# INLINE fromPrimIORef #-}
1077−fromPrimIORef :: (IsStream t, MonadIO m, Prim a) => IORef a -> t m a
1078−fromPrimIORef = fromStreamD . D.fromPrimIORef
1079−
1080661-- | Takes a callback setter function and provides it with a callback. The
1081662-- callback when invoked adds a value at the tail of the stream. Returns a
1082663-- stream of values generated by the callback.
@@ -1084,3270 +665,239 @@ fromPrimIORef = fromStreamD . D.fromPrimIORef
1084665-- /Internal/
1085666--
1086667{-# INLINE fromCallback #-}
1087−fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> SerialT m a
1088−fromCallback setCallback = concatM $ do
1089− (callback, stream) <- D.newCallbackStream
1090− setCallback callback
1091− return stream
1092−
1093−------------------------------------------------------------------------------
1094−-- Time related
1095−------------------------------------------------------------------------------
1096−
1097−-- | @timesWith g@ returns a stream of time value tuples. The first component
1098−-- of the tuple is an absolute time reference (epoch) denoting the start of the
1099−-- stream and the second component is a time relative to the reference.
1100−--
1101−-- The argument @g@ specifies the granularity of the relative time in seconds.
1102−-- A lower granularity clock gives higher precision but is more expensive in
1103−-- terms of CPU usage. Any granularity lower than 1 ms is treated as 1 ms.
1104−--
1105−-- @
1106−-- >>> S.mapM_ (\x -> print x >> threadDelay 1000000) $ S.timesWith 0.01
1107−-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 0))
1108−-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1002028000))
1109−-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1996656000))
1110−-- @
1111−--
1112−-- Note: This API is not safe on 32-bit machines.
1113−--
1114−-- /Internal/
1115−--
1116−{-# INLINE timesWith #-}
1117−timesWith :: (IsStream t, MonadAsync m) => Double -> t m (AbsTime, RelTime64)
1118−timesWith g = fromStreamD $ D.times g
1119−
1120−-- | @times@ returns a stream of time value tuples with clock of 10 ms
1121−-- granularity. The first component of the tuple is an absolute time reference
1122−-- (epoch) denoting the start of the stream and the second component is a time
1123−-- relative to the reference.
1124−--
1125−-- @
1126−-- >>> S.mapM_ (\x -> print x >> threadDelay 1000000) $ S.times
1127−-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 0))
1128−-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1002028000))
1129−-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1996656000))
1130−-- @
1131−--
1132−-- Note: This API is not safe on 32-bit machines.
1133−--
1134−-- /Internal/
1135−--
1136−{-# INLINE times #-}
1137−times :: (IsStream t, MonadAsync m) => t m (AbsTime, RelTime64)
1138−times = timesWith 0.01
1139−
1140−-- | @absTimesWith g@ returns a stream of absolute timestamps using a clock of
1141−-- granularity @g@ specified in seconds. A low granularity clock is more
1142−-- expensive in terms of CPU usage. Any granularity lower than 1 ms is treated
1143−-- as 1 ms.
1144−--
1145−-- @
1146−-- >>> S.mapM_ print $ S.delayPre 1 $ S.absTimesWith 0.01
1147−-- @
1148−--
1149−-- Note: This API is not safe on 32-bit machines.
1150−--
1151−-- /Internal/
1152−--
1153−{-# INLINE absTimesWith #-}
1154−absTimesWith :: (IsStream t, MonadAsync m, Functor (t m))
1155− => Double -> t m AbsTime
1156−absTimesWith = fmap (uncurry addToAbsTime64) . timesWith
1157−
1158−-- | @absTimes@ returns a stream of absolute timestamps using a clock of 10 ms
1159−-- granularity.
1160−--
1161−-- @
1162−-- >>> S.mapM_ print $ S.delayPre 1 $ S.absTimes
1163−-- @
1164−--
1165−-- Note: This API is not safe on 32-bit machines.
1166−--
1167−-- /Internal/
1168−--
1169−{-# INLINE absTimes #-}
1170−absTimes :: (IsStream t, MonadAsync m, Functor (t m)) => t m AbsTime
1171−absTimes = fmap (uncurry addToAbsTime64) times
1172−
1173−{-# DEPRECATED currentTime "Please use absTimes instead" #-}
1174−{-# INLINE currentTime #-}
1175−currentTime :: (IsStream t, MonadAsync m, Functor (t m))
1176− => Double -> t m AbsTime
1177−currentTime = absTimesWith
1178−
1179−-- | @relTimesWith g@ returns a stream of relative time values starting from 0,
1180−-- using a clock of granularity @g@ specified in seconds. A low granularity
1181−-- clock is more expensive in terms of CPU usage. Any granularity lower than 1
1182−-- ms is treated as 1 ms.
1183−--
1184−-- @
1185−-- >>> S.mapM_ print $ S.delayPre 1 $ S.relTimesWith 0.01
1186−-- > RelTime64 (NanoSecond64 0)
1187−-- > RelTime64 (NanoSecond64 91139000)
1188−-- > RelTime64 (NanoSecond64 204052000)
1189−-- @
1190−--
1191−-- Note: This API is not safe on 32-bit machines.
1192−--
1193−-- /Internal/
1194−--
1195−{-# INLINE relTimesWith #-}
1196−relTimesWith :: (IsStream t, MonadAsync m, Functor (t m))
1197− => Double -> t m RelTime64
1198−relTimesWith = fmap snd . timesWith
1199−
1200−-- | @relTimes@ returns a stream of relative time values starting from 0,
1201−-- using a clock of granularity 10 ms.
1202−--
1203−-- @
1204−-- >>> S.mapM_ print $ S.delayPre 1 $ S.relTimes
1205−-- @
1206−--
1207−-- Note: This API is not safe on 32-bit machines.
1208−--
1209−-- /Internal/
1210−--
1211−{-# INLINE relTimes #-}
1212−relTimes :: (IsStream t, MonadAsync m, Functor (t m)) => t m RelTime64
1213−relTimes = fmap snd times
1214−
1215−-- | @durations g@ returns a stream of relative time values measuring the time
1216−-- elapsed since the immediate predecessor element of the stream was generated.
1217−-- The first element of the stream is always 0. @durations@ uses a clock of
1218−-- granularity @g@ specified in seconds. A low granularity clock is more
1219−-- expensive in terms of CPU usage. The minimum granularity is 1 millisecond.
1220−-- Durations lower than 1 ms will be 0.
1221−--
1222−-- Note: This API is not safe on 32-bit machines.
1223−--
1224−-- /Unimplemented/
1225−--
1226−{-# INLINE durations #-}
1227−durations :: -- (IsStream t, MonadAsync m) =>
1228− Double -> t m RelTime64
1229−durations = undefined
1230−
1231−-- | Generate ticks at the specified rate. The rate is adaptive, the tick
1232−-- generation speed can be increased or decreased at different times to achieve
1233−-- the specified rate. The specific behavior for different styles of 'Rate'
1234−-- specifications is documented under 'Rate'. The effective maximum rate
1235−-- achieved by a stream is governed by the processor speed.
1236−--
1237−-- /Unimplemented/
1238−--
1239−{-# INLINE ticks #-}
1240−ticks :: -- (IsStream t, MonadAsync m) =>
1241− Rate -> t m ()
1242−ticks = undefined
1243−
1244−-- | Generate a singleton event at or after the specified absolute time. Note
1245−-- that this is different from a threadDelay, a threadDelay starts from the
1246−-- time when the action is evaluated, whereas if we use AbsTime based timeout
1247−-- it will immediately expire if the action is evaluated too late.
1248−--
1249−-- /Unimplemented/
1250−--
1251−{-# INLINE timeout #-}
1252−timeout :: -- (IsStream t, MonadAsync m) =>
1253− AbsTime -> t m ()
1254−timeout = undefined
1255−
1256−------------------------------------------------------------------------------
1257−-- Elimination by Folding
1258−------------------------------------------------------------------------------
1259−
1260−-- | Right associative/lazy pull fold. @foldrM build final stream@ constructs
1261−-- an output structure using the step function @build@. @build@ is invoked with
1262−-- the next input element and the remaining (lazy) tail of the output
1263−-- structure. It builds a lazy output expression using the two. When the "tail
1264−-- structure" in the output expression is evaluated it calls @build@ again thus
1265−-- lazily consuming the input @stream@ until either the output expression built
1266−-- by @build@ is free of the "tail" or the input is exhausted in which case
1267−-- @final@ is used as the terminating case for the output structure. For more
1268−-- details see the description in the previous section.
1269−--
1270−-- Example, determine if any element is 'odd' in a stream:
1271−--
1272−-- >>> S.foldrM (\x xs -> if odd x then return True else xs) (return False) $ S.fromList (2:4:5:undefined)
1273−-- > True
1274−--
1275−-- /Since: 0.7.0 (signature changed)/
1276−--
1277−-- /Since: 0.2.0 (signature changed)/
1278−--
1279−-- /Since: 0.1.0/
1280−{-# INLINE foldrM #-}
1281−foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b
1282−foldrM = P.foldrM
1283−
1284−-- | Right fold to a streaming monad.
1285−--
1286−-- > foldrS S.cons S.nil === id
1287−--
1288−-- 'foldrS' can be used to perform stateless stream to stream transformations
1289−-- like map and filter in general. It can be coupled with a scan to perform
1290−-- stateful transformations. However, note that the custom map and filter
1291−-- routines can be much more efficient than this due to better stream fusion.
1292−--
1293−-- >>> S.toList $ S.foldrS S.cons S.nil $ S.fromList [1..5]
1294−-- > [1,2,3,4,5]
1295−--
1296−-- Find if any element in the stream is 'True':
1297−--
1298−-- >>> S.toList $ S.foldrS (\x xs -> if odd x then return True else xs) (return False) $ (S.fromList (2:4:5:undefined) :: SerialT IO Int)
1299−-- > [True]
1300−--
1301−-- Map (+2) on odd elements and filter out the even elements:
1302−--
1303−-- >>> S.toList $ S.foldrS (\x xs -> if odd x then (x + 2) `S.cons` xs else xs) S.nil $ (S.fromList [1..5] :: SerialT IO Int)
1304−-- > [3,5,7]
1305−--
1306−-- 'foldrM' can also be represented in terms of 'foldrS', however, the former
1307−-- is much more efficient:
1308−--
1309−-- > foldrM f z s = runIdentityT $ foldrS (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
1310−--
1311−-- /Internal/
1312−{-# INLINE foldrS #-}
1313−foldrS :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
1314−foldrS = K.foldrS
1315−
1316−-- | Right fold to a transformer monad. This is the most general right fold
1317−-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
1318−-- implementation can be more efficient:
1319−--
1320−-- > foldrS = foldrT
1321−-- > foldrM f z s = runIdentityT $ foldrT (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
1322−--
1323−-- 'foldrT' can be used to translate streamly streams to other transformer
1324−-- monads e.g. to a different streaming type.
1325−--
1326−-- /Internal/
1327−{-# INLINE foldrT #-}
1328−foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
1329− => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
1330−foldrT f z s = S.foldrT f z (toStreamS s)
1331−
1332−-- | Right fold, lazy for lazy monads and pure streams, and strict for strict
1333−-- monads.
1334−--
1335−-- Please avoid using this routine in strict monads like IO unless you need a
1336−-- strict right fold. This is provided only for use in lazy monads (e.g.
1337−-- Identity) or pure streams. Note that with this signature it is not possible
1338−-- to implement a lazy foldr when the monad @m@ is strict. In that case it
1339−-- would be strict in its accumulator and therefore would necessarily consume
1340−-- all its input.
1341−--
1342−-- @since 0.1.0
1343−{-# INLINE foldr #-}
1344−foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
1345−foldr = P.foldr
1346−
1347−-- XXX This seems to be of limited use as it cannot be used to construct
1348−-- recursive structures and for reduction foldl1' is better.
1349−--
1350−-- | Lazy right fold for non-empty streams, using first element as the starting
1351−-- value. Returns 'Nothing' if the stream is empty.
1352−--
1353−-- @since 0.5.0
1354−{-# INLINE foldr1 #-}
1355−{-# DEPRECATED foldr1 "Use foldrM instead." #-}
1356−foldr1 :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a)
1357−foldr1 f m = S.foldr1 f (toStreamS m)
1358−
1359−-- | Strict left fold with an extraction function. Like the standard strict
1360−-- left fold, but applies a user supplied extraction function (the third
1361−-- argument) to the folded value at the end. This is designed to work with the
1362−-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
1363−--
1364−-- @since 0.2.0
1365−{-# DEPRECATED foldx "Please use foldl' followed by fmap instead." #-}
1366−{-# INLINE foldx #-}
1367−foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
1368−foldx = P.foldlx'
1369−
1370−-- | Left associative/strict push fold. @foldl' reduce initial stream@ invokes
1371−-- @reduce@ with the accumulator and the next input in the input stream, using
1372−-- @initial@ as the initial value of the current value of the accumulator. When
1373−-- the input is exhausted the current value of the accumulator is returned.
1374−-- Make sure to use a strict data structure for accumulator to not build
1375−-- unnecessary lazy expressions unless that's what you want. See the previous
1376−-- section for more details.
1377−--
1378−-- @since 0.2.0
1379−{-# INLINE foldl' #-}
1380−foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
1381−foldl' = P.foldl'
1382−
1383−-- | Strict left fold, for non-empty streams, using first element as the
1384−-- starting value. Returns 'Nothing' if the stream is empty.
1385−--
1386−-- @since 0.5.0
1387−{-# INLINE foldl1' #-}
1388−foldl1' :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a)
1389−foldl1' step m = do
1390− r <- uncons m
1391− case r of
1392− Nothing -> return Nothing
1393− Just (h, t) -> do
1394− res <- foldl' step h t
1395− return $ Just res
1396−
1397−-- | Like 'foldx', but with a monadic step function.
1398−--
1399−-- @since 0.2.0
1400−{-# DEPRECATED foldxM "Please use foldlM' followed by fmap instead." #-}
1401−{-# INLINE foldxM #-}
1402−foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
1403−foldxM = P.foldlMx'
1404−
1405−-- | Like 'foldl'' but with a monadic step function.
1406−--
1407−-- /Since: 0.2.0/
1408−--
1409−-- /Since: 0.8.0 (signature change)/
1410−{-# INLINE foldlM' #-}
1411−foldlM' :: Monad m => (b -> a -> m b) -> m b -> SerialT m a -> m b
1412−foldlM' step begin m = S.foldlM' step begin $ toStreamS m
1413−
1414−------------------------------------------------------------------------------
1415−-- Running a Fold
1416−------------------------------------------------------------------------------
1417−
1418−-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
1419−-- expression strictly at each step. The behavior is similar to 'foldl''. A
1420−-- 'Fold' can terminate early without consuming the full stream. See the
1421−-- documentation of individual 'Fold's for termination behavior.
1422−--
1423−-- >>> S.fold FL.sum (S.enumerateFromTo 1 100)
1424−-- 5050
1425−--
1426−-- @since 0.7.0
1427−{-# INLINE fold #-}
1428−fold :: Monad m => Fold m a b -> SerialT m a -> m b
1429−fold = P.foldOnce
1430−
1431−------------------------------------------------------------------------------
1432−-- Running a sink
1433−------------------------------------------------------------------------------
1434−
1435−{-
1436−-- | Drain a stream to a 'Sink'.
1437−{-# INLINE runSink #-}
1438−runSink :: Monad m => Sink m a -> SerialT m a -> m ()
1439−runSink = fold . toFold
1440−-}
1441−
1442−------------------------------------------------------------------------------
1443−-- Running a Parser
1444−------------------------------------------------------------------------------
1445−
1446−-- | Parse a stream using the supplied 'Parser'.
1447−--
1448−-- /Internal/
1449−--
1450−{-# INLINE_NORMAL parseD #-}
1451−parseD :: MonadThrow m => PRD.Parser m a b -> SerialT m a -> m b
1452−parseD (PRD.Parser step initial extract) = P.parselMx' step initial extract
1453−
1454−{-# INLINE parseK #-}
1455−parseK :: MonadThrow m => PRK.Parser m a b -> SerialT m a -> m b
1456−parseK = parse
1457−
1458−-- | Parse a stream using the supplied 'Parser'.
1459−--
1460−-- /Internal/
1461−--
1462−{-# INLINE [3] parse #-}
1463−parse :: MonadThrow m => Parser m a b -> SerialT m a -> m b
1464−parse = parseD . PRK.fromParserK
1465−
1466−------------------------------------------------------------------------------
1467−-- Specialized folds
1468−------------------------------------------------------------------------------
1469−
1470−-- |
1471−-- > drain = mapM_ (\_ -> return ())
1472−-- > drain = fold Fold.drain
1473−--
1474−-- Run a stream, discarding the results. By default it interprets the stream
1475−-- as 'SerialT', to run other types of streams use the type adapting
1476−-- combinators for example @drain . 'asyncly'@.
1477−--
1478−-- @since 0.7.0
1479−{-# INLINE drain #-}
1480−drain :: Monad m => SerialT m a -> m ()
1481−drain = P.drain
1482−
1483−-- | Run a stream, discarding the results. By default it interprets the stream
1484−-- as 'SerialT', to run other types of streams use the type adapting
1485−-- combinators for example @runStream . 'asyncly'@.
1486−--
1487−-- @since 0.2.0
1488−{-# DEPRECATED runStream "Please use \"drain\" instead" #-}
1489−{-# INLINE runStream #-}
1490−runStream :: Monad m => SerialT m a -> m ()
1491−runStream = drain
1492−
1493−-- |
1494−-- > drainN n = drain . take n
1495−-- > drainN n = fold (Fold.ltake n Fold.drain)
1496−--
1497−-- Run maximum up to @n@ iterations of a stream.
1498−--
1499−-- @since 0.7.0
1500−{-# INLINE drainN #-}
1501−drainN :: Monad m => Int -> SerialT m a -> m ()
1502−drainN n = drain . take n
1503−
1504−-- |
1505−-- > runN n = runStream . take n
1506−--
1507−-- Run maximum up to @n@ iterations of a stream.
1508−--
1509−-- @since 0.6.0
1510−{-# DEPRECATED runN "Please use \"drainN\" instead" #-}
1511−{-# INLINE runN #-}
1512−runN :: Monad m => Int -> SerialT m a -> m ()
1513−runN = drainN
1514−
1515−-- |
1516−-- > drainWhile p = drain . takeWhile p
1517−-- > drainWhile p = fold (Fold.sliceSepBy (not . p) Fold.drain)
1518−--
1519−-- Run a stream as long as the predicate holds true.
1520−--
1521−-- @since 0.7.0
1522−{-# INLINE drainWhile #-}
1523−drainWhile :: Monad m => (a -> Bool) -> SerialT m a -> m ()
1524−drainWhile p = drain . takeWhile p
1525−
1526−-- |
1527−-- > runWhile p = runStream . takeWhile p
1528−--
1529−-- Run a stream as long as the predicate holds true.
1530−--
1531−-- @since 0.6.0
1532−{-# DEPRECATED runWhile "Please use \"drainWhile\" instead" #-}
1533−{-# INLINE runWhile #-}
1534−runWhile :: Monad m => (a -> Bool) -> SerialT m a -> m ()
1535−runWhile = drainWhile
1536−
1537−-- | Determine whether the stream is empty.
1538−--
1539−-- > null = fold Fold.null
1540−--
1541−-- @since 0.1.1
1542−{-# INLINE null #-}
1543−null :: Monad m => SerialT m a -> m Bool
1544−null = S.null . toStreamS
1545−
1546−-- | Extract the first element of the stream, if any.
1547−--
1548−-- > head = (!! 0)
1549−-- > head = fold Fold.head
1550−--
1551−-- @since 0.1.0
1552−{-# INLINE head #-}
1553−head :: Monad m => SerialT m a -> m (Maybe a)
1554−head = S.head . toStreamS
1555−
1556−-- | Extract the first element of the stream, if any, otherwise use the
1557−-- supplied default value. It can help avoid one branch in high performance
1558−-- code.
1559−--
1560−-- /Internal/
1561−{-# INLINE headElse #-}
1562−headElse :: Monad m => a -> SerialT m a -> m a
1563−headElse x = D.headElse x . toStreamD
1564−
1565−-- |
1566−-- > tail = fmap (fmap snd) . uncons
1567−--
1568−-- Extract all but the first element of the stream, if any.
1569−--
1570−-- @since 0.1.1
1571−{-# INLINE tail #-}
1572−tail :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
1573−tail m = K.tail (K.adapt m)
1574−
1575−-- | Extract all but the last element of the stream, if any.
1576−--
1577−-- @since 0.5.0
1578−{-# INLINE init #-}
1579−init :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
1580−init m = K.init (K.adapt m)
1581−
1582−-- | Extract the last element of the stream, if any.
1583−--
1584−-- > last xs = xs !! (length xs - 1)
1585−-- > last = fold Fold.last
1586−--
1587−-- @since 0.1.1
1588−{-# INLINE last #-}
1589−last :: Monad m => SerialT m a -> m (Maybe a)
1590−last m = S.last $ toStreamS m
1591−
1592−-- | Determine whether an element is present in the stream.
1593−--
1594−-- > elem = fold Fold.elem
1595−--
1596−-- @since 0.1.0
1597−{-# INLINE elem #-}
1598−elem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
1599−elem e m = S.elem e (toStreamS m)
1600−
1601−-- | Determine whether an element is not present in the stream.
1602−--
1603−-- > notElem = fold Fold.notElem
1604−--
1605−-- @since 0.1.0
1606−{-# INLINE notElem #-}
1607−notElem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
1608−notElem e m = S.notElem e (toStreamS m)
1609−
1610−-- | Determine the length of the stream.
1611−--
1612−-- > notElem = fold Fold.length
1613−--
1614−-- @since 0.1.0
1615−{-# INLINE length #-}
1616−length :: Monad m => SerialT m a -> m Int
1617−length = foldl' (\n _ -> n + 1) 0
1618−
1619−-- | Determine whether all elements of a stream satisfy a predicate.
1620−--
1621−-- > all = fold Fold.all
1622−--
1623−-- @since 0.1.0
1624−{-# INLINE all #-}
1625−all :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
1626−all p m = S.all p (toStreamS m)
1627−
1628−-- | Determine whether any of the elements of a stream satisfy a predicate.
1629−--
1630−-- > any = fold Fold.any
1631−--
1632−-- @since 0.1.0
1633−{-# INLINE any #-}
1634−any :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
1635−any p m = S.any p (toStreamS m)
1636−
1637−-- | Determines if all elements of a boolean stream are True.
1638−--
1639−-- > and = fold Fold.and
1640−--
1641−-- @since 0.5.0
1642−{-# INLINE and #-}
1643−and :: Monad m => SerialT m Bool -> m Bool
1644−and = all (==True)
1645−
1646−-- | Determines whether at least one element of a boolean stream is True.
1647−--
1648−-- > or = fold Fold.or
1649−--
1650−-- @since 0.5.0
1651−{-# INLINE or #-}
1652−or :: Monad m => SerialT m Bool -> m Bool
1653−or = any (==True)
1654−
1655−-- | Determine the sum of all elements of a stream of numbers. Returns @0@ when
1656−-- the stream is empty. Note that this is not numerically stable for floating
1657−-- point numbers.
1658−--
1659−-- > sum = fold Fold.sum
1660−--
1661−-- @since 0.1.0
1662−{-# INLINE sum #-}
1663−sum :: (Monad m, Num a) => SerialT m a -> m a
1664−sum = foldl' (+) 0
1665−
1666−-- | Determine the product of all elements of a stream of numbers. Returns @1@
1667−-- when the stream is empty.
1668−--
1669−-- > product = fold Fold.product
1670−--
1671−-- @since 0.1.1
1672−{-# INLINE product #-}
1673−product :: (Monad m, Num a) => SerialT m a -> m a
1674−product = foldl' (*) 1
1675−
1676−-- | Fold a stream of monoid elements by appending them.
1677−--
1678−-- > mconcat = fold Fold.mconcat
1679−--
1680−-- /Internal/
1681−{-# INLINE mconcat #-}
1682−mconcat :: (Monad m, Monoid a) => SerialT m a -> m a
1683−mconcat = foldr mappend mempty
1684−
1685−-- |
1686−-- @
1687−-- minimum = 'minimumBy' compare
1688−-- minimum = fold Fold.minimum
1689−-- @
1690−--
1691−-- Determine the minimum element in a stream.
1692−--
1693−-- @since 0.1.0
1694−{-# INLINE minimum #-}
1695−minimum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
1696−minimum m = S.minimum (toStreamS m)
1697−
1698−-- | Determine the minimum element in a stream using the supplied comparison
1699−-- function.
1700−--
1701−-- > minimumBy = fold Fold.minimumBy
1702−--
1703−-- @since 0.6.0
1704−{-# INLINE minimumBy #-}
1705−minimumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
1706−minimumBy cmp m = S.minimumBy cmp (toStreamS m)
1707−
1708−-- |
1709−-- @
1710−-- maximum = 'maximumBy' compare
1711−-- maximum = fold Fold.maximum
1712−-- @
1713−--
1714−-- Determine the maximum element in a stream.
1715−--
1716−-- @since 0.1.0
1717−{-# INLINE maximum #-}
1718−maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
1719−maximum = P.maximum
1720−
1721−-- | Determine the maximum element in a stream using the supplied comparison
1722−-- function.
1723−--
1724−-- > maximumBy = fold Fold.maximumBy
1725−--
1726−-- @since 0.6.0
1727−{-# INLINE maximumBy #-}
1728−maximumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
1729−maximumBy cmp m = S.maximumBy cmp (toStreamS m)
1730−
1731−-- | Lookup the element at the given index.
1732−--
1733−-- @since 0.6.0
1734−{-# INLINE (!!) #-}
1735−(!!) :: Monad m => SerialT m a -> Int -> m (Maybe a)
1736−m !! i = toStreamS m S.!! i
1737−
1738−-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
1739−-- first pair where the key equals the given value @a@.
1740−--
1741−-- > lookup = snd <$> find ((==) . fst)
1742−-- > lookup = fold Fold.lookup
1743−--
1744−-- @since 0.5.0
1745−{-# INLINE lookup #-}
1746−lookup :: (Monad m, Eq a) => a -> SerialT m (a, b) -> m (Maybe b)
1747−lookup a m = S.lookup a (toStreamS m)
1748−
1749−-- | Like 'findM' but with a non-monadic predicate.
1750−--
1751−-- > find p = findM (return . p)
1752−-- > find = fold Fold.find
1753−--
1754−-- @since 0.5.0
1755−{-# INLINE find #-}
1756−find :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe a)
1757−find p m = S.find p (toStreamS m)
1758−
1759−-- | Returns the first element that satisfies the given predicate.
1760−--
1761−-- > findM = fold Fold.findM
1762−--
1763−-- @since 0.6.0
1764−{-# INLINE findM #-}
1765−findM :: Monad m => (a -> m Bool) -> SerialT m a -> m (Maybe a)
1766−findM p m = S.findM p (toStreamS m)
1767−
1768−-- | Find all the indices where the element in the stream satisfies the given
1769−-- predicate.
1770−--
1771−-- > findIndices = fold Fold.findIndices
1772−--
1773−-- @since 0.5.0
1774−{-# INLINE findIndices #-}
1775−findIndices :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m Int
1776−findIndices p m = fromStreamS $ S.findIndices p (toStreamS m)
1777−
1778−-- | Returns the first index that satisfies the given predicate.
1779−--
1780−-- > findIndex = fold Fold.findIndex
1781−--
1782−-- @since 0.5.0
1783−{-# INLINE findIndex #-}
1784−findIndex :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe Int)
1785−findIndex p = head . findIndices p
1786−
1787−-- | Find all the indices where the value of the element in the stream is equal
1788−-- to the given value.
1789−--
1790−-- > elemIndices a = findIndices (== a)
1791−--
1792−-- @since 0.5.0
1793−{-# INLINE elemIndices #-}
1794−elemIndices :: (IsStream t, Eq a, Monad m) => a -> t m a -> t m Int
1795−elemIndices a = findIndices (== a)
1796−
1797−-- | Returns the first index where a given value is found in the stream.
1798−--
1799−-- > elemIndex a = findIndex (== a)
1800−--
1801−-- @since 0.5.0
1802−{-# INLINE elemIndex #-}
1803−elemIndex :: (Monad m, Eq a) => a -> SerialT m a -> m (Maybe Int)
1804−elemIndex a = findIndex (== a)
1805−
1806−------------------------------------------------------------------------------
1807−-- Substreams
1808−------------------------------------------------------------------------------
1809−
1810−-- | Returns 'True' if the first stream is the same as or a prefix of the
1811−-- second. A stream is a prefix of itself.
1812−--
1813−-- @
1814−-- > S.isPrefixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
1815−-- True
1816−-- @
1817−--
1818−-- @since 0.6.0
1819−{-# INLINE isPrefixOf #-}
1820−isPrefixOf :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m Bool
1821−isPrefixOf m1 m2 = D.isPrefixOf (toStreamD m1) (toStreamD m2)
1822−
1823−-- Note: isPrefixOf uses the prefix stream only once. In contrast, isSuffixOf
1824−-- may use the suffix stream many times. To run in optimal memory we do not
1825−-- want to buffer the suffix stream in memory therefore we need an ability to
1826−-- clone (or consume it multiple times) the suffix stream without any side
1827−-- effects so that multiple potential suffix matches can proceed in parallel
1828−-- without buffering the suffix stream. For example, we may create the suffix
1829−-- stream from a file handle, however, if we evaluate the stream multiple
1830−-- times, once for each match, we will need a different file handle each time
1831−-- which may exhaust the file descriptors. Instead, we want to share the same
1832−-- underlying file descriptor, use pread on it to generate the stream and clone
1833−-- the stream for each match. Therefore the suffix stream should be built in
1834−-- such a way that it can be consumed multiple times without any problems.
1835−
1836−-- XXX Can be implemented with better space/time complexity.
1837−-- Space: @O(n)@ worst case where @n@ is the length of the suffix.
1838−
1839−-- | Returns 'True' if the first stream is a suffix of the second. A stream is
1840−-- considered a suffix of itself.
1841−--
1842−-- @
1843−-- > S.isSuffixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
1844−-- True
1845−-- @
1846−--
1847−-- Space: @O(n)@, buffers entire input stream and the suffix.
1848−--
1849−-- /Internal/
1850−--
1851−-- /Suboptimal/ - Help wanted.
1852−--
1853−{-# INLINE isSuffixOf #-}
1854−isSuffixOf :: (Monad m, Eq a) => SerialT m a -> SerialT m a -> m Bool
1855−isSuffixOf suffix stream = reverse suffix `isPrefixOf` reverse stream
1856−
1857−-- | Returns 'True' if the first stream is an infix of the second. A stream is
1858−-- considered an infix of itself.
1859−--
1860−-- @
1861−-- > S.isInfixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
1862−-- True
1863−-- @
1864−--
1865−-- Space: @O(n)@ worst case where @n@ is the length of the infix.
1866−--
1867−-- /Internal/
1868−--
1869−-- /Requires 'Storable' constraint/ - Help wanted.
1870−--
1871−{-# INLINE isInfixOf #-}
1872−isInfixOf :: (MonadIO m, Eq a, Enum a, Storable a)
1873− => SerialT m a -> SerialT m a -> m Bool
1874−isInfixOf infx stream = do
1875− arr <- fold A.write infx
1876− -- XXX can use breakOnSeq instead (when available)
1877− r <- null $ drop 1 $ splitOnSeq arr FL.drain stream
1878− return (not r)
1879−
1880−-- | Returns 'True' if all the elements of the first stream occur, in order, in
1881−-- the second stream. The elements do not have to occur consecutively. A stream
1882−-- is a subsequence of itself.
1883−--
1884−-- @
1885−-- > S.isSubsequenceOf (S.fromList "hlo") (S.fromList "hello" :: SerialT IO Char)
1886−-- True
1887−-- @
1888−--
1889−-- @since 0.6.0
1890−{-# INLINE isSubsequenceOf #-}
1891−isSubsequenceOf :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m Bool
1892−isSubsequenceOf m1 m2 = D.isSubsequenceOf (toStreamD m1) (toStreamD m2)
1893−
1894−-- | @stripPrefix prefix stream@ strips @prefix@ from @stream@ if it is a
1895−-- prefix of stream. Returns 'Nothing' if the stream does not start with the
1896−-- given prefix, stripped stream otherwise. Returns @Just nil@ when the prefix
1897−-- is the same as the stream.
1898−--
1899−-- Space: @O(1)@
1900−--
1901−-- @since 0.6.0
1902−{-# INLINE stripPrefix #-}
1903−stripPrefix
1904− :: (Eq a, IsStream t, Monad m)
1905− => t m a -> t m a -> m (Maybe (t m a))
1906−stripPrefix m1 m2 = fmap fromStreamD <$>
1907− D.stripPrefix (toStreamD m1) (toStreamD m2)
1908−
1909−-- Note: If we want to return a Maybe value to know whether the
1910−-- suffix/infix was present or not along with the stripped stream then
1911−-- we need to buffer the whole input stream.
1912−--
1913−-- | Drops the given suffix from a stream. Returns 'Nothing' if the stream does
1914−-- not end with the given suffix. Returns @Just nil@ when the suffix is the
1915−-- same as the stream.
1916−--
1917−-- It may be more efficient to convert the stream to an Array and use
1918−-- stripSuffix on that especially if the elements have a Storable or Prim
1919−-- instance.
1920−--
1921−-- Space: @O(n)@, buffers the entire input stream as well as the suffix
1922−--
1923−-- /Internal/
1924−{-# INLINE stripSuffix #-}
1925−stripSuffix
1926− :: (Monad m, Eq a)
1927− => SerialT m a -> SerialT m a -> m (Maybe (SerialT m a))
1928−stripSuffix m1 m2 = fmap reverse <$> stripPrefix (reverse m1) (reverse m2)
1929−
1930−-- | Drop prefix from the input stream if present.
1931−--
1932−-- Space: @O(1)@
1933−--
1934−-- /Unimplemented/ - Help wanted.
1935−{-# INLINE dropPrefix #-}
1936−dropPrefix ::
1937− -- (Eq a, IsStream t, Monad m) =>
1938− t m a -> t m a -> t m a
1939−dropPrefix = error "Not implemented yet!"
1940−
1941−-- | Drop all matching infix from the input stream if present. Infix stream
1942−-- may be consumed multiple times.
1943−--
1944−-- Space: @O(n)@ where n is the length of the infix.
1945−--
1946−-- /Unimplemented/ - Help wanted.
1947−{-# INLINE dropInfix #-}
1948−dropInfix ::
1949− -- (Eq a, IsStream t, Monad m) =>
1950− t m a -> t m a -> t m a
1951−dropInfix = error "Not implemented yet!"
1952−
1953−-- | Drop suffix from the input stream if present. Suffix stream may be
1954−-- consumed multiple times.
1955−--
1956−-- Space: @O(n)@ where n is the length of the suffix.
1957−--
1958−-- /Unimplemented/ - Help wanted.
1959−{-# INLINE dropSuffix #-}
1960−dropSuffix ::
1961− -- (Eq a, IsStream t, Monad m) =>
1962− t m a -> t m a -> t m a
1963−dropSuffix = error "Not implemented yet!"
1964−
1965−------------------------------------------------------------------------------
1966−-- Map and Fold
1967−------------------------------------------------------------------------------
1968−
1969−-- XXX this can utilize parallel mapping if we implement it as drain . mapM
1970−-- |
1971−-- > mapM_ = drain . mapM
1972−--
1973−-- Apply a monadic action to each element of the stream and discard the output
1974−-- of the action. This is not really a pure transformation operation but a
1975−-- transformation followed by fold.
1976−--
1977−-- @since 0.1.0
1978−{-# INLINE mapM_ #-}
1979−mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
1980−mapM_ f m = S.mapM_ f $ toStreamS m
1981−
1982−------------------------------------------------------------------------------
1983−-- Conversions
1984−------------------------------------------------------------------------------
1985−
1986−-- |
1987−-- @
1988−-- toList = S.foldr (:) []
1989−-- @
1990−--
1991−-- Convert a stream into a list in the underlying monad. The list can be
1992−-- consumed lazily in a lazy monad (e.g. 'Identity'). In a strict monad (e.g.
1993−-- IO) the whole list is generated and buffered before it can be consumed.
1994−--
1995−-- /Warning!/ working on large lists accumulated as buffers in memory could be
1996−-- very inefficient, consider using "Streamly.Array" instead.
1997−--
1998−-- @since 0.1.0
1999−{-# INLINE toList #-}
2000−toList :: Monad m => SerialT m a -> m [a]
2001−toList = P.toList
2002−
2003−-- |
2004−-- @
2005−-- toListRev = S.foldl' (flip (:)) []
2006−-- @
2007−--
2008−-- Convert a stream into a list in reverse order in the underlying monad.
2009−--
2010−-- /Warning!/ working on large lists accumulated as buffers in memory could be
2011−-- very inefficient, consider using "Streamly.Array" instead.
2012−--
2013−-- /Internal/
2014−{-# INLINE toListRev #-}
2015−toListRev :: Monad m => SerialT m a -> m [a]
2016−toListRev = D.toListRev . toStreamD
2017−
2018−-- |
2019−-- @
2020−-- toHandle h = S.mapM_ $ hPutStrLn h
2021−-- @
2022−--
2023−-- Write a stream of Strings to an IO Handle.
2024−--
2025−-- @since 0.1.0
2026−{-# DEPRECATED toHandle
2027− "Please use Streamly.FileSystem.Handle module (see the changelog)" #-}
2028−toHandle :: MonadIO m => IO.Handle -> SerialT m String -> m ()
2029−toHandle h = go
2030− where
2031− go m1 =
2032− let stop = return ()
2033− single a = liftIO (IO.hPutStrLn h a)
2034− yieldk a r = liftIO (IO.hPutStrLn h a) >> go r
2035− in K.foldStream defState yieldk single stop m1
2036−
2037−-- XXX rename these to write/writeRev to make the naming consistent with folds
2038−-- in other modules.
2039−--
2040−-- | A fold that buffers its input to a pure stream.
2041−--
2042−-- /Warning!/ working on large streams accumulated as buffers in memory could
2043−-- be very inefficient, consider using "Streamly.Data.Array" instead.
2044−--
2045−-- /Internal/
2046−{-# INLINE toStream #-}
2047−toStream :: Monad m => Fold m a (SerialT Identity a)
2048−toStream = Fold (\f x -> return $ FL.Partial $ f . (x `K.cons`))
2049− (return id)
2050− (return . ($ K.nil))
2051−
2052−-- This is more efficient than 'toStream'. toStream is exactly the same as
2053−-- reversing the stream after toStreamRev.
2054−--
2055−-- | Buffers the input stream to a pure stream in the reverse order of the
2056−-- input.
2057−--
2058−-- /Warning!/ working on large streams accumulated as buffers in memory could
2059−-- be very inefficient, consider using "Streamly.Data.Array" instead.
2060−--
2061−-- /Internal/
2062−
2063−-- xn : ... : x2 : x1 : []
2064−{-# INLINABLE toStreamRev #-}
2065−toStreamRev :: Monad m => Fold m a (SerialT Identity a)
2066−toStreamRev = Fold (\xs x -> return $ FL.Partial $ x `K.cons` xs) (return K.nil) return
2067−
2068−-- | Convert a stream to a pure stream.
2069−--
2070−-- @
2071−-- toPure = foldr cons nil
2072−-- @
2073−--
2074−-- /Internal/
2075−--
2076−{-# INLINE toPure #-}
2077−toPure :: Monad m => SerialT m a -> m (SerialT Identity a)
2078−toPure = foldr K.cons K.nil
2079−
2080−-- | Convert a stream to a pure stream in reverse order.
2081−--
2082−-- @
2083−-- toPureRev = foldl' (flip cons) nil
2084−-- @
2085−--
2086−-- /Internal/
2087−--
2088−{-# INLINE toPureRev #-}
2089−toPureRev :: Monad m => SerialT m a -> m (SerialT Identity a)
2090−toPureRev = foldl' (flip K.cons) K.nil
2091−
2092−------------------------------------------------------------------------------
2093−-- Concurrent Application
2094−------------------------------------------------------------------------------
2095−
2096−infixr 0 |$
2097−infixr 0 |$.
2098−
2099−infixl 1 |&
2100−infixl 1 |&.
2101−
2102−-- | Parallel transform application operator; applies a stream transformation
2103−-- function @t m a -> t m b@ to a stream @t m a@ concurrently; the input stream
2104−-- is evaluated asynchronously in an independent thread yielding elements to a
2105−-- buffer and the transformation function runs in another thread consuming the
2106−-- input from the buffer. '|$' is just like regular function application
2107−-- operator '$' except that it is concurrent.
2108−--
2109−-- If you read the signature as @(t m a -> t m b) -> (t m a -> t m b)@ you can
2110−-- look at it as a transformation that converts a transform function to a
2111−-- buffered concurrent transform function.
2112−--
2113−-- The following code prints a value every second even though each stage adds a
2114−-- 1 second delay.
2115−--
2116−--
2117−-- @
2118−-- drain $
2119−-- S.mapM (\\x -> threadDelay 1000000 >> print x)
2120−-- |$ S.repeatM (threadDelay 1000000 >> return 1)
2121−-- @
2122−--
2123−-- /Concurrent/
2124−--
2125−-- /Since: 0.3.0 ("Streamly")/
2126−--
2127−-- @since 0.8.0
2128−{-# INLINE (|$) #-}
2129−(|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> (t m a -> t m b)
2130−-- (|$) f = f . Async.mkAsync
2131−(|$) f = f . D.mkParallel
2132−
2133−-- | Same as '|$'.
2134−--
2135−-- /Internal/
2136−--
2137−{-# INLINE applyAsync #-}
2138−applyAsync :: (IsStream t, MonadAsync m)
2139− => (t m a -> t m b) -> (t m a -> t m b)
2140−applyAsync = (|$)
2141−
2142−-- | Parallel reverse function application operator for streams; just like the
2143−-- regular reverse function application operator '&' except that it is
2144−-- concurrent.
2145−--
2146−-- @
2147−-- drain $
2148−-- S.repeatM (threadDelay 1000000 >> return 1)
2149−-- |& S.mapM (\\x -> threadDelay 1000000 >> print x)
2150−-- @
2151−--
2152−-- /Concurrent/
2153−--
2154−-- /Since: 0.3.0 ("Streamly")/
2155−--
2156−-- @since 0.8.0
2157−{-# INLINE (|&) #-}
2158−(|&) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> t m b) -> t m b
2159−x |& f = f |$ x
2160−
2161−-- | Parallel fold application operator; applies a fold function @t m a -> m b@
2162−-- to a stream @t m a@ concurrently; The the input stream is evaluated
2163−-- asynchronously in an independent thread yielding elements to a buffer and
2164−-- the folding action runs in another thread consuming the input from the
2165−-- buffer.
2166−--
2167−-- If you read the signature as @(t m a -> m b) -> (t m a -> m b)@ you can look
2168−-- at it as a transformation that converts a fold function to a buffered
2169−-- concurrent fold function.
2170−--
2171−-- The @.@ at the end of the operator is a mnemonic for termination of the
2172−-- stream.
2173−--
2174−-- @
2175−-- S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
2176−-- |$. S.repeatM (threadDelay 1000000 >> return 1)
2177−-- @
2178−--
2179−-- /Concurrent/
2180−--
2181−-- /Since: 0.3.0 ("Streamly")/
2182−--
2183−-- @since 0.8.0
2184−{-# INLINE (|$.) #-}
2185−(|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
2186−-- (|$.) f = f . Async.mkAsync
2187−(|$.) f = f . D.mkParallel
2188−
2189−-- | Same as '|$.'.
2190−--
2191−-- /Internal/
2192−--
2193−{-# INLINE foldAsync #-}
2194−foldAsync :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
2195−foldAsync = (|$.)
2196−
2197−-- | Parallel reverse function application operator for applying a run or fold
2198−-- functions to a stream. Just like '|$.' except that the operands are reversed.
2199−--
2200−-- @
2201−-- S.repeatM (threadDelay 1000000 >> return 1)
2202−-- |&. S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
2203−-- @
2204−--
2205−-- /Concurrent/
2206−--
2207−-- /Since: 0.3.0 ("Streamly")/
2208−--
2209−-- @since 0.8.0
2210−{-# INLINE (|&.) #-}
2211−(|&.) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> m b) -> m b
2212−x |&. f = f |$. x
2213−
2214−------------------------------------------------------------------------------
2215−-- General Transformation
2216−------------------------------------------------------------------------------
2217−
2218−-- | Use a 'Pipe' to transform a stream.
2219−--
2220−-- /Internal/
2221−--
2222−{-# INLINE transform #-}
2223−transform :: (IsStream t, Monad m) => Pipe m a b -> t m a -> t m b
2224−transform pipe xs = fromStreamD $ D.transform pipe (toStreamD xs)
2225−
2226−------------------------------------------------------------------------------
2227−-- Transformation by Folding (Scans)
2228−------------------------------------------------------------------------------
2229−
2230−-- XXX It may be useful to have a version of scan where we can keep the
2231−-- accumulator independent of the value emitted. So that we do not necessarily
2232−-- have to keep a value in the accumulator which we are not using. We can pass
2233−-- an extraction function that will take the accumulator and the current value
2234−-- of the element and emit the next value in the stream. That will also make it
2235−-- possible to modify the accumulator after using it. In fact, the step function
2236−-- can return new accumulator and the value to be emitted. The signature would
2237−-- be more like mapAccumL. Or we can change the signature of scanx to
2238−-- accommodate this.
2239−--
2240−-- | Strict left scan with an extraction function. Like 'scanl'', but applies a
2241−-- user supplied extraction function (the third argument) at each step. This is
2242−-- designed to work with the @foldl@ library. The suffix @x@ is a mnemonic for
2243−-- extraction.
2244−--
2245−-- /Since 0.2.0/
2246−--
2247−-- /Since: 0.7.0 (Monad m constraint)/
2248−{-# DEPRECATED scanx "Please use scanl followed by map instead." #-}
2249−{-# INLINE scanx #-}
2250−scanx :: (IsStream t, Monad m) => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
2251−scanx = P.scanlx'
2252−
2253−-- XXX this needs to be concurrent
2254−-- XXX because of the use of D.cons for appending, scanlM' has quadratic
2255−-- complexity when iterated over a stream. We should use StreamK style scanlM'
2256−-- for linear performance on iteration.
2257−--
2258−-- | Like 'scanl'' but with a monadic step function and a monadic seed.
2259−--
2260−-- /Since: 0.4.0/
2261−--
2262−-- /Since: 0.8.0 (signature change)/
2263−{-# INLINE scanlM' #-}
2264−scanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
2265−scanlM' step begin m = fromStreamD $ D.scanlM' step begin $ toStreamD m
2266−
2267−-- | @scanlMAfter' accumulate initial done stream@ is like 'scanlM'' except
2268−-- that it provides an additional @done@ function to be applied on the
2269−-- accumulator when the stream stops. The result of @done@ is also emitted in
2270−-- the stream.
2271−--
2272−-- This function can be used to allocate a resource in the beginning of the
2273−-- scan and release it when the stream ends or to flush the internal state of
2274−-- the scan at the end.
2275−--
2276−-- /Internal/
2277−--
2278−{-# INLINE scanlMAfter' #-}
2279−scanlMAfter' :: (IsStream t, Monad m)
2280− => (b -> a -> m b) -> m b -> (b -> m b) -> t m a -> t m b
2281−scanlMAfter' step initial done stream =
2282− fromStreamD $ D.scanlMAfter' step initial done $ toStreamD stream
2283−
2284−-- XXX because of the use of D.cons for appending, scanl' has quadratic
2285−-- complexity when iterated over a stream. We should use StreamK style scanlM'
2286−-- for linear performance on iteration.
2287−
2288−-- | Strict left scan. Like 'map', 'scanl'' too is a one to one transformation,
2289−-- however it adds an extra element.
2290−--
2291−-- @
2292−-- > S.toList $ S.scanl' (+) 0 $ fromList [1,2,3,4]
2293−-- [0,1,3,6,10]
2294−-- @
2295−--
2296−-- @
2297−-- > S.toList $ S.scanl' (flip (:)) [] $ S.fromList [1,2,3,4]
2298−-- [[],[1],[2,1],[3,2,1],[4,3,2,1]]
2299−-- @
2300−--
2301−-- The output of 'scanl'' is the initial value of the accumulator followed by
2302−-- all the intermediate steps and the final result of 'foldl''.
2303−--
2304−-- By streaming the accumulated state after each fold step, we can share the
2305−-- state across multiple stages of stream composition. Each stage can modify or
2306−-- extend the state, do some processing with it and emit it for the next stage,
2307−-- thus modularizing the stream processing. This can be useful in
2308−-- stateful or event-driven programming.
2309−--
2310−-- Consider the following monolithic example, computing the sum and the product
2311−-- of the elements in a stream in one go using a @foldl'@:
2312−--
2313−-- @
2314−-- > S.foldl' (\\(s, p) x -> (s + x, p * x)) (0,1) $ S.fromList \[1,2,3,4]
2315−-- (10,24)
2316−-- @
2317−--
2318−-- Using @scanl'@ we can make it modular by computing the sum in the first
2319−-- stage and passing it down to the next stage for computing the product:
2320−--
2321−-- @
2322−-- > S.foldl' (\\(_, p) (s, x) -> (s, p * x)) (0,1)
2323−-- $ S.scanl' (\\(s, _) x -> (s + x, x)) (0,1)
2324−-- $ S.fromList \[1,2,3,4]
2325−-- (10,24)
2326−-- @
2327−--
2328−-- IMPORTANT: 'scanl'' evaluates the accumulator to WHNF. To avoid building
2329−-- lazy expressions inside the accumulator, it is recommended that a strict
2330−-- data structure is used for accumulator.
2331−--
2332−-- See also: 'usingStateT'
2333−--
2334−-- @since 0.2.0
2335−{-# INLINE scanl' #-}
2336−scanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
2337−scanl' step z m = fromStreamS $ S.scanl' step z $ toStreamS m
2338−
2339−-- | Like 'scanl'' but does not stream the initial value of the accumulator.
2340−--
2341−-- > postscanl' f z xs = S.drop 1 $ S.scanl' f z xs
2342−--
2343−-- @since 0.7.0
2344−{-# INLINE postscanl' #-}
2345−postscanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
2346−postscanl' step z m = fromStreamD $ D.postscanl' step z $ toStreamD m
2347−
2348−-- XXX this needs to be concurrent
2349−-- | Like 'postscanl'' but with a monadic step function and a monadic seed.
2350−--
2351−-- /Since: 0.7.0/
2352−--
2353−-- /Since: 0.8.0 (signature change)/
2354−{-# INLINE postscanlM' #-}
2355−postscanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
2356−postscanlM' step z m = fromStreamD $ D.postscanlM' step z $ toStreamD m
2357−
2358−-- XXX prescanl does not sound very useful, enable only if there is a
2359−-- compelling use case.
2360−--
2361−-- | Like scanl' but does not stream the final value of the accumulator.
2362−--
2363−-- /Internal/
2364−{-# INLINE prescanl' #-}
2365−prescanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
2366−prescanl' step z m = fromStreamD $ D.prescanl' step z $ toStreamD m
2367−
2368−-- XXX this needs to be concurrent
2369−-- | Like prescanl' but with a monadic step function and a monadic seed.
2370−--
2371−-- /Internal/
2372−{-# INLINE prescanlM' #-}
2373−prescanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
2374−prescanlM' step z m = fromStreamD $ D.prescanlM' step z $ toStreamD m
2375−
2376−-- XXX this needs to be concurrent
2377−-- | Like 'scanl1'' but with a monadic step function.
2378−--
2379−-- @since 0.6.0
2380−{-# INLINE scanl1M' #-}
2381−scanl1M' :: (IsStream t, Monad m) => (a -> a -> m a) -> t m a -> t m a
2382−scanl1M' step m = fromStreamD $ D.scanl1M' step $ toStreamD m
2383−
2384−-- | Like 'scanl'' but for a non-empty stream. The first element of the stream
2385−-- is used as the initial value of the accumulator. Does nothing if the stream
2386−-- is empty.
2387−--
2388−-- @
2389−-- > S.toList $ S.scanl1 (+) $ fromList [1,2,3,4]
2390−-- [1,3,6,10]
2391−-- @
2392−--
2393−-- @since 0.6.0
2394−{-# INLINE scanl1' #-}
2395−scanl1' :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> t m a
2396−scanl1' step m = fromStreamD $ D.scanl1' step $ toStreamD m
2397−
2398−------------------------------------------------------------------------------
2399−-- Scanning with a Fold
2400−------------------------------------------------------------------------------
2401−
2402−-- | Scan a stream using the given monadic fold.
2403−--
2404−-- @since 0.7.0
2405−{-# INLINE scan #-}
2406−scan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
2407−scan = P.scanOnce
2408−
2409−-- | Postscan a stream using the given monadic fold.
2410−--
2411−-- @since 0.7.0
2412−{-# INLINE postscan #-}
2413−postscan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
2414−postscan = P.postscanOnce
2415−
2416−------------------------------------------------------------------------------
2417−-- Stateful Transformations
2418−------------------------------------------------------------------------------
2419−
2420−-- XXX this is not a one-to-one map so calling it map may not be right.
2421−-- We can perhaps call it zipWithTail or rollWith.
2422−--
2423−-- | Apply a function on every two successive elements of a stream. If the
2424−-- stream consists of a single element the output is an empty stream.
2425−--
2426−-- This is the stream equivalent of the list idiom @zipWith f xs (tail xs)@.
2427−--
2428−-- /Internal/
2429−--
2430−{-# INLINE rollingMap #-}
2431−rollingMap :: (IsStream t, Monad m) => (a -> a -> b) -> t m a -> t m b
2432−rollingMap f m = fromStreamD $ D.rollingMap f $ toStreamD m
2433−
2434−-- | Like 'rollingMap' but with an effectful map function.
2435−--
2436−-- /Internal/
2437−--
2438−{-# INLINE rollingMapM #-}
2439−rollingMapM :: (IsStream t, Monad m) => (a -> a -> m b) -> t m a -> t m b
2440−rollingMapM f m = fromStreamD $ D.rollingMapM f $ toStreamD m
2441−
2442−------------------------------------------------------------------------------
2443−-- Transformation by Filtering
2444−------------------------------------------------------------------------------
2445−
2446−-- | Include only those elements that pass a predicate.
2447−--
2448−-- @since 0.1.0
2449−{-# INLINE filter #-}
2450−#if __GLASGOW_HASKELL__ != 802
2451−-- GHC 8.2.2 crashes with this code, when used with "stack"
2452−filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
2453−filter p m = fromStreamS $ S.filter p $ toStreamS m
2454−#else
2455−filter :: IsStream t => (a -> Bool) -> t m a -> t m a
2456−filter = K.filter
2457−#endif
2458−
2459−-- | Same as 'filter' but with a monadic predicate.
2460−--
2461−-- @since 0.4.0
2462−{-# INLINE filterM #-}
2463−filterM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
2464−filterM p m = fromStreamD $ D.filterM p $ toStreamD m
2465−
2466−-- | Drop repeated elements that are adjacent to each other.
2467−--
2468−-- @since 0.6.0
2469−{-# INLINE uniq #-}
2470−uniq :: (Eq a, IsStream t, Monad m) => t m a -> t m a
2471−uniq = fromStreamD . D.uniq . toStreamD
2472−
2473−-- | Ensures that all the elements of the stream are identical and then returns
2474−-- that unique element.
2475−--
2476−-- @since 0.6.0
2477−{-# INLINE the #-}
2478−the :: (Eq a, Monad m) => SerialT m a -> m (Maybe a)
2479−the m = S.the (toStreamS m)
2480−
2481−-- | Take first 'n' elements from the stream and discard the rest.
2482−--
2483−-- @since 0.1.0
2484−{-# INLINE take #-}
2485−take :: (IsStream t, Monad m) => Int -> t m a -> t m a
2486−take n m = fromStreamS $ S.take n $ toStreamS
2487− (maxYields (Just (fromIntegral n)) m)
2488−
2489−-- | End the stream as soon as the predicate fails on an element.
2490−--
2491−-- @since 0.1.0
2492−{-# INLINE takeWhile #-}
2493−takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
2494−takeWhile p m = fromStreamS $ S.takeWhile p $ toStreamS m
2495−
2496−-- | Same as 'takeWhile' but with a monadic predicate.
2497−--
2498−-- @since 0.4.0
2499−{-# INLINE takeWhileM #-}
2500−takeWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
2501−takeWhileM p m = fromStreamD $ D.takeWhileM p $ toStreamD m
2502−
2503−-- | @takeByTime duration@ yields stream elements upto specified time
2504−-- @duration@. The duration starts when the stream is evaluated for the first
2505−-- time, before the first element is yielded. The time duration is checked
2506−-- before generating each element, if the duration has expired the stream
2507−-- stops.
2508−--
2509−-- The total time taken in executing the stream is guaranteed to be /at least/
2510−-- @duration@, however, because the duration is checked before generating an
2511−-- element, the upper bound is indeterminate and depends on the time taken in
2512−-- generating and processing the last element.
2513−--
2514−-- No element is yielded if the duration is zero. At least one element is
2515−-- yielded if the duration is non-zero.
2516−--
2517−-- /Internal/
2518−--
2519−{-# INLINE takeByTime #-}
2520−takeByTime ::(MonadIO m, IsStream t, TimeUnit64 d) => d -> t m a -> t m a
2521−takeByTime d = fromStreamD . D.takeByTime d . toStreamD
2522−
2523−-- | Discard first 'n' elements from the stream and take the rest.
2524−--
2525−-- @since 0.1.0
2526−{-# INLINE drop #-}
2527−drop :: (IsStream t, Monad m) => Int -> t m a -> t m a
2528−drop n m = fromStreamS $ S.drop n $ toStreamS m
2529−
2530−-- | Drop elements in the stream as long as the predicate succeeds and then
2531−-- take the rest of the stream.
2532−--
2533−-- @since 0.1.0
2534−{-# INLINE dropWhile #-}
2535−dropWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
2536−dropWhile p m = fromStreamS $ S.dropWhile p $ toStreamS m
2537−
2538−-- | Same as 'dropWhile' but with a monadic predicate.
2539−--
2540−-- @since 0.4.0
2541−{-# INLINE dropWhileM #-}
2542−dropWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
2543−dropWhileM p m = fromStreamD $ D.dropWhileM p $ toStreamD m
2544−
2545−-- | @dropByTime duration@ drops stream elements until specified @duration@ has
2546−-- passed. The duration begins when the stream is evaluated for the first
2547−-- time. The time duration is checked /after/ generating a stream element, the
2548−-- element is yielded if the duration has expired otherwise it is dropped.
2549−--
2550−-- The time elapsed before starting to generate the first element is /at most/
2551−-- @duration@, however, because the duration expiry is checked after the
2552−-- element is generated, the lower bound is indeterminate and depends on the
2553−-- time taken in generating an element.
2554−--
2555−-- All elements are yielded if the duration is zero.
2556−--
2557−-- /Internal/
2558−--
2559−{-# INLINE dropByTime #-}
2560−dropByTime ::(MonadIO m, IsStream t, TimeUnit64 d) => d -> t m a -> t m a
2561−dropByTime d = fromStreamD . D.dropByTime d . toStreamD
2562−
2563−------------------------------------------------------------------------------
2564−-- Transformation by Mapping
2565−------------------------------------------------------------------------------
2566−
2567−-- |
2568−-- @
2569−-- mapM f = sequence . map f
2570−-- @
2571−--
2572−-- Apply a monadic function to each element of the stream and replace it with
2573−-- the output of the resulting action.
2574−--
2575−-- @
2576−-- > drain $ S.mapM putStr $ S.fromList ["a", "b", "c"]
2577−-- abc
2578−--
2579−-- drain $ S.replicateM 10 (return 1)
2580−-- & (serially . S.mapM (\\x -> threadDelay 1000000 >> print x))
2581−--
2582−-- drain $ S.replicateM 10 (return 1)
2583−-- & (asyncly . S.mapM (\\x -> threadDelay 1000000 >> print x))
2584−-- @
2585−--
2586−-- /Concurrent (do not use with 'parallely' on infinite streams)/
2587−--
2588−-- @since 0.1.0
2589−{-# INLINE_EARLY mapM #-}
2590−mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
2591−mapM = K.mapM
2592−
2593−{-# RULES "mapM serial" mapM = mapMSerial #-}
2594−{-# INLINE mapMSerial #-}
2595−mapMSerial :: Monad m => (a -> m b) -> SerialT m a -> SerialT m b
2596−mapMSerial = Serial.mapM
2597−
2598−-- |
2599−-- @
2600−-- sequence = mapM id
2601−-- @
2602−--
2603−-- Replace the elements of a stream of monadic actions with the outputs of
2604−-- those actions.
2605−--
2606−-- @
2607−-- > drain $ S.sequence $ S.fromList [putStr "a", putStr "b", putStrLn "c"]
2608−-- abc
2609−--
2610−-- drain $ S.replicateM 10 (return $ threadDelay 1000000 >> print 1)
2611−-- & (serially . S.sequence)
2612−--
2613−-- drain $ S.replicateM 10 (return $ threadDelay 1000000 >> print 1)
2614−-- & (asyncly . S.sequence)
2615−-- @
2616−--
2617−-- /Concurrent (do not use with 'parallely' on infinite streams)/
2618−--
2619−-- @since 0.1.0
2620−{-# INLINE sequence #-}
2621−sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
2622−sequence m = fromStreamS $ S.sequence (toStreamS m)
2623−
2624−-- $smapM_Notes
2625−--
2626−-- The stateful step function can be simplified to @(s -> a -> m b)@ to provide
2627−-- a read-only environment. However, that would just be 'mapM'.
2628−--
2629−-- The initial action could be @m (s, Maybe b)@, and we can also add a final
2630−-- action @s -> m (Maybe b)@. This can be used to get pre/post scan like
2631−-- functionality and also to flush the state in the end like scanlMAfter'.
2632−-- We can also use it along with a fusible version of bracket to get
2633−-- scanlMAfter' like functionality. See issue #677.
2634−--
2635−-- This can be further generalized to a type similar to Fold/Parser, giving it
2636−-- filtering and parsing capability as well (this is in fact equivalent to
2637−-- parseMany):
2638−--
2639−-- smapM :: (s -> a -> m (Step s b)) -> m s -> t m a -> t m b
2640−--
2641−
2642−-- | A stateful 'mapM', equivalent to a left scan, more like mapAccumL.
2643−-- Hopefully, this is a better alternative to @scan@. Separation of state from
2644−-- the output makes it easier to think in terms of a shared state, and also
2645−-- makes it easier to keep the state fully strict and the output lazy.
2646−--
2647−-- See also: 'scanlM''
2648−--
2649−-- /Internal/
2650−--
2651−{-# INLINE smapM #-}
2652−smapM :: (IsStream t, Monad m) =>
2653− (s -> a -> m (s, b))
2654− -> m s
2655− -> t m a
2656− -> t m b
2657−smapM step initial stream =
2658− -- XXX implement this directly instead of using scanlM'
2659− -- Once we have postscanlM' with monadic initial we can use this code
2660− -- let r = postscanlM'
2661− -- (\(s, _) a -> step s a)
2662− -- (fmap (,undefined) initial)
2663− -- stream
2664− let r = postscanlM'
2665− (\(s, _) a -> step s a)
2666− (fmap (,undefined) initial)
2667− stream
2668− in Serial.map snd r
2669−
2670−------------------------------------------------------------------------------
2671−-- Maybe Streams
2672−------------------------------------------------------------------------------
2673−
2674−-- | Map a 'Maybe' returning function to a stream, filter out the 'Nothing'
2675−-- elements, and return a stream of values extracted from 'Just'.
2676−--
2677−-- Equivalent to:
2678−--
2679−-- @
2680−-- mapMaybe f = S.map 'fromJust' . S.filter 'isJust' . S.map f
2681−-- @
2682−--
2683−-- @since 0.3.0
2684−{-# INLINE mapMaybe #-}
2685−mapMaybe :: (IsStream t, Monad m) => (a -> Maybe b) -> t m a -> t m b
2686−mapMaybe f m = fromStreamS $ S.mapMaybe f $ toStreamS m
2687−
2688−-- | Like 'mapMaybe' but maps a monadic function.
2689−--
2690−-- Equivalent to:
2691−--
2692−-- @
2693−-- mapMaybeM f = S.map 'fromJust' . S.filter 'isJust' . S.mapM f
2694−-- @
2695−--
2696−-- /Concurrent (do not use with 'parallely' on infinite streams)/
2697−--
2698−-- @since 0.3.0
2699−{-# INLINE_EARLY mapMaybeM #-}
2700−mapMaybeM :: (IsStream t, MonadAsync m, Functor (t m))
2701− => (a -> m (Maybe b)) -> t m a -> t m b
2702−mapMaybeM f = fmap fromJust . filter isJust . K.mapM f
2703−
2704−{-# RULES "mapMaybeM serial" mapMaybeM = mapMaybeMSerial #-}
2705−{-# INLINE mapMaybeMSerial #-}
2706−mapMaybeMSerial :: Monad m => (a -> m (Maybe b)) -> SerialT m a -> SerialT m b
2707−mapMaybeMSerial f m = fromStreamD $ D.mapMaybeM f $ toStreamD m
2708−
2709−-- | In a stream of 'Maybe's, discard 'Nothing's and unwrap 'Just's.
2710−--
2711−-- /Internal/
2712−--
2713−catMaybes :: (IsStream t, Monad m, Functor (t m)) => t m (Maybe a) -> t m a
2714−catMaybes = fmap fromJust . filter isJust
2715−
2716−------------------------------------------------------------------------------
2717−-- Transformation by Reordering
2718−------------------------------------------------------------------------------
2719−
2720−-- XXX Use a compact region list to temporarily store the list, in both reverse
2721−-- as well as in reverse'.
2722−--
2723−-- /Note:/ 'reverse'' is much faster than this, use that when performance
2724−-- matters.
2725−--
2726−-- > reverse = S.foldlT (flip S.cons) S.nil
2727−--
2728−-- | Returns the elements of the stream in reverse order. The stream must be
2729−-- finite. Note that this necessarily buffers the entire stream in memory.
2730−--
2731−-- /Since 0.7.0 (Monad m constraint)/
2732−--
2733−-- /Since: 0.1.1/
2734−{-# INLINE reverse #-}
2735−reverse :: (IsStream t, Monad m) => t m a -> t m a
2736−reverse s = fromStreamS $ S.reverse $ toStreamS s
2737−
2738−-- | Like 'reverse' but several times faster, requires a 'Storable' instance.
2739−--
2740−-- /Internal/
2741−{-# INLINE reverse' #-}
2742−reverse' :: (IsStream t, MonadIO m, Storable a) => t m a -> t m a
2743−reverse' s = fromStreamD $ D.reverse' $ toStreamD s
2744−
2745−------------------------------------------------------------------------------
2746−-- Transformation by Inserting
2747−------------------------------------------------------------------------------
2748−
2749−-- intersperseM = intersperseBySpan 1
2750−
2751−-- | Insert an effect and its output before consuming an element of a stream
2752−-- except the first one.
2753−--
2754−-- @
2755−-- >>> S.toList $ S.trace putChar $ S.intersperseM (putChar '.' >> return ',') $ S.fromList "hello"
2756−-- > h.,e.,l.,l.,o"h,e,l,l,o"
2757−-- @
2758−--
2759−-- @since 0.5.0
2760−{-# INLINE intersperseM #-}
2761−intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
2762−intersperseM m = fromStreamS . S.intersperseM m . toStreamS
2763−
2764−-- | Insert a side effect before consuming an element of a stream except the
2765−-- first one.
2766−--
2767−-- @
2768−-- >>> S.drain $ S.trace putChar $ S.intersperseM_ (putChar '.') $ S.fromList "hello"
2769−-- > h.e.l.l.o
2770−-- @
2771−--
2772−-- /Internal/
2773−{-# INLINE intersperseM_ #-}
2774−intersperseM_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
2775−intersperseM_ m = fromStreamD . D.intersperseM_ m . toStreamD
2776−
2777−-- | Insert a pure value between successive elements of a stream.
2778−--
2779−-- @
2780−-- > S.toList $ S.intersperse ',' $ S.fromList "hello"
2781−-- "h,e,l,l,o"
2782−-- @
2783−--
2784−-- @since 0.7.0
2785−{-# INLINE intersperse #-}
2786−intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
2787−intersperse a = fromStreamS . S.intersperse a . toStreamS
2788−
2789−-- | Insert an effect and its output after consuming an element of a stream.
2790−--
2791−-- @
2792−-- >>> S.toList $ S.trace putChar $ S.intersperseSuffix (putChar '.' >> return ',') $ S.fromList "hello"
2793−-- > h.,e.,l.,l.,o.,"h,e,l,l,o,"
2794−-- @
2795−--
2796−-- /Internal/
2797−{-# INLINE intersperseSuffix #-}
2798−intersperseSuffix :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
2799−intersperseSuffix m = fromStreamD . D.intersperseSuffix m . toStreamD
2800−
2801−-- | Insert a side effect after consuming an element of a stream.
2802−--
2803−-- @
2804−-- > S.mapM_ putChar $ S.intersperseSuffix_ (threadDelay 1000000) $ S.fromList "hello"
2805−-- @
2806−--
2807−-- /Internal/
2808−--
2809−{-# INLINE intersperseSuffix_ #-}
2810−intersperseSuffix_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
2811−intersperseSuffix_ m = fromStreamD . D.intersperseSuffix_ m . toStreamD
2812−
2813−-- | Insert a side effect before consuming an element of a stream.
2814−--
2815−-- @
2816−-- >>> S.toList $ S.trace putChar $ S.interspersePrefix_ (putChar '.' >> return ',') $ S.fromList "hello"
2817−-- > .h.e.l.l.o"hello"
2818−-- @
2819−--
2820−-- See also: 'trace_'
2821−--
2822−-- /Concurrent/
2823−--
2824−-- /Internal/
2825−--
2826−{-# INLINE interspersePrefix_ #-}
2827−interspersePrefix_ :: (IsStream t, MonadAsync m) => m b -> t m a -> t m a
2828−interspersePrefix_ m = mapM (\x -> void m >> return x)
2829−
2830−-- Note: delay must be serial.
2831−--
2832−-- | Introduce a delay of specified seconds before consuming an element of the
2833−-- stream except the first one.
2834−--
2835−-- @
2836−-- >>> S.mapM_ print $ S.timestamped $ S.delay 1 $ S.enumerateFromTo 1 3
2837−-- > (AbsTime (TimeSpec {sec = 2502706, nsec = 751137000}),1)
2838−-- > (AbsTime (TimeSpec {sec = 2502707, nsec = 743535000}),2)
2839−-- > (AbsTime (TimeSpec {sec = 2502708, nsec = 749758000}),3)
2840−-- @
2841−--
2842−-- /Internal/
2843−--
2844−{-# INLINE delay #-}
2845−delay :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
2846−delay n = intersperseM_ $ liftIO $ threadDelay $ round $ n * 1000000
2847−
2848−-- Note: delay must be serial.
2849−--
2850−-- | Introduce a delay of specified seconds after consuming an element of a
2851−-- stream.
2852−--
2853−-- @
2854−-- >>> S.mapM_ print $ S.timestamped $ S.delayPost 1 $ S.enumerateFromTo 1 3
2855−-- > (AbsTime (TimeSpec {sec = 2502826, nsec = 119030000}),1)
2856−-- > (AbsTime (TimeSpec {sec = 2502827, nsec = 111393000}),2)
2857−-- > (AbsTime (TimeSpec {sec = 2502828, nsec = 112221000}),3)
2858−-- @
2859−--
2860−-- /Internal/
2861−--
2862−{-# INLINE delayPost #-}
2863−delayPost :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
2864−delayPost n = intersperseSuffix_ $ liftIO $ threadDelay $ round $ n * 1000000
2865−
2866−-- Note: delay must be serial, that's why 'trace_' is used.
2867−--
2868−-- | Introduce a delay of specified seconds before consuming an element of a
2869−-- stream.
2870−--
2871−-- @
2872−-- >>> S.mapM_ print $ S.timestamped $ S.delayPre 1 $ S.enumerateFromTo 1 3
2873−-- > (AbsTime (TimeSpec {sec = 2502207, nsec = 533177000}),1)
2874−-- > (AbsTime (TimeSpec {sec = 2502208, nsec = 530859000}),2)
2875−-- > (AbsTime (TimeSpec {sec = 2502209, nsec = 531619000}),3)
2876−-- @
2877−--
2878−-- /Internal/
2879−--
2880−{-# INLINE delayPre #-}
2881−delayPre :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
2882−delayPre n = trace_ $ liftIO $ threadDelay $ round $ n * 1000000
2883−
2884−-- | Like 'intersperseSuffix' but intersperses an effectful action into the
2885−-- input stream after every @n@ elements and after the last element.
2886−--
2887−-- @
2888−-- > S.toList $ S.intersperseSuffixBySpan 2 (return ',') $ S.fromList "hello"
2889−-- "he,ll,o,"
2890−-- @
2891−--
2892−-- /Internal/
2893−--
2894−{-# INLINE intersperseSuffixBySpan #-}
2895−intersperseSuffixBySpan :: (IsStream t, MonadAsync m)
2896− => Int -> m a -> t m a -> t m a
2897−intersperseSuffixBySpan n eff =
2898− fromStreamD . D.intersperseSuffixBySpan n eff . toStreamD
2899−
2900−{-
2901−-- | Intersperse a monadic action into the input stream after every @n@
2902−-- elements.
2903−--
2904−-- @
2905−-- > S.toList $ S.intersperseBySpan 2 (return ',') $ S.fromList "hello"
2906−-- "he,ll,o"
2907−-- @
2908−--
2909−-- @since 0.7.0
2910−{-# INLINE intersperseBySpan #-}
2911−intersperseBySpan :: IsStream t => Int -> m a -> t m a -> t m a
2912−intersperseBySpan _n _f _xs = undefined
2913−-}
2914−
2915−-- | Intersperse a monadic action into the input stream after every @n@
2916−-- seconds.
2917−--
2918−-- @
2919−-- > S.drain $ S.interjectSuffix 1 (putChar ',') $ S.mapM (\\x -> threadDelay 1000000 >> putChar x) $ S.fromList "hello"
2920−-- "h,e,l,l,o"
2921−-- @
2922−--
2923−-- /Internal/
2924−{-# INLINE interjectSuffix #-}
2925−interjectSuffix
2926− :: (IsStream t, MonadAsync m)
2927− => Double -> m a -> t m a -> t m a
2928−interjectSuffix n f xs = xs `Par.parallelFst` repeatM timed
2929− where timed = liftIO (threadDelay (round $ n * 1000000)) >> f
2930−
2931−-- | @insertBy cmp elem stream@ inserts @elem@ before the first element in
2932−-- @stream@ that is less than @elem@ when compared using @cmp@.
2933−--
2934−-- @
2935−-- insertBy cmp x = 'mergeBy' cmp ('yield' x)
2936−-- @
2937−--
2938−-- @
2939−-- > S.toList $ S.insertBy compare 2 $ S.fromList [1,3,5]
2940−-- [1,2,3,5]
2941−-- @
2942−--
2943−-- @since 0.6.0
2944−{-# INLINE insertBy #-}
2945−insertBy ::
2946− (IsStream t, Monad m) => (a -> a -> Ordering) -> a -> t m a -> t m a
2947−insertBy cmp x m = fromStreamS $ S.insertBy cmp x (toStreamS m)
2948−
2949−------------------------------------------------------------------------------
2950−-- Deleting
2951−------------------------------------------------------------------------------
2952−
2953−-- | Deletes the first occurrence of the element in the stream that satisfies
2954−-- the given equality predicate.
2955−--
2956−-- @
2957−-- > S.toList $ S.deleteBy (==) 3 $ S.fromList [1,3,3,5]
2958−-- [1,3,5]
2959−-- @
2960−--
2961−-- @since 0.6.0
2962−{-# INLINE deleteBy #-}
2963−deleteBy :: (IsStream t, Monad m) => (a -> a -> Bool) -> a -> t m a -> t m a
2964−deleteBy cmp x m = fromStreamS $ S.deleteBy cmp x (toStreamS m)
2965−
2966−------------------------------------------------------------------------------
2967−-- Zipping
2968−------------------------------------------------------------------------------
2969−
2970−-- |
2971−-- > indexed = S.postscanl' (\(i, _) x -> (i + 1, x)) (-1,undefined)
2972−-- > indexed = S.zipWith (,) (S.enumerateFrom 0)
2973−--
2974−-- Pair each element in a stream with its index, starting from index 0.
2975−--
2976−-- @
2977−-- > S.toList $ S.indexed $ S.fromList "hello"
2978−-- [(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')]
2979−-- @
2980−--
2981−-- @since 0.6.0
2982−{-# INLINE indexed #-}
2983−indexed :: (IsStream t, Monad m) => t m a -> t m (Int, a)
2984−indexed = fromStreamD . D.indexed . toStreamD
2985−
2986−-- |
2987−-- > indexedR n = S.postscanl' (\(i, _) x -> (i - 1, x)) (n + 1,undefined)
2988−-- > indexedR n = S.zipWith (,) (S.enumerateFromThen n (n - 1))
2989−--
2990−-- Pair each element in a stream with its index, starting from the
2991−-- given index @n@ and counting down.
2992−--
2993−-- @
2994−-- > S.toList $ S.indexedR 10 $ S.fromList "hello"
2995−-- [(10,'h'),(9,'e'),(8,'l'),(7,'l'),(6,'o')]
2996−-- @
2997−--
2998−-- @since 0.6.0
2999−{-# INLINE indexedR #-}
3000−indexedR :: (IsStream t, Monad m) => Int -> t m a -> t m (Int, a)
3001−indexedR n = fromStreamD . D.indexedR n . toStreamD
3002−
3003−-- Note: The timestamp stream must be the second stream in the zip so that the
3004−-- timestamp is generated after generating the stream element and not before.
3005−-- If we do not do that then the following example will generate the same
3006−-- timestamp for first two elements:
3007−--
3008−-- S.mapM_ print $ S.timestamped $ S.delay $ S.enumerateFromTo 1 3
3009−--
3010−-- | Pair each element in a stream with an absolute timestamp, using a clock of
3011−-- specified granularity. The timestamp is generated just before the element
3012−-- is consumed.
3013−--
3014−-- @
3015−-- >>> S.mapM_ print $ S.timestampWith 0.01 $ S.delay 1 $ S.enumerateFromTo 1 3
3016−-- @
3017−--
3018−-- /Internal/
3019−--
3020−{-# INLINE timestampWith #-}
3021−timestampWith :: (IsStream t, MonadAsync m, Functor (t m))
3022− => Double -> t m a -> t m (AbsTime, a)
3023−timestampWith g stream = Z.zipWith (flip (,)) stream (absTimesWith g)
3024−
3025−-- TBD: check performance vs a custom implementation without using zipWith.
3026−--
3027−-- | Pair each element in a stream with an absolute timestamp, using a clock of
3028−-- 10 ms granularity. The timestamp is generated just before the element is
3029−-- consumed.
3030−--
3031−-- @
3032−-- >>> S.mapM_ print $ S.timestamped $ S.delay 1 $ S.enumerateFromTo 1 3
3033−-- (AbsTime (TimeSpec {sec = 2460689, nsec = 641121000}),1)
3034−-- (AbsTime (TimeSpec {sec = 2460690, nsec = 639334000}),2)
3035−-- (AbsTime (TimeSpec {sec = 2460691, nsec = 644479000}),3)
3036−-- @
3037−--
3038−-- /Internal/
3039−--
3040−{-# INLINE timestamped #-}
3041−timestamped :: (IsStream t, MonadAsync m, Functor (t m))
3042− => t m a -> t m (AbsTime, a)
3043−timestamped = timestampWith 0.01
3044−
3045−-- | Pair each element in a stream with relative times starting from 0, using a
3046−-- clock with the specified granularity. The time is measured just before the
3047−-- element is consumed.
3048−--
3049−-- @
3050−-- >>> S.mapM_ print $ S.timeIndexWith 0.01 $ S.delay 1 $ S.enumerateFromTo 1 3
3051−-- @
3052−--
3053−-- /Internal/
3054−--
3055−{-# INLINE timeIndexWith #-}
3056−timeIndexWith :: (IsStream t, MonadAsync m, Functor (t m))
3057− => Double -> t m a -> t m (RelTime64, a)
3058−timeIndexWith g stream = Z.zipWith (flip (,)) stream (relTimesWith g)
3059−
3060−-- | Pair each element in a stream with relative times starting from 0, using a
3061−-- 10 ms granularity clock. The time is measured just before the element is
3062−-- consumed.
3063−--
3064−-- @
3065−-- >>> S.mapM_ print $ S.timeIndexed $ S.delay 1 $ S.enumerateFromTo 1 3
3066−-- (RelTime64 (NanoSecond64 0),1)
3067−-- (RelTime64 (NanoSecond64 996239000),2)
3068−-- (RelTime64 (NanoSecond64 1996712000),3)
3069−-- @
3070−--
3071−-- /Internal/
3072−--
3073−{-# INLINE timeIndexed #-}
3074−timeIndexed :: (IsStream t, MonadAsync m, Functor (t m))
3075− => t m a -> t m (RelTime64, a)
3076−timeIndexed = timeIndexWith 0.01
3077−
3078−------------------------------------------------------------------------------
3079−-- Comparison
3080−------------------------------------------------------------------------------
3081−
3082−-- | Compare two streams for equality using an equality function.
3083−--
3084−-- @since 0.6.0
3085−{-# INLINABLE eqBy #-}
3086−eqBy :: (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> m Bool
3087−eqBy = P.eqBy
3088−
3089−-- | Compare two streams lexicographically using a comparison function.
3090−--
3091−-- @since 0.6.0
3092−{-# INLINABLE cmpBy #-}
3093−cmpBy
3094− :: (IsStream t, Monad m)
3095− => (a -> b -> Ordering) -> t m a -> t m b -> m Ordering
3096−cmpBy = P.cmpBy
3097−
3098−------------------------------------------------------------------------------
3099−-- Merge
3100−------------------------------------------------------------------------------
3101−
3102−-- | Merge two streams using a comparison function. The head elements of both
3103−-- the streams are compared and the smaller of the two elements is emitted, if
3104−-- both elements are equal then the element from the first stream is used
3105−-- first.
3106−--
3107−-- If the streams are sorted in ascending order, the resulting stream would
3108−-- also remain sorted in ascending order.
3109−--
3110−-- @
3111−-- > S.toList $ S.mergeBy compare (S.fromList [1,3,5]) (S.fromList [2,4,6,8])
3112−-- [1,2,3,4,5,6,8]
3113−-- @
3114−--
3115−-- @since 0.6.0
3116−{-# INLINABLE mergeBy #-}
3117−mergeBy ::
3118− (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> t m a -> t m a
3119−mergeBy f m1 m2 = fromStreamS $ S.mergeBy f (toStreamS m1) (toStreamS m2)
3120−
3121−-- | Like 'mergeBy' but with a monadic comparison function.
3122−--
3123−-- Merge two streams randomly:
3124−--
3125−-- @
3126−-- > randomly _ _ = randomIO >>= \x -> return $ if x then LT else GT
3127−-- > S.toList $ S.mergeByM randomly (S.fromList [1,1,1,1]) (S.fromList [2,2,2,2])
3128−-- [2,1,2,2,2,1,1,1]
3129−-- @
3130−--
3131−-- Merge two streams in a proportion of 2:1:
3132−--
3133−-- @
3134−-- proportionately m n = do
3135−-- ref <- newIORef $ cycle $ concat [replicate m LT, replicate n GT]
3136−-- return $ \\_ _ -> do
3137−-- r <- readIORef ref
3138−-- writeIORef ref $ tail r
3139−-- return $ head r
3140−--
3141−-- main = do
3142−-- f <- proportionately 2 1
3143−-- xs <- S.toList $ S.mergeByM f (S.fromList [1,1,1,1,1,1]) (S.fromList [2,2,2])
3144−-- print xs
3145−-- @
3146−-- @
3147−-- [1,1,2,1,1,2,1,1,2]
3148−-- @
3149−--
3150−-- @since 0.6.0
3151−{-# INLINABLE mergeByM #-}
3152−mergeByM
3153− :: (IsStream t, Monad m)
3154− => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
3155−mergeByM f m1 m2 = fromStreamS $ S.mergeByM f (toStreamS m1) (toStreamS m2)
3156−
3157−{-
3158−-- | Like 'mergeByM' but stops merging as soon as any of the two streams stops.
3159−{-# INLINABLE mergeEndByAny #-}
3160−mergeEndByAny
3161− :: (IsStream t, Monad m)
3162− => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
3163−mergeEndByAny f m1 m2 = fromStreamD $
3164− D.mergeEndByAny f (toStreamD m1) (toStreamD m2)
3165−
3166−-- Like 'mergeByM' but stops merging as soon as the first stream stops.
3167−{-# INLINABLE mergeEndByFirst #-}
3168−mergeEndByFirst
3169− :: (IsStream t, Monad m)
3170− => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
3171−mergeEndByFirst f m1 m2 = fromStreamS $
3172− D.mergeEndByFirst f (toStreamD m1) (toStreamD m2)
3173−-}
3174−
3175−-- Holding this back for now, we may want to use the name "merge" differently
3176−{-
3177−-- | Same as @'mergeBy' 'compare'@.
3178−--
3179−-- @
3180−-- > S.toList $ S.merge (S.fromList [1,3,5]) (S.fromList [2,4,6,8])
3181−-- [1,2,3,4,5,6,8]
3182−-- @
3183−--
3184−-- @since 0.6.0
3185−{-# INLINABLE merge #-}
3186−merge ::
3187− (IsStream t, Monad m, Ord a) => t m a -> t m a -> t m a
3188−merge = mergeBy compare
3189−-}
3190−
3191−-- | Like 'mergeBy' but merges concurrently (i.e. both the elements being
3192−-- merged are generated concurrently).
3193−--
3194−-- @since 0.6.0
3195−{-# INLINE mergeAsyncBy #-}
3196−mergeAsyncBy :: (IsStream t, MonadAsync m)
3197− => (a -> a -> Ordering) -> t m a -> t m a -> t m a
3198−mergeAsyncBy f = mergeAsyncByM (\a b -> return $ f a b)
3199−
3200−-- | Like 'mergeByM' but merges concurrently (i.e. both the elements being
3201−-- merged are generated concurrently).
3202−--
3203−-- @since 0.6.0
3204−{-# INLINE mergeAsyncByM #-}
3205−mergeAsyncByM :: (IsStream t, MonadAsync m)
3206− => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
3207−mergeAsyncByM f m1 m2 = fromStreamD $
3208− D.mergeByM f (D.mkParallelD $ toStreamD m1) (D.mkParallelD $ toStreamD m2)
3209−
3210−------------------------------------------------------------------------------
3211−-- Flattening Lists
3212−------------------------------------------------------------------------------
3213−
3214−-- | @concatMapWith merge map stream@ is a two dimensional looping combinator.
3215−-- The first argument specifies a merge or concat function that is used to
3216−-- merge the streams generated by applying the second argument i.e. the @map@
3217−-- function to each element of the input stream. The concat function could be
3218−-- 'serial', 'parallel', 'async', 'ahead' or any other zip or merge function
3219−-- and the second argument could be any stream generation function using a
3220−-- seed.
3221−--
3222−-- /Compare 'foldMapWith'/
3223−--
3224−-- /Since: 0.7.0/
3225−--
3226−-- /Since: 0.8.0 (signature change)/
3227−{-# INLINE concatMapWith #-}
3228−concatMapWith
3229− :: IsStream t
3230− => (t m b -> t m b -> t m b)
3231− -> (a -> t m b)
3232− -> t m a
3233− -> t m b
3234−concatMapWith = K.concatMapBy
3235−
3236−-- | Like 'concatMapWith' but carries a state which can be used to share
3237−-- information across multiple steps of concat.
3238−--
3239−-- @
3240−-- concatSmapMWith combine f initial = concatMapWith combine id . smapM f initial
3241−-- @
3242−--
3243−-- /Internal/
3244−--
3245−{-# INLINE concatSmapMWith #-}
3246−concatSmapMWith
3247− :: (IsStream t, Monad m)
3248− => (t m b -> t m b -> t m b)
3249− -> (s -> a -> m (s, t m b))
3250− -> m s
3251− -> t m a
3252− -> t m b
3253−concatSmapMWith combine f initial = concatMapWith combine id . smapM f initial
3254−
3255−-- | Map a stream producing function on each element of the stream and then
3256−-- flatten the results into a single stream.
3257−--
3258−-- @
3259−-- concatMap f = 'concat . map f'
3260−-- concatMap = 'concatMapWith' 'Serial.serial'
3261−-- concatMap f = 'concatMapM' (return . f)
3262−-- concatMap f = 'concatUnfold' (UF.lmap f UF.fromStream)
3263−-- @
3264−--
3265−-- @since 0.6.0
3266−{-# INLINE concatMap #-}
3267−concatMap ::(IsStream t, Monad m) => (a -> t m b) -> t m a -> t m b
3268−concatMap f m = fromStreamD $ D.concatMap (toStreamD . f) (toStreamD m)
3269−
3270−-- | Flatten a stream of streams to a single stream.
3271−--
3272−-- @
3273−-- concat = concatMap id
3274−-- @
3275−--
3276−-- /Internal/
3277−{-# INLINE concat #-}
3278−concat :: (IsStream t, Monad m) => t m (t m a) -> t m a
3279−concat = concatMap id
3280−
3281−-- | Append the outputs of two streams, yielding all the elements from the
3282−-- first stream and then yielding all the elements from the second stream.
3283−--
3284−-- IMPORTANT NOTE: This could be 100x faster than @serial/<>@ for appending a
3285−-- few (say 100) streams because it can fuse via stream fusion. However, it
3286−-- does not scale for a large number of streams (say 1000s) and becomes
3287−-- qudartically slow. Therefore use this for custom appending of a few streams
3288−-- but use 'concatMap' or 'concatMapWith serial' for appending @n@ streams or
3289−-- infinite containers of streams.
3290−--
3291−-- /Internal/
3292−{-# INLINE append #-}
3293−append ::(IsStream t, Monad m) => t m b -> t m b -> t m b
3294−append m1 m2 = fromStreamD $ D.append (toStreamD m1) (toStreamD m2)
3295−
3296−-- XXX Same as 'wSerial'. We should perhaps rename wSerial to interleave.
3297−-- XXX Document the interleaving behavior of side effects in all the
3298−-- interleaving combinators.
3299−-- XXX Write time-domain equivalents of these. In the time domain we can
3300−-- interleave two streams such that the value of second stream is always taken
3301−-- from its last value even if no new value is being yielded, like
3302−-- zipWithLatest. It would be something like interleaveWithLatest.
3303−--
3304−-- | Interleaves the outputs of two streams, yielding elements from each stream
3305−-- alternately, starting from the first stream. If any of the streams finishes
3306−-- early the other stream continues alone until it too finishes.
3307−--
3308−-- >>> :set -XOverloadedStrings
3309−-- >>> interleave "ab" ",,,," :: SerialT Identity Char
3310−-- fromList "a,b,,,"
3311−-- >>> interleave "abcd" ",," :: SerialT Identity Char
3312−-- fromList "a,b,cd"
3313−--
3314−-- 'interleave' is dual to 'interleaveMin', it can be called @interleaveMax@.
3315−--
3316−-- Do not use at scale in concatMapWith.
3317−--
3318−-- /Internal/
3319−{-# INLINE interleave #-}
3320−interleave ::(IsStream t, Monad m) => t m b -> t m b -> t m b
3321−interleave m1 m2 = fromStreamD $ D.interleave (toStreamD m1) (toStreamD m2)
3322−
3323−-- | Interleaves the outputs of two streams, yielding elements from each stream
3324−-- alternately, starting from the first stream. As soon as the first stream
3325−-- finishes, the output stops, discarding the remaining part of the second
3326−-- stream. In this case, the last element in the resulting stream would be from
3327−-- the second stream. If the second stream finishes early then the first stream
3328−-- still continues to yield elements until it finishes.
3329−--
3330−-- >>> :set -XOverloadedStrings
3331−-- >>> interleaveSuffix "abc" ",,,," :: SerialT Identity Char
3332−-- fromList "a,b,c,"
3333−-- >>> interleaveSuffix "abc" "," :: SerialT Identity Char
3334−-- fromList "a,bc"
3335−--
3336−-- 'interleaveSuffix' is a dual of 'interleaveInfix'.
3337−--
3338−-- Do not use at scale in concatMapWith.
3339−--
3340−-- /Internal/
3341−{-# INLINE interleaveSuffix #-}
3342−interleaveSuffix ::(IsStream t, Monad m) => t m b -> t m b -> t m b
3343−interleaveSuffix m1 m2 =
3344− fromStreamD $ D.interleaveSuffix (toStreamD m1) (toStreamD m2)
3345−
3346−-- | Interleaves the outputs of two streams, yielding elements from each stream
3347−-- alternately, starting from the first stream and ending at the first stream.
3348−-- If the second stream is longer than the first, elements from the second
3349−-- stream are infixed with elements from the first stream. If the first stream
3350−-- is longer then it continues yielding elements even after the second stream
3351−-- has finished.
3352−--
3353−-- >>> :set -XOverloadedStrings
3354−-- >>> interleaveInfix "abc" ",,,," :: SerialT Identity Char
3355−-- fromList "a,b,c"
3356−-- >>> interleaveInfix "abc" "," :: SerialT Identity Char
3357−-- fromList "a,bc"
3358−--
3359−-- 'interleaveInfix' is a dual of 'interleaveSuffix'.
3360−--
3361−-- Do not use at scale in concatMapWith.
3362−--
3363−-- /Internal/
3364−{-# INLINE interleaveInfix #-}
3365−interleaveInfix ::(IsStream t, Monad m) => t m b -> t m b -> t m b
3366−interleaveInfix m1 m2 =
3367− fromStreamD $ D.interleaveInfix (toStreamD m1) (toStreamD m2)
3368−
3369−-- | Interleaves the outputs of two streams, yielding elements from each stream
3370−-- alternately, starting from the first stream. The output stops as soon as any
3371−-- of the two streams finishes, discarding the remaining part of the other
3372−-- stream. The last element of the resulting stream would be from the longer
3373−-- stream.
3374−--
3375−-- >>> :set -XOverloadedStrings
3376−-- >>> interleaveMin "ab" ",,,," :: SerialT Identity Char
3377−-- fromList "a,b,"
3378−-- >>> interleaveMin "abcd" ",," :: SerialT Identity Char
3379−-- fromList "a,b,c"
3380−--
3381−-- 'interleaveMin' is dual to 'interleave'.
3382−--
3383−-- Do not use at scale in concatMapWith.
3384−--
3385−-- /Internal/
3386−{-# INLINE interleaveMin #-}
3387−interleaveMin ::(IsStream t, Monad m) => t m b -> t m b -> t m b
3388−interleaveMin m1 m2 = fromStreamD $ D.interleaveMin (toStreamD m1) (toStreamD m2)
3389−
3390−-- | Schedule the execution of two streams in a fair round-robin manner,
3391−-- executing each stream once, alternately. Execution of a stream may not
3392−-- necessarily result in an output, a stream may chose to @Skip@ producing an
3393−-- element until later giving the other stream a chance to run. Therefore, this
3394−-- combinator fairly interleaves the execution of two streams rather than
3395−-- fairly interleaving the output of the two streams. This can be useful in
3396−-- co-operative multitasking without using explicit threads. This can be used
3397−-- as an alternative to `async`.
3398−--
3399−-- Do not use at scale in concatMapWith.
3400−--
3401−-- /Internal/
3402−{-# INLINE roundrobin #-}
3403−roundrobin ::(IsStream t, Monad m) => t m b -> t m b -> t m b
3404−roundrobin m1 m2 = fromStreamD $ D.roundRobin (toStreamD m1) (toStreamD m2)
3405−
3406−-- | Map a stream producing monadic function on each element of the stream
3407−-- and then flatten the results into a single stream. Since the stream
3408−-- generation function is monadic, unlike 'concatMap', it can produce an
3409−-- effect at the beginning of each iteration of the inner loop.
3410−--
3411−-- @since 0.6.0
3412−{-# INLINE concatMapM #-}
3413−concatMapM :: (IsStream t, Monad m) => (a -> m (t m b)) -> t m a -> t m b
3414−concatMapM f m = fromStreamD $ D.concatMapM (fmap toStreamD . f) (toStreamD m)
3415−
3416−-- | Given a stream value in the underlying monad, lift and join the underlying
3417−-- monad with the stream monad.
3418−--
3419−-- @
3420−-- concatM = concat . yieldM
3421−-- concatM = concat . lift -- requires @(MonadTrans t)@
3422−-- concatM = join . lift -- requires @(MonadTrans t@, @Monad (t m))@
3423−-- @
3424−--
3425−-- See also: 'concat', 'sequence'
3426−--
3427−-- /Internal/
3428−--
3429−{-# INLINE concatM #-}
3430−concatM :: (IsStream t, Monad m) => m (t m a) -> t m a
3431−concatM generator = concatMapM (\() -> generator) (yield ())
3432−
3433−-- | Like 'concatMap' but uses an 'Unfold' for stream generation. Unlike
3434−-- 'concatMap' this can fuse the 'Unfold' code with the inner loop and
3435−-- therefore provide many times better performance.
3436−--
3437−-- @since 0.7.0
3438−{-# INLINE concatUnfold #-}
3439−concatUnfold ::(IsStream t, Monad m) => Unfold m a b -> t m a -> t m b
3440−concatUnfold u m = fromStreamD $ D.concatMapU u (toStreamD m)
3441−
3442−-- | Like 'concatUnfold' but interleaves the streams in the same way as
3443−-- 'interleave' behaves instead of appending them.
3444−--
3445−-- /Internal/
3446−{-# INLINE concatUnfoldInterleave #-}
3447−concatUnfoldInterleave ::(IsStream t, Monad m)
3448− => Unfold m a b -> t m a -> t m b
3449−concatUnfoldInterleave u m =
3450− fromStreamD $ D.concatUnfoldInterleave u (toStreamD m)
3451−
3452−-- | Like 'concatUnfold' but executes the streams in the same way as
3453−-- 'roundrobin'.
3454−--
3455−-- /Internal/
3456−{-# INLINE concatUnfoldRoundrobin #-}
3457−concatUnfoldRoundrobin ::(IsStream t, Monad m)
3458− => Unfold m a b -> t m a -> t m b
3459−concatUnfoldRoundrobin u m =
3460− fromStreamD $ D.concatUnfoldRoundrobin u (toStreamD m)
3461−
3462−-- XXX we can swap the order of arguments to gintercalate so that the
3463−-- definition of concatUnfold becomes simpler? The first stream should be
3464−-- infixed inside the second one. However, if we change the order in
3465−-- "interleave" as well similarly, then that will make it a bit unintuitive.
3466−--
3467−-- > concatUnfold unf str =
3468−-- > gintercalate unf str (UF.nilM (\_ -> return ())) (repeat ())
3469−--
3470−-- | 'interleaveInfix' followed by unfold and concat.
3471−--
3472−-- /Internal/
3473−{-# INLINE gintercalate #-}
3474−gintercalate
3475− :: (IsStream t, Monad m)
3476− => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
3477−gintercalate unf1 str1 unf2 str2 =
3478− D.fromStreamD $ D.gintercalate
3479− unf1 (D.toStreamD str1)
3480− unf2 (D.toStreamD str2)
3481−
3482−-- XXX The order of arguments in "intercalate" is consistent with the list
3483−-- intercalate but inconsistent with gintercalate and other stream interleaving
3484−-- combinators. We can change the order of the arguments in other combinators
3485−-- but then 'interleave' combinator may become a bit unintuitive because we
3486−-- will be starting with the second stream.
3487−
3488−-- > intercalate seed unf str = gintercalate unf str unf (repeatM seed)
3489−-- > intercalate a unf str = concatUnfold unf $ intersperse a str
3490−--
3491−-- | 'intersperse' followed by unfold and concat.
3492−--
3493−-- > unwords = intercalate " " UF.fromList
3494−--
3495−-- >>> intercalate " " UF.fromList ["abc", "def", "ghi"]
3496−-- > "abc def ghi"
3497−--
3498−-- /Internal/
3499−{-# INLINE intercalate #-}
3500−intercalate :: (IsStream t, Monad m)
3501− => b -> Unfold m b c -> t m b -> t m c
3502−intercalate seed unf str = D.fromStreamD $
3503− D.concatMapU unf $ D.intersperse seed (toStreamD str)
3504−
3505−-- > interpose x unf str = gintercalate unf str UF.identity (repeat x)
3506−--
3507−-- | Unfold the elements of a stream, intersperse the given element between the
3508−-- unfolded streams and then concat them into a single stream.
3509−--
3510−-- > unwords = S.interpose ' '
3511−--
3512−-- /Internal/
3513−{-# INLINE interpose #-}
3514−interpose :: (IsStream t, Monad m)
3515− => c -> Unfold m b c -> t m b -> t m c
3516−interpose x unf str =
3517− D.fromStreamD $ D.interpose (return x) unf (D.toStreamD str)
3518−
3519−-- | 'interleaveSuffix' followed by unfold and concat.
3520−--
3521−-- /Internal/
3522−{-# INLINE gintercalateSuffix #-}
3523−gintercalateSuffix
3524− :: (IsStream t, Monad m)
3525− => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
3526−gintercalateSuffix unf1 str1 unf2 str2 =
3527− D.fromStreamD $ D.gintercalateSuffix
3528− unf1 (D.toStreamD str1)
3529− unf2 (D.toStreamD str2)
3530−
3531−-- > intercalateSuffix seed unf str = gintercalateSuffix unf str unf (repeatM seed)
3532−-- > intercalateSuffix a unf str = concatUnfold unf $ intersperseSuffix a str
3533−--
3534−-- | 'intersperseSuffix' followed by unfold and concat.
3535−--
3536−-- > unlines = intercalateSuffix "\n" UF.fromList
3537−--
3538−-- >>> intercalate "\n" UF.fromList ["abc", "def", "ghi"]
3539−-- > "abc\ndef\nghi\n"
3540−--
3541−-- /Internal/
3542−{-# INLINE intercalateSuffix #-}
3543−intercalateSuffix :: (IsStream t, Monad m)
3544− => b -> Unfold m b c -> t m b -> t m c
3545−intercalateSuffix seed unf str = fromStreamD $ D.concatMapU unf
3546− $ D.intersperseSuffix (return seed) (D.toStreamD str)
3547−
3548−-- interposeSuffix x unf str = gintercalateSuffix unf str UF.identity (repeat x)
3549−--
3550−-- | Unfold the elements of a stream, append the given element after each
3551−-- unfolded stream and then concat them into a single stream.
3552−--
3553−-- > unlines = S.interposeSuffix '\n'
3554−--
3555−-- /Internal/
3556−{-# INLINE interposeSuffix #-}
3557−interposeSuffix :: (IsStream t, Monad m)
3558− => c -> Unfold m b c -> t m b -> t m c
3559−interposeSuffix x unf str =
3560− D.fromStreamD $ D.interposeSuffix (return x) unf (D.toStreamD str)
3561−
3562−------------------------------------------------------------------------------
3563−-- Flattening Trees
3564−------------------------------------------------------------------------------
3565−
3566−-- | Like 'iterateM' but iterates after mapping a stream generator on the
3567−-- output.
3568−--
3569−-- Yield an input element in the output stream, map a stream generator on it
3570−-- and then do the same on the resulting stream. This can be used for a depth
3571−-- first traversal of a tree like structure.
3572−--
3573−-- Note that 'iterateM' is a special case of 'iterateMapWith':
3574−--
3575−-- @
3576−-- iterateM f = iterateMapWith serial (yieldM . f) . yieldM
3577−-- @
3578−--
3579−-- It can be used to traverse a tree structure. For example, to list a
3580−-- directory tree:
3581−--
3582−-- @
3583−-- Stream.iterateMapWith Stream.serial
3584−-- (either Dir.toEither (const nil))
3585−-- (yield (Left "tmp"))
3586−-- @
3587−--
3588−-- /Internal/
3589−--
3590−{-# INLINE iterateMapWith #-}
3591−iterateMapWith
3592− :: IsStream t
3593− => (t m a -> t m a -> t m a)
3594− -> (a -> t m a)
3595− -> t m a
3596− -> t m a
3597−iterateMapWith combine f = concatMapWith combine go
3598− where
3599− go x = yield x `combine` concatMapWith combine go (f x)
3600−
3601−{-
3602−{-# INLINE iterateUnfold #-}
3603−iterateUnfold :: (IsStream t, MonadAsync m)
3604− => Unfold m a a -> t m a -> t m a
3605−iterateUnfold unf xs = undefined
3606−-}
3607−
3608−------------------------------------------------------------------------------
3609−-- Flattening Graphs
3610−------------------------------------------------------------------------------
3611−
3612−-- To traverse graphs we need a state to be carried around in the traversal.
3613−-- For example, we can use a hashmap to store the visited status of nodes.
3614−
3615−-- | Like 'iterateMap' but carries a state in the stream generation function.
3616−-- This can be used to traverse graph like structures, we can remember the
3617−-- visited nodes in the state to avoid cycles.
3618−--
3619−-- Note that a combination of 'iterateMap' and 'usingState' can also be used to
3620−-- traverse graphs. However, this function provides a more localized state
3621−-- instead of using a global state.
3622−--
3623−-- See also: 'mfix'
3624−--
3625−-- /Internal/
3626−--
3627−{-# INLINE iterateSmapMWith #-}
3628−iterateSmapMWith
3629− :: (IsStream t, Monad m)
3630− => (t m a -> t m a -> t m a)
3631− -> (b -> a -> m (b, t m a))
3632− -> m b
3633− -> t m a
3634− -> t m a
3635−iterateSmapMWith combine f initial stream =
3636− concatMap (\b -> concatMapWith combine (go b) stream) (yieldM initial)
3637−
3638− where
3639−
3640− go b a = yield a `combine` feedback b a
3641−
3642− feedback b a =
3643− concatMap
3644− (\(b1, s) -> concatMapWith combine (go b1) s)
3645− (yieldM $ f b a)
3646−
3647−------------------------------------------------------------------------------
3648−-- Either streams
3649−------------------------------------------------------------------------------
3650−
3651−-- | Discard 'Right's and unwrap 'Left's in an 'Either' stream.
3652−--
3653−-- /Internal/
3654−--
3655−lefts :: (IsStream t, Monad m, Functor (t m)) => t m (Either a b) -> t m a
3656−lefts = fmap (fromLeft undefined) . filter isLeft
3657−
3658−-- | Discard 'Left's and unwrap 'Right's in an 'Either' stream.
3659−--
3660−-- /Internal/
3661−--
3662−rights :: (IsStream t, Monad m, Functor (t m)) => t m (Either a b) -> t m b
3663−rights = fmap (fromRight undefined) . filter isRight
3664−
3665−-- | In an 'Either' stream iterate on 'Left's. This is a special case of
3666−-- 'iterateMapWith':
3667−--
3668−-- @
3669−-- iterateMapLeftsWith combine f = iterateMapWith combine (either f (const nil))
3670−-- @
3671−--
3672−-- To traverse a directory tree:
3673−--
3674−-- @
3675−-- iterateMapLeftsWith serial Dir.toEither (yield (Left "tmp"))
3676−-- @
3677−--
3678−-- /Internal/
3679−--
3680−{-# INLINE iterateMapLeftsWith #-}
3681−iterateMapLeftsWith
3682− :: IsStream t
3683− => (t m (Either a b) -> t m (Either a b) -> t m (Either a b))
3684− -> (a -> t m (Either a b))
3685− -> t m (Either a b)
3686− -> t m (Either a b)
3687−iterateMapLeftsWith combine f = iterateMapWith combine (either f (const K.nil))
3688−
3689−------------------------------------------------------------------------------
3690−-- Folding/Parsing chunks in a stream
3691−------------------------------------------------------------------------------
3692−
3693−-- Splitting operations that take a predicate and a Fold can be
3694−-- expressed using parseMany. Operations like chunksOf, intervalsOf, split*,
3695−-- can be expressed using parseMany when used with an appropriate Parser.
3696−--
3697−-- XXX We need takeGE/takeBetween to implement "some" using "many".
3698−
3699−-- | Apply a 'Fold' repeatedly on a stream and emit the parsed values in the
3700−-- output stream.
3701−--
3702−-- This is the streaming dual of the 'Streamly.Internal.Data.Fold.many'
3703−-- parse combinator.
3704−--
3705−-- >>> f = Fold.ltake 2 Fold.sum
3706−-- >>> Stream.toList $ Stream.foldMany f $ Stream.fromList [1..10]
3707−-- > [3,7,11,15,19]
3708−--
3709−-- >>> f = Fold.sliceEndWith Fold.toList
3710−-- >>> Stream.toList $ Stream.foldMany f $ Stream.fromList "hello\nworld"
3711−-- > ["hello\n","world"]
3712−--
3713−-- /Internal/
3714−--
3715−{-# INLINE foldMany #-}
3716−foldMany
3717− :: (IsStream t, Monad m)
3718− => Fold m a b
3719− -> t m a
3720− -> t m b
3721−foldMany f m = D.fromStreamD $ D.foldMany f (D.toStreamD m)
3722−
3723−-- | Apply a stream of folds to an input stream and emit the results in the
3724−-- output stream.
3725−--
3726−-- /Internal/
3727−--
3728−{-# INLINE foldSequence #-}
3729−foldSequence
3730− :: -- (IsStream t, Monad m) =>
3731− t m (Fold m a b)
3732− -> t m a
3733− -> t m b
3734−foldSequence _f _m = undefined
3735−
3736−-- | Iterate a fold generator on a stream. The initial value @b@ is used to
3737−-- generate the first fold, the fold is applied on the stream and the result of
3738−-- the fold is used to generate the next fold and so on.
3739−--
3740−-- >>> f x = Fold.ltake 2 (Fold.mconcatTo x)
3741−-- >>> s = Stream.map Sum $ Stream.fromList [1..10]
3742−-- >>> Stream.toList $ Stream.map getSum $ Stream.foldIterate f 0 s
3743−-- > [3,10,21,36,55,55]
3744−--
3745−-- This is the streaming equivalent of monad like sequenced application of
3746−-- folds where next fold is dependent on the previous fold.
3747−--
3748−-- /Internal/
3749−--
3750−{-# INLINE foldIterate #-}
3751−foldIterate
3752− :: -- (IsStream t, Monad m) =>
3753− (b -> Fold m a b)
3754− -> b
3755− -> t m a
3756− -> t m b
3757−foldIterate _f _i _m = undefined
3758−-- D.fromStreamD $ D.foldIterate f i (D.toStreamD m)
3759−
3760−-- | Apply a 'Parser' repeatedly on a stream and emit the parsed values in the
3761−-- output stream.
3762−--
3763−-- This is the streaming equivalent of the 'Streamly.Internal.Data.Parser.many'
3764−-- parse combinator.
3765−--
3766−-- >>> S.toList $ S.parseMany (PR.take 2 $ PR.fromFold FL.sum) $ S.fromList [1..10]
3767−-- > [3,7,11,15,19]
3768−--
3769−-- >>> S.toList $ S.parseMany (PR.line FL.toList) $ S.fromList "hello\nworld"
3770−-- > ["hello\n","world"]
3771−--
3772−-- /Internal/
3773−--
3774−{-# INLINE parseMany #-}
3775−parseMany
3776− :: (IsStream t, MonadThrow m)
3777− => Parser m a b
3778− -> t m a
3779− -> t m b
3780−parseMany p m =
3781− D.fromStreamD $ D.parseMany (PRK.fromParserK p) (D.toStreamD m)
3782−
3783−{-# INLINE parseManyD #-}
3784−parseManyD
3785− :: (IsStream t, MonadThrow m)
3786− => PRD.Parser m a b
3787− -> t m a
3788− -> t m b
3789−parseManyD p m =
3790− D.fromStreamD $ D.parseMany p (D.toStreamD m)
3791−
3792−-- | Apply a stream of parsers to an input stream and emit the results in the
3793−-- output stream.
3794−--
3795−-- /Internal/
3796−--
3797−{-# INLINE parseSequence #-}
3798−parseSequence
3799− :: -- (IsStream t, Monad m) =>
3800− t m (Parser m a b)
3801− -> t m a
3802− -> t m b
3803−parseSequence _f _m = undefined
3804−
3805−-- | @parseManyTill collect test stream@ tries the parser @test@ on the input,
3806−-- if @test@ fails it backtracks and tries @collect@, after @collect@ succeeds
3807−-- @test@ is tried again and so on. The parser stops when @test@ succeeds. The
3808−-- output of @test@ is discarded and the output of @collect@ is emitted in the
3809−-- output stream. The parser fails if @collect@ fails.
3810−--
3811−-- /Unimplemented/
3812−--
3813−{-# INLINE parseManyTill #-}
3814−parseManyTill ::
3815− -- (IsStream t, MonadThrow m) =>
3816− Parser m a b
3817− -> Parser m a x
3818− -> t m a
3819− -> t m b
3820−parseManyTill = undefined
3821−
3822−-- | Iterate a parser generating function on a stream. The initial value @b@ is
3823−-- used to generate the first parser, the parser is applied on the stream and
3824−-- the result is used to generate the next parser and so on.
3825−--
3826−-- >>> S.toList $ S.map getSum $ S.parseIterate (\b -> PR.take 2 (FL.mconcatTo b)) 0 $ S.map Sum $ S.fromList [1..10]
3827−-- > [3,10,21,36,55,55]
3828−--
3829−-- This is the streaming equivalent of monad like sequenced application of
3830−-- parsers where next parser is dependent on the previous parser.
3831−--
3832−-- /Internal/
3833−--
3834−{-# INLINE parseIterate #-}
3835−parseIterate
3836− :: (IsStream t, MonadThrow m)
3837− => (b -> Parser m a b)
3838− -> b
3839− -> t m a
3840− -> t m b
3841−parseIterate f i m = D.fromStreamD $
3842− D.parseIterate (PRK.fromParserK . f) i (D.toStreamD m)
3843−
3844−------------------------------------------------------------------------------
3845−-- Grouping/Splitting
3846−------------------------------------------------------------------------------
3847−
3848−------------------------------------------------------------------------------
3849−-- Grouping without looking at elements
3850−------------------------------------------------------------------------------
3851−--
3852−------------------------------------------------------------------------------
3853−-- Binary APIs
3854−------------------------------------------------------------------------------
3855−--
3856−
3857−------------------------------------------------------------------------------
3858−-- N-ary APIs
3859−------------------------------------------------------------------------------
3860−
3861−------------------------------------------------------------------------------
3862−-- Generalized grouping
3863−------------------------------------------------------------------------------
3864−
3865−-- This combinator is the most general grouping combinator and can be used to
3866−-- implement all other grouping combinators.
3867−--
3868−-- XXX check if this can implement the splitOn combinator i.e. we can slide in
3869−-- new elements, slide out old elements and incrementally compute the hash.
3870−-- Also, can we implement the windowed classification combinators using this?
3871−--
3872−-- In fact this is a parse. Instead of using a special return value in the fold
3873−-- we are using a mapping function.
3874−--
3875−-- Note that 'scanl'' (usually followed by a map to extract the desired value
3876−-- from the accumulator) can be used to realize many implementations e.g. a
3877−-- sliding window implementation. A scan followed by a mapMaybe is also a good
3878−-- pattern to express many problems where we want to emit a filtered output and
3879−-- not emit an output on every input.
3880−--
3881−-- Passing on of the initial accumulator value to the next fold is equivalent
3882−-- to returning the leftover concept.
3883−
3884−{-
3885−-- | @groupScan splitter fold stream@ folds the input stream using @fold@.
3886−-- @splitter@ is applied on the accumulator of the fold every time an item is
3887−-- consumed by the fold. The fold continues until @splitter@ returns a 'Just'
3888−-- value. A 'Just' result from the @splitter@ specifies a result to be emitted
3889−-- in the output stream and the initial value of the accumulator for the next
3890−-- group's fold. This allows us to control whether to start fresh for the next
3891−-- fold or to continue from the previous fold's output.
3892−--
3893−{-# INLINE groupScan #-}
3894−groupScan
3895− :: (IsStream t, Monad m)
3896− => (x -> m (Maybe (b, x))) -> Fold m a x -> t m a -> t m b
3897−groupScan split fold m = undefined
3898−-}
3899−
3900−-- | Group the input stream into groups of @n@ elements each and then fold each
3901−-- group using the provided fold function.
3902−--
3903−-- >> S.toList $ S.chunksOf 2 FL.sum (S.enumerateFromTo 1 10)
3904−-- > [3,7,11,15,19]
3905−--
3906−-- This can be considered as an n-fold version of 'ltake' where we apply
3907−-- 'ltake' repeatedly on the leftover stream until the stream exhausts.
3908−--
3909−-- @since 0.7.0
3910−{-# INLINE chunksOf #-}
3911−chunksOf
3912− :: (IsStream t, Monad m)
3913− => Int -> Fold m a b -> t m a -> t m b
3914−chunksOf n f = foldMany (FL.ltake n f)
3915−
3916−-- |
3917−--
3918−-- /Internal/
3919−{-# INLINE chunksOf2 #-}
3920−chunksOf2
3921− :: (IsStream t, Monad m)
3922− => Int -> m c -> Fold2 m c a b -> t m a -> t m b
3923−chunksOf2 n action f m = D.fromStreamD $ D.groupsOf2 n action f (D.toStreamD m)
3924−
3925−-- | @arraysOf n stream@ groups the elements in the input stream into arrays of
3926−-- @n@ elements each.
3927−--
3928−-- Same as the following but may be more efficient:
3929−--
3930−-- > arraysOf n = S.chunksOf n (A.writeN n)
3931−--
3932−-- /Internal/
3933−{-# INLINE arraysOf #-}
3934−arraysOf :: (IsStream t, MonadIO m, Storable a)
3935− => Int -> t m a -> t m (Array a)
3936−arraysOf n = chunksOf n (writeNUnsafe n)
3937−
3938−-- XXX we can implement this by repeatedly applying the 'lrunFor' fold.
3939−-- XXX add this example after fixing the serial stream rate control
3940−-- >>> S.toList $ S.take 5 $ intervalsOf 1 FL.sum $ constRate 2 $ S.enumerateFrom 1
3941−-- > [3,7,11,15,19]
3942−--
3943−-- | Group the input stream into windows of @n@ second each and then fold each
3944−-- group using the provided fold function.
3945−--
3946−-- @since 0.7.0
3947−{-# INLINE intervalsOf #-}
3948−intervalsOf
3949− :: (IsStream t, MonadAsync m)
3950− => Double -> Fold m a b -> t m a -> t m b
3951−intervalsOf n f xs =
3952− splitWithSuffix isNothing (FL.lcatMaybes f)
3953− (interjectSuffix n (return Nothing) (Serial.map Just xs))
668+fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> SerialT m a
669+fromCallback setCallback = concatM $ do
670+ (callback, stream) <- D.newCallbackStream
671+ setCallback callback
672+ return stream
3954673
3955674------------------------------------------------------------------------------
3956−-- N-ary APIs
675+-- Specialized folds
3957676------------------------------------------------------------------------------
3958677
3959−-- | @groupsBy cmp f $ S.fromList [a,b,c,...]@ assigns the element @a@ to the
3960−-- first group, if @b \`cmp` a@ is 'True' then @b@ is also assigned to the same
3961−-- group. If @c \`cmp` a@ is 'True' then @c@ is also assigned to the same
3962−-- group and so on. When the comparison fails a new group is started. Each
3963−-- group is folded using the fold @f@ and the result of the fold is emitted in
3964−-- the output stream.
678+-- |
679+-- > drainN n = drain . take n
680+-- > drainN n = fold (Fold.ltake n Fold.drain)
3965681--
3966−-- >>> S.toList $ S.groupsBy (>) FL.toList $ S.fromList [1,3,7,0,2,5]
3967−-- > [[1,3,7],[0,2,5]]
682+-- Run maximum up to @n@ iterations of a stream.
3968683--
3969684-- @since 0.7.0
3970−{-# INLINE groupsBy #-}
3971−groupsBy
3972− :: (IsStream t, Monad m)
3973− => (a -> a -> Bool)
3974− -> Fold m a b
3975− -> t m a
3976− -> t m b
3977−groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
3978−
3979−-- | Unlike @groupsBy@ this function performs a rolling comparison of two
3980−-- successive elements in the input stream. @groupsByRolling cmp f $ S.fromList
3981−-- [a,b,c,...]@ assigns the element @a@ to the first group, if @a \`cmp` b@ is
3982−-- 'True' then @b@ is also assigned to the same group. If @b \`cmp` c@ is
3983−-- 'True' then @c@ is also assigned to the same group and so on. When the
3984−-- comparison fails a new group is started. Each group is folded using the fold
3985−-- @f@.
685+{-# INLINE drainN #-}
686+drainN :: Monad m => Int -> SerialT m a -> m ()
687+drainN n = drain . take n
688+
689+-- |
690+-- > runN n = runStream . take n
3986691--
3987−-- >>> S.toList $ S.groupsByRolling (\a b -> a + 1 == b) FL.toList $ S.fromList [1,2,3,7,8,9]
3988−-- > [[1,2,3],[7,8,9]]
692+-- Run maximum up to @n@ iterations of a stream.
3989693--
3990−-- @since 0.7.0
3991−{-# INLINE groupsByRolling #-}
3992−groupsByRolling
3993− :: (IsStream t, Monad m)
3994− => (a -> a -> Bool)
3995− -> Fold m a b
3996− -> t m a
3997− -> t m b
3998−groupsByRolling cmp f m = D.fromStreamD $ D.groupsRollingBy cmp f (D.toStreamD m)
694+-- @since 0.6.0
695+{-# DEPRECATED runN "Please use \"drainN\" instead" #-}
696+{-# INLINE runN #-}
697+runN :: Monad m => Int -> SerialT m a -> m ()
698+runN = drainN
3999699
4000700-- |
4001−-- > groups = groupsBy (==)
4002−-- > groups = groupsByRolling (==)
4003−--
4004−-- Groups contiguous spans of equal elements together in individual groups.
701+-- > drainWhile p = drain . takeWhile p
702+-- > drainWhile p = fold (Fold.sliceSepBy (not . p) Fold.drain)
4005703--
4006−-- >>> S.toList $ S.groups FL.toList $ S.fromList [1,1,2,2]
4007−-- > [[1,1],[2,2]]
704+-- Run a stream as long as the predicate holds true.
4008705--
4009706-- @since 0.7.0
4010−{-# INLINE groups #-}
4011−groups :: (IsStream t, Monad m, Eq a) => Fold m a b -> t m a -> t m b
4012−groups = groupsBy (==)
707+{-# INLINE drainWhile #-}
708+drainWhile :: Monad m => (a -> Bool) -> SerialT m a -> m ()
709+drainWhile p = drain . takeWhile p
710+
711+-- |
712+-- > runWhile p = runStream . takeWhile p
713+--
714+-- Run a stream as long as the predicate holds true.
715+--
716+-- @since 0.6.0
717+{-# DEPRECATED runWhile "Please use \"drainWhile\" instead" #-}
718+{-# INLINE runWhile #-}
719+runWhile :: Monad m => (a -> Bool) -> SerialT m a -> m ()
720+runWhile = drainWhile
4013721
4014722------------------------------------------------------------------------------
4015−-- N-ary split on a predicate
723+-- Transformation by Inserting
4016724------------------------------------------------------------------------------
4017725
4018−-- TODO: Use a Splitter configuration similar to the "split" package to make it
4019−-- possible to express all splitting combinations. In general, we can have
4020−-- infix/suffix/prefix/condensing of separators, dropping both leading/trailing
4021−-- separators. We can have a single split operation taking the splitter config
4022−-- as argument.
4023−
4024−-- | Split on an infixed separator element, dropping the separator. Splits the
4025−-- stream on separator elements determined by the supplied predicate, separator
4026−-- is considered as infixed between two segments, if one side of the separator
4027−-- is missing then it is parsed as an empty stream. The supplied 'Fold' is
4028−-- applied on the split segments. With '-' representing non-separator elements
4029−-- and '.' as separator, 'splitOn' splits as follows:
726+-- | Intersperse a monadic action into the input stream after every @n@
727+-- seconds.
4030728--
4031729-- @
4032−-- "--.--" => "--" "--"
4033−-- "--." => "--" ""
4034−-- ".--" => "" "--"
730+-- > S.drain $ S.interjectSuffix 1 (putChar ',') $ S.mapM (\\x -> threadDelay 1000000 >> putChar x) $ S.fromList "hello"
731+-- "h,e,l,l,o"
4035732-- @
4036733--
4037−-- @splitOn (== x)@ is an inverse of @intercalate (S.yield x)@
4038−--
4039−-- Let's use the following definition for illustration:
4040−--
4041−-- > splitOn' p xs = S.toList $ S.splitOn p (FL.toList) (S.fromList xs)
4042−--
4043−-- >>> splitOn' (== '.') ""
4044−-- [""]
4045−--
4046−-- >>> splitOn' (== '.') "."
4047−-- ["",""]
734+-- /Internal/
735+{-# INLINE interjectSuffix #-}
736+interjectSuffix
737+ :: (IsStream t, MonadAsync m)
738+ => Double -> m a -> t m a -> t m a
739+interjectSuffix n f xs = xs `Par.parallelFst` repeatM timed
740+ where timed = liftIO (threadDelay (round $ n * 1000000)) >> f
741+
742+-------------------------------------------------------------------------------
743+-- Indexing
744+-------------------------------------------------------------------------------
745+
746+-- Note: The timestamp stream must be the second stream in the zip so that the
747+-- timestamp is generated after generating the stream element and not before.
748+-- If we do not do that then the following example will generate the same
749+-- timestamp for first two elements:
4048750--
4049−-- >>> splitOn' (== '.') ".a"
4050−-- > ["","a"]
751+-- S.mapM_ print $ S.timestamped $ S.delay $ S.enumerateFromTo 1 3
4051752--
4052−-- >>> splitOn' (== '.') "a."
4053−-- > ["a",""]
753+-- | Pair each element in a stream with an absolute timestamp, using a clock of
754+-- specified granularity. The timestamp is generated just before the element
755+-- is consumed.
4054756--
4055−-- >>> splitOn' (== '.') "a.b"
4056−-- > ["a","b"]
757+-- @
758+-- >>> S.mapM_ print $ S.timestampWith 0.01 $ S.delay 1 $ S.enumerateFromTo 1 3
759+-- @
4057760--
4058−-- >>> splitOn' (== '.') "a..b"
4059−-- > ["a","","b"]
761+-- /Internal/
4060762--
4061−-- @since 0.7.0
763+{-# INLINE timestampWith #-}
764+timestampWith :: (IsStream t, MonadAsync m, Functor (t m))
765+ => Double -> t m a -> t m (AbsTime, a)
766+timestampWith g stream = Z.zipWith (flip (,)) stream (absTimesWith g)
4062767
4063−-- This can be considered as an n-fold version of 'breakOn' where we apply
4064−-- 'breakOn' successively on the input stream, dropping the first element
4065−-- of the second segment after each break.
768+-- TBD: check performance vs a custom implementation without using zipWith.
4066769--
4067−{-# INLINE splitOn #-}
4068−splitOn
4069− :: (IsStream t, Monad m)
4070− => (a -> Bool) -> Fold m a b -> t m a -> t m b
4071−splitOn predicate f = foldMany (FL.sliceSepBy predicate f)
770+-- /Internal/
771+--
772+{-# INLINE timestamped #-}
773+timestamped :: (IsStream t, MonadAsync m, Functor (t m))
774+ => t m a -> t m (AbsTime, a)
775+timestamped = timestampWith 0.01
4072776
4073−-- | Like 'splitOn' but the separator is considered as suffixed to the segments
4074−-- in the stream. A missing suffix at the end is allowed. A separator at the
4075−-- beginning is parsed as empty segment. With '-' representing elements and
4076−-- '.' as separator, 'splitOnSuffix' splits as follows:
777+-- | Pair each element in a stream with relative times starting from 0, using a
778+-- clock with the specified granularity. The time is measured just before the
779+-- element is consumed.
4077780--
4078781-- @
4079−-- "--.--." => "--" "--"
4080−-- "--.--" => "--" "--"
4081−-- ".--." => "" "--"
782+-- >>> S.mapM_ print $ S.timeIndexWith 0.01 $ S.delay 1 $ S.enumerateFromTo 1 3
4082783-- @
4083784--
4084−-- > splitOnSuffix' p xs = S.toList $ S.splitSuffixBy p (FL.toList) (S.fromList xs)
4085−--
4086−-- >>> splitOnSuffix' (== '.') ""
4087−-- []
4088−--
4089−-- >>> splitOnSuffix' (== '.') "."
4090−-- [""]
4091−--
4092−-- >>> splitOnSuffix' (== '.') "a"
4093−-- ["a"]
4094−--
4095−-- >>> splitOnSuffix' (== '.') ".a"
4096−-- > ["","a"]
4097−--
4098−-- >>> splitOnSuffix' (== '.') "a."
4099−-- > ["a"]
4100−--
4101−-- >>> splitOnSuffix' (== '.') "a.b"
4102−-- > ["a","b"]
4103−--
4104−-- >>> splitOnSuffix' (== '.') "a.b."
4105−-- > ["a","b"]
4106−--
4107−-- >>> splitOnSuffix' (== '.') "a..b.."
4108−-- > ["a","","b",""]
4109−--
4110−-- > lines = splitOnSuffix (== '\n')
785+-- /Internal/
4111786--
4112−-- @since 0.7.0
787+{-# INLINE timeIndexWith #-}
788+timeIndexWith :: (IsStream t, MonadAsync m, Functor (t m))
789+ => Double -> t m a -> t m (RelTime64, a)
790+timeIndexWith g stream = Z.zipWith (flip (,)) stream (relTimesWith g)
4113791
4114−-- This can be considered as an n-fold version of 'breakPost' where we apply
4115−-- 'breakPost' successively on the input stream, dropping the first element
4116−-- of the second segment after each break.
4117−--
4118−{-# INLINE splitOnSuffix #-}
4119−splitOnSuffix
4120− :: (IsStream t, Monad m)
4121− => (a -> Bool) -> Fold m a b -> t m a -> t m b
4122−splitOnSuffix predicate f m =
4123− D.fromStreamD $ D.foldMany1 (FL.sliceSepBy predicate f) (D.toStreamD m)
4124−
4125−-- | Like 'splitOn' after stripping leading, trailing, and repeated separators.
4126−-- Therefore, @".a..b."@ with '.' as the separator would be parsed as
4127−-- @["a","b"]@. In other words, its like parsing words from whitespace
4128−-- separated text.
4129−--
4130−-- > wordsBy' p xs = S.toList $ S.wordsBy p (FL.toList) (S.fromList xs)
4131−--
4132−-- >>> wordsBy' (== ',') ""
4133−-- > []
4134−--
4135−-- >>> wordsBy' (== ',') ","
4136−-- > []
792+-- | Pair each element in a stream with relative times starting from 0, using a
793+-- 10 ms granularity clock. The time is measured just before the element is
794+-- consumed.
4137795--
4138−-- >>> wordsBy' (== ',') ",a,,b,"
4139−-- > ["a","b"]
796+-- @
797+-- >>> S.mapM_ print $ S.timeIndexed $ S.delay 1 $ S.enumerateFromTo 1 3
798+-- (RelTime64 (NanoSecond64 0),1)
799+-- (RelTime64 (NanoSecond64 996239000),2)
800+-- (RelTime64 (NanoSecond64 1996712000),3)
801+-- @
4140802--
4141−-- > words = wordsBy isSpace
803+-- /Internal/
4142804--
4143−-- @since 0.7.0
805+{-# INLINE timeIndexed #-}
806+timeIndexed :: (IsStream t, MonadAsync m, Functor (t m))
807+ => t m a -> t m (RelTime64, a)
808+timeIndexed = timeIndexWith 0.01
4144809
4145−-- It is equivalent to splitting in any of the infix/prefix/suffix styles
4146−-- followed by removal of empty segments.
4147−{-# INLINE wordsBy #-}
4148−wordsBy
4149− :: (IsStream t, Monad m)
4150− => (a -> Bool) -> Fold m a b -> t m a -> t m b
4151−wordsBy predicate f m =
4152− D.fromStreamD $ D.wordsBy predicate f (D.toStreamD m)
810+------------------------------------------------------------------------------
811+-- Searching
812+------------------------------------------------------------------------------
4153813
4154−-- | Like 'splitOnSuffix' but keeps the suffix attached to the resulting
4155−-- splits.
4156−--
4157−-- > splitWithSuffix' p xs = S.toList $ S.splitWithSuffix p (FL.toList) (S.fromList xs)
4158−--
4159−-- >>> splitWithSuffix' (== '.') ""
4160−-- []
4161−--
4162−-- >>> splitWithSuffix' (== '.') "."
4163−-- ["."]
4164−--
4165−-- >>> splitWithSuffix' (== '.') "a"
4166−-- ["a"]
4167−--
4168−-- >>> splitWithSuffix' (== '.') ".a"
4169−-- > [".","a"]
4170−--
4171−-- >>> splitWithSuffix' (== '.') "a."
4172−-- > ["a."]
4173−--
4174−-- >>> splitWithSuffix' (== '.') "a.b"
4175−-- > ["a.","b"]
4176−--
4177−-- >>> splitWithSuffix' (== '.') "a.b."
4178−-- > ["a.","b."]
814+-- | Returns the first index that satisfies the given predicate.
4179815--
4180−-- >>> splitWithSuffix' (== '.') "a..b.."
4181−-- > ["a.",".","b.","."]
816+-- > findIndex = fold Fold.findIndex
4182817--
4183−-- @since 0.7.0
818+-- @since 0.5.0
819+{-# INLINE findIndex #-}
820+findIndex :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe Int)
821+findIndex p = head . findIndices p
4184822
4185−-- This can be considered as an n-fold version of 'breakPost' where we apply
4186−-- 'breakPost' successively on the input stream.
823+-- | Returns the first index where a given value is found in the stream.
4187824--
4188−{-# INLINE splitWithSuffix #-}
4189−splitWithSuffix
4190− :: (IsStream t, Monad m)
4191− => (a -> Bool) -> Fold m a b -> t m a -> t m b
4192−splitWithSuffix predicate f m =
4193− D.fromStreamD $ D.foldMany1 (FL.sliceEndWith predicate f) (D.toStreamD m)
825+-- > elemIndex a = findIndex (== a)
826+--
827+-- @since 0.5.0
828+{-# INLINE elemIndex #-}
829+elemIndex :: (Monad m, Eq a) => a -> SerialT m a -> m (Maybe Int)
830+elemIndex a = findIndex (== a)
4194831
4195832------------------------------------------------------------------------------
4196−-- Split on a delimiter sequence
833+-- Substreams
4197834------------------------------------------------------------------------------
4198835
4199−-- Int list examples for splitOn:
4200−--
4201−-- >>> splitList [] [1,2,3,3,4]
4202−-- > [[1],[2],[3],[3],[4]]
4203−--
4204−-- >>> splitList [5] [1,2,3,3,4]
4205−-- > [[1,2,3,3,4]]
4206−--
4207−-- >>> splitList [1] [1,2,3,3,4]
4208−-- > [[],[2,3,3,4]]
836+-- | Returns 'True' if the first stream is a suffix of the second. A stream is
837+-- considered a suffix of itself.
4209838--
4210−-- >>> splitList [4] [1,2,3,3,4]
4211−-- > [[1,2,3,3],[]]
839+-- @
840+-- > S.isSuffixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
841+-- True
842+-- @
4212843--
4213−-- >>> splitList [2] [1,2,3,3,4]
4214−-- > [[1],[3,3,4]]
844+-- Space: @O(n)@, buffers entire input stream and the suffix.
4215845--
4216−-- >>> splitList [3] [1,2,3,3,4]
4217−-- > [[1,2],[],[4]]
846+-- /Internal/
4218847--
4219−-- >>> splitList [3,3] [1,2,3,3,4]
4220−-- > [[1,2],[4]]
848+-- /Suboptimal/ - Help wanted.
4221849--
4222−-- >>> splitList [1,2,3,3,4] [1,2,3,3,4]
4223−-- > [[],[]]
850+{-# INLINE isSuffixOf #-}
851+isSuffixOf :: (Monad m, Eq a) => SerialT m a -> SerialT m a -> m Bool
852+isSuffixOf suffix stream = reverse suffix `isPrefixOf` reverse stream
4224853
4225−-- | Like 'splitOn' but the separator is a sequence of elements instead of a
4226−-- single element.
4227−--
4228−-- For illustration, let's define a function that operates on pure lists:
854+-- | Returns 'True' if the first stream is an infix of the second. A stream is
855+-- considered an infix of itself.
4229856--
4230857-- @
4231−-- splitOnSeq' pat xs = S.toList $ S.splitOnSeq (A.fromList pat) (FL.toList) (S.fromList xs)
858+-- > S.isInfixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
859+-- True
4232860-- @
4233861--
4234−-- >>> splitOnSeq' "" "hello"
4235−-- > ["h","e","l","l","o"]
4236−--
4237−-- >>> splitOnSeq' "hello" ""
4238−-- > [""]
4239−--
4240−-- >>> splitOnSeq' "hello" "hello"
4241−-- > ["",""]
4242−--
4243−-- >>> splitOnSeq' "x" "hello"
4244−-- > ["hello"]
4245−--
4246−-- >>> splitOnSeq' "h" "hello"
4247−-- > ["","ello"]
4248−--
4249−-- >>> splitOnSeq' "o" "hello"
4250−-- > ["hell",""]
4251−--
4252−-- >>> splitOnSeq' "e" "hello"
4253−-- > ["h","llo"]
4254−--
4255−-- >>> splitOnSeq' "l" "hello"
4256−-- > ["he","","o"]
4257−--
4258−-- >>> splitOnSeq' "ll" "hello"
4259−-- > ["he","o"]
4260−--
4261−-- 'splitOnSeq' is an inverse of 'intercalate'. The following law always holds:
4262−--
4263−-- > intercalate . splitOn == id
4264−--
4265−-- The following law holds when the separator is non-empty and contains none of
4266−-- the elements present in the input lists:
4267−--
4268−-- > splitOn . intercalate == id
862+-- Space: @O(n)@ worst case where @n@ is the length of the infix.
4269863--
4270864-- /Internal/
4271−
4272−-- XXX We can use a polymorphic vector implemented by Array# to represent the
4273−-- sequence, that way we can avoid the Storable constraint. If we still need
4274−-- Storable Array for performance, we can use a separate splitOnArray API for
4275−-- that. We can also have an API where the sequence itself is a lazy stream, so
4276−-- that we can search files in files for example.
4277−{-# INLINE splitOnSeq #-}
4278−splitOnSeq
4279− :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
4280− => Array a -> Fold m a b -> t m a -> t m b
4281−splitOnSeq patt f m = D.fromStreamD $ D.splitOnSeq patt f (D.toStreamD m)
4282−
4283−{-
4284−-- This can be implemented easily using Rabin Karp
4285−-- | Split on any one of the given patterns.
4286−{-# INLINE splitOnAny #-}
4287−splitOnAny
4288− :: (IsStream t, Monad m, Storable a, Integral a)
4289− => [Array a] -> Fold m a b -> t m a -> t m b
4290−splitOnAny subseq f m = undefined -- D.fromStreamD $ D.splitOnAny f subseq (D.toStreamD m)
4291−-}
4292−
4293−-- | Like 'splitSuffixBy' but the separator is a sequence of elements, instead
4294−-- of a predicate for a single element.
4295−--
4296−-- > splitOnSuffixSeq_ pat xs = S.toList $ S.splitOnSuffixSeq (A.fromList pat) (FL.toList) (S.fromList xs)
4297−--
4298−-- >>> splitOnSuffixSeq_ "." ""
4299−-- []
4300865--
4301−-- >>> splitOnSuffixSeq_ "." "."
4302−-- [""]
4303−--
4304−-- >>> splitOnSuffixSeq_ "." "a"
4305−-- ["a"]
4306−--
4307−-- >>> splitOnSuffixSeq_ "." ".a"
4308−-- > ["","a"]
4309−--
4310−-- >>> splitOnSuffixSeq_ "." "a."
4311−-- > ["a"]
4312−--
4313−-- >>> splitOnSuffixSeq_ "." "a.b"
4314−-- > ["a","b"]
4315−--
4316−-- >>> splitOnSuffixSeq_ "." "a.b."
4317−-- > ["a","b"]
4318−--
4319−-- >>> splitOnSuffixSeq_ "." "a..b.."
4320−-- > ["a","","b",""]
4321−--
4322−-- > lines = splitOnSuffixSeq "\n"
866+-- /Requires 'Storable' constraint/ - Help wanted.
4323867--
4324−-- 'splitOnSuffixSeq' is an inverse of 'intercalateSuffix'. The following law
4325−-- always holds:
868+{-# INLINE isInfixOf #-}
869+isInfixOf :: (MonadIO m, Eq a, Enum a, Storable a)
870+ => SerialT m a -> SerialT m a -> m Bool
871+isInfixOf infx stream = do
872+ arr <- fold A.write infx
873+ -- XXX can use breakOnSeq instead (when available)
874+ r <- null $ drop 1 $ splitOnSeq arr FL.drain stream
875+ return (not r)
876+
877+-- Note: If we want to return a Maybe value to know whether the
878+-- suffix/infix was present or not along with the stripped stream then
879+-- we need to buffer the whole input stream.
4326880--
4327−-- > intercalateSuffix . splitOnSuffixSeq == id
881+-- | Drops the given suffix from a stream. Returns 'Nothing' if the stream does
882+-- not end with the given suffix. Returns @Just nil@ when the suffix is the
883+-- same as the stream.
4328884--
4329−-- The following law holds when the separator is non-empty and contains none of
4330−-- the elements present in the input lists:
885+-- It may be more efficient to convert the stream to an Array and use
886+-- stripSuffix on that especially if the elements have a Storable or Prim
887+-- instance.
4331888--
4332−-- > splitSuffixOn . intercalateSuffix == id
889+-- Space: @O(n)@, buffers the entire input stream as well as the suffix
4333890--
4334891-- /Internal/
4335−{-# INLINE splitOnSuffixSeq #-}
4336−splitOnSuffixSeq
4337− :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
4338− => Array a -> Fold m a b -> t m a -> t m b
4339−splitOnSuffixSeq patt f m =
4340− D.fromStreamD $ D.splitOnSuffixSeq False patt f (D.toStreamD m)
892+{-# INLINE stripSuffix #-}
893+stripSuffix
894+ :: (Monad m, Eq a)
895+ => SerialT m a -> SerialT m a -> m (Maybe (SerialT m a))
896+stripSuffix m1 m2 = fmap reverse <$> stripPrefix (reverse m1) (reverse m2)
4341897
4342−{-
4343−-- | Like 'splitOn' but drops any empty splits.
4344−--
4345−{-# INLINE wordsOn #-}
4346−wordsOn
4347− :: (IsStream t, Monad m, Storable a, Eq a)
4348− => Array a -> Fold m a b -> t m a -> t m b
4349−wordsOn subseq f m = undefined -- D.fromStreamD $ D.wordsOn f subseq (D.toStreamD m)
4350−-}
898+------------------------------------------------------------------------------
899+-- Split on a delimiter sequence
900+------------------------------------------------------------------------------
4351901
4352902-- XXX use a non-monadic intersperse to remove the MonadAsync constraint.
4353903--
@@ -4390,276 +940,160 @@ splitBySeq
4390940splitBySeq patt f m =
4391941 intersperseM (fold f (A.toStream patt)) $ splitOnSeq patt f m
4392942
4393−-- | Like 'splitOnSuffixSeq' but keeps the suffix intact in the splits.
4394−--
4395−-- > splitWithSuffixSeq'_ pat xs = S.toList $ S.splitWithSuffixSeq (A.fromList pat) (FL.toList) (S.fromList xs)
4396−--
4397−-- >>> splitWithSuffixSeq' "." ""
4398−-- [""]
4399−--
4400−-- >>> splitWithSuffixSeq' "." "."
4401−-- ["."]
4402−--
4403−-- >>> splitWithSuffixSeq' "." "a"
4404−-- ["a"]
943+------------------------------------------------------------------------------
944+-- Flattening Trees
945+------------------------------------------------------------------------------
946+
947+-- | Like 'iterateM' but iterates after mapping a stream generator on the
948+-- output.
4405949--
4406−-- >>> splitWithSuffixSeq' "." ".a"
4407−-- > [".","a"]
950+-- Yield an input element in the output stream, map a stream generator on it
951+-- and then do the same on the resulting stream. This can be used for a depth
952+-- first traversal of a tree like structure.
4408953--
4409−-- >>> splitWithSuffixSeq' "." "a."
4410−-- > ["a."]
954+-- Note that 'iterateM' is a special case of 'iterateMapWith':
4411955--
4412−-- >>> splitWithSuffixSeq' "." "a.b"
4413−-- > ["a.","b"]
956+-- @
957+-- iterateM f = iterateMapWith serial (yieldM . f) . yieldM
958+-- @
4414959--
4415−-- >>> splitWithSuffixSeq' "." "a.b."
4416−-- > ["a.","b."]
960+-- It can be used to traverse a tree structure. For example, to list a
961+-- directory tree:
4417962--
4418−-- >>> splitWithSuffixSeq' "." "a..b.."
4419−-- > ["a.",".","b.","."]
963+-- @
964+-- Stream.iterateMapWith Stream.serial
965+-- (either Dir.toEither (const nil))
966+-- (yield (Left "tmp"))
967+-- @
4420968--
4421969-- /Internal/
4422−{-# INLINE splitWithSuffixSeq #-}
4423−splitWithSuffixSeq
4424− :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
4425− => Array a -> Fold m a b -> t m a -> t m b
4426−splitWithSuffixSeq patt f m =
4427− D.fromStreamD $ D.splitOnSuffixSeq True patt f (D.toStreamD m)
970+--
971+{-# INLINE iterateMapWith #-}
972+iterateMapWith
973+ :: IsStream t
974+ => (t m a -> t m a -> t m a)
975+ -> (a -> t m a)
976+ -> t m a
977+ -> t m a
978+iterateMapWith combine f = concatMapWith combine go
979+ where
980+ go x = yield x `combine` concatMapWith combine go (f x)
4428981
4429982{-
4430−-- This can be implemented easily using Rabin Karp
4431−-- | Split post any one of the given patterns.
4432−{-# INLINE splitOnSuffixSeqAny #-}
4433−splitOnSuffixSeqAny
4434− :: (IsStream t, Monad m, Storable a, Integral a)
4435− => [Array a] -> Fold m a b -> t m a -> t m b
4436−splitOnSuffixSeqAny subseq f m = undefined
4437− -- D.fromStreamD $ D.splitPostAny f subseq (D.toStreamD m)
983+{-# INLINE iterateUnfold #-}
984+iterateUnfold :: (IsStream t, MonadAsync m)
985+ => Unfold m a a -> t m a -> t m a
986+iterateUnfold unf xs = undefined
4438987-}
4439988
4440989------------------------------------------------------------------------------
4441−-- Nested Split
990+-- Flattening Graphs
4442991------------------------------------------------------------------------------
4443992
4444−-- | @splitInnerBy splitter joiner stream@ splits the inner containers @f a@ of
4445−-- an input stream @t m (f a)@ using the @splitter@ function. Container
4446−-- elements @f a@ are collected until a split occurs, then all the elements
4447−-- before the split are joined using the @joiner@ function.
993+-- To traverse graphs we need a state to be carried around in the traversal.
994+-- For example, we can use a hashmap to store the visited status of nodes.
995+
996+-- | Like 'iterateMap' but carries a state in the stream generation function.
997+-- This can be used to traverse graph like structures, we can remember the
998+-- visited nodes in the state to avoid cycles.
4448999--
4449−-- For example, if we have a stream of @Array Word8@, we may want to split the
4450−-- stream into arrays representing lines separated by '\n' byte such that the
4451−-- resulting stream after a split would be one array for each line.
1000+-- Note that a combination of 'iterateMap' and 'usingState' can also be used to
1001+-- traverse graphs. However, this function provides a more localized state
1002+-- instead of using a global state.
44521003--
4453−-- CAUTION! This is not a true streaming function as the container size after
4454−-- the split and merge may not be bounded.
1004+-- See also: 'mfix'
44551005--
44561006-- /Internal/
4457−{-# INLINE splitInnerBy #-}
4458−splitInnerBy
4459− :: (IsStream t, Monad m)
4460− => (f a -> m (f a, Maybe (f a))) -- splitter
4461− -> (f a -> f a -> m (f a)) -- joiner
4462− -> t m (f a)
4463− -> t m (f a)
4464−splitInnerBy splitter joiner xs =
4465− D.fromStreamD $ D.splitInnerBy splitter joiner $ D.toStreamD xs
4466−
4467−-- | Like 'splitInnerBy' but splits assuming the separator joins the segment in
4468−-- a suffix style.
44691007--
4470−-- /Internal/
4471−{-# INLINE splitInnerBySuffix #-}
4472−splitInnerBySuffix
4473− :: (IsStream t, Monad m, Eq (f a), Monoid (f a))
4474− => (f a -> m (f a, Maybe (f a))) -- splitter
4475− -> (f a -> f a -> m (f a)) -- joiner
4476− -> t m (f a)
4477− -> t m (f a)
4478−splitInnerBySuffix splitter joiner xs =
4479− D.fromStreamD $ D.splitInnerBySuffix splitter joiner $ D.toStreamD xs
4480−
4481−------------------------------------------------------------------------------
4482−-- Reorder in sequence
4483−------------------------------------------------------------------------------
4484−
4485−{-
4486−-- Buffer until the next element in sequence arrives. The function argument
4487−-- determines the difference in sequence numbers. This could be useful in
4488−-- implementing sequenced streams, for example, TCP reassembly.
4489−{-# INLINE reassembleBy #-}
4490−reassembleBy
1008+{-# INLINE iterateSmapMWith #-}
1009+iterateSmapMWith
44911010 :: (IsStream t, Monad m)
4492− => Fold m a b
4493− -> (a -> a -> Int)
1011+ => (t m a -> t m a -> t m a)
1012+ -> (b -> a -> m (b, t m a))
1013+ -> m b
44941014 -> t m a
4495− -> t m b
4496−reassembleBy = undefined
4497−-}
1015+ -> t m a
1016+iterateSmapMWith combine f initial stream =
1017+ concatMap (\b -> concatMapWith combine (go b) stream) (yieldM initial)
1018+
1019+ where
1020+
1021+ go b a = yield a `combine` feedback b a
1022+
1023+ feedback b a =
1024+ concatMap
1025+ (\(b1, s) -> concatMapWith combine (go b1) s)
1026+ (yieldM $ f b a)
44981027
44991028------------------------------------------------------------------------------
4500−-- Distributing
1029+-- Flattening Lists
45011030------------------------------------------------------------------------------
45021031
4503−-- | Tap the data flowing through a stream into a 'Fold'. For example, you may
4504−-- add a tap to log the contents flowing through the stream. The fold is used
4505−-- only for effects, its result is discarded.
4506−--
4507−-- @
4508−-- Fold m a b
4509−-- |
4510−-- -----stream m a ---------------stream m a-----
4511−--
4512−-- @
4513−--
4514−-- @
4515−-- > S.drain $ S.tap (FL.drainBy print) (S.enumerateFromTo 1 2)
4516−-- 1
4517−-- 2
4518−-- @
4519−--
4520−-- Compare with 'trace'.
4521−--
4522−-- @since 0.7.0
4523−{-# INLINE tap #-}
4524−tap :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> t m a
4525−tap f xs = D.fromStreamD $ D.tap f (D.toStreamD xs)
4526−
4527−-- | @tapOffsetEvery offset n@ taps every @n@th element in the stream
4528−-- starting at @offset@. @offset@ can be between @0@ and @n - 1@. Offset 0
4529−-- means start at the first element in the stream. If the offset is outside
4530−-- this range then @offset `mod` n@ is used as offset.
1032+-- | Given a stream value in the underlying monad, lift and join the underlying
1033+-- monad with the stream monad.
45311034--
45321035-- @
4533−-- >>> S.drain $ S.tapOffsetEvery 0 2 (FL.mapM print FL.toList) $ S.enumerateFromTo 0 10
4534−-- > [0,2,4,6,8,10]
1036+-- concatM = concat . yieldM
1037+-- concatM = concat . lift -- requires @(MonadTrans t)@
1038+-- concatM = join . lift -- requires @(MonadTrans t@, @Monad (t m))@
45351039-- @
45361040--
4537−-- /Internal/
4538−--
4539−{-# INLINE tapOffsetEvery #-}
4540−tapOffsetEvery :: (IsStream t, Monad m)
4541− => Int -> Int -> FL.Fold m a b -> t m a -> t m a
4542−tapOffsetEvery offset n f xs =
4543− D.fromStreamD $ D.tapOffsetEvery offset n f (D.toStreamD xs)
4544−
4545−-- | Redirect a copy of the stream to a supplied fold and run it concurrently
4546−-- in an independent thread. The fold may buffer some elements. The buffer size
4547−-- is determined by the prevailing 'maxBuffer' setting.
1041+-- See also: 'concat', 'sequence'
45481042--
4549−-- @
4550−-- Stream m a -> m b
4551−-- |
4552−-- -----stream m a ---------------stream m a-----
1043+-- /Internal/
45531044--
4554−-- @
1045+{-# INLINE concatM #-}
1046+concatM :: (IsStream t, Monad m) => m (t m a) -> t m a
1047+concatM generator = concatMapM (\() -> generator) (yield ())
1048+
1049+------------------------------------------------------------------------------
1050+-- Either streams
1051+------------------------------------------------------------------------------
1052+
1053+-- | In an 'Either' stream iterate on 'Left's. This is a special case of
1054+-- 'iterateMapWith':
45551055--
45561056-- @
4557−-- > S.drain $ S.tapAsync (S.mapM_ print) (S.enumerateFromTo 1 2)
4558−-- 1
4559−-- 2
1057+-- iterateMapLeftsWith combine f = iterateMapWith combine (either f (const nil))
45601058-- @
45611059--
4562−-- Exceptions from the concurrently running fold are propagated to the current
4563−-- computation. Note that, because of buffering in the fold, exceptions may be
4564−-- delayed and may not correspond to the current element being processed in the
4565−-- parent stream, but we guarantee that before the parent stream stops the tap
4566−-- finishes and all exceptions from it are drained.
4567−--
4568−--
4569−-- Compare with 'tap'.
4570−--
4571−-- /Internal/
4572−{-# INLINE tapAsync #-}
4573−tapAsync :: (IsStream t, MonadAsync m) => FL.Fold m a b -> t m a -> t m a
4574−tapAsync f xs = D.fromStreamD $ D.tapAsync f (D.toStreamD xs)
4575−
4576−-- | @pollCounts predicate transform fold stream@ counts those elements in the
4577−-- stream that pass the @predicate@. The resulting count stream is sent to
4578−-- another thread which transforms it using @transform@ and then folds it using
4579−-- @fold@. The thread is automatically cleaned up if the stream stops or
4580−-- aborts due to exception.
4581−--
4582−-- For example, to print the count of elements processed every second:
1060+-- To traverse a directory tree:
45831061--
45841062-- @
4585−-- > S.drain $ S.pollCounts (const True) (S.rollingMap (-) . S.delayPost 1) (FL.drainBy print)
4586−-- $ S.enumerateFrom 0
1063+-- iterateMapLeftsWith serial Dir.toEither (yield (Left "tmp"))
45871064-- @
45881065--
4589−-- Note: This may not work correctly on 32-bit machines.
4590−--
45911066-- /Internal/
45921067--
4593−{-# INLINE pollCounts #-}
4594−pollCounts ::
4595− (IsStream t, MonadAsync m)
4596− => (a -> Bool)
4597− -> (t m Int -> t m Int)
4598− -> Fold m Int b
4599− -> t m a
4600− -> t m a
4601−pollCounts predicate transf f xs =
4602− D.fromStreamD
4603− $ D.pollCounts predicate (D.toStreamD . transf . D.fromStreamD) f
4604− $ D.toStreamD xs
4605−
4606−-- | Calls the supplied function with the number of elements consumed
4607−-- every @n@ seconds. The given function is run in a separate thread
4608−-- until the end of the stream. In case there is an exception in the
4609−-- stream the thread is killed during the next major GC.
4610−--
4611−-- Note: The action is not guaranteed to run if the main thread exits.
4612−--
4613−-- @
4614−-- > delay n = threadDelay (round $ n * 1000000) >> return n
4615−-- > S.drain $ S.tapRate 2 (\\n -> print $ show n ++ " elements processed") (delay 1 S.|: delay 0.5 S.|: delay 0.5 S.|: S.nil)
4616−-- 2 elements processed
4617−-- 1 elements processed
4618−-- @
4619−--
4620−-- Note: This may not work correctly on 32-bit machines.
4621−--
4622−-- /Internal/
4623−{-# INLINE tapRate #-}
4624−tapRate ::
4625− (IsStream t, MonadAsync m, MonadCatch m)
4626− => Double
4627− -> (Int -> m b)
4628− -> t m a
4629− -> t m a
4630−tapRate n f xs = D.fromStreamD $ D.tapRate n f $ D.toStreamD xs
1068+{-# INLINE iterateMapLeftsWith #-}
1069+iterateMapLeftsWith
1070+ :: IsStream t
1071+ => (t m (Either a b) -> t m (Either a b) -> t m (Either a b))
1072+ -> (a -> t m (Either a b))
1073+ -> t m (Either a b)
1074+ -> t m (Either a b)
1075+iterateMapLeftsWith combine f = iterateMapWith combine (either f (const K.nil))
46311076
4632−-- | Apply a monadic function to each element flowing through the stream and
4633−-- discard the results.
4634−--
4635−-- @
4636−-- > S.drain $ S.trace print (S.enumerateFromTo 1 2)
4637−-- 1
4638−-- 2
4639−-- @
4640−--
4641−-- Compare with 'tap'.
4642−--
4643−-- @since 0.7.0
4644−{-# INLINE trace #-}
4645−trace :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m a
4646−trace f = mapM (\x -> void (f x) >> return x)
1077+-------------------------------------------------------------------------------
1078+-- Breaking
1079+-------------------------------------------------------------------------------
46471080
4648−-- | Perform a side effect before yielding each element of the stream and
4649−-- discard the results.
4650−--
4651−-- @
4652−-- > S.drain $ S.trace_ (print "got here") (S.enumerateFromTo 1 2)
4653−-- "got here"
4654−-- "got here"
4655−-- @
1081+-- XXX we can implement this by repeatedly applying the 'lrunFor' fold.
1082+-- XXX add this example after fixing the serial stream rate control
1083+-- >>> S.toList $ S.take 5 $ intervalsOf 1 FL.sum $ constRate 2 $ S.enumerateFrom 1
1084+-- > [3,7,11,15,19]
46561085--
4657−-- See also: 'trace', 'interspersePrefix_'
1086+-- | Group the input stream into windows of @n@ second each and then fold each
1087+-- group using the provided fold function.
46581088--
4659−-- /Internal/
4660−{-# INLINE trace_ #-}
4661−trace_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
4662−trace_ eff = Serial.mapM (\x -> eff >> return x)
1089+-- @since 0.7.0
1090+{-# INLINE intervalsOf #-}
1091+intervalsOf
1092+ :: (IsStream t, MonadAsync m)
1093+ => Double -> Fold m a b -> t m a -> t m b
1094+intervalsOf n f xs =
1095+ splitWithSuffix isNothing (FL.lcatMaybes f)
1096+ (interjectSuffix n (return Nothing) (Serial.map Just xs))
46631097
46641098------------------------------------------------------------------------------
46651099-- Windowed classification
@@ -5134,297 +1568,3 @@ classifySessionsOf ::
51341568 -> t m (k, b)
51351569classifySessionsOf interval =
51361570 classifySessionsBy 1 interval False
5137−
5138−------------------------------------------------------------------------------
5139−-- Exceptions
5140−------------------------------------------------------------------------------
5141−
5142−-- | Run the action @m b@ before the stream yields its first element.
5143−--
5144−-- > before action xs = 'nilM' action <> xs
5145−--
5146−-- @since 0.7.0
5147−{-# INLINE before #-}
5148−before :: (IsStream t, Monad m) => m b -> t m a -> t m a
5149−before action xs = D.fromStreamD $ D.before action $ D.toStreamD xs
5150−
5151−-- | Like 'after', with following differences:
5152−--
5153−-- * action @m b@ won't run if the stream is garbage collected
5154−-- after partial evaluation.
5155−-- * Monad @m@ does not require any other constraints.
5156−-- * has slightly better performance than 'after'.
5157−--
5158−-- Same as the following, but with stream fusion:
5159−--
5160−-- > after_ action xs = xs <> 'nilM' action
5161−--
5162−-- /Internal/
5163−--
5164−{-# INLINE after_ #-}
5165−after_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
5166−after_ action xs = D.fromStreamD $ D.after_ action $ D.toStreamD xs
5167−
5168−-- | Run the action @m b@ whenever the stream @t m a@ stops normally, or if it
5169−-- is garbage collected after a partial lazy evaluation.
5170−--
5171−-- The semantics of the action @m b@ are similar to the semantics of cleanup
5172−-- action in 'bracket'.
5173−--
5174−-- /See also 'after_'/
5175−--
5176−-- @since 0.7.0
5177−--
5178−{-# INLINE after #-}
5179−after :: (IsStream t, MonadIO m, MonadBaseControl IO m)
5180− => m b -> t m a -> t m a
5181−after action xs = D.fromStreamD $ D.after action $ D.toStreamD xs
5182−
5183−-- | Run the action @m b@ if the stream aborts due to an exception. The
5184−-- exception is not caught, simply rethrown.
5185−--
5186−-- /Inhibits stream fusion/
5187−--
5188−-- @since 0.7.0
5189−{-# INLINE onException #-}
5190−onException :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a
5191−onException action xs = D.fromStreamD $ D.onException action $ D.toStreamD xs
5192−
5193−-- | Like 'finally' with following differences:
5194−--
5195−-- * action @m b@ won't run if the stream is garbage collected
5196−-- after partial evaluation.
5197−-- * does not require a 'MonadAsync' constraint.
5198−-- * has slightly better performance than 'finally'.
5199−--
5200−-- /Inhibits stream fusion/
5201−--
5202−-- /Internal/
5203−--
5204−{-# INLINE finally_ #-}
5205−finally_ :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a
5206−finally_ action xs = D.fromStreamD $ D.finally_ action $ D.toStreamD xs
5207−
5208−-- | Run the action @m b@ whenever the stream @t m a@ stops normally, aborts
5209−-- due to an exception or if it is garbage collected after a partial lazy
5210−-- evaluation.
5211−--
5212−-- The semantics of running the action @m b@ are similar to the cleanup action
5213−-- semantics described in 'bracket'.
5214−--
5215−-- @
5216−-- finally release = bracket (return ()) (const release)
5217−-- @
5218−--
5219−-- /See also 'finally_'/
5220−--
5221−-- /Inhibits stream fusion/
5222−--
5223−-- @since 0.7.0
5224−--
5225−{-# INLINE finally #-}
5226−finally :: (IsStream t, MonadAsync m, MonadCatch m) => m b -> t m a -> t m a
5227−finally action xs = D.fromStreamD $ D.finally action $ D.toStreamD xs
5228−
5229−-- | Like 'bracket' but with following differences:
5230−--
5231−-- * alloc action @m b@ runs with async exceptions enabled
5232−-- * cleanup action @b -> m c@ won't run if the stream is garbage collected
5233−-- after partial evaluation.
5234−-- * does not require a 'MonadAsync' constraint.
5235−-- * has slightly better performance than 'bracket'.
5236−--
5237−-- /Inhibits stream fusion/
5238−--
5239−-- /Internal/
5240−--
5241−{-# INLINE bracket_ #-}
5242−bracket_ :: (IsStream t, MonadCatch m)
5243− => m b -> (b -> m c) -> (b -> t m a) -> t m a
5244−bracket_ bef aft bet = D.fromStreamD $
5245− D.bracket_ bef aft (toStreamD . bet)
5246−
5247−-- | Run the alloc action @m b@ with async exceptions disabled but keeping
5248−-- blocking operations interruptible (see 'Control.Exception.mask'). Use the
5249−-- output @b@ as input to @b -> t m a@ to generate an output stream.
5250−--
5251−-- @b@ is usually a resource under the state of monad @m@, e.g. a file
5252−-- handle, that requires a cleanup after use. The cleanup action @b -> m c@,
5253−-- runs whenever the stream ends normally, due to a sync or async exception or
5254−-- if it gets garbage collected after a partial lazy evaluation.
5255−--
5256−-- 'bracket' only guarantees that the cleanup action runs, and it runs with
5257−-- async exceptions enabled. The action must ensure that it can successfully
5258−-- cleanup the resource in the face of sync or async exceptions.
5259−--
5260−-- When the stream ends normally or on a sync exception, cleanup action runs
5261−-- immediately in the current thread context, whereas in other cases it runs in
5262−-- the GC context, therefore, cleanup may be delayed until the GC gets to run.
5263−--
5264−-- /See also: 'bracket_'/
5265−--
5266−-- /Inhibits stream fusion/
5267−--
5268−-- @since 0.7.0
5269−--
5270−{-# INLINE bracket #-}
5271−bracket :: (IsStream t, MonadAsync m, MonadCatch m)
5272− => m b -> (b -> m c) -> (b -> t m a) -> t m a
5273−bracket bef aft bet = D.fromStreamD $
5274− D.bracket bef aft (toStreamD . bet)
5275−
5276−-- | Like 'handle' but the exception handler is also provided with the stream
5277−-- that generated the exception as input. The exception handler can thus
5278−-- re-evaluate the stream to retry the action that failed. The exception
5279−-- handler can again call 'ghandle' on it to retry the action multiple times.
5280−--
5281−-- This is highly experimental. In a stream of actions we can map the stream
5282−-- with a retry combinator to retry each action on failure.
5283−--
5284−-- /Inhibits stream fusion/
5285−--
5286−-- /Internal/
5287−--
5288−{-# INLINE ghandle #-}
5289−ghandle :: (IsStream t, MonadCatch m, Exception e)
5290− => (e -> t m a -> t m a) -> t m a -> t m a
5291−ghandle handler =
5292− D.fromStreamD
5293− . D.ghandle (\e xs -> D.toStreamD $ handler e (D.fromStreamD xs))
5294− . D.toStreamD
5295−
5296−-- | When evaluating a stream if an exception occurs, stream evaluation aborts
5297−-- and the specified exception handler is run with the exception as argument.
5298−--
5299−-- /Inhibits stream fusion/
5300−--
5301−-- @since 0.7.0
5302−{-# INLINE handle #-}
5303−handle :: (IsStream t, MonadCatch m, Exception e)
5304− => (e -> t m a) -> t m a -> t m a
5305−handle handler xs =
5306− D.fromStreamD $ D.handle (D.toStreamD . handler) $ D.toStreamD xs
5307−
5308−-- Keep concating either streams as long as rights are generated, stop as soon
5309−-- as a left is generated and concat the left stream.
5310−--
5311−-- See also: 'handle'
5312−--
5313−-- /Unimplemented/
5314−--
5315−{-
5316−concatMapEitherWith
5317− :: -- (IsStream t, MonadAsync m) =>
5318− (forall x. t m x -> t m x -> t m x)
5319− -> (a -> t m (Either (t m b) b))
5320− -> t m a
5321− -> t m b
5322−concatMapEitherWith = undefined
5323−-}
5324−
5325−------------------------------------------------------------------------------
5326−-- Generalize the underlying monad
5327−------------------------------------------------------------------------------
5328−
5329−-- | Transform the inner monad of a stream using a natural transformation.
5330−--
5331−-- / Internal/
5332−--
5333−{-# INLINE hoist #-}
5334−hoist :: (Monad m, Monad n)
5335− => (forall x. m x -> n x) -> SerialT m a -> SerialT n a
5336−hoist f xs = fromStreamS $ S.hoist f (toStreamS xs)
5337−
5338−-- | Generalize the inner monad of the stream from 'Identity' to any monad.
5339−--
5340−-- / Internal/
5341−--
5342−{-# INLINE generally #-}
5343−generally :: (IsStream t, Monad m) => t Identity a -> t m a
5344−generally xs = fromStreamS $ S.hoist (return . runIdentity) (toStreamS xs)
5345−
5346−------------------------------------------------------------------------------
5347−-- Add and remove a monad transformer
5348−------------------------------------------------------------------------------
5349−
5350−-- | Lift the inner monad @m@ of a stream @t m a@ to @tr m@ using the monad
5351−-- transformer @tr@.
5352−--
5353−-- / Internal/
5354−--
5355−{-# INLINE liftInner #-}
5356−liftInner :: (Monad m, IsStream t, MonadTrans tr, Monad (tr m))
5357− => t m a -> t (tr m) a
5358−liftInner xs = fromStreamD $ D.liftInner (toStreamD xs)
5359−
5360−------------------------------------------------------------------------------
5361−-- Sharing read only state in a stream
5362−------------------------------------------------------------------------------
5363−
5364−-- | Evaluate the inner monad of a stream as 'ReaderT'.
5365−--
5366−-- / Internal/
5367−--
5368−{-# INLINE runReaderT #-}
5369−runReaderT :: (IsStream t, Monad m) => m s -> t (ReaderT s m) a -> t m a
5370−runReaderT s xs = fromStreamD $ D.runReaderT s (toStreamD xs)
5371−
5372−-- | Run a stream transformation using a given environment.
5373−--
5374−-- See also: 'Serial.map'
5375−--
5376−-- / Internal/
5377−--
5378−{-# INLINE usingReaderT #-}
5379−usingReaderT
5380− :: (Monad m, IsStream t)
5381− => m r
5382− -> (t (ReaderT r m) a -> t (ReaderT r m) a)
5383− -> t m a
5384− -> t m a
5385−usingReaderT r f xs = runReaderT r $ f $ liftInner xs
5386−
5387−------------------------------------------------------------------------------
5388−-- Sharing read write state in a stream
5389−------------------------------------------------------------------------------
5390−
5391−-- | Evaluate the inner monad of a stream as 'StateT'.
5392−--
5393−-- This is supported only for 'SerialT' as concurrent state updation may not be
5394−-- safe.
5395−--
5396−-- / Internal/
5397−--
5398−{-# INLINE evalStateT #-}
5399−evalStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m a
5400−evalStateT s xs = fromStreamD $ D.evalStateT s (toStreamD xs)
5401−
5402−-- | Run a stateful (StateT) stream transformation using a given state.
5403−--
5404−-- This is supported only for 'SerialT' as concurrent state updation may not be
5405−-- safe.
5406−--
5407−-- See also: 'scanl''
5408−--
5409−-- / Internal/
5410−--
5411−{-# INLINE usingStateT #-}
5412−usingStateT
5413− :: Monad m
5414− => m s
5415− -> (SerialT (StateT s m) a -> SerialT (StateT s m) a)
5416− -> SerialT m a
5417− -> SerialT m a
5418−usingStateT s f xs = evalStateT s $ f $ liftInner xs
5419−
5420−-- | Evaluate the inner monad of a stream as 'StateT' and emit the resulting
5421−-- state and value pair after each step.
5422−--
5423−-- This is supported only for 'SerialT' as concurrent state updation may not be
5424−-- safe.
5425−--
5426−-- / Internal/
5427−--
5428−{-# INLINE runStateT #-}
5429−runStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m (s, a)
5430−runStateT s xs = fromStreamD $ D.runStateT s (toStreamD xs)
src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hsnew file+932
@@ -0,0 +1,932 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.IsStream.Eliminate
3+-- Copyright : (c) 2020 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+
9+module Streamly.Internal.Data.Stream.IsStream.Eliminate
10+ (
11+ -- * Elimination
12+ -- ** Deconstruction
13+ uncons
14+ , tail
15+ , init
16+
17+ -- ** Folding
18+ -- ** Right Folds
19+ , foldrM
20+ , foldrS
21+ , foldrT
22+ , foldr
23+
24+ -- ** Left Folds
25+ , foldl'
26+ , foldl1'
27+ , foldlM'
28+
29+ -- ** Composable Left Folds
30+ -- | See "Streamly.Internal.Data.Fold"
31+ , fold
32+
33+ -- ** Parsers
34+ -- | See "Streamly.Internal.Data.Parser"
35+ , parse
36+ , parseK
37+ , parseD
38+
39+ -- ** Concurrent Folds
40+ , foldAsync
41+ , (|$.)
42+ , (|&.)
43+
44+ -- ** Full Folds
45+
46+ -- -- ** To Summary (Full Folds)
47+ , drain
48+ , last
49+ , length
50+ , sum
51+ , product
52+ , mconcat
53+
54+ -- -- ** To Summary (Maybe) (Full Folds)
55+ , maximumBy
56+ , maximum
57+ , minimumBy
58+ , minimum
59+ , the
60+
61+ -- ** Lazy Folds
62+ -- -- ** To Containers (Full Folds)
63+ , toList
64+ , toListRev
65+ , toPure
66+ , toPureRev
67+
68+ -- ** Composable Left Folds
69+
70+ , toStream -- XXX rename to write?
71+ , toStreamRev -- XXX rename to writeRev?
72+
73+ -- ** Partial Folds
74+
75+ -- -- ** To Elements (Partial Folds)
76+
77+ -- -- | Folds that extract selected elements of a stream or their properties.
78+ , (!!)
79+ , head
80+ , headElse
81+ , findM
82+ , find
83+ , lookup
84+
85+ -- -- ** To Boolean (Partial Folds)
86+ , null
87+ , elem
88+ , notElem
89+ , all
90+ , any
91+ , and
92+ , or
93+
94+ -- ** Multi-Stream folds
95+ -- Full equivalence
96+ , eqBy
97+ , cmpBy
98+
99+ -- finding subsequences
100+ , isPrefixOf
101+ , isSubsequenceOf
102+
103+ -- trimming sequences
104+ , stripPrefix
105+ -- , stripInfix
106+ , dropPrefix
107+ , dropInfix
108+ , dropSuffix
109+
110+ -- * Deprecated
111+ , foldx
112+ , foldxM
113+ , foldr1
114+ , runStream
115+ , toHandle
116+ )
117+where
118+
119+#include "inline.hs"
120+
121+import Control.Monad.Catch (MonadThrow)
122+import Control.Monad.IO.Class (MonadIO(..))
123+import Control.Monad.Trans.Class (MonadTrans(..))
124+import Data.Functor.Identity (Identity (..))
125+import Streamly.Internal.Data.Fold.Types (Fold (..))
126+import Streamly.Internal.Data.Parser (Parser (..))
127+import Streamly.Internal.Data.SVar (MonadAsync, defState)
128+import Streamly.Internal.Data.Stream.Prelude (toStreamS)
129+import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
130+import Streamly.Internal.Data.Stream.StreamK (IsStream)
131+import Streamly.Internal.Data.Stream.Serial (SerialT)
132+
133+import qualified Streamly.Internal.Data.Fold as FL
134+import qualified Streamly.Internal.Data.Stream.Prelude as P
135+import qualified Streamly.Internal.Data.Stream.StreamK as K
136+import qualified Streamly.Internal.Data.Stream.StreamD as D
137+import qualified Streamly.Internal.Data.Parser.ParserK.Types as PRK
138+import qualified Streamly.Internal.Data.Parser.ParserD as PRD
139+import qualified System.IO as IO
140+#ifdef USE_STREAMK_ONLY
141+import qualified Streamly.Internal.Data.Stream.StreamK as S
142+#else
143+import qualified Streamly.Internal.Data.Stream.StreamD as S
144+#endif
145+
146+import Prelude hiding
147+ ( filter, drop, dropWhile, take, takeWhile, zipWith, foldr
148+ , foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem
149+ , notElem, maximum, minimum, head, last, tail, length, null
150+ , reverse, iterate, init, and, or, lookup, foldr1, (!!)
151+ , scanl, scanl1, replicate, concatMap, span, splitAt, break
152+ , repeat, concat, mconcat)
153+
154+------------------------------------------------------------------------------
155+-- Deconstruction
156+------------------------------------------------------------------------------
157+
158+-- | Decompose a stream into its head and tail. If the stream is empty, returns
159+-- 'Nothing'. If the stream is non-empty, returns @Just (a, ma)@, where @a@ is
160+-- the head of the stream and @ma@ its tail.
161+--
162+-- This is a brute force primitive. Avoid using it as long as possible, use it
163+-- when no other combinator can do the job. This can be used to do pretty much
164+-- anything in an imperative manner, as it just breaks down the stream into
165+-- individual elements and we can loop over them as we deem fit. For example,
166+-- this can be used to convert a streamly stream into other stream types.
167+--
168+-- @since 0.1.0
169+{-# INLINE uncons #-}
170+uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a))
171+uncons m = K.uncons (K.adapt m)
172+
173+------------------------------------------------------------------------------
174+-- Elimination by Folding
175+------------------------------------------------------------------------------
176+
177+-- | Right associative/lazy pull fold. @foldrM build final stream@ constructs
178+-- an output structure using the step function @build@. @build@ is invoked with
179+-- the next input element and the remaining (lazy) tail of the output
180+-- structure. It builds a lazy output expression using the two. When the "tail
181+-- structure" in the output expression is evaluated it calls @build@ again thus
182+-- lazily consuming the input @stream@ until either the output expression built
183+-- by @build@ is free of the "tail" or the input is exhausted in which case
184+-- @final@ is used as the terminating case for the output structure. For more
185+-- details see the description in the previous section.
186+--
187+-- Example, determine if any element is 'odd' in a stream:
188+--
189+-- >>> S.foldrM (\x xs -> if odd x then return True else xs) (return False) $ S.fromList (2:4:5:undefined)
190+-- > True
191+--
192+-- /Since: 0.7.0 (signature changed)/
193+--
194+-- /Since: 0.2.0 (signature changed)/
195+--
196+-- /Since: 0.1.0/
197+{-# INLINE foldrM #-}
198+foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b
199+foldrM = P.foldrM
200+
201+-- | Right fold to a streaming monad.
202+--
203+-- > foldrS S.cons S.nil === id
204+--
205+-- 'foldrS' can be used to perform stateless stream to stream transformations
206+-- like map and filter in general. It can be coupled with a scan to perform
207+-- stateful transformations. However, note that the custom map and filter
208+-- routines can be much more efficient than this due to better stream fusion.
209+--
210+-- >>> S.toList $ S.foldrS S.cons S.nil $ S.fromList [1..5]
211+-- > [1,2,3,4,5]
212+--
213+-- Find if any element in the stream is 'True':
214+--
215+-- >>> S.toList $ S.foldrS (\x xs -> if odd x then return True else xs) (return False) $ (S.fromList (2:4:5:undefined) :: SerialT IO Int)
216+-- > [True]
217+--
218+-- Map (+2) on odd elements and filter out the even elements:
219+--
220+-- >>> S.toList $ S.foldrS (\x xs -> if odd x then (x + 2) `S.cons` xs else xs) S.nil $ (S.fromList [1..5] :: SerialT IO Int)
221+-- > [3,5,7]
222+--
223+-- 'foldrM' can also be represented in terms of 'foldrS', however, the former
224+-- is much more efficient:
225+--
226+-- > foldrM f z s = runIdentityT $ foldrS (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
227+--
228+-- /Internal/
229+{-# INLINE foldrS #-}
230+foldrS :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
231+foldrS = K.foldrS
232+
233+-- | Right fold to a transformer monad. This is the most general right fold
234+-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
235+-- implementation can be more efficient:
236+--
237+-- > foldrS = foldrT
238+-- > foldrM f z s = runIdentityT $ foldrT (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
239+--
240+-- 'foldrT' can be used to translate streamly streams to other transformer
241+-- monads e.g. to a different streaming type.
242+--
243+-- /Internal/
244+{-# INLINE foldrT #-}
245+foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
246+ => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
247+foldrT f z s = S.foldrT f z (toStreamS s)
248+
249+-- | Right fold, lazy for lazy monads and pure streams, and strict for strict
250+-- monads.
251+--
252+-- Please avoid using this routine in strict monads like IO unless you need a
253+-- strict right fold. This is provided only for use in lazy monads (e.g.
254+-- Identity) or pure streams. Note that with this signature it is not possible
255+-- to implement a lazy foldr when the monad @m@ is strict. In that case it
256+-- would be strict in its accumulator and therefore would necessarily consume
257+-- all its input.
258+--
259+-- @since 0.1.0
260+{-# INLINE foldr #-}
261+foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
262+foldr = P.foldr
263+
264+-- XXX This seems to be of limited use as it cannot be used to construct
265+-- recursive structures and for reduction foldl1' is better.
266+--
267+-- | Lazy right fold for non-empty streams, using first element as the starting
268+-- value. Returns 'Nothing' if the stream is empty.
269+--
270+-- @since 0.5.0
271+{-# INLINE foldr1 #-}
272+{-# DEPRECATED foldr1 "Use foldrM instead." #-}
273+foldr1 :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a)
274+foldr1 f m = S.foldr1 f (toStreamS m)
275+
276+-- | Strict left fold with an extraction function. Like the standard strict
277+-- left fold, but applies a user supplied extraction function (the third
278+-- argument) to the folded value at the end. This is designed to work with the
279+-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
280+--
281+-- @since 0.2.0
282+{-# DEPRECATED foldx "Please use foldl' followed by fmap instead." #-}
283+{-# INLINE foldx #-}
284+foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
285+foldx = P.foldlx'
286+
287+-- | Left associative/strict push fold. @foldl' reduce initial stream@ invokes
288+-- @reduce@ with the accumulator and the next input in the input stream, using
289+-- @initial@ as the initial value of the current value of the accumulator. When
290+-- the input is exhausted the current value of the accumulator is returned.
291+-- Make sure to use a strict data structure for accumulator to not build
292+-- unnecessary lazy expressions unless that's what you want. See the previous
293+-- section for more details.
294+--
295+-- @since 0.2.0
296+{-# INLINE foldl' #-}
297+foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
298+foldl' = P.foldl'
299+
300+-- | Strict left fold, for non-empty streams, using first element as the
301+-- starting value. Returns 'Nothing' if the stream is empty.
302+--
303+-- @since 0.5.0
304+{-# INLINE foldl1' #-}
305+foldl1' :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a)
306+foldl1' step m = do
307+ r <- uncons m
308+ case r of
309+ Nothing -> return Nothing
310+ Just (h, t) -> do
311+ res <- foldl' step h t
312+ return $ Just res
313+
314+-- | Like 'foldx', but with a monadic step function.
315+--
316+-- @since 0.2.0
317+{-# DEPRECATED foldxM "Please use foldlM' followed by fmap instead." #-}
318+{-# INLINE foldxM #-}
319+foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
320+foldxM = P.foldlMx'
321+
322+-- | Like 'foldl'' but with a monadic step function.
323+--
324+-- /Since: 0.2.0/
325+--
326+-- /Since: 0.8.0 (signature change)/
327+{-# INLINE foldlM' #-}
328+foldlM' :: Monad m => (b -> a -> m b) -> m b -> SerialT m a -> m b
329+foldlM' step begin m = S.foldlM' step begin $ toStreamS m
330+
331+------------------------------------------------------------------------------
332+-- Running a Fold
333+------------------------------------------------------------------------------
334+
335+-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
336+-- expression strictly at each step. The behavior is similar to 'foldl''. A
337+-- 'Fold' can terminate early without consuming the full stream. See the
338+-- documentation of individual 'Fold's for termination behavior.
339+--
340+-- >>> S.fold FL.sum (S.enumerateFromTo 1 100)
341+-- 5050
342+--
343+-- @since 0.7.0
344+{-# INLINE fold #-}
345+fold :: Monad m => Fold m a b -> SerialT m a -> m b
346+fold = P.foldOnce
347+
348+------------------------------------------------------------------------------
349+-- Running a sink
350+------------------------------------------------------------------------------
351+
352+{-
353+-- | Drain a stream to a 'Sink'.
354+{-# INLINE runSink #-}
355+runSink :: Monad m => Sink m a -> SerialT m a -> m ()
356+runSink = fold . toFold
357+-}
358+
359+------------------------------------------------------------------------------
360+-- Running a Parser
361+------------------------------------------------------------------------------
362+
363+-- | Parse a stream using the supplied 'Parser'.
364+--
365+-- /Internal/
366+--
367+{-# INLINE_NORMAL parseD #-}
368+parseD :: MonadThrow m => PRD.Parser m a b -> SerialT m a -> m b
369+parseD (PRD.Parser step initial extract) = P.parselMx' step initial extract
370+
371+{-# INLINE parseK #-}
372+parseK :: MonadThrow m => PRK.Parser m a b -> SerialT m a -> m b
373+parseK = parse
374+
375+-- | Parse a stream using the supplied 'Parser'.
376+--
377+-- /Internal/
378+--
379+{-# INLINE [3] parse #-}
380+parse :: MonadThrow m => Parser m a b -> SerialT m a -> m b
381+parse = parseD . PRK.fromParserK
382+
383+------------------------------------------------------------------------------
384+-- Specialized folds
385+------------------------------------------------------------------------------
386+
387+-- |
388+-- > drain = mapM_ (\_ -> return ())
389+-- > drain = fold Fold.drain
390+--
391+-- Run a stream, discarding the results. By default it interprets the stream
392+-- as 'SerialT', to run other types of streams use the type adapting
393+-- combinators for example @drain . 'asyncly'@.
394+--
395+-- @since 0.7.0
396+{-# INLINE drain #-}
397+drain :: Monad m => SerialT m a -> m ()
398+drain = P.drain
399+
400+-- | Run a stream, discarding the results. By default it interprets the stream
401+-- as 'SerialT', to run other types of streams use the type adapting
402+-- combinators for example @runStream . 'asyncly'@.
403+--
404+-- @since 0.2.0
405+{-# DEPRECATED runStream "Please use \"drain\" instead" #-}
406+{-# INLINE runStream #-}
407+runStream :: Monad m => SerialT m a -> m ()
408+runStream = drain
409+
410+-- | Determine whether the stream is empty.
411+--
412+-- > null = fold Fold.null
413+--
414+-- @since 0.1.1
415+{-# INLINE null #-}
416+null :: Monad m => SerialT m a -> m Bool
417+null = S.null . toStreamS
418+
419+-- | Extract the first element of the stream, if any.
420+--
421+-- > head = (!! 0)
422+-- > head = fold Fold.head
423+--
424+-- @since 0.1.0
425+{-# INLINE head #-}
426+head :: Monad m => SerialT m a -> m (Maybe a)
427+head = S.head . toStreamS
428+
429+-- | Extract the first element of the stream, if any, otherwise use the
430+-- supplied default value. It can help avoid one branch in high performance
431+-- code.
432+--
433+-- /Internal/
434+{-# INLINE headElse #-}
435+headElse :: Monad m => a -> SerialT m a -> m a
436+headElse x = D.headElse x . toStreamD
437+
438+-- |
439+-- > tail = fmap (fmap snd) . uncons
440+--
441+-- Extract all but the first element of the stream, if any.
442+--
443+-- @since 0.1.1
444+{-# INLINE tail #-}
445+tail :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
446+tail m = K.tail (K.adapt m)
447+
448+-- | Extract all but the last element of the stream, if any.
449+--
450+-- @since 0.5.0
451+{-# INLINE init #-}
452+init :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
453+init m = K.init (K.adapt m)
454+
455+-- | Extract the last element of the stream, if any.
456+--
457+-- > last xs = xs !! (length xs - 1)
458+-- > last = fold Fold.last
459+--
460+-- @since 0.1.1
461+{-# INLINE last #-}
462+last :: Monad m => SerialT m a -> m (Maybe a)
463+last m = S.last $ toStreamS m
464+
465+-- | Determine whether an element is present in the stream.
466+--
467+-- > elem = fold Fold.elem
468+--
469+-- @since 0.1.0
470+{-# INLINE elem #-}
471+elem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
472+elem e m = S.elem e (toStreamS m)
473+
474+-- | Determine whether an element is not present in the stream.
475+--
476+-- > notElem = fold Fold.length
477+--
478+-- @since 0.1.0
479+{-# INLINE notElem #-}
480+notElem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
481+notElem e m = S.notElem e (toStreamS m)
482+
483+-- | Determine the length of the stream.
484+--
485+-- @since 0.1.0
486+{-# INLINE length #-}
487+length :: Monad m => SerialT m a -> m Int
488+length = foldl' (\n _ -> n + 1) 0
489+
490+-- | Determine whether all elements of a stream satisfy a predicate.
491+--
492+-- > all = fold Fold.all
493+--
494+-- @since 0.1.0
495+{-# INLINE all #-}
496+all :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
497+all p m = S.all p (toStreamS m)
498+
499+-- | Determine whether any of the elements of a stream satisfy a predicate.
500+--
501+-- > any = fold Fold.any
502+--
503+-- @since 0.1.0
504+{-# INLINE any #-}
505+any :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
506+any p m = S.any p (toStreamS m)
507+
508+-- | Determines if all elements of a boolean stream are True.
509+--
510+-- > and = fold Fold.and
511+--
512+-- @since 0.5.0
513+{-# INLINE and #-}
514+and :: Monad m => SerialT m Bool -> m Bool
515+and = all (==True)
516+
517+-- | Determines whether at least one element of a boolean stream is True.
518+--
519+-- > or = fold Fold.or
520+--
521+-- @since 0.5.0
522+{-# INLINE or #-}
523+or :: Monad m => SerialT m Bool -> m Bool
524+or = any (==True)
525+
526+-- | Determine the sum of all elements of a stream of numbers. Returns @0@ when
527+-- the stream is empty. Note that this is not numerically stable for floating
528+-- point numbers.
529+--
530+-- > sum = fold Fold.sum
531+--
532+-- @since 0.1.0
533+{-# INLINE sum #-}
534+sum :: (Monad m, Num a) => SerialT m a -> m a
535+sum = foldl' (+) 0
536+
537+-- | Determine the product of all elements of a stream of numbers. Returns @1@
538+-- when the stream is empty.
539+--
540+-- > product = fold Fold.product
541+--
542+-- @since 0.1.1
543+{-# INLINE product #-}
544+product :: (Monad m, Num a) => SerialT m a -> m a
545+product = foldl' (*) 1
546+
547+-- | Fold a stream of monoid elements by appending them.
548+--
549+-- > mconcat = fold Fold.mconcat
550+--
551+-- /Internal/
552+{-# INLINE mconcat #-}
553+mconcat :: (Monad m, Monoid a) => SerialT m a -> m a
554+mconcat = foldr mappend mempty
555+
556+-- |
557+-- @
558+-- minimum = 'minimumBy' compare
559+ -- minimum = fold Fold.minimum
560+-- @
561+--
562+-- Determine the minimum element in a stream.
563+--
564+-- @since 0.1.0
565+{-# INLINE minimum #-}
566+minimum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
567+minimum m = S.minimum (toStreamS m)
568+
569+-- | Determine the minimum element in a stream using the supplied comparison
570+-- function.
571+--
572+-- > minimumBy = fold Fold.minimumBy
573+--
574+-- @since 0.6.0
575+{-# INLINE minimumBy #-}
576+minimumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
577+minimumBy cmp m = S.minimumBy cmp (toStreamS m)
578+
579+-- |
580+-- @
581+-- maximum = 'maximumBy' compare
582+-- maximum = fold Fold.maximum
583+-- @
584+--
585+-- Determine the maximum element in a stream.
586+--
587+-- @since 0.1.0
588+{-# INLINE maximum #-}
589+maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
590+maximum = P.maximum
591+
592+-- | Determine the maximum element in a stream using the supplied comparison
593+-- function.
594+--
595+-- > maximumBy = fold Fold.maximumBy
596+--
597+-- @since 0.6.0
598+{-# INLINE maximumBy #-}
599+maximumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
600+maximumBy cmp m = S.maximumBy cmp (toStreamS m)
601+
602+-- | Ensures that all the elements of the stream are identical and then returns
603+-- that unique element.
604+--
605+-- @since 0.6.0
606+{-# INLINE the #-}
607+the :: (Eq a, Monad m) => SerialT m a -> m (Maybe a)
608+the m = S.the (toStreamS m)
609+
610+-- | Lookup the element at the given index.
611+--
612+-- @since 0.6.0
613+{-# INLINE (!!) #-}
614+(!!) :: Monad m => SerialT m a -> Int -> m (Maybe a)
615+m !! i = toStreamS m S.!! i
616+
617+-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
618+-- first pair where the key equals the given value @a@.
619+--
620+-- > lookup = snd <$> find ((==) . fst)
621+-- > lookup = fold Fold.lookup
622+--
623+-- @since 0.5.0
624+{-# INLINE lookup #-}
625+lookup :: (Monad m, Eq a) => a -> SerialT m (a, b) -> m (Maybe b)
626+lookup a m = S.lookup a (toStreamS m)
627+
628+-- | Like 'findM' but with a non-monadic predicate.
629+--
630+-- > find p = findM (return . p)
631+-- > find = fold Fold.find
632+--
633+-- @since 0.5.0
634+{-# INLINE find #-}
635+find :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe a)
636+find p m = S.find p (toStreamS m)
637+
638+-- | Returns the first element that satisfies the given predicate.
639+--
640+-- > findM = fold Fold.findM
641+--
642+-- @since 0.6.0
643+{-# INLINE findM #-}
644+findM :: Monad m => (a -> m Bool) -> SerialT m a -> m (Maybe a)
645+findM p m = S.findM p (toStreamS m)
646+
647+------------------------------------------------------------------------------
648+-- Substreams
649+------------------------------------------------------------------------------
650+
651+-- | Returns 'True' if the first stream is the same as or a prefix of the
652+-- second. A stream is a prefix of itself.
653+--
654+-- @
655+-- > S.isPrefixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
656+-- True
657+-- @
658+--
659+-- @since 0.6.0
660+{-# INLINE isPrefixOf #-}
661+isPrefixOf :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m Bool
662+isPrefixOf m1 m2 = D.isPrefixOf (toStreamD m1) (toStreamD m2)
663+
664+-- Note: isPrefixOf uses the prefix stream only once. In contrast, isSuffixOf
665+-- may use the suffix stream many times. To run in optimal memory we do not
666+-- want to buffer the suffix stream in memory therefore we need an ability to
667+-- clone (or consume it multiple times) the suffix stream without any side
668+-- effects so that multiple potential suffix matches can proceed in parallel
669+-- without buffering the suffix stream. For example, we may create the suffix
670+-- stream from a file handle, however, if we evaluate the stream multiple
671+-- times, once for each match, we will need a different file handle each time
672+-- which may exhaust the file descriptors. Instead, we want to share the same
673+-- underlying file descriptor, use pread on it to generate the stream and clone
674+-- the stream for each match. Therefore the suffix stream should be built in
675+-- such a way that it can be consumed multiple times without any problems.
676+
677+-- XXX Can be implemented with better space/time complexity.
678+-- Space: @O(n)@ worst case where @n@ is the length of the suffix.
679+
680+-- | Returns 'True' if all the elements of the first stream occur, in order, in
681+-- the second stream. The elements do not have to occur consecutively. A stream
682+-- is a subsequence of itself.
683+--
684+-- @
685+-- > S.isSubsequenceOf (S.fromList "hlo") (S.fromList "hello" :: SerialT IO Char)
686+-- True
687+-- @
688+--
689+-- @since 0.6.0
690+{-# INLINE isSubsequenceOf #-}
691+isSubsequenceOf :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m Bool
692+isSubsequenceOf m1 m2 = D.isSubsequenceOf (toStreamD m1) (toStreamD m2)
693+
694+-- | @stripPrefix prefix stream@ strips @prefix@ from @stream@ if it is a
695+-- prefix of stream. Returns 'Nothing' if the stream does not start with the
696+-- given prefix, stripped stream otherwise. Returns @Just nil@ when the prefix
697+-- is the same as the stream.
698+--
699+-- Space: @O(1)@
700+--
701+-- @since 0.6.0
702+{-# INLINE stripPrefix #-}
703+stripPrefix
704+ :: (Eq a, IsStream t, Monad m)
705+ => t m a -> t m a -> m (Maybe (t m a))
706+stripPrefix m1 m2 = fmap fromStreamD <$>
707+ D.stripPrefix (toStreamD m1) (toStreamD m2)
708+
709+-- | Drop prefix from the input stream if present.
710+--
711+-- Space: @O(1)@
712+--
713+-- /Unimplemented/ - Help wanted.
714+{-# INLINE dropPrefix #-}
715+dropPrefix ::
716+ -- (Eq a, IsStream t, Monad m) =>
717+ t m a -> t m a -> t m a
718+dropPrefix = error "Not implemented yet!"
719+
720+-- | Drop all matching infix from the input stream if present. Infix stream
721+-- may be consumed multiple times.
722+--
723+-- Space: @O(n)@ where n is the length of the infix.
724+--
725+-- /Unimplemented/ - Help wanted.
726+{-# INLINE dropInfix #-}
727+dropInfix ::
728+ -- (Eq a, IsStream t, Monad m) =>
729+ t m a -> t m a -> t m a
730+dropInfix = error "Not implemented yet!"
731+
732+-- | Drop suffix from the input stream if present. Suffix stream may be
733+-- consumed multiple times.
734+--
735+-- Space: @O(n)@ where n is the length of the suffix.
736+--
737+-- /Unimplemented/ - Help wanted.
738+{-# INLINE dropSuffix #-}
739+dropSuffix ::
740+ -- (Eq a, IsStream t, Monad m) =>
741+ t m a -> t m a -> t m a
742+dropSuffix = error "Not implemented yet!"
743+
744+------------------------------------------------------------------------------
745+-- Concurrent Application
746+------------------------------------------------------------------------------
747+
748+infixr 0 |$.
749+infixl 1 |&.
750+
751+-- | Parallel fold application operator; applies a fold function @t m a -> m b@
752+-- to a stream @t m a@ concurrently; The the input stream is evaluated
753+-- asynchronously in an independent thread yielding elements to a buffer and
754+-- the folding action runs in another thread consuming the input from the
755+-- buffer.
756+--
757+-- If you read the signature as @(t m a -> m b) -> (t m a -> m b)@ you can look
758+-- at it as a transformation that converts a fold function to a buffered
759+-- concurrent fold function.
760+--
761+-- The @.@ at the end of the operator is a mnemonic for termination of the
762+-- stream.
763+--
764+-- @
765+-- S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
766+-- |$. S.repeatM (threadDelay 1000000 >> return 1)
767+-- @
768+--
769+-- /Concurrent/
770+--
771+-- /Since: 0.3.0 ("Streamly")/
772+--
773+-- @since 0.8.0
774+{-# INLINE (|$.) #-}
775+(|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
776+-- (|$.) f = f . Async.mkAsync
777+(|$.) f = f . D.mkParallel
778+
779+-- | Same as '|$.'.
780+--
781+-- /Internal/
782+--
783+{-# INLINE foldAsync #-}
784+foldAsync :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
785+foldAsync = (|$.)
786+
787+-- | Parallel reverse function application operator for applying a run or fold
788+-- functions to a stream. Just like '|$.' except that the operands are reversed.
789+--
790+-- @
791+-- S.repeatM (threadDelay 1000000 >> return 1)
792+-- |&. S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
793+-- @
794+--
795+-- /Concurrent/
796+--
797+-- /Since: 0.3.0 ("Streamly")/
798+--
799+-- @since 0.8.0
800+{-# INLINE (|&.) #-}
801+(|&.) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> m b) -> m b
802+x |&. f = f |$. x
803+
804+------------------------------------------------------------------------------
805+-- Conversions
806+------------------------------------------------------------------------------
807+
808+-- |
809+-- @
810+-- toList = S.foldr (:) []
811+-- @
812+--
813+-- Convert a stream into a list in the underlying monad. The list can be
814+-- consumed lazily in a lazy monad (e.g. 'Identity'). In a strict monad (e.g.
815+-- IO) the whole list is generated and buffered before it can be consumed.
816+--
817+-- /Warning!/ working on large lists accumulated as buffers in memory could be
818+-- very inefficient, consider using "Streamly.Array" instead.
819+--
820+-- @since 0.1.0
821+{-# INLINE toList #-}
822+toList :: Monad m => SerialT m a -> m [a]
823+toList = P.toList
824+
825+-- |
826+-- @
827+-- toListRev = S.foldl' (flip (:)) []
828+-- @
829+--
830+-- Convert a stream into a list in reverse order in the underlying monad.
831+--
832+-- /Warning!/ working on large lists accumulated as buffers in memory could be
833+-- very inefficient, consider using "Streamly.Array" instead.
834+--
835+-- /Internal/
836+{-# INLINE toListRev #-}
837+toListRev :: Monad m => SerialT m a -> m [a]
838+toListRev = D.toListRev . toStreamD
839+
840+-- |
841+-- @
842+-- toHandle h = S.mapM_ $ hPutStrLn h
843+-- @
844+--
845+-- Write a stream of Strings to an IO Handle.
846+--
847+-- @since 0.1.0
848+{-# DEPRECATED toHandle
849+ "Please use Streamly.FileSystem.Handle module (see the changelog)" #-}
850+toHandle :: MonadIO m => IO.Handle -> SerialT m String -> m ()
851+toHandle h = go
852+ where
853+ go m1 =
854+ let stop = return ()
855+ single a = liftIO (IO.hPutStrLn h a)
856+ yieldk a r = liftIO (IO.hPutStrLn h a) >> go r
857+ in K.foldStream defState yieldk single stop m1
858+
859+-- XXX rename these to write/writeRev to make the naming consistent with folds
860+-- in other modules.
861+--
862+-- | A fold that buffers its input to a pure stream.
863+--
864+-- /Warning!/ working on large streams accumulated as buffers in memory could
865+-- be very inefficient, consider using "Streamly.Data.Array" instead.
866+--
867+-- /Internal/
868+{-# INLINE toStream #-}
869+toStream :: Monad m => Fold m a (SerialT Identity a)
870+toStream = Fold (\f x -> return $ FL.Partial $ f . (x `K.cons`))
871+ (return id)
872+ (return . ($ K.nil))
873+
874+-- This is more efficient than 'toStream'. toStream is exactly the same as
875+-- reversing the stream after toStreamRev.
876+--
877+-- | Buffers the input stream to a pure stream in the reverse order of the
878+-- input.
879+--
880+-- /Warning!/ working on large streams accumulated as buffers in memory could
881+-- be very inefficient, consider using "Streamly.Data.Array" instead.
882+--
883+-- /Internal/
884+
885+-- xn : ... : x2 : x1 : []
886+{-# INLINABLE toStreamRev #-}
887+toStreamRev :: Monad m => Fold m a (SerialT Identity a)
888+toStreamRev = Fold (\xs x -> return $ FL.Partial $ x `K.cons` xs) (return K.nil) return
889+
890+-- | Convert a stream to a pure stream.
891+--
892+-- @
893+-- toPure = foldr cons nil
894+-- @
895+--
896+-- /Internal/
897+--
898+{-# INLINE toPure #-}
899+toPure :: Monad m => SerialT m a -> m (SerialT Identity a)
900+toPure = foldr K.cons K.nil
901+
902+-- | Convert a stream to a pure stream in reverse order.
903+--
904+-- @
905+-- toPureRev = foldl' (flip cons) nil
906+-- @
907+--
908+-- /Internal/
909+--
910+{-# INLINE toPureRev #-}
911+toPureRev :: Monad m => SerialT m a -> m (SerialT Identity a)
912+toPureRev = foldl' (flip K.cons) K.nil
913+
914+------------------------------------------------------------------------------
915+-- Comparison
916+------------------------------------------------------------------------------
917+
918+-- | Compare two streams for equality using an equality function.
919+--
920+-- @since 0.6.0
921+{-# INLINABLE eqBy #-}
922+eqBy :: (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> m Bool
923+eqBy = P.eqBy
924+
925+-- | Compare two streams lexicographically using a comparison function.
926+--
927+-- @since 0.6.0
928+{-# INLINABLE cmpBy #-}
929+cmpBy
930+ :: (IsStream t, Monad m)
931+ => (a -> b -> Ordering) -> t m a -> t m b -> m Ordering
932+cmpBy = P.cmpBy
src/Streamly/Internal/Data/Stream/IsStream/Exceptions.hsnew file+228
@@ -0,0 +1,228 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.IsStream.Exceptions
3+-- Copyright : (c) 2020 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+
9+module Streamly.Internal.Data.Stream.IsStream.Exceptions
10+ (
11+ -- * Exceptions
12+ before
13+ , after_
14+ , after
15+ , bracket_
16+ , bracket
17+ , onException
18+ , finally_
19+ , finally
20+ , ghandle
21+ , handle
22+ )
23+where
24+
25+import Control.Exception (Exception)
26+import Control.Monad.Catch (MonadCatch)
27+import Control.Monad.IO.Class (MonadIO(..))
28+import Control.Monad.Trans.Control (MonadBaseControl)
29+import Streamly.Internal.Data.SVar (MonadAsync)
30+import Streamly.Internal.Data.Stream.StreamD (toStreamD)
31+import Streamly.Internal.Data.Stream.StreamK (IsStream)
32+
33+import qualified Streamly.Internal.Data.Stream.StreamD as D
34+
35+import Prelude hiding
36+ ( filter, drop, dropWhile, take, takeWhile, zipWith, foldr
37+ , foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem
38+ , notElem, maximum, minimum, head, last, tail, length, null
39+ , reverse, iterate, init, and, or, lookup, foldr1, (!!)
40+ , scanl, scanl1, replicate, concatMap, span, splitAt, break
41+ , repeat, concat, mconcat)
42+
43+------------------------------------------------------------------------------
44+-- Exceptions
45+------------------------------------------------------------------------------
46+
47+-- | Run the action @m b@ before the stream yields its first element.
48+--
49+-- > before action xs = 'nilM' action <> xs
50+--
51+-- @since 0.7.0
52+{-# INLINE before #-}
53+before :: (IsStream t, Monad m) => m b -> t m a -> t m a
54+before action xs = D.fromStreamD $ D.before action $ D.toStreamD xs
55+
56+-- | Like 'after', with following differences:
57+--
58+-- * action @m b@ won't run if the stream is garbage collected
59+-- after partial evaluation.
60+-- * Monad @m@ does not require any other constraints.
61+-- * has slightly better performance than 'after'.
62+--
63+-- Same as the following, but with stream fusion:
64+--
65+-- > after_ action xs = xs <> 'nilM' action
66+--
67+-- /Internal/
68+--
69+{-# INLINE after_ #-}
70+after_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
71+after_ action xs = D.fromStreamD $ D.after_ action $ D.toStreamD xs
72+
73+-- | Run the action @m b@ whenever the stream @t m a@ stops normally, or if it
74+-- is garbage collected after a partial lazy evaluation.
75+--
76+-- The semantics of the action @m b@ are similar to the semantics of cleanup
77+-- action in 'bracket'.
78+--
79+-- /See also 'after_'/
80+--
81+-- @since 0.7.0
82+--
83+{-# INLINE after #-}
84+after :: (IsStream t, MonadIO m, MonadBaseControl IO m)
85+ => m b -> t m a -> t m a
86+after action xs = D.fromStreamD $ D.after action $ D.toStreamD xs
87+
88+-- | Run the action @m b@ if the stream aborts due to an exception. The
89+-- exception is not caught, simply rethrown.
90+--
91+-- /Inhibits stream fusion/
92+--
93+-- @since 0.7.0
94+{-# INLINE onException #-}
95+onException :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a
96+onException action xs = D.fromStreamD $ D.onException action $ D.toStreamD xs
97+
98+-- | Like 'finally' with following differences:
99+--
100+-- * action @m b@ won't run if the stream is garbage collected
101+-- after partial evaluation.
102+-- * does not require a 'MonadAsync' constraint.
103+-- * has slightly better performance than 'finally'.
104+--
105+-- /Inhibits stream fusion/
106+--
107+-- /Internal/
108+--
109+{-# INLINE finally_ #-}
110+finally_ :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a
111+finally_ action xs = D.fromStreamD $ D.finally_ action $ D.toStreamD xs
112+
113+-- | Run the action @m b@ whenever the stream @t m a@ stops normally, aborts
114+-- due to an exception or if it is garbage collected after a partial lazy
115+-- evaluation.
116+--
117+-- The semantics of running the action @m b@ are similar to the cleanup action
118+-- semantics described in 'bracket'.
119+--
120+-- @
121+-- finally release = bracket (return ()) (const release)
122+-- @
123+--
124+-- /See also 'finally_'/
125+--
126+-- /Inhibits stream fusion/
127+--
128+-- @since 0.7.0
129+--
130+{-# INLINE finally #-}
131+finally :: (IsStream t, MonadAsync m, MonadCatch m) => m b -> t m a -> t m a
132+finally action xs = D.fromStreamD $ D.finally action $ D.toStreamD xs
133+
134+-- | Like 'bracket' but with following differences:
135+--
136+-- * alloc action @m b@ runs with async exceptions enabled
137+-- * cleanup action @b -> m c@ won't run if the stream is garbage collected
138+-- after partial evaluation.
139+-- * does not require a 'MonadAsync' constraint.
140+-- * has slightly better performance than 'bracket'.
141+--
142+-- /Inhibits stream fusion/
143+--
144+-- /Internal/
145+--
146+{-# INLINE bracket_ #-}
147+bracket_ :: (IsStream t, MonadCatch m)
148+ => m b -> (b -> m c) -> (b -> t m a) -> t m a
149+bracket_ bef aft bet = D.fromStreamD $
150+ D.bracket_ bef aft (toStreamD . bet)
151+
152+-- | Run the alloc action @m b@ with async exceptions disabled but keeping
153+-- blocking operations interruptible (see 'Control.Exception.mask'). Use the
154+-- output @b@ as input to @b -> t m a@ to generate an output stream.
155+--
156+-- @b@ is usually a resource under the state of monad @m@, e.g. a file
157+-- handle, that requires a cleanup after use. The cleanup action @b -> m c@,
158+-- runs whenever the stream ends normally, due to a sync or async exception or
159+-- if it gets garbage collected after a partial lazy evaluation.
160+--
161+-- 'bracket' only guarantees that the cleanup action runs, and it runs with
162+-- async exceptions enabled. The action must ensure that it can successfully
163+-- cleanup the resource in the face of sync or async exceptions.
164+--
165+-- When the stream ends normally or on a sync exception, cleanup action runs
166+-- immediately in the current thread context, whereas in other cases it runs in
167+-- the GC context, therefore, cleanup may be delayed until the GC gets to run.
168+--
169+-- /See also: 'bracket_'/
170+--
171+-- /Inhibits stream fusion/
172+--
173+-- @since 0.7.0
174+--
175+{-# INLINE bracket #-}
176+bracket :: (IsStream t, MonadAsync m, MonadCatch m)
177+ => m b -> (b -> m c) -> (b -> t m a) -> t m a
178+bracket bef aft bet = D.fromStreamD $
179+ D.bracket bef aft (toStreamD . bet)
180+
181+-- | Like 'handle' but the exception handler is also provided with the stream
182+-- that generated the exception as input. The exception handler can thus
183+-- re-evaluate the stream to retry the action that failed. The exception
184+-- handler can again call 'ghandle' on it to retry the action multiple times.
185+--
186+-- This is highly experimental. In a stream of actions we can map the stream
187+-- with a retry combinator to retry each action on failure.
188+--
189+-- /Inhibits stream fusion/
190+--
191+-- /Internal/
192+--
193+{-# INLINE ghandle #-}
194+ghandle :: (IsStream t, MonadCatch m, Exception e)
195+ => (e -> t m a -> t m a) -> t m a -> t m a
196+ghandle handler =
197+ D.fromStreamD
198+ . D.ghandle (\e xs -> D.toStreamD $ handler e (D.fromStreamD xs))
199+ . D.toStreamD
200+
201+-- | When evaluating a stream if an exception occurs, stream evaluation aborts
202+-- and the specified exception handler is run with the exception as argument.
203+--
204+-- /Inhibits stream fusion/
205+--
206+-- @since 0.7.0
207+{-# INLINE handle #-}
208+handle :: (IsStream t, MonadCatch m, Exception e)
209+ => (e -> t m a) -> t m a -> t m a
210+handle handler xs =
211+ D.fromStreamD $ D.handle (D.toStreamD . handler) $ D.toStreamD xs
212+
213+-- Keep concating either streams as long as rights are generated, stop as soon
214+-- as a left is generated and concat the left stream.
215+--
216+-- See also: 'handle'
217+--
218+-- /Unimplemented/
219+--
220+{-
221+concatMapEitherWith
222+ :: -- (IsStream t, MonadAsync m) =>
223+ (forall x. t m x -> t m x -> t m x)
224+ -> (a -> t m (Either (t m b) b))
225+ -> t m a
226+ -> t m b
227+concatMapEitherWith = undefined
228+-}
src/Streamly/Internal/Data/Stream/IsStream/Generate.hsnew file+644
@@ -0,0 +1,644 @@
1+{-# OPTIONS_GHC -Wno-orphans #-}
2+
3+-- |
4+-- Module : Streamly.Internal.Data.Stream.IsStream.Generate
5+-- Copyright : (c) 2020 Composewell Technologies
6+-- License : BSD-3-Clause
7+-- Maintainer : streamly@composewell.com
8+-- Stability : experimental
9+-- Portability : GHC
10+
11+module Streamly.Internal.Data.Stream.IsStream.Generate
12+ (
13+ -- ** From Values
14+ yield
15+ , yieldM
16+ , repeat
17+ , repeatM
18+ , replicate
19+ , replicateM
20+
21+ -- ** Enumeration
22+ -- , Enumerable (..)
23+ -- , enumerate
24+ -- , enumerateTo
25+
26+ -- ** Time Enumeration
27+ , times
28+ , absTimes
29+ , absTimesWith
30+ , relTimes
31+ , relTimesWith
32+ , durations
33+ , ticks
34+ , timeout
35+ , currentTime
36+
37+ -- ** From Generators
38+ , unfoldr
39+ , unfoldrM
40+ , unfold
41+ , unfold0
42+ , fromIndices
43+ , fromIndicesM
44+
45+ -- ** Iteration
46+ , iterate
47+ , iterateM
48+
49+ -- ** Cyclic Elements
50+ , K.mfix
51+
52+ -- ** From Containers
53+ , P.fromList
54+ , fromListM
55+ , K.fromFoldable
56+ , fromFoldableM
57+ , fromPrimIORef
58+
59+ -- * Deprecated
60+ , each
61+ , fromHandle
62+ )
63+where
64+
65+#include "inline.hs"
66+
67+import Control.Monad.IO.Class (MonadIO(..))
68+import Data.Void (Void)
69+import Streamly.Internal.Data.Unfold.Types (Unfold)
70+import Streamly.Internal.Data.SVar (MonadAsync, Rate (..))
71+import Streamly.Internal.Data.Stream.Prelude (fromStreamS)
72+import Streamly.Internal.Data.Stream.StreamD (fromStreamD)
73+import Streamly.Internal.Data.Stream.StreamK (IsStream(consM))
74+import Streamly.Internal.Data.Stream.Serial (SerialT, WSerialT)
75+import Streamly.Internal.Data.Stream.Zip (ZipSerialM)
76+import Streamly.Internal.Data.Time.Units
77+ ( AbsTime
78+ , RelTime64, addToAbsTime64)
79+import Streamly.Internal.Data.IORef.Prim (Prim, IORef)
80+
81+import qualified Streamly.Internal.Data.Stream.Prelude as P
82+import qualified Streamly.Internal.Data.Stream.StreamK as K
83+import qualified Streamly.Internal.Data.Stream.StreamD as D
84+import qualified Streamly.Internal.Data.Stream.Serial as Serial
85+import qualified Prelude
86+import qualified System.IO as IO
87+#ifdef USE_STREAMK_ONLY
88+import qualified Streamly.Internal.Data.Stream.StreamK as S
89+#else
90+import qualified Streamly.Internal.Data.Stream.StreamD as S
91+#endif
92+
93+import Prelude hiding
94+ ( filter, drop, dropWhile, take, takeWhile, zipWith, foldr
95+ , foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem
96+ , notElem, maximum, minimum, head, last, tail, length, null
97+ , reverse, iterate, init, and, or, lookup, foldr1, (!!)
98+ , scanl, scanl1, replicate, concatMap, span, splitAt, break
99+ , repeat, concat, mconcat)
100+
101+------------------------------------------------------------------------------
102+-- Generation by Unfolding
103+------------------------------------------------------------------------------
104+
105+-- |
106+-- @
107+-- unfoldr step s =
108+-- case step s of
109+-- Nothing -> 'K.nil'
110+-- Just (a, b) -> a \`cons` unfoldr step b
111+-- @
112+--
113+-- Build a stream by unfolding a /pure/ step function @step@ starting from a
114+-- seed @s@. The step function returns the next element in the stream and the
115+-- next seed value. When it is done it returns 'Nothing' and the stream ends.
116+-- For example,
117+--
118+-- @
119+-- let f b =
120+-- if b > 3
121+-- then Nothing
122+-- else Just (b, b + 1)
123+-- in toList $ unfoldr f 0
124+-- @
125+-- @
126+-- [0,1,2,3]
127+-- @
128+--
129+-- @since 0.1.0
130+{-# INLINE_EARLY unfoldr #-}
131+unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a
132+unfoldr step seed = fromStreamS (S.unfoldr step seed)
133+{-# RULES "unfoldr fallback to StreamK" [1]
134+ forall a b. S.toStreamK (S.unfoldr a b) = K.unfoldr a b #-}
135+
136+-- | Build a stream by unfolding a /monadic/ step function starting from a
137+-- seed. The step function returns the next element in the stream and the next
138+-- seed value. When it is done it returns 'Nothing' and the stream ends. For
139+-- example,
140+--
141+-- @
142+-- let f b =
143+-- if b > 3
144+-- then return Nothing
145+-- else print b >> return (Just (b, b + 1))
146+-- in drain $ unfoldrM f 0
147+-- @
148+-- @
149+-- 0
150+-- 1
151+-- 2
152+-- 3
153+-- @
154+-- When run concurrently, the next unfold step can run concurrently with the
155+-- processing of the output of the previous step. Note that more than one step
156+-- cannot run concurrently as the next step depends on the output of the
157+-- previous step.
158+--
159+-- @
160+-- (asyncly $ S.unfoldrM (\\n -> liftIO (threadDelay 1000000) >> return (Just (n, n + 1))) 0)
161+-- & S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
162+-- @
163+--
164+-- /Concurrent/
165+--
166+-- /Since: 0.1.0/
167+{-# INLINE_EARLY unfoldrM #-}
168+unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
169+unfoldrM = K.unfoldrM
170+
171+{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
172+{-# INLINE_EARLY unfoldrMSerial #-}
173+unfoldrMSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
174+unfoldrMSerial = Serial.unfoldrM
175+
176+{-# RULES "unfoldrM wSerial" unfoldrM = unfoldrMWSerial #-}
177+{-# INLINE_EARLY unfoldrMWSerial #-}
178+unfoldrMWSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> WSerialT m a
179+unfoldrMWSerial = Serial.unfoldrM
180+
181+{-# RULES "unfoldrM zipSerial" unfoldrM = unfoldrMZipSerial #-}
182+{-# INLINE_EARLY unfoldrMZipSerial #-}
183+unfoldrMZipSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> ZipSerialM m a
184+unfoldrMZipSerial = Serial.unfoldrM
185+
186+-- | Convert an 'Unfold' into a stream by supplying it an input seed.
187+--
188+-- >>> unfold (UF.replicateM 10) (putStrLn "hello")
189+--
190+-- /Since: 0.7.0/
191+{-# INLINE unfold #-}
192+unfold :: (IsStream t, Monad m) => Unfold m a b -> a -> t m b
193+unfold unf x = fromStreamD $ D.unfold unf x
194+
195+-- | Convert an 'Unfold' with a closed input end into a stream.
196+--
197+-- /Internal/
198+{-# INLINE unfold0 #-}
199+unfold0 :: (IsStream t, Monad m) => Unfold m Void b -> t m b
200+unfold0 unf = unfold unf (error "unfold0: unexpected void evaluation")
201+
202+------------------------------------------------------------------------------
203+-- Specialized Generation
204+------------------------------------------------------------------------------
205+
206+-- Faster than yieldM because there is no bind.
207+--
208+-- |
209+-- @
210+-- yield a = a \`cons` nil
211+-- @
212+--
213+-- Create a singleton stream from a pure value.
214+--
215+-- The following holds in monadic streams, but not in Zip streams:
216+--
217+-- @
218+-- yield = pure
219+-- yield = yieldM . pure
220+-- @
221+--
222+-- In Zip applicative streams 'yield' is not the same as 'pure' because in that
223+-- case 'pure' is equivalent to 'repeat' instead. 'yield' and 'pure' are
224+-- equally efficient, in other cases 'yield' may be slightly more efficient
225+-- than the other equivalent definitions.
226+--
227+-- @since 0.4.0
228+{-# INLINE yield #-}
229+yield :: IsStream t => a -> t m a
230+yield = K.yield
231+
232+-- |
233+-- @
234+-- yieldM m = m \`consM` nil
235+-- @
236+--
237+-- Create a singleton stream from a monadic action.
238+--
239+-- @
240+-- > toList $ yieldM getLine
241+-- hello
242+-- ["hello"]
243+-- @
244+--
245+-- @since 0.4.0
246+{-# INLINE yieldM #-}
247+yieldM :: (Monad m, IsStream t) => m a -> t m a
248+yieldM = K.yieldM
249+
250+-- |
251+-- @
252+-- fromIndices f = let g i = f i \`cons` g (i + 1) in g 0
253+-- @
254+--
255+-- Generate an infinite stream, whose values are the output of a function @f@
256+-- applied on the corresponding index. Index starts at 0.
257+--
258+-- @
259+-- > S.toList $ S.take 5 $ S.fromIndices id
260+-- [0,1,2,3,4]
261+-- @
262+--
263+-- @since 0.6.0
264+{-# INLINE fromIndices #-}
265+fromIndices :: (IsStream t, Monad m) => (Int -> a) -> t m a
266+fromIndices = fromStreamS . S.fromIndices
267+
268+--
269+-- |
270+-- @
271+-- fromIndicesM f = let g i = f i \`consM` g (i + 1) in g 0
272+-- @
273+--
274+-- Generate an infinite stream, whose values are the output of a monadic
275+-- function @f@ applied on the corresponding index. Index starts at 0.
276+--
277+-- /Concurrent/
278+--
279+-- @since 0.6.0
280+{-# INLINE_EARLY fromIndicesM #-}
281+fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
282+fromIndicesM = K.fromIndicesM
283+
284+{-# RULES "fromIndicesM serial" fromIndicesM = fromIndicesMSerial #-}
285+{-# INLINE fromIndicesMSerial #-}
286+fromIndicesMSerial :: MonadAsync m => (Int -> m a) -> SerialT m a
287+fromIndicesMSerial = fromStreamS . S.fromIndicesM
288+
289+-- |
290+-- @
291+-- replicateM = take n . repeatM
292+-- @
293+--
294+-- Generate a stream by performing a monadic action @n@ times. Same as:
295+--
296+-- @
297+-- drain $ serially $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
298+-- drain $ asyncly $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
299+-- @
300+--
301+-- /Concurrent/
302+--
303+-- @since 0.1.1
304+{-# INLINE_EARLY replicateM #-}
305+replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
306+replicateM = K.replicateM
307+
308+{-# RULES "replicateM serial" replicateM = replicateMSerial #-}
309+{-# INLINE replicateMSerial #-}
310+replicateMSerial :: MonadAsync m => Int -> m a -> SerialT m a
311+replicateMSerial n = fromStreamS . S.replicateM n
312+
313+-- |
314+-- @
315+-- replicate = take n . repeat
316+-- @
317+--
318+-- Generate a stream of length @n@ by repeating a value @n@ times.
319+--
320+-- @since 0.6.0
321+{-# INLINE_NORMAL replicate #-}
322+replicate :: (IsStream t, Monad m) => Int -> a -> t m a
323+replicate n = fromStreamS . S.replicate n
324+
325+-- |
326+-- Generate an infinite stream by repeating a pure value.
327+--
328+-- @since 0.4.0
329+{-# INLINE_NORMAL repeat #-}
330+repeat :: (IsStream t, Monad m) => a -> t m a
331+repeat = fromStreamS . S.repeat
332+
333+-- |
334+-- @
335+-- repeatM = fix . consM
336+-- repeatM = cycle1 . yieldM
337+-- @
338+--
339+-- Generate a stream by repeatedly executing a monadic action forever.
340+--
341+-- @
342+-- drain $ serially $ S.take 10 $ S.repeatM $ (threadDelay 1000000 >> print 1)
343+-- drain $ asyncly $ S.take 10 $ S.repeatM $ (threadDelay 1000000 >> print 1)
344+-- @
345+--
346+-- /Concurrent, infinite (do not use with 'parallely')/
347+--
348+-- @since 0.2.0
349+{-# INLINE_EARLY repeatM #-}
350+repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
351+repeatM = K.repeatM
352+
353+{-# RULES "repeatM serial" repeatM = repeatMSerial #-}
354+{-# INLINE repeatMSerial #-}
355+repeatMSerial :: MonadAsync m => m a -> SerialT m a
356+repeatMSerial = fromStreamS . S.repeatM
357+
358+-- |
359+-- @
360+-- iterate f x = x \`cons` iterate f x
361+-- @
362+--
363+-- Generate an infinite stream with @x@ as the first element and each
364+-- successive element derived by applying the function @f@ on the previous
365+-- element.
366+--
367+-- @
368+-- > S.toList $ S.take 5 $ S.iterate (+1) 1
369+-- [1,2,3,4,5]
370+-- @
371+--
372+-- @since 0.1.2
373+{-# INLINE_NORMAL iterate #-}
374+iterate :: (IsStream t, Monad m) => (a -> a) -> a -> t m a
375+iterate step = fromStreamS . S.iterate step
376+
377+-- |
378+-- @
379+-- iterateM f m = m >>= \a -> return a \`consM` iterateM f (f a)
380+-- @
381+--
382+-- Generate an infinite stream with the first element generated by the action
383+-- @m@ and each successive element derived by applying the monadic function
384+-- @f@ on the previous element.
385+--
386+-- When run concurrently, the next iteration can run concurrently with the
387+-- processing of the previous iteration. Note that more than one iteration
388+-- cannot run concurrently as the next iteration depends on the output of the
389+-- previous iteration.
390+--
391+-- @
392+-- drain $ serially $ S.take 10 $ S.iterateM
393+-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) (return 0)
394+--
395+-- drain $ asyncly $ S.take 10 $ S.iterateM
396+-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) (return 0)
397+-- @
398+--
399+-- /Concurrent/
400+--
401+-- /Since: 0.1.2/
402+--
403+-- /Since: 0.7.0 (signature change)/
404+{-# INLINE_EARLY iterateM #-}
405+iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
406+iterateM = K.iterateM
407+
408+{-# RULES "iterateM serial" iterateM = iterateMSerial #-}
409+{-# INLINE iterateMSerial #-}
410+iterateMSerial :: MonadAsync m => (a -> m a) -> m a -> SerialT m a
411+iterateMSerial step = fromStreamS . S.iterateM step
412+
413+------------------------------------------------------------------------------
414+-- Conversions
415+------------------------------------------------------------------------------
416+
417+-- |
418+-- @
419+-- fromListM = 'Prelude.foldr' 'K.consM' 'K.nil'
420+-- @
421+--
422+-- Construct a stream from a list of monadic actions. This is more efficient
423+-- than 'fromFoldableM' for serial streams.
424+--
425+-- @since 0.4.0
426+{-# INLINE_EARLY fromListM #-}
427+fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a
428+fromListM = fromStreamD . D.fromListM
429+{-# RULES "fromListM fallback to StreamK" [1]
430+ forall a. D.toStreamK (D.fromListM a) = fromFoldableM a #-}
431+
432+-- |
433+-- @
434+-- fromFoldableM = 'Prelude.foldr' 'consM' 'K.nil'
435+-- @
436+--
437+-- Construct a stream from a 'Foldable' containing monadic actions.
438+--
439+-- @
440+-- drain $ serially $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
441+-- drain $ asyncly $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
442+-- @
443+--
444+-- /Concurrent (do not use with 'parallely' on infinite containers)/
445+--
446+-- @since 0.3.0
447+{-# INLINE fromFoldableM #-}
448+fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a
449+fromFoldableM = Prelude.foldr consM K.nil
450+
451+-- | Same as 'fromFoldable'.
452+--
453+-- @since 0.1.0
454+{-# DEPRECATED each "Please use fromFoldable instead." #-}
455+{-# INLINE each #-}
456+each :: (IsStream t, Foldable f) => f a -> t m a
457+each = K.fromFoldable
458+
459+-- | Read lines from an IO Handle into a stream of Strings.
460+--
461+-- @since 0.1.0
462+{-# DEPRECATED fromHandle
463+ "Please use Streamly.FileSystem.Handle module (see the changelog)" #-}
464+fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
465+fromHandle h = go
466+ where
467+ go = K.mkStream $ \_ yld _ stp -> do
468+ eof <- liftIO $ IO.hIsEOF h
469+ if eof
470+ then stp
471+ else do
472+ str <- liftIO $ IO.hGetLine h
473+ yld str go
474+
475+-- | Construct a stream by reading a 'Prim' 'IORef' repeatedly.
476+--
477+-- /Internal/
478+--
479+{-# INLINE fromPrimIORef #-}
480+fromPrimIORef :: (IsStream t, MonadIO m, Prim a) => IORef a -> t m a
481+fromPrimIORef = fromStreamD . D.fromPrimIORef
482+
483+------------------------------------------------------------------------------
484+-- Time related
485+------------------------------------------------------------------------------
486+
487+-- | @timesWith g@ returns a stream of time value tuples. The first component
488+-- of the tuple is an absolute time reference (epoch) denoting the start of the
489+-- stream and the second component is a time relative to the reference.
490+--
491+-- The argument @g@ specifies the granularity of the relative time in seconds.
492+-- A lower granularity clock gives higher precision but is more expensive in
493+-- terms of CPU usage. Any granularity lower than 1 ms is treated as 1 ms.
494+--
495+-- @
496+-- >>> S.mapM_ (\x -> print x >> threadDelay 1000000) $ S.timesWith 0.01
497+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 0))
498+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1002028000))
499+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1996656000))
500+-- @
501+--
502+-- Note: This API is not safe on 32-bit machines.
503+--
504+-- /Internal/
505+--
506+{-# INLINE timesWith #-}
507+timesWith :: (IsStream t, MonadAsync m) => Double -> t m (AbsTime, RelTime64)
508+timesWith g = fromStreamD $ D.times g
509+
510+-- | @times@ returns a stream of time value tuples with clock of 10 ms
511+-- granularity. The first component of the tuple is an absolute time reference
512+-- (epoch) denoting the start of the stream and the second component is a time
513+-- relative to the reference.
514+--
515+-- @
516+-- >>> S.mapM_ (\x -> print x >> threadDelay 1000000) $ S.times
517+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 0))
518+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1002028000))
519+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1996656000))
520+-- @
521+--
522+-- Note: This API is not safe on 32-bit machines.
523+--
524+-- /Internal/
525+--
526+{-# INLINE times #-}
527+times :: (IsStream t, MonadAsync m) => t m (AbsTime, RelTime64)
528+times = timesWith 0.01
529+
530+-- | @absTimesWith g@ returns a stream of absolute timestamps using a clock of
531+-- granularity @g@ specified in seconds. A low granularity clock is more
532+-- expensive in terms of CPU usage. Any granularity lower than 1 ms is treated
533+-- as 1 ms.
534+--
535+-- @
536+-- >>> S.mapM_ print $ S.delayPre 1 $ S.absTimesWith 0.01
537+-- @
538+--
539+-- Note: This API is not safe on 32-bit machines.
540+--
541+-- /Internal/
542+--
543+{-# INLINE absTimesWith #-}
544+absTimesWith :: (IsStream t, MonadAsync m, Functor (t m))
545+ => Double -> t m AbsTime
546+absTimesWith = fmap (uncurry addToAbsTime64) . timesWith
547+
548+-- | @absTimes@ returns a stream of absolute timestamps using a clock of 10 ms
549+-- granularity.
550+--
551+-- @
552+-- >>> S.mapM_ print $ S.delayPre 1 $ S.absTimes
553+-- @
554+--
555+-- Note: This API is not safe on 32-bit machines.
556+--
557+-- /Internal/
558+--
559+{-# INLINE absTimes #-}
560+absTimes :: (IsStream t, MonadAsync m, Functor (t m)) => t m AbsTime
561+absTimes = fmap (uncurry addToAbsTime64) times
562+
563+{-# DEPRECATED currentTime "Please use absTimes instead" #-}
564+{-# INLINE currentTime #-}
565+currentTime :: (IsStream t, MonadAsync m, Functor (t m))
566+ => Double -> t m AbsTime
567+currentTime = absTimesWith
568+
569+-- | @relTimesWith g@ returns a stream of relative time values starting from 0,
570+-- using a clock of granularity @g@ specified in seconds. A low granularity
571+-- clock is more expensive in terms of CPU usage. Any granularity lower than 1
572+-- ms is treated as 1 ms.
573+--
574+-- @
575+-- >>> S.mapM_ print $ S.delayPre 1 $ S.relTimesWith 0.01
576+-- > RelTime64 (NanoSecond64 0)
577+-- > RelTime64 (NanoSecond64 91139000)
578+-- > RelTime64 (NanoSecond64 204052000)
579+-- @
580+--
581+-- Note: This API is not safe on 32-bit machines.
582+--
583+-- /Internal/
584+--
585+{-# INLINE relTimesWith #-}
586+relTimesWith :: (IsStream t, MonadAsync m, Functor (t m))
587+ => Double -> t m RelTime64
588+relTimesWith = fmap snd . timesWith
589+
590+-- | @relTimes@ returns a stream of relative time values starting from 0,
591+-- using a clock of granularity 10 ms.
592+--
593+-- @
594+-- >>> S.mapM_ print $ S.delayPre 1 $ S.relTimes
595+-- @
596+--
597+-- Note: This API is not safe on 32-bit machines.
598+--
599+-- /Internal/
600+--
601+{-# INLINE relTimes #-}
602+relTimes :: (IsStream t, MonadAsync m, Functor (t m)) => t m RelTime64
603+relTimes = fmap snd times
604+
605+-- | @durations g@ returns a stream of relative time values measuring the time
606+-- elapsed since the immediate predecessor element of the stream was generated.
607+-- The first element of the stream is always 0. @durations@ uses a clock of
608+-- granularity @g@ specified in seconds. A low granularity clock is more
609+-- expensive in terms of CPU usage. The minimum granularity is 1 millisecond.
610+-- Durations lower than 1 ms will be 0.
611+--
612+-- Note: This API is not safe on 32-bit machines.
613+--
614+-- /Unimplemented/
615+--
616+{-# INLINE durations #-}
617+durations :: -- (IsStream t, MonadAsync m) =>
618+ Double -> t m RelTime64
619+durations = undefined
620+
621+-- | Generate ticks at the specified rate. The rate is adaptive, the tick
622+-- generation speed can be increased or decreased at different times to achieve
623+-- the specified rate. The specific behavior for different styles of 'Rate'
624+-- specifications is documented under 'Rate'. The effective maximum rate
625+-- achieved by a stream is governed by the processor speed.
626+--
627+-- /Unimplemented/
628+--
629+{-# INLINE ticks #-}
630+ticks :: -- (IsStream t, MonadAsync m) =>
631+ Rate -> t m ()
632+ticks = undefined
633+
634+-- | Generate a singleton event at or after the specified absolute time. Note
635+-- that this is different from a threadDelay, a threadDelay starts from the
636+-- time when the action is evaluated, whereas if we use AbsTime based timeout
637+-- it will immediately expire if the action is evaluated too late.
638+--
639+-- /Unimplemented/
640+--
641+{-# INLINE timeout #-}
642+timeout :: -- (IsStream t, MonadAsync m) =>
643+ AbsTime -> t m ()
644+timeout = undefined
src/Streamly/Internal/Data/Stream/IsStream/Transform.hsnew file+2719
@@ -0,0 +1,2719 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.IsStream.Transform
3+-- Copyright : (c) 2020 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+
9+module Streamly.Internal.Data.Stream.IsStream.Transform
10+ (
11+ -- * Transformation
12+ transform
13+
14+ -- ** Mapping
15+ , Serial.map
16+ , sequence
17+ , mapM
18+ , smapM
19+ -- $smapM_Notes
20+
21+ -- ** Special Maps
22+ , mapM_
23+ , trace
24+ , trace_
25+ , tap
26+ , tapOffsetEvery
27+ , tapAsync
28+ , tapRate
29+ , pollCounts
30+
31+ -- ** Scanning
32+ -- ** Left scans
33+ , scanl'
34+ , scanlM'
35+ , scanlMAfter'
36+ , postscanl'
37+ , postscanlM'
38+ , prescanl'
39+ , prescanlM'
40+ , scanl1'
41+ , scanl1M'
42+
43+ -- ** Scan Using Fold
44+ , scan
45+ , postscan
46+
47+ -- XXX Once we have pipes the contravariant transformations can be
48+ -- represented by attaching pipes before a transformation.
49+ --
50+ -- , lscanl'
51+ -- , lscanlM'
52+ -- , lscanl1'
53+ -- , lscanl1M'
54+ --
55+ -- , lpostscanl'
56+ -- , lpostscanlM'
57+ -- , lprescanl'
58+ -- , lprescanlM'
59+
60+ -- ** Concurrent Transformation
61+ , D.mkParallel
62+ -- Par.mkParallel
63+ , applyAsync
64+ , (|$)
65+ , (|&)
66+
67+ -- ** Filtering
68+
69+ , filter
70+ , filterM
71+
72+ -- ** Deleting Elements
73+ , deleteBy
74+ , uniq
75+ -- , uniqBy -- by predicate e.g. to remove duplicate "/" in a path
76+ -- , uniqOn -- to remove duplicate sequences
77+ -- , pruneBy -- dropAround + uniqBy - like words
78+
79+ -- ** Inserting Elements
80+
81+ , insertBy
82+ , intersperseM
83+ , intersperseM_
84+ , intersperse
85+ , intersperseSuffix
86+ , intersperseSuffix_
87+ , interspersePrefix_
88+ , intersperseSuffixBySpan
89+ -- , intersperseBySpan
90+ -- , intersperseByIndices -- using an index function/stream
91+
92+ -- time domain intersperse
93+ -- , intersperseByTime
94+ -- , intersperseByEvent
95+ , delay
96+ , delayPost
97+ , delayPre
98+
99+ -- ** Indexing
100+ , indexed
101+ , indexedR
102+ -- , timestampedR -- timer
103+
104+ -- ** Reordering
105+ , reverse
106+ , reverse'
107+
108+ -- ** Composable Left Folds
109+ -- | See "Streamly.Internal.Data.Fold"
110+ , foldMany
111+ , foldSequence
112+ , foldIterate
113+
114+ -- ** Parsers
115+ -- | See "Streamly.Internal.Data.Parser"
116+ , parseMany
117+ , parseManyD
118+ , parseManyTill
119+ , parseSequence
120+ , parseIterate
121+
122+ -- ** Trimming
123+ , take
124+ -- , takeGE
125+ -- , takeBetween
126+ , takeByTime
127+ -- , takeEnd
128+ , takeWhile
129+ , takeWhileM
130+ -- , takeWhileEnd
131+ , drop
132+ , dropByTime
133+ -- , dropEnd
134+ , dropWhile
135+ , dropWhileM
136+ -- , dropWhileEnd
137+ -- , dropAround
138+
139+ -- ** Breaking
140+
141+ -- Nary
142+ , chunksOf
143+ , chunksOf2
144+ , arraysOf
145+
146+ -- ** Searching
147+ -- -- *** Searching Elements
148+ , findIndices
149+ , elemIndices
150+
151+ -- -- *** Searching Sequences
152+ -- , seqIndices -- search a sequence in the stream
153+
154+ -- -- *** Searching Multiple Sequences
155+ -- , seqIndicesAny -- search any of the given sequence in the stream
156+
157+ -- -- -- ** Searching Streams
158+ -- -- | Finding a stream within another stream.
159+
160+ -- ** Splitting
161+ -- | Streams can be sliced into segments in space or in time. We use the
162+ -- term @chunk@ to refer to a spatial length of the stream (spatial window)
163+ -- and the term @session@ to refer to a length in time (time window).
164+
165+ -- -- *** Using Element Separators
166+ , splitOn
167+ , splitOnSuffix
168+ -- , splitOnPrefix
169+
170+ -- , splitBy
171+ , splitWithSuffix
172+ -- , splitByPrefix
173+ , wordsBy -- stripAndCompactBy
174+
175+ -- -- *** Splitting By Sequences
176+ , splitOnSeq
177+ , splitOnSuffixSeq
178+ -- , splitOnPrefixSeq
179+
180+ -- Keeping the delimiters
181+ , splitWithSuffixSeq
182+ -- , splitByPrefixSeq
183+ -- , wordsBySeq
184+
185+ -- Splitting using multiple sequence separators
186+ -- , splitOnAnySeq
187+ -- , splitOnAnySuffixSeq
188+ -- , splitOnAnyPrefixSeq
189+
190+ -- -- *** Splitting By Streams
191+ -- -- | Splitting a stream using another stream as separator.
192+
193+ -- Nested splitting
194+ , splitInnerBy
195+ , splitInnerBySuffix
196+
197+ -- ** Grouping
198+ -- In imperative terms, grouped folding can be considered as a nested loop
199+ -- where we loop over the stream to group elements and then loop over
200+ -- individual groups to fold them to a single value that is yielded in the
201+ -- output stream.
202+
203+ -- , groupScan
204+
205+ , groups
206+ , groupsBy
207+ , groupsByRolling
208+
209+ -- ** Group map
210+ , rollingMapM
211+ , rollingMap
212+
213+ -- ** Appending
214+ , serial
215+ , append
216+
217+ -- ** Interleaving
218+ , interleave
219+ , interleaveMin
220+ , interleaveSuffix
221+ , interleaveInfix
222+
223+ , wSerial
224+ , Serial.wSerialFst
225+ , Serial.wSerialMin
226+
227+ -- ** Scheduling
228+ , ahead
229+ , async
230+ , wAsync
231+ , roundrobin
232+
233+ -- ** Parallel
234+ , parallel
235+ , Par.parallelFst
236+ , Par.parallelMin
237+
238+ -- ** Merging
239+ -- , merge
240+ , mergeBy
241+ , mergeByM
242+ , mergeAsyncBy
243+ , mergeAsyncByM
244+
245+ -- ** Zipping
246+ , Z.zipWith
247+ , Z.zipWithM
248+ , Z.zipAsyncWith
249+ , Z.zipAsyncWithM
250+
251+ -- ** Flattening a Container of Streams
252+ , concatFoldableWith
253+ , concatMapFoldableWith
254+ , concatForFoldableWith
255+
256+ -- ** Flattening a Stream of Streams
257+ , concat
258+ , concatMap
259+ , concatMapM
260+ , concatMapWith
261+ , concatSmapMWith
262+ -- , bindWith
263+
264+ -- ** Flattening Using Unfolds
265+ , concatUnfold
266+ , concatUnfoldInterleave
267+ , concatUnfoldRoundrobin
268+
269+ -- ** Inserting Streams in Streams
270+ , gintercalate
271+ , gintercalateSuffix
272+ , intercalate
273+ , intercalateSuffix
274+ , interpose
275+ , interposeSuffix
276+ -- , interposeBy
277+
278+ -- * Generalize Inner Monad
279+ , hoist
280+ , generally
281+
282+ -- * Transform Inner Monad
283+ , liftInner
284+ , usingReaderT
285+ , runReaderT
286+ , evalStateT
287+ , usingStateT
288+ , runStateT
289+
290+ -- ** Maybe Streams
291+ , catMaybes
292+ , mapMaybe
293+ , mapMaybeM
294+
295+ -- ** Either Streams
296+ , lefts
297+ , rights
298+
299+ -- * Deprecated
300+ , scanx
301+ )
302+where
303+
304+#include "inline.hs"
305+
306+import Control.Concurrent (threadDelay)
307+import Control.Monad (void)
308+import Control.Monad.Catch (MonadCatch, MonadThrow)
309+import Control.Monad.IO.Class (MonadIO(..))
310+import Control.Monad.Trans.Reader (ReaderT)
311+import Control.Monad.Trans.State.Strict (StateT)
312+import Control.Monad.Trans.Class (MonadTrans(..))
313+import Data.Either (isLeft, isRight)
314+import Data.Functor.Identity (Identity (..))
315+import Data.Maybe (isJust, fromJust)
316+import Foreign.Storable (Storable)
317+import Streamly.Internal.BaseCompat (fromLeft, fromRight)
318+import Streamly.Internal.Data.Fold.Types (Fold (..), Fold2 (..))
319+import Streamly.Internal.Data.Parser (Parser (..))
320+import Streamly.Internal.Data.Unfold.Types (Unfold)
321+import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array, writeNUnsafe)
322+import Streamly.Internal.Data.SVar (MonadAsync)
323+import Streamly.Internal.Data.Stream.Ahead (ahead)
324+import Streamly.Internal.Data.Stream.Async (async, wAsync)
325+import Streamly.Internal.Data.Stream.Combinators (maxYields)
326+import Streamly.Internal.Data.Stream.Parallel (parallel)
327+import Streamly.Internal.Data.Stream.Prelude
328+ (fromStreamS, toStreamS, concatFoldableWith, concatMapFoldableWith
329+ , concatForFoldableWith)
330+import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
331+import Streamly.Internal.Data.Stream.StreamK (IsStream)
332+import Streamly.Internal.Data.Stream.Serial (SerialT, serial, wSerial)
333+import Streamly.Internal.Data.Pipe.Types (Pipe (..))
334+import Streamly.Internal.Data.Time.Units (TimeUnit64)
335+
336+import qualified Streamly.Internal.Data.Fold as FL
337+import qualified Streamly.Internal.Data.Stream.Prelude as P
338+import qualified Streamly.Internal.Data.Stream.StreamK as K
339+import qualified Streamly.Internal.Data.Stream.StreamD as D
340+import qualified Streamly.Internal.Data.Stream.Serial as Serial
341+import qualified Streamly.Internal.Data.Stream.Parallel as Par
342+import qualified Streamly.Internal.Data.Stream.Zip as Z
343+import qualified Streamly.Internal.Data.Parser.ParserK.Types as PRK
344+import qualified Streamly.Internal.Data.Parser.ParserD as PRD
345+#ifdef USE_STREAMK_ONLY
346+import qualified Streamly.Internal.Data.Stream.StreamK as S
347+#else
348+import qualified Streamly.Internal.Data.Stream.StreamD as S
349+#endif
350+
351+import Prelude hiding
352+ ( filter, drop, dropWhile, take, takeWhile, zipWith, foldr
353+ , foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem
354+ , notElem, maximum, minimum, head, last, tail, length, null
355+ , reverse, iterate, init, and, or, lookup, foldr1, (!!)
356+ , scanl, scanl1, replicate, concatMap, span, splitAt, break
357+ , repeat, concat, mconcat)
358+
359+------------------------------------------------------------------------------
360+-- Searching
361+------------------------------------------------------------------------------
362+
363+-- | Find all the indices where the element in the stream satisfies the given
364+-- predicate.
365+--
366+-- > findIndices = fold Fold.findIndices
367+--
368+-- @since 0.5.0
369+{-# INLINE findIndices #-}
370+findIndices :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m Int
371+findIndices p m = fromStreamS $ S.findIndices p (toStreamS m)
372+
373+-- | Find all the indices where the value of the element in the stream is equal
374+-- to the given value.
375+--
376+-- > elemIndices a = findIndices (== a)
377+--
378+-- @since 0.5.0
379+{-# INLINE elemIndices #-}
380+elemIndices :: (IsStream t, Eq a, Monad m) => a -> t m a -> t m Int
381+elemIndices a = findIndices (== a)
382+
383+------------------------------------------------------------------------------
384+-- Map and Fold
385+------------------------------------------------------------------------------
386+
387+-- XXX this can utilize parallel mapping if we implement it as drain . mapM
388+-- |
389+-- > mapM_ = drain . mapM
390+--
391+-- Apply a monadic action to each element of the stream and discard the output
392+-- of the action. This is not really a pure transformation operation but a
393+-- transformation followed by fold.
394+--
395+-- @since 0.1.0
396+{-# INLINE mapM_ #-}
397+mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
398+mapM_ f m = S.mapM_ f $ toStreamS m
399+
400+------------------------------------------------------------------------------
401+-- Concurrent Application
402+------------------------------------------------------------------------------
403+
404+infixr 0 |$
405+infixl 1 |&
406+
407+-- | Parallel transform application operator; applies a stream transformation
408+-- function @t m a -> t m b@ to a stream @t m a@ concurrently; the input stream
409+-- is evaluated asynchronously in an independent thread yielding elements to a
410+-- buffer and the transformation function runs in another thread consuming the
411+-- input from the buffer. '|$' is just like regular function application
412+-- operator '$' except that it is concurrent.
413+--
414+-- If you read the signature as @(t m a -> t m b) -> (t m a -> t m b)@ you can
415+-- look at it as a transformation that converts a transform function to a
416+-- buffered concurrent transform function.
417+--
418+-- The following code prints a value every second even though each stage adds a
419+-- 1 second delay.
420+--
421+--
422+-- @
423+-- drain $
424+-- S.mapM (\\x -> threadDelay 1000000 >> print x)
425+-- |$ S.repeatM (threadDelay 1000000 >> return 1)
426+-- @
427+--
428+-- /Concurrent/
429+--
430+-- /Since: 0.3.0 ("Streamly")/
431+--
432+-- @since 0.8.0
433+{-# INLINE (|$) #-}
434+(|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> (t m a -> t m b)
435+-- (|$) f = f . Async.mkAsync
436+(|$) f = f . D.mkParallel
437+
438+-- | Same as '|$'.
439+--
440+-- /Internal/
441+--
442+{-# INLINE applyAsync #-}
443+applyAsync :: (IsStream t, MonadAsync m)
444+ => (t m a -> t m b) -> (t m a -> t m b)
445+applyAsync = (|$)
446+
447+-- | Parallel reverse function application operator for streams; just like the
448+-- regular reverse function application operator '&' except that it is
449+-- concurrent.
450+--
451+-- @
452+-- drain $
453+-- S.repeatM (threadDelay 1000000 >> return 1)
454+-- |& S.mapM (\\x -> threadDelay 1000000 >> print x)
455+-- @
456+--
457+-- /Concurrent/
458+--
459+-- /Since: 0.3.0 ("Streamly")/
460+--
461+-- @since 0.8.0
462+{-# INLINE (|&) #-}
463+(|&) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> t m b) -> t m b
464+x |& f = f |$ x
465+
466+------------------------------------------------------------------------------
467+-- General Transformation
468+------------------------------------------------------------------------------
469+
470+-- | Use a 'Pipe' to transform a stream.
471+--
472+-- /Internal/
473+--
474+{-# INLINE transform #-}
475+transform :: (IsStream t, Monad m) => Pipe m a b -> t m a -> t m b
476+transform pipe xs = fromStreamD $ D.transform pipe (toStreamD xs)
477+
478+------------------------------------------------------------------------------
479+-- Transformation by Folding (Scans)
480+------------------------------------------------------------------------------
481+
482+-- XXX It may be useful to have a version of scan where we can keep the
483+-- accumulator independent of the value emitted. So that we do not necessarily
484+-- have to keep a value in the accumulator which we are not using. We can pass
485+-- an extraction function that will take the accumulator and the current value
486+-- of the element and emit the next value in the stream. That will also make it
487+-- possible to modify the accumulator after using it. In fact, the step function
488+-- can return new accumulator and the value to be emitted. The signature would
489+-- be more like mapAccumL. Or we can change the signature of scanx to
490+-- accommodate this.
491+--
492+-- | Strict left scan with an extraction function. Like 'scanl'', but applies a
493+-- user supplied extraction function (the third argument) at each step. This is
494+-- designed to work with the @foldl@ library. The suffix @x@ is a mnemonic for
495+-- extraction.
496+--
497+-- /Since 0.2.0/
498+--
499+-- /Since: 0.7.0 (Monad m constraint)/
500+{-# DEPRECATED scanx "Please use scanl followed by map instead." #-}
501+{-# INLINE scanx #-}
502+scanx :: (IsStream t, Monad m) => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
503+scanx = P.scanlx'
504+
505+-- XXX this needs to be concurrent
506+-- XXX because of the use of D.cons for appending, scanlM' has quadratic
507+-- complexity when iterated over a stream. We should use StreamK style scanlM'
508+-- for linear performance on iteration.
509+--
510+-- | Like 'scanl'' but with a monadic step function and a monadic seed.
511+--
512+-- /Since: 0.4.0/
513+--
514+-- /Since: 0.8.0 (signature change)/
515+{-# INLINE scanlM' #-}
516+scanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
517+scanlM' step begin m = fromStreamD $ D.scanlM' step begin $ toStreamD m
518+
519+-- | @scanlMAfter' accumulate initial done stream@ is like 'scanlM'' except
520+-- that it provides an additional @done@ function to be applied on the
521+-- accumulator when the stream stops. The result of @done@ is also emitted in
522+-- the stream.
523+--
524+-- This function can be used to allocate a resource in the beginning of the
525+-- scan and release it when the stream ends or to flush the internal state of
526+-- the scan at the end.
527+--
528+-- /Internal/
529+--
530+{-# INLINE scanlMAfter' #-}
531+scanlMAfter' :: (IsStream t, Monad m)
532+ => (b -> a -> m b) -> m b -> (b -> m b) -> t m a -> t m b
533+scanlMAfter' step initial done stream =
534+ fromStreamD $ D.scanlMAfter' step initial done $ toStreamD stream
535+
536+-- XXX because of the use of D.cons for appending, scanl' has quadratic
537+-- complexity when iterated over a stream. We should use StreamK style scanlM'
538+-- for linear performance on iteration.
539+
540+-- | Strict left scan. Like 'map', 'scanl'' too is a one to one transformation,
541+-- however it adds an extra element.
542+--
543+-- @
544+-- > S.toList $ S.scanl' (+) 0 $ fromList [1,2,3,4]
545+-- [0,1,3,6,10]
546+-- @
547+--
548+-- @
549+-- > S.toList $ S.scanl' (flip (:)) [] $ S.fromList [1,2,3,4]
550+-- [[],[1],[2,1],[3,2,1],[4,3,2,1]]
551+-- @
552+--
553+-- The output of 'scanl'' is the initial value of the accumulator followed by
554+-- all the intermediate steps and the final result of 'foldl''.
555+--
556+-- By streaming the accumulated state after each fold step, we can share the
557+-- state across multiple stages of stream composition. Each stage can modify or
558+-- extend the state, do some processing with it and emit it for the next stage,
559+-- thus modularizing the stream processing. This can be useful in
560+-- stateful or event-driven programming.
561+--
562+-- Consider the following monolithic example, computing the sum and the product
563+-- of the elements in a stream in one go using a @foldl'@:
564+--
565+-- @
566+-- > S.foldl' (\\(s, p) x -> (s + x, p * x)) (0,1) $ S.fromList \[1,2,3,4]
567+-- (10,24)
568+-- @
569+--
570+-- Using @scanl'@ we can make it modular by computing the sum in the first
571+-- stage and passing it down to the next stage for computing the product:
572+--
573+-- @
574+-- > S.foldl' (\\(_, p) (s, x) -> (s, p * x)) (0,1)
575+-- $ S.scanl' (\\(s, _) x -> (s + x, x)) (0,1)
576+-- $ S.fromList \[1,2,3,4]
577+-- (10,24)
578+-- @
579+--
580+-- IMPORTANT: 'scanl'' evaluates the accumulator to WHNF. To avoid building
581+-- lazy expressions inside the accumulator, it is recommended that a strict
582+-- data structure is used for accumulator.
583+--
584+-- See also: 'usingStateT'
585+--
586+-- @since 0.2.0
587+{-# INLINE scanl' #-}
588+scanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
589+scanl' step z m = fromStreamS $ S.scanl' step z $ toStreamS m
590+
591+-- | Like 'scanl'' but does not stream the initial value of the accumulator.
592+--
593+-- > postscanl' f z xs = S.drop 1 $ S.scanl' f z xs
594+--
595+-- @since 0.7.0
596+{-# INLINE postscanl' #-}
597+postscanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
598+postscanl' step z m = fromStreamD $ D.postscanl' step z $ toStreamD m
599+
600+-- XXX this needs to be concurrent
601+-- | Like 'postscanl'' but with a monadic step function and a monadic seed.
602+--
603+-- /Since: 0.7.0/
604+--
605+-- /Since: 0.8.0 (signature change)/
606+{-# INLINE postscanlM' #-}
607+postscanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
608+postscanlM' step z m = fromStreamD $ D.postscanlM' step z $ toStreamD m
609+
610+-- XXX prescanl does not sound very useful, enable only if there is a
611+-- compelling use case.
612+--
613+-- | Like scanl' but does not stream the final value of the accumulator.
614+--
615+-- /Internal/
616+{-# INLINE prescanl' #-}
617+prescanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
618+prescanl' step z m = fromStreamD $ D.prescanl' step z $ toStreamD m
619+
620+-- XXX this needs to be concurrent
621+-- | Like prescanl' but with a monadic step function and a monadic seed.
622+--
623+-- /Internal/
624+{-# INLINE prescanlM' #-}
625+prescanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
626+prescanlM' step z m = fromStreamD $ D.prescanlM' step z $ toStreamD m
627+
628+-- XXX this needs to be concurrent
629+-- | Like 'scanl1'' but with a monadic step function.
630+--
631+-- @since 0.6.0
632+{-# INLINE scanl1M' #-}
633+scanl1M' :: (IsStream t, Monad m) => (a -> a -> m a) -> t m a -> t m a
634+scanl1M' step m = fromStreamD $ D.scanl1M' step $ toStreamD m
635+
636+-- | Like 'scanl'' but for a non-empty stream. The first element of the stream
637+-- is used as the initial value of the accumulator. Does nothing if the stream
638+-- is empty.
639+--
640+-- @
641+-- > S.toList $ S.scanl1 (+) $ fromList [1,2,3,4]
642+-- [1,3,6,10]
643+-- @
644+--
645+-- @since 0.6.0
646+{-# INLINE scanl1' #-}
647+scanl1' :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> t m a
648+scanl1' step m = fromStreamD $ D.scanl1' step $ toStreamD m
649+
650+------------------------------------------------------------------------------
651+-- Scanning with a Fold
652+------------------------------------------------------------------------------
653+
654+-- | Scan a stream using the given monadic fold.
655+--
656+-- @since 0.7.0
657+{-# INLINE scan #-}
658+scan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
659+scan = P.scanOnce
660+
661+-- | Postscan a stream using the given monadic fold.
662+--
663+-- @since 0.7.0
664+{-# INLINE postscan #-}
665+postscan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
666+postscan = P.postscanOnce
667+
668+------------------------------------------------------------------------------
669+-- Stateful Transformations
670+------------------------------------------------------------------------------
671+
672+-- XXX this is not a one-to-one map so calling it map may not be right.
673+-- We can perhaps call it zipWithTail or rollWith.
674+--
675+-- | Apply a function on every two successive elements of a stream. If the
676+-- stream consists of a single element the output is an empty stream.
677+--
678+-- This is the stream equivalent of the list idiom @zipWith f xs (tail xs)@.
679+--
680+-- /Internal/
681+--
682+{-# INLINE rollingMap #-}
683+rollingMap :: (IsStream t, Monad m) => (a -> a -> b) -> t m a -> t m b
684+rollingMap f m = fromStreamD $ D.rollingMap f $ toStreamD m
685+
686+-- | Like 'rollingMap' but with an effectful map function.
687+--
688+-- /Internal/
689+--
690+{-# INLINE rollingMapM #-}
691+rollingMapM :: (IsStream t, Monad m) => (a -> a -> m b) -> t m a -> t m b
692+rollingMapM f m = fromStreamD $ D.rollingMapM f $ toStreamD m
693+
694+------------------------------------------------------------------------------
695+-- Transformation by Filtering
696+------------------------------------------------------------------------------
697+
698+-- | Include only those elements that pass a predicate.
699+--
700+-- @since 0.1.0
701+{-# INLINE filter #-}
702+#if __GLASGOW_HASKELL__ != 802
703+-- GHC 8.2.2 crashes with this code, when used with "stack"
704+filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
705+filter p m = fromStreamS $ S.filter p $ toStreamS m
706+#else
707+filter :: IsStream t => (a -> Bool) -> t m a -> t m a
708+filter = K.filter
709+#endif
710+
711+-- | Same as 'filter' but with a monadic predicate.
712+--
713+-- @since 0.4.0
714+{-# INLINE filterM #-}
715+filterM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
716+filterM p m = fromStreamD $ D.filterM p $ toStreamD m
717+
718+-- | Drop repeated elements that are adjacent to each other.
719+--
720+-- @since 0.6.0
721+{-# INLINE uniq #-}
722+uniq :: (Eq a, IsStream t, Monad m) => t m a -> t m a
723+uniq = fromStreamD . D.uniq . toStreamD
724+
725+-- | Take first 'n' elements from the stream and discard the rest.
726+--
727+-- @since 0.1.0
728+{-# INLINE take #-}
729+take :: (IsStream t, Monad m) => Int -> t m a -> t m a
730+take n m = fromStreamS $ S.take n $ toStreamS
731+ (maxYields (Just (fromIntegral n)) m)
732+
733+-- | End the stream as soon as the predicate fails on an element.
734+--
735+-- @since 0.1.0
736+{-# INLINE takeWhile #-}
737+takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
738+takeWhile p m = fromStreamS $ S.takeWhile p $ toStreamS m
739+
740+-- | Same as 'takeWhile' but with a monadic predicate.
741+--
742+-- @since 0.4.0
743+{-# INLINE takeWhileM #-}
744+takeWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
745+takeWhileM p m = fromStreamD $ D.takeWhileM p $ toStreamD m
746+
747+-- | @takeByTime duration@ yields stream elements upto specified time
748+-- @duration@. The duration starts when the stream is evaluated for the first
749+-- time, before the first element is yielded. The time duration is checked
750+-- before generating each element, if the duration has expired the stream
751+-- stops.
752+--
753+-- The total time taken in executing the stream is guaranteed to be /at least/
754+-- @duration@, however, because the duration is checked before generating an
755+-- element, the upper bound is indeterminate and depends on the time taken in
756+-- generating and processing the last element.
757+--
758+-- No element is yielded if the duration is zero. At least one element is
759+-- yielded if the duration is non-zero.
760+--
761+-- /Internal/
762+--
763+{-# INLINE takeByTime #-}
764+takeByTime ::(MonadIO m, IsStream t, TimeUnit64 d) => d -> t m a -> t m a
765+takeByTime d = fromStreamD . D.takeByTime d . toStreamD
766+
767+-- | Discard first 'n' elements from the stream and take the rest.
768+--
769+-- @since 0.1.0
770+{-# INLINE drop #-}
771+drop :: (IsStream t, Monad m) => Int -> t m a -> t m a
772+drop n m = fromStreamS $ S.drop n $ toStreamS m
773+
774+-- | Drop elements in the stream as long as the predicate succeeds and then
775+-- take the rest of the stream.
776+--
777+-- @since 0.1.0
778+{-# INLINE dropWhile #-}
779+dropWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
780+dropWhile p m = fromStreamS $ S.dropWhile p $ toStreamS m
781+
782+-- | Same as 'dropWhile' but with a monadic predicate.
783+--
784+-- @since 0.4.0
785+{-# INLINE dropWhileM #-}
786+dropWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
787+dropWhileM p m = fromStreamD $ D.dropWhileM p $ toStreamD m
788+
789+-- | @dropByTime duration@ drops stream elements until specified @duration@ has
790+-- passed. The duration begins when the stream is evaluated for the first
791+-- time. The time duration is checked /after/ generating a stream element, the
792+-- element is yielded if the duration has expired otherwise it is dropped.
793+--
794+-- The time elapsed before starting to generate the first element is /at most/
795+-- @duration@, however, because the duration expiry is checked after the
796+-- element is generated, the lower bound is indeterminate and depends on the
797+-- time taken in generating an element.
798+--
799+-- All elements are yielded if the duration is zero.
800+--
801+-- /Internal/
802+--
803+{-# INLINE dropByTime #-}
804+dropByTime ::(MonadIO m, IsStream t, TimeUnit64 d) => d -> t m a -> t m a
805+dropByTime d = fromStreamD . D.dropByTime d . toStreamD
806+
807+------------------------------------------------------------------------------
808+-- Transformation by Mapping
809+------------------------------------------------------------------------------
810+
811+-- |
812+-- @
813+-- mapM f = sequence . map f
814+-- @
815+--
816+-- Apply a monadic function to each element of the stream and replace it with
817+-- the output of the resulting action.
818+--
819+-- @
820+-- > drain $ S.mapM putStr $ S.fromList ["a", "b", "c"]
821+-- abc
822+--
823+-- drain $ S.replicateM 10 (return 1)
824+-- & (serially . S.mapM (\\x -> threadDelay 1000000 >> print x))
825+--
826+-- drain $ S.replicateM 10 (return 1)
827+-- & (asyncly . S.mapM (\\x -> threadDelay 1000000 >> print x))
828+-- @
829+--
830+-- /Concurrent (do not use with 'parallely' on infinite streams)/
831+--
832+-- @since 0.1.0
833+{-# INLINE_EARLY mapM #-}
834+mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
835+mapM = K.mapM
836+
837+{-# RULES "mapM serial" mapM = mapMSerial #-}
838+{-# INLINE mapMSerial #-}
839+mapMSerial :: Monad m => (a -> m b) -> SerialT m a -> SerialT m b
840+mapMSerial = Serial.mapM
841+
842+-- |
843+-- @
844+-- sequence = mapM id
845+-- @
846+--
847+-- Replace the elements of a stream of monadic actions with the outputs of
848+-- those actions.
849+--
850+-- @
851+-- > drain $ S.sequence $ S.fromList [putStr "a", putStr "b", putStrLn "c"]
852+-- abc
853+--
854+-- drain $ S.replicateM 10 (return $ threadDelay 1000000 >> print 1)
855+-- & (serially . S.sequence)
856+--
857+-- drain $ S.replicateM 10 (return $ threadDelay 1000000 >> print 1)
858+-- & (asyncly . S.sequence)
859+-- @
860+--
861+-- /Concurrent (do not use with 'parallely' on infinite streams)/
862+--
863+-- @since 0.1.0
864+{-# INLINE sequence #-}
865+sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
866+sequence m = fromStreamS $ S.sequence (toStreamS m)
867+
868+-- $smapM_Notes
869+--
870+-- The stateful step function can be simplified to @(s -> a -> m b)@ to provide
871+-- a read-only environment. However, that would just be 'mapM'.
872+--
873+-- The initial action could be @m (s, Maybe b)@, and we can also add a final
874+-- action @s -> m (Maybe b)@. This can be used to get pre/post scan like
875+-- functionality and also to flush the state in the end like scanlMAfter'.
876+-- We can also use it along with a fusible version of bracket to get
877+-- scanlMAfter' like functionality. See issue #677.
878+--
879+-- This can be further generalized to a type similar to Fold/Parser, giving it
880+-- filtering and parsing capability as well (this is in fact equivalent to
881+-- parseMany):
882+--
883+-- smapM :: (s -> a -> m (Step s b)) -> m s -> t m a -> t m b
884+--
885+
886+-- | A stateful 'mapM', equivalent to a left scan, more like mapAccumL.
887+-- Hopefully, this is a better alternative to @scan@. Separation of state from
888+-- the output makes it easier to think in terms of a shared state, and also
889+-- makes it easier to keep the state fully strict and the output lazy.
890+--
891+-- See also: 'scanlM''
892+--
893+-- /Internal/
894+--
895+{-# INLINE smapM #-}
896+smapM :: (IsStream t, Monad m) =>
897+ (s -> a -> m (s, b))
898+ -> m s
899+ -> t m a
900+ -> t m b
901+smapM step initial stream =
902+ -- XXX implement this directly instead of using scanlM'
903+ -- Once we have postscanlM' with monadic initial we can use this code
904+ -- let r = postscanlM'
905+ -- (\(s, _) a -> step s a)
906+ -- (fmap (,undefined) initial)
907+ -- stream
908+ let r = postscanlM'
909+ (\(s, _) a -> step s a)
910+ (fmap (,undefined) initial)
911+ stream
912+ in Serial.map snd r
913+
914+------------------------------------------------------------------------------
915+-- Maybe Streams
916+------------------------------------------------------------------------------
917+
918+-- | Map a 'Maybe' returning function to a stream, filter out the 'Nothing'
919+-- elements, and return a stream of values extracted from 'Just'.
920+--
921+-- Equivalent to:
922+--
923+-- @
924+-- mapMaybe f = S.map 'fromJust' . S.filter 'isJust' . S.map f
925+-- @
926+--
927+-- @since 0.3.0
928+{-# INLINE mapMaybe #-}
929+mapMaybe :: (IsStream t, Monad m) => (a -> Maybe b) -> t m a -> t m b
930+mapMaybe f m = fromStreamS $ S.mapMaybe f $ toStreamS m
931+
932+-- | Like 'mapMaybe' but maps a monadic function.
933+--
934+-- Equivalent to:
935+--
936+-- @
937+-- mapMaybeM f = S.map 'fromJust' . S.filter 'isJust' . S.mapM f
938+-- @
939+--
940+-- /Concurrent (do not use with 'parallely' on infinite streams)/
941+--
942+-- @since 0.3.0
943+{-# INLINE_EARLY mapMaybeM #-}
944+mapMaybeM :: (IsStream t, MonadAsync m, Functor (t m))
945+ => (a -> m (Maybe b)) -> t m a -> t m b
946+mapMaybeM f = fmap fromJust . filter isJust . K.mapM f
947+
948+{-# RULES "mapMaybeM serial" mapMaybeM = mapMaybeMSerial #-}
949+{-# INLINE mapMaybeMSerial #-}
950+mapMaybeMSerial :: Monad m => (a -> m (Maybe b)) -> SerialT m a -> SerialT m b
951+mapMaybeMSerial f m = fromStreamD $ D.mapMaybeM f $ toStreamD m
952+
953+-- | In a stream of 'Maybe's, discard 'Nothing's and unwrap 'Just's.
954+--
955+-- /Internal/
956+--
957+catMaybes :: (IsStream t, Monad m, Functor (t m)) => t m (Maybe a) -> t m a
958+catMaybes = fmap fromJust . filter isJust
959+
960+------------------------------------------------------------------------------
961+-- Transformation by Reordering
962+------------------------------------------------------------------------------
963+
964+-- XXX Use a compact region list to temporarily store the list, in both reverse
965+-- as well as in reverse'.
966+--
967+-- /Note:/ 'reverse'' is much faster than this, use that when performance
968+-- matters.
969+--
970+-- > reverse = S.foldlT (flip S.cons) S.nil
971+--
972+-- | Returns the elements of the stream in reverse order. The stream must be
973+-- finite. Note that this necessarily buffers the entire stream in memory.
974+--
975+-- /Since 0.7.0 (Monad m constraint)/
976+--
977+-- /Since: 0.1.1/
978+{-# INLINE reverse #-}
979+reverse :: (IsStream t, Monad m) => t m a -> t m a
980+reverse s = fromStreamS $ S.reverse $ toStreamS s
981+
982+-- | Like 'reverse' but several times faster, requires a 'Storable' instance.
983+--
984+-- /Internal/
985+{-# INLINE reverse' #-}
986+reverse' :: (IsStream t, MonadIO m, Storable a) => t m a -> t m a
987+reverse' s = fromStreamD $ D.reverse' $ toStreamD s
988+
989+------------------------------------------------------------------------------
990+-- Transformation by Inserting
991+------------------------------------------------------------------------------
992+
993+-- intersperseM = intersperseBySpan 1
994+
995+-- | Insert an effect and its output before consuming an element of a stream
996+-- except the first one.
997+--
998+-- @
999+-- >>> S.toList $ S.trace putChar $ S.intersperseM (putChar '.' >> return ',') $ S.fromList "hello"
1000+-- > h.,e.,l.,l.,o"h,e,l,l,o"
1001+-- @
1002+--
1003+-- @since 0.5.0
1004+{-# INLINE intersperseM #-}
1005+intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
1006+intersperseM m = fromStreamS . S.intersperseM m . toStreamS
1007+
1008+-- | Insert a side effect before consuming an element of a stream except the
1009+-- first one.
1010+--
1011+-- @
1012+-- >>> S.drain $ S.trace putChar $ S.intersperseM_ (putChar '.') $ S.fromList "hello"
1013+-- > h.e.l.l.o
1014+-- @
1015+--
1016+-- /Internal/
1017+{-# INLINE intersperseM_ #-}
1018+intersperseM_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
1019+intersperseM_ m = fromStreamD . D.intersperseM_ m . toStreamD
1020+
1021+-- | Insert a pure value between successive elements of a stream.
1022+--
1023+-- @
1024+-- > S.toList $ S.intersperse ',' $ S.fromList "hello"
1025+-- "h,e,l,l,o"
1026+-- @
1027+--
1028+-- @since 0.7.0
1029+{-# INLINE intersperse #-}
1030+intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
1031+intersperse a = fromStreamS . S.intersperse a . toStreamS
1032+
1033+-- | Insert an effect and its output after consuming an element of a stream.
1034+--
1035+-- @
1036+-- >>> S.toList $ S.trace putChar $ S.intersperseSuffix (putChar '.' >> return ',') $ S.fromList "hello"
1037+-- > h.,e.,l.,l.,o.,"h,e,l,l,o,"
1038+-- @
1039+--
1040+-- /Internal/
1041+{-# INLINE intersperseSuffix #-}
1042+intersperseSuffix :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
1043+intersperseSuffix m = fromStreamD . D.intersperseSuffix m . toStreamD
1044+
1045+-- | Insert a side effect after consuming an element of a stream.
1046+--
1047+-- @
1048+-- > S.mapM_ putChar $ S.intersperseSuffix_ (threadDelay 1000000) $ S.fromList "hello"
1049+-- @
1050+--
1051+-- /Internal/
1052+--
1053+{-# INLINE intersperseSuffix_ #-}
1054+intersperseSuffix_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
1055+intersperseSuffix_ m = fromStreamD . D.intersperseSuffix_ m . toStreamD
1056+
1057+-- | Insert a side effect before consuming an element of a stream.
1058+--
1059+-- @
1060+-- >>> S.toList $ S.trace putChar $ S.interspersePrefix_ (putChar '.' >> return ',') $ S.fromList "hello"
1061+-- > .h.e.l.l.o"hello"
1062+-- @
1063+--
1064+-- See also: 'trace_'
1065+--
1066+-- /Concurrent/
1067+--
1068+-- /Internal/
1069+--
1070+{-# INLINE interspersePrefix_ #-}
1071+interspersePrefix_ :: (IsStream t, MonadAsync m) => m b -> t m a -> t m a
1072+interspersePrefix_ m = mapM (\x -> void m >> return x)
1073+
1074+-- Note: delay must be serial.
1075+--
1076+-- | Introduce a delay of specified seconds before consuming an element of the
1077+-- stream except the first one.
1078+--
1079+-- @
1080+-- >>> S.mapM_ print $ S.timestamped $ S.delay 1 $ S.enumerateFromTo 1 3
1081+-- > (AbsTime (TimeSpec {sec = 2502706, nsec = 751137000}),1)
1082+-- > (AbsTime (TimeSpec {sec = 2502707, nsec = 743535000}),2)
1083+-- > (AbsTime (TimeSpec {sec = 2502708, nsec = 749758000}),3)
1084+-- @
1085+--
1086+-- /Internal/
1087+--
1088+{-# INLINE delay #-}
1089+delay :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
1090+delay n = intersperseM_ $ liftIO $ threadDelay $ round $ n * 1000000
1091+
1092+-- Note: delay must be serial.
1093+--
1094+-- | Introduce a delay of specified seconds after consuming an element of a
1095+-- stream.
1096+--
1097+-- @
1098+-- >>> S.mapM_ print $ S.timestamped $ S.delayPost 1 $ S.enumerateFromTo 1 3
1099+-- > (AbsTime (TimeSpec {sec = 2502826, nsec = 119030000}),1)
1100+-- > (AbsTime (TimeSpec {sec = 2502827, nsec = 111393000}),2)
1101+-- > (AbsTime (TimeSpec {sec = 2502828, nsec = 112221000}),3)
1102+-- @
1103+--
1104+-- /Internal/
1105+--
1106+{-# INLINE delayPost #-}
1107+delayPost :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
1108+delayPost n = intersperseSuffix_ $ liftIO $ threadDelay $ round $ n * 1000000
1109+
1110+-- Note: delay must be serial, that's why 'trace_' is used.
1111+--
1112+-- | Introduce a delay of specified seconds before consuming an element of a
1113+-- stream.
1114+--
1115+-- @
1116+-- >>> S.mapM_ print $ S.timestamped $ S.delayPre 1 $ S.enumerateFromTo 1 3
1117+-- > (AbsTime (TimeSpec {sec = 2502207, nsec = 533177000}),1)
1118+-- > (AbsTime (TimeSpec {sec = 2502208, nsec = 530859000}),2)
1119+-- > (AbsTime (TimeSpec {sec = 2502209, nsec = 531619000}),3)
1120+-- @
1121+--
1122+-- /Internal/
1123+--
1124+{-# INLINE delayPre #-}
1125+delayPre :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
1126+delayPre n = trace_ $ liftIO $ threadDelay $ round $ n * 1000000
1127+
1128+-- | Like 'intersperseSuffix' but intersperses an effectful action into the
1129+-- input stream after every @n@ elements and after the last element.
1130+--
1131+-- @
1132+-- > S.toList $ S.intersperseSuffixBySpan 2 (return ',') $ S.fromList "hello"
1133+-- "he,ll,o,"
1134+-- @
1135+--
1136+-- /Internal/
1137+--
1138+{-# INLINE intersperseSuffixBySpan #-}
1139+intersperseSuffixBySpan :: (IsStream t, MonadAsync m)
1140+ => Int -> m a -> t m a -> t m a
1141+intersperseSuffixBySpan n eff =
1142+ fromStreamD . D.intersperseSuffixBySpan n eff . toStreamD
1143+
1144+{-
1145+-- | Intersperse a monadic action into the input stream after every @n@
1146+-- elements.
1147+--
1148+-- @
1149+-- > S.toList $ S.intersperseBySpan 2 (return ',') $ S.fromList "hello"
1150+-- "he,ll,o"
1151+-- @
1152+--
1153+-- @since 0.7.0
1154+{-# INLINE intersperseBySpan #-}
1155+intersperseBySpan :: IsStream t => Int -> m a -> t m a -> t m a
1156+intersperseBySpan _n _f _xs = undefined
1157+-}
1158+
1159+-- | @insertBy cmp elem stream@ inserts @elem@ before the first element in
1160+-- @stream@ that is less than @elem@ when compared using @cmp@.
1161+--
1162+-- @
1163+-- insertBy cmp x = 'mergeBy' cmp ('yield' x)
1164+-- @
1165+--
1166+-- @
1167+-- > S.toList $ S.insertBy compare 2 $ S.fromList [1,3,5]
1168+-- [1,2,3,5]
1169+-- @
1170+--
1171+-- @since 0.6.0
1172+{-# INLINE insertBy #-}
1173+insertBy ::
1174+ (IsStream t, Monad m) => (a -> a -> Ordering) -> a -> t m a -> t m a
1175+insertBy cmp x m = fromStreamS $ S.insertBy cmp x (toStreamS m)
1176+
1177+------------------------------------------------------------------------------
1178+-- Deleting
1179+------------------------------------------------------------------------------
1180+
1181+-- | Deletes the first occurrence of the element in the stream that satisfies
1182+-- the given equality predicate.
1183+--
1184+-- @
1185+-- > S.toList $ S.deleteBy (==) 3 $ S.fromList [1,3,3,5]
1186+-- [1,3,5]
1187+-- @
1188+--
1189+-- @since 0.6.0
1190+{-# INLINE deleteBy #-}
1191+deleteBy :: (IsStream t, Monad m) => (a -> a -> Bool) -> a -> t m a -> t m a
1192+deleteBy cmp x m = fromStreamS $ S.deleteBy cmp x (toStreamS m)
1193+
1194+------------------------------------------------------------------------------
1195+-- Zipping
1196+------------------------------------------------------------------------------
1197+
1198+-- |
1199+-- > indexed = S.postscanl' (\(i, _) x -> (i + 1, x)) (-1,undefined)
1200+-- > indexed = S.zipWith (,) (S.enumerateFrom 0)
1201+--
1202+-- Pair each element in a stream with its index, starting from index 0.
1203+--
1204+-- @
1205+-- > S.toList $ S.indexed $ S.fromList "hello"
1206+-- [(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')]
1207+-- @
1208+--
1209+-- @since 0.6.0
1210+{-# INLINE indexed #-}
1211+indexed :: (IsStream t, Monad m) => t m a -> t m (Int, a)
1212+indexed = fromStreamD . D.indexed . toStreamD
1213+
1214+-- |
1215+-- > indexedR n = S.postscanl' (\(i, _) x -> (i - 1, x)) (n + 1,undefined)
1216+-- > indexedR n = S.zipWith (,) (S.enumerateFromThen n (n - 1))
1217+--
1218+-- Pair each element in a stream with its index, starting from the
1219+-- given index @n@ and counting down.
1220+--
1221+-- @
1222+-- > S.toList $ S.indexedR 10 $ S.fromList "hello"
1223+-- [(10,'h'),(9,'e'),(8,'l'),(7,'l'),(6,'o')]
1224+-- @
1225+--
1226+-- @since 0.6.0
1227+{-# INLINE indexedR #-}
1228+indexedR :: (IsStream t, Monad m) => Int -> t m a -> t m (Int, a)
1229+indexedR n = fromStreamD . D.indexedR n . toStreamD
1230+
1231+------------------------------------------------------------------------------
1232+-- Merge
1233+------------------------------------------------------------------------------
1234+
1235+-- | Merge two streams using a comparison function. The head elements of both
1236+-- the streams are compared and the smaller of the two elements is emitted, if
1237+-- both elements are equal then the element from the first stream is used
1238+-- first.
1239+--
1240+-- If the streams are sorted in ascending order, the resulting stream would
1241+-- also remain sorted in ascending order.
1242+--
1243+-- @
1244+-- > S.toList $ S.mergeBy compare (S.fromList [1,3,5]) (S.fromList [2,4,6,8])
1245+-- [1,2,3,4,5,6,8]
1246+-- @
1247+--
1248+-- @since 0.6.0
1249+{-# INLINABLE mergeBy #-}
1250+mergeBy ::
1251+ (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1252+mergeBy f m1 m2 = fromStreamS $ S.mergeBy f (toStreamS m1) (toStreamS m2)
1253+
1254+-- | Like 'mergeBy' but with a monadic comparison function.
1255+--
1256+-- Merge two streams randomly:
1257+--
1258+-- @
1259+-- > randomly _ _ = randomIO >>= \x -> return $ if x then LT else GT
1260+-- > S.toList $ S.mergeByM randomly (S.fromList [1,1,1,1]) (S.fromList [2,2,2,2])
1261+-- [2,1,2,2,2,1,1,1]
1262+-- @
1263+--
1264+-- Merge two streams in a proportion of 2:1:
1265+--
1266+-- @
1267+-- proportionately m n = do
1268+-- ref <- newIORef $ cycle $ concat [replicate m LT, replicate n GT]
1269+-- return $ \\_ _ -> do
1270+-- r <- readIORef ref
1271+-- writeIORef ref $ tail r
1272+-- return $ head r
1273+--
1274+-- main = do
1275+-- f <- proportionately 2 1
1276+-- xs <- S.toList $ S.mergeByM f (S.fromList [1,1,1,1,1,1]) (S.fromList [2,2,2])
1277+-- print xs
1278+-- @
1279+-- @
1280+-- [1,1,2,1,1,2,1,1,2]
1281+-- @
1282+--
1283+-- @since 0.6.0
1284+{-# INLINABLE mergeByM #-}
1285+mergeByM
1286+ :: (IsStream t, Monad m)
1287+ => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1288+mergeByM f m1 m2 = fromStreamS $ S.mergeByM f (toStreamS m1) (toStreamS m2)
1289+
1290+{-
1291+-- | Like 'mergeByM' but stops merging as soon as any of the two streams stops.
1292+{-# INLINABLE mergeEndByAny #-}
1293+mergeEndByAny
1294+ :: (IsStream t, Monad m)
1295+ => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1296+mergeEndByAny f m1 m2 = fromStreamD $
1297+ D.mergeEndByAny f (toStreamD m1) (toStreamD m2)
1298+
1299+-- Like 'mergeByM' but stops merging as soon as the first stream stops.
1300+{-# INLINABLE mergeEndByFirst #-}
1301+mergeEndByFirst
1302+ :: (IsStream t, Monad m)
1303+ => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1304+mergeEndByFirst f m1 m2 = fromStreamS $
1305+ D.mergeEndByFirst f (toStreamD m1) (toStreamD m2)
1306+-}
1307+
1308+-- Holding this back for now, we may want to use the name "merge" differently
1309+{-
1310+-- | Same as @'mergeBy' 'compare'@.
1311+--
1312+-- @
1313+-- > S.toList $ S.merge (S.fromList [1,3,5]) (S.fromList [2,4,6,8])
1314+-- [1,2,3,4,5,6,8]
1315+-- @
1316+--
1317+-- @since 0.6.0
1318+{-# INLINABLE merge #-}
1319+merge ::
1320+ (IsStream t, Monad m, Ord a) => t m a -> t m a -> t m a
1321+merge = mergeBy compare
1322+-}
1323+
1324+-- | Like 'mergeBy' but merges concurrently (i.e. both the elements being
1325+-- merged are generated concurrently).
1326+--
1327+-- @since 0.6.0
1328+{-# INLINE mergeAsyncBy #-}
1329+mergeAsyncBy :: (IsStream t, MonadAsync m)
1330+ => (a -> a -> Ordering) -> t m a -> t m a -> t m a
1331+mergeAsyncBy f = mergeAsyncByM (\a b -> return $ f a b)
1332+
1333+-- | Like 'mergeByM' but merges concurrently (i.e. both the elements being
1334+-- merged are generated concurrently).
1335+--
1336+-- @since 0.6.0
1337+{-# INLINE mergeAsyncByM #-}
1338+mergeAsyncByM :: (IsStream t, MonadAsync m)
1339+ => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
1340+mergeAsyncByM f m1 m2 = fromStreamD $
1341+ D.mergeByM f (D.mkParallelD $ toStreamD m1) (D.mkParallelD $ toStreamD m2)
1342+
1343+------------------------------------------------------------------------------
1344+-- Flattening Lists
1345+------------------------------------------------------------------------------
1346+
1347+-- | @concatMapWith merge map stream@ is a two dimensional looping combinator.
1348+-- The first argument specifies a merge or concat function that is used to
1349+-- merge the streams generated by applying the second argument i.e. the @map@
1350+-- function to each element of the input stream. The concat function could be
1351+-- 'serial', 'parallel', 'async', 'ahead' or any other zip or merge function
1352+-- and the second argument could be any stream generation function using a
1353+-- seed.
1354+--
1355+-- /Compare 'foldMapWith'/
1356+--
1357+-- /Since: 0.7.0/
1358+--
1359+-- /Since: 0.8.0 (signature change)/
1360+{-# INLINE concatMapWith #-}
1361+concatMapWith
1362+ :: IsStream t
1363+ => (t m b -> t m b -> t m b)
1364+ -> (a -> t m b)
1365+ -> t m a
1366+ -> t m b
1367+concatMapWith = K.concatMapBy
1368+
1369+-- | Like 'concatMapWith' but carries a state which can be used to share
1370+-- information across multiple steps of concat.
1371+--
1372+-- @
1373+-- concatSmapMWith combine f initial = concatMapWith combine id . smapM f initial
1374+-- @
1375+--
1376+-- /Internal/
1377+--
1378+{-# INLINE concatSmapMWith #-}
1379+concatSmapMWith
1380+ :: (IsStream t, Monad m)
1381+ => (t m b -> t m b -> t m b)
1382+ -> (s -> a -> m (s, t m b))
1383+ -> m s
1384+ -> t m a
1385+ -> t m b
1386+concatSmapMWith combine f initial = concatMapWith combine id . smapM f initial
1387+
1388+-- | Map a stream producing function on each element of the stream and then
1389+-- flatten the results into a single stream.
1390+--
1391+-- @
1392+-- concatMap f = 'concat . map f'
1393+-- concatMap = 'concatMapWith' 'Serial.serial'
1394+-- concatMap f = 'concatMapM' (return . f)
1395+-- concatMap f = 'concatUnfold' (UF.lmap f UF.fromStream)
1396+-- @
1397+--
1398+-- @since 0.6.0
1399+{-# INLINE concatMap #-}
1400+concatMap ::(IsStream t, Monad m) => (a -> t m b) -> t m a -> t m b
1401+concatMap f m = fromStreamD $ D.concatMap (toStreamD . f) (toStreamD m)
1402+
1403+-- | Flatten a stream of streams to a single stream.
1404+--
1405+-- @
1406+-- concat = concatMap id
1407+-- @
1408+--
1409+-- /Internal/
1410+{-# INLINE concat #-}
1411+concat :: (IsStream t, Monad m) => t m (t m a) -> t m a
1412+concat = concatMap id
1413+
1414+-- | Append the outputs of two streams, yielding all the elements from the
1415+-- first stream and then yielding all the elements from the second stream.
1416+--
1417+-- IMPORTANT NOTE: This could be 100x faster than @serial/<>@ for appending a
1418+-- few (say 100) streams because it can fuse via stream fusion. However, it
1419+-- does not scale for a large number of streams (say 1000s) and becomes
1420+-- qudartically slow. Therefore use this for custom appending of a few streams
1421+-- but use 'concatMap' or 'concatMapWith serial' for appending @n@ streams or
1422+-- infinite containers of streams.
1423+--
1424+-- /Internal/
1425+{-# INLINE append #-}
1426+append ::(IsStream t, Monad m) => t m b -> t m b -> t m b
1427+append m1 m2 = fromStreamD $ D.append (toStreamD m1) (toStreamD m2)
1428+
1429+-- XXX Same as 'wSerial'. We should perhaps rename wSerial to interleave.
1430+-- XXX Document the interleaving behavior of side effects in all the
1431+-- interleaving combinators.
1432+-- XXX Write time-domain equivalents of these. In the time domain we can
1433+-- interleave two streams such that the value of second stream is always taken
1434+-- from its last value even if no new value is being yielded, like
1435+-- zipWithLatest. It would be something like interleaveWithLatest.
1436+--
1437+-- | Interleaves the outputs of two streams, yielding elements from each stream
1438+-- alternately, starting from the first stream. If any of the streams finishes
1439+-- early the other stream continues alone until it too finishes.
1440+--
1441+-- >>> :set -XOverloadedStrings
1442+-- >>> interleave "ab" ",,,," :: SerialT Identity Char
1443+-- fromList "a,b,,,"
1444+-- >>> interleave "abcd" ",," :: SerialT Identity Char
1445+-- fromList "a,b,cd"
1446+--
1447+-- 'interleave' is dual to 'interleaveMin', it can be called @interleaveMax@.
1448+--
1449+-- Do not use at scale in concatMapWith.
1450+--
1451+-- /Internal/
1452+{-# INLINE interleave #-}
1453+interleave ::(IsStream t, Monad m) => t m b -> t m b -> t m b
1454+interleave m1 m2 = fromStreamD $ D.interleave (toStreamD m1) (toStreamD m2)
1455+
1456+-- | Interleaves the outputs of two streams, yielding elements from each stream
1457+-- alternately, starting from the first stream. As soon as the first stream
1458+-- finishes, the output stops, discarding the remaining part of the second
1459+-- stream. In this case, the last element in the resulting stream would be from
1460+-- the second stream. If the second stream finishes early then the first stream
1461+-- still continues to yield elements until it finishes.
1462+--
1463+-- >>> :set -XOverloadedStrings
1464+-- >>> interleaveSuffix "abc" ",,,," :: SerialT Identity Char
1465+-- fromList "a,b,c,"
1466+-- >>> interleaveSuffix "abc" "," :: SerialT Identity Char
1467+-- fromList "a,bc"
1468+--
1469+-- 'interleaveSuffix' is a dual of 'interleaveInfix'.
1470+--
1471+-- Do not use at scale in concatMapWith.
1472+--
1473+-- /Internal/
1474+{-# INLINE interleaveSuffix #-}
1475+interleaveSuffix ::(IsStream t, Monad m) => t m b -> t m b -> t m b
1476+interleaveSuffix m1 m2 =
1477+ fromStreamD $ D.interleaveSuffix (toStreamD m1) (toStreamD m2)
1478+
1479+-- | Interleaves the outputs of two streams, yielding elements from each stream
1480+-- alternately, starting from the first stream and ending at the first stream.
1481+-- If the second stream is longer than the first, elements from the second
1482+-- stream are infixed with elements from the first stream. If the first stream
1483+-- is longer then it continues yielding elements even after the second stream
1484+-- has finished.
1485+--
1486+-- >>> :set -XOverloadedStrings
1487+-- >>> interleaveInfix "abc" ",,,," :: SerialT Identity Char
1488+-- fromList "a,b,c"
1489+-- >>> interleaveInfix "abc" "," :: SerialT Identity Char
1490+-- fromList "a,bc"
1491+--
1492+-- 'interleaveInfix' is a dual of 'interleaveSuffix'.
1493+--
1494+-- Do not use at scale in concatMapWith.
1495+--
1496+-- /Internal/
1497+{-# INLINE interleaveInfix #-}
1498+interleaveInfix ::(IsStream t, Monad m) => t m b -> t m b -> t m b
1499+interleaveInfix m1 m2 =
1500+ fromStreamD $ D.interleaveInfix (toStreamD m1) (toStreamD m2)
1501+
1502+-- | Interleaves the outputs of two streams, yielding elements from each stream
1503+-- alternately, starting from the first stream. The output stops as soon as any
1504+-- of the two streams finishes, discarding the remaining part of the other
1505+-- stream. The last element of the resulting stream would be from the longer
1506+-- stream.
1507+--
1508+-- >>> :set -XOverloadedStrings
1509+-- >>> interleaveMin "ab" ",,,," :: SerialT Identity Char
1510+-- fromList "a,b,"
1511+-- >>> interleaveMin "abcd" ",," :: SerialT Identity Char
1512+-- fromList "a,b,c"
1513+--
1514+-- 'interleaveMin' is dual to 'interleave'.
1515+--
1516+-- Do not use at scale in concatMapWith.
1517+--
1518+-- /Internal/
1519+{-# INLINE interleaveMin #-}
1520+interleaveMin ::(IsStream t, Monad m) => t m b -> t m b -> t m b
1521+interleaveMin m1 m2 = fromStreamD $ D.interleaveMin (toStreamD m1) (toStreamD m2)
1522+
1523+-- | Schedule the execution of two streams in a fair round-robin manner,
1524+-- executing each stream once, alternately. Execution of a stream may not
1525+-- necessarily result in an output, a stream may chose to @Skip@ producing an
1526+-- element until later giving the other stream a chance to run. Therefore, this
1527+-- combinator fairly interleaves the execution of two streams rather than
1528+-- fairly interleaving the output of the two streams. This can be useful in
1529+-- co-operative multitasking without using explicit threads. This can be used
1530+-- as an alternative to `async`.
1531+--
1532+-- Do not use at scale in concatMapWith.
1533+--
1534+-- /Internal/
1535+{-# INLINE roundrobin #-}
1536+roundrobin ::(IsStream t, Monad m) => t m b -> t m b -> t m b
1537+roundrobin m1 m2 = fromStreamD $ D.roundRobin (toStreamD m1) (toStreamD m2)
1538+
1539+-- | Map a stream producing monadic function on each element of the stream
1540+-- and then flatten the results into a single stream. Since the stream
1541+-- generation function is monadic, unlike 'concatMap', it can produce an
1542+-- effect at the beginning of each iteration of the inner loop.
1543+--
1544+-- @since 0.6.0
1545+{-# INLINE concatMapM #-}
1546+concatMapM :: (IsStream t, Monad m) => (a -> m (t m b)) -> t m a -> t m b
1547+concatMapM f m = fromStreamD $ D.concatMapM (fmap toStreamD . f) (toStreamD m)
1548+
1549+-- | Like 'concatMap' but uses an 'Unfold' for stream generation. Unlike
1550+-- 'concatMap' this can fuse the 'Unfold' code with the inner loop and
1551+-- therefore provide many times better performance.
1552+--
1553+-- @since 0.7.0
1554+{-# INLINE concatUnfold #-}
1555+concatUnfold ::(IsStream t, Monad m) => Unfold m a b -> t m a -> t m b
1556+concatUnfold u m = fromStreamD $ D.concatMapU u (toStreamD m)
1557+
1558+-- | Like 'concatUnfold' but interleaves the streams in the same way as
1559+-- 'interleave' behaves instead of appending them.
1560+--
1561+-- /Internal/
1562+{-# INLINE concatUnfoldInterleave #-}
1563+concatUnfoldInterleave ::(IsStream t, Monad m)
1564+ => Unfold m a b -> t m a -> t m b
1565+concatUnfoldInterleave u m =
1566+ fromStreamD $ D.concatUnfoldInterleave u (toStreamD m)
1567+
1568+-- | Like 'concatUnfold' but executes the streams in the same way as
1569+-- 'roundrobin'.
1570+--
1571+-- /Internal/
1572+{-# INLINE concatUnfoldRoundrobin #-}
1573+concatUnfoldRoundrobin ::(IsStream t, Monad m)
1574+ => Unfold m a b -> t m a -> t m b
1575+concatUnfoldRoundrobin u m =
1576+ fromStreamD $ D.concatUnfoldRoundrobin u (toStreamD m)
1577+
1578+-- XXX we can swap the order of arguments to gintercalate so that the
1579+-- definition of concatUnfold becomes simpler? The first stream should be
1580+-- infixed inside the second one. However, if we change the order in
1581+-- "interleave" as well similarly, then that will make it a bit unintuitive.
1582+--
1583+-- > concatUnfold unf str =
1584+-- > gintercalate unf str (UF.nilM (\_ -> return ())) (repeat ())
1585+--
1586+-- | 'interleaveInfix' followed by unfold and concat.
1587+--
1588+-- /Internal/
1589+{-# INLINE gintercalate #-}
1590+gintercalate
1591+ :: (IsStream t, Monad m)
1592+ => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
1593+gintercalate unf1 str1 unf2 str2 =
1594+ D.fromStreamD $ D.gintercalate
1595+ unf1 (D.toStreamD str1)
1596+ unf2 (D.toStreamD str2)
1597+
1598+-- XXX The order of arguments in "intercalate" is consistent with the list
1599+-- intercalate but inconsistent with gintercalate and other stream interleaving
1600+-- combinators. We can change the order of the arguments in other combinators
1601+-- but then 'interleave' combinator may become a bit unintuitive because we
1602+-- will be starting with the second stream.
1603+
1604+-- > intercalate seed unf str = gintercalate unf str unf (repeatM seed)
1605+-- > intercalate a unf str = concatUnfold unf $ intersperse a str
1606+--
1607+-- | 'intersperse' followed by unfold and concat.
1608+--
1609+-- > unwords = intercalate " " UF.fromList
1610+--
1611+-- >>> intercalate " " UF.fromList ["abc", "def", "ghi"]
1612+-- > "abc def ghi"
1613+--
1614+-- /Internal/
1615+{-# INLINE intercalate #-}
1616+intercalate :: (IsStream t, Monad m)
1617+ => b -> Unfold m b c -> t m b -> t m c
1618+intercalate seed unf str = D.fromStreamD $
1619+ D.concatMapU unf $ D.intersperse seed (toStreamD str)
1620+
1621+-- > interpose x unf str = gintercalate unf str UF.identity (repeat x)
1622+--
1623+-- | Unfold the elements of a stream, intersperse the given element between the
1624+-- unfolded streams and then concat them into a single stream.
1625+--
1626+-- > unwords = S.interpose ' '
1627+--
1628+-- /Internal/
1629+{-# INLINE interpose #-}
1630+interpose :: (IsStream t, Monad m)
1631+ => c -> Unfold m b c -> t m b -> t m c
1632+interpose x unf str =
1633+ D.fromStreamD $ D.interpose (return x) unf (D.toStreamD str)
1634+
1635+-- | 'interleaveSuffix' followed by unfold and concat.
1636+--
1637+-- /Internal/
1638+{-# INLINE gintercalateSuffix #-}
1639+gintercalateSuffix
1640+ :: (IsStream t, Monad m)
1641+ => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
1642+gintercalateSuffix unf1 str1 unf2 str2 =
1643+ D.fromStreamD $ D.gintercalateSuffix
1644+ unf1 (D.toStreamD str1)
1645+ unf2 (D.toStreamD str2)
1646+
1647+-- > intercalateSuffix seed unf str = gintercalateSuffix unf str unf (repeatM seed)
1648+-- > intercalateSuffix a unf str = concatUnfold unf $ intersperseSuffix a str
1649+--
1650+-- | 'intersperseSuffix' followed by unfold and concat.
1651+--
1652+-- > unlines = intercalateSuffix "\n" UF.fromList
1653+--
1654+-- >>> intercalate "\n" UF.fromList ["abc", "def", "ghi"]
1655+-- > "abc\ndef\nghi\n"
1656+--
1657+-- /Internal/
1658+{-# INLINE intercalateSuffix #-}
1659+intercalateSuffix :: (IsStream t, Monad m)
1660+ => b -> Unfold m b c -> t m b -> t m c
1661+intercalateSuffix seed unf str = fromStreamD $ D.concatMapU unf
1662+ $ D.intersperseSuffix (return seed) (D.toStreamD str)
1663+
1664+-- interposeSuffix x unf str = gintercalateSuffix unf str UF.identity (repeat x)
1665+--
1666+-- | Unfold the elements of a stream, append the given element after each
1667+-- unfolded stream and then concat them into a single stream.
1668+--
1669+-- > unlines = S.interposeSuffix '\n'
1670+--
1671+-- /Internal/
1672+{-# INLINE interposeSuffix #-}
1673+interposeSuffix :: (IsStream t, Monad m)
1674+ => c -> Unfold m b c -> t m b -> t m c
1675+interposeSuffix x unf str =
1676+ D.fromStreamD $ D.interposeSuffix (return x) unf (D.toStreamD str)
1677+
1678+------------------------------------------------------------------------------
1679+-- Either streams
1680+------------------------------------------------------------------------------
1681+
1682+-- | Discard 'Right's and unwrap 'Left's in an 'Either' stream.
1683+--
1684+-- /Internal/
1685+--
1686+lefts :: (IsStream t, Monad m, Functor (t m)) => t m (Either a b) -> t m a
1687+lefts = fmap (fromLeft undefined) . filter isLeft
1688+
1689+-- | Discard 'Left's and unwrap 'Right's in an 'Either' stream.
1690+--
1691+-- /Internal/
1692+--
1693+rights :: (IsStream t, Monad m, Functor (t m)) => t m (Either a b) -> t m b
1694+rights = fmap (fromRight undefined) . filter isRight
1695+
1696+------------------------------------------------------------------------------
1697+-- Parsing
1698+------------------------------------------------------------------------------
1699+
1700+-- Splitting operations that take a predicate and a Fold can be
1701+-- expressed using parseMany. Operations like chunksOf, intervalsOf, split*,
1702+-- can be expressed using parseMany when used with an appropriate Parser.
1703+--
1704+-- XXX We need takeGE/takeBetween to implement "some" using "many".
1705+
1706+-- | Apply a 'Fold' repeatedly on a stream and emit the parsed values in the
1707+-- output stream.
1708+--
1709+-- This is the streaming dual of the 'Streamly.Internal.Data.Fold.many'
1710+-- parse combinator.
1711+--
1712+-- >>> f = Fold.ltake 2 Fold.sum
1713+-- >>> Stream.toList $ Stream.foldMany f $ Stream.fromList [1..10]
1714+-- > [3,7,11,15,19]
1715+--
1716+-- >>> f = Fold.sliceEndWith Fold.toList
1717+-- >>> Stream.toList $ Stream.foldMany f $ Stream.fromList "hello\nworld"
1718+-- > ["hello\n","world"]
1719+--
1720+-- /Internal/
1721+--
1722+{-# INLINE foldMany #-}
1723+foldMany
1724+ :: (IsStream t, Monad m)
1725+ => Fold m a b
1726+ -> t m a
1727+ -> t m b
1728+foldMany f m = D.fromStreamD $ D.foldMany f (D.toStreamD m)
1729+
1730+-- | Apply a stream of folds to an input stream and emit the results in the
1731+-- output stream.
1732+--
1733+-- /Internal/
1734+--
1735+{-# INLINE foldSequence #-}
1736+foldSequence
1737+ :: -- (IsStream t, Monad m) =>
1738+ t m (Fold m a b)
1739+ -> t m a
1740+ -> t m b
1741+foldSequence _f _m = undefined
1742+
1743+-- | Iterate a fold generator on a stream. The initial value @b@ is used to
1744+-- generate the first fold, the fold is applied on the stream and the result of
1745+-- the fold is used to generate the next fold and so on.
1746+--
1747+-- >>> f x = Fold.ltake 2 (Fold.mconcatTo x)
1748+-- >>> s = Stream.map Sum $ Stream.fromList [1..10]
1749+-- >>> Stream.toList $ Stream.map getSum $ Stream.foldIterate f 0 s
1750+-- > [3,10,21,36,55,55]
1751+--
1752+-- This is the streaming equivalent of monad like sequenced application of
1753+-- folds where next fold is dependent on the previous fold.
1754+--
1755+-- /Internal/
1756+--
1757+{-# INLINE foldIterate #-}
1758+foldIterate
1759+ :: -- (IsStream t, Monad m) =>
1760+ (b -> Fold m a b)
1761+ -> b
1762+ -> t m a
1763+ -> t m b
1764+foldIterate _f _i _m = undefined
1765+-- D.fromStreamD $ D.foldIterate f i (D.toStreamD m)
1766+
1767+-- | Apply a 'Parser' repeatedly on a stream and emit the parsed values in the
1768+-- output stream.
1769+--
1770+-- This is the streaming equivalent of the 'Streamly.Internal.Data.Parser.many'
1771+-- parse combinator.
1772+--
1773+-- >>> S.toList $ S.parseMany (PR.take 2 $ PR.fromFold FL.sum) $ S.fromList [1..10]
1774+-- > [3,7,11,15,19]
1775+--
1776+-- >>> S.toList $ S.parseMany (PR.line FL.toList) $ S.fromList "hello\nworld"
1777+-- > ["hello\n","world"]
1778+--
1779+-- /Internal/
1780+--
1781+{-# INLINE parseMany #-}
1782+parseMany
1783+ :: (IsStream t, MonadThrow m)
1784+ => Parser m a b
1785+ -> t m a
1786+ -> t m b
1787+parseMany p m =
1788+ D.fromStreamD $ D.parseMany (PRK.fromParserK p) (D.toStreamD m)
1789+
1790+{-# INLINE parseManyD #-}
1791+parseManyD
1792+ :: (IsStream t, MonadThrow m)
1793+ => PRD.Parser m a b
1794+ -> t m a
1795+ -> t m b
1796+parseManyD p m =
1797+ D.fromStreamD $ D.parseMany p (D.toStreamD m)
1798+
1799+-- | Apply a stream of parsers to an input stream and emit the results in the
1800+-- output stream.
1801+--
1802+-- /Internal/
1803+--
1804+{-# INLINE parseSequence #-}
1805+parseSequence
1806+ :: -- (IsStream t, Monad m) =>
1807+ t m (Parser m a b)
1808+ -> t m a
1809+ -> t m b
1810+parseSequence _f _m = undefined
1811+
1812+-- | @parseManyTill collect test stream@ tries the parser @test@ on the input,
1813+-- if @test@ fails it backtracks and tries @collect@, after @collect@ succeeds
1814+-- @test@ is tried again and so on. The parser stops when @test@ succeeds. The
1815+-- output of @test@ is discarded and the output of @collect@ is emitted in the
1816+-- output stream. The parser fails if @collect@ fails.
1817+--
1818+-- /Unimplemented/
1819+--
1820+{-# INLINE parseManyTill #-}
1821+parseManyTill ::
1822+ -- (IsStream t, MonadThrow m) =>
1823+ Parser m a b
1824+ -> Parser m a x
1825+ -> t m a
1826+ -> t m b
1827+parseManyTill = undefined
1828+
1829+-- | Iterate a parser generating function on a stream. The initial value @b@ is
1830+-- used to generate the first parser, the parser is applied on the stream and
1831+-- the result is used to generate the next parser and so on.
1832+--
1833+-- >>> S.toList $ S.map getSum $ S.parseIterate (\b -> PR.take 2 (FL.mconcatTo b)) 0 $ S.map Sum $ S.fromList [1..10]
1834+-- > [3,10,21,36,55,55]
1835+--
1836+-- This is the streaming equivalent of monad like sequenced application of
1837+-- parsers where next parser is dependent on the previous parser.
1838+--
1839+-- /Internal/
1840+--
1841+{-# INLINE parseIterate #-}
1842+parseIterate
1843+ :: (IsStream t, MonadThrow m)
1844+ => (b -> Parser m a b)
1845+ -> b
1846+ -> t m a
1847+ -> t m b
1848+parseIterate f i m = D.fromStreamD $
1849+ D.parseIterate (PRK.fromParserK . f) i (D.toStreamD m)
1850+
1851+------------------------------------------------------------------------------
1852+-- Grouping/Splitting
1853+------------------------------------------------------------------------------
1854+
1855+------------------------------------------------------------------------------
1856+-- Grouping without looking at elements
1857+------------------------------------------------------------------------------
1858+--
1859+------------------------------------------------------------------------------
1860+-- Binary APIs
1861+------------------------------------------------------------------------------
1862+--
1863+
1864+------------------------------------------------------------------------------
1865+-- N-ary APIs
1866+------------------------------------------------------------------------------
1867+
1868+------------------------------------------------------------------------------
1869+-- Generalized grouping
1870+------------------------------------------------------------------------------
1871+
1872+-- This combinator is the most general grouping combinator and can be used to
1873+-- implement all other grouping combinators.
1874+--
1875+-- XXX check if this can implement the splitOn combinator i.e. we can slide in
1876+-- new elements, slide out old elements and incrementally compute the hash.
1877+-- Also, can we implement the windowed classification combinators using this?
1878+--
1879+-- In fact this is a parse. Instead of using a special return value in the fold
1880+-- we are using a mapping function.
1881+--
1882+-- Note that 'scanl'' (usually followed by a map to extract the desired value
1883+-- from the accumulator) can be used to realize many implementations e.g. a
1884+-- sliding window implementation. A scan followed by a mapMaybe is also a good
1885+-- pattern to express many problems where we want to emit a filtered output and
1886+-- not emit an output on every input.
1887+--
1888+-- Passing on of the initial accumulator value to the next fold is equivalent
1889+-- to returning the leftover concept.
1890+
1891+{-
1892+-- | @groupScan splitter fold stream@ folds the input stream using @fold@.
1893+-- @splitter@ is applied on the accumulator of the fold every time an item is
1894+-- consumed by the fold. The fold continues until @splitter@ returns a 'Just'
1895+-- value. A 'Just' result from the @splitter@ specifies a result to be emitted
1896+-- in the output stream and the initial value of the accumulator for the next
1897+-- group's fold. This allows us to control whether to start fresh for the next
1898+-- fold or to continue from the previous fold's output.
1899+--
1900+{-# INLINE groupScan #-}
1901+groupScan
1902+ :: (IsStream t, Monad m)
1903+ => (x -> m (Maybe (b, x))) -> Fold m a x -> t m a -> t m b
1904+groupScan split fold m = undefined
1905+-}
1906+
1907+-- | Group the input stream into groups of @n@ elements each and then fold each
1908+-- group using the provided fold function.
1909+--
1910+-- >> S.toList $ S.chunksOf 2 FL.sum (S.enumerateFromTo 1 10)
1911+-- > [3,7,11,15,19]
1912+--
1913+-- This can be considered as an n-fold version of 'ltake' where we apply
1914+-- 'ltake' repeatedly on the leftover stream until the stream exhausts.
1915+--
1916+-- @since 0.7.0
1917+{-# INLINE chunksOf #-}
1918+chunksOf
1919+ :: (IsStream t, Monad m)
1920+ => Int -> Fold m a b -> t m a -> t m b
1921+chunksOf n f = foldMany (FL.ltake n f)
1922+
1923+-- |
1924+--
1925+-- /Internal/
1926+{-# INLINE chunksOf2 #-}
1927+chunksOf2
1928+ :: (IsStream t, Monad m)
1929+ => Int -> m c -> Fold2 m c a b -> t m a -> t m b
1930+chunksOf2 n action f m = D.fromStreamD $ D.groupsOf2 n action f (D.toStreamD m)
1931+
1932+-- | @arraysOf n stream@ groups the elements in the input stream into arrays of
1933+-- @n@ elements each.
1934+--
1935+-- Same as the following but may be more efficient:
1936+--
1937+-- > arraysOf n = S.chunksOf n (A.writeN n)
1938+--
1939+-- /Internal/
1940+{-# INLINE arraysOf #-}
1941+arraysOf :: (IsStream t, MonadIO m, Storable a)
1942+ => Int -> t m a -> t m (Array a)
1943+arraysOf n = chunksOf n (writeNUnsafe n)
1944+
1945+------------------------------------------------------------------------------
1946+-- N-ary APIs
1947+------------------------------------------------------------------------------
1948+
1949+-- | @groupsBy cmp f $ S.fromList [a,b,c,...]@ assigns the element @a@ to the
1950+-- first group, if @b \`cmp` a@ is 'True' then @b@ is also assigned to the same
1951+-- group. If @c \`cmp` a@ is 'True' then @c@ is also assigned to the same
1952+-- group and so on. When the comparison fails a new group is started. Each
1953+-- group is folded using the fold @f@ and the result of the fold is emitted in
1954+-- the output stream.
1955+--
1956+-- >>> S.toList $ S.groupsBy (>) FL.toList $ S.fromList [1,3,7,0,2,5]
1957+-- > [[1,3,7],[0,2,5]]
1958+--
1959+-- @since 0.7.0
1960+{-# INLINE groupsBy #-}
1961+groupsBy
1962+ :: (IsStream t, Monad m)
1963+ => (a -> a -> Bool)
1964+ -> Fold m a b
1965+ -> t m a
1966+ -> t m b
1967+groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
1968+
1969+-- | Unlike @groupsBy@ this function performs a rolling comparison of two
1970+-- successive elements in the input stream. @groupsByRolling cmp f $ S.fromList
1971+-- [a,b,c,...]@ assigns the element @a@ to the first group, if @a \`cmp` b@ is
1972+-- 'True' then @b@ is also assigned to the same group. If @b \`cmp` c@ is
1973+-- 'True' then @c@ is also assigned to the same group and so on. When the
1974+-- comparison fails a new group is started. Each group is folded using the fold
1975+-- @f@.
1976+--
1977+-- >>> S.toList $ S.groupsByRolling (\a b -> a + 1 == b) FL.toList $ S.fromList [1,2,3,7,8,9]
1978+-- > [[1,2,3],[7,8,9]]
1979+--
1980+-- @since 0.7.0
1981+{-# INLINE groupsByRolling #-}
1982+groupsByRolling
1983+ :: (IsStream t, Monad m)
1984+ => (a -> a -> Bool)
1985+ -> Fold m a b
1986+ -> t m a
1987+ -> t m b
1988+groupsByRolling cmp f m = D.fromStreamD $ D.groupsRollingBy cmp f (D.toStreamD m)
1989+
1990+-- |
1991+-- > groups = groupsBy (==)
1992+-- > groups = groupsByRolling (==)
1993+--
1994+-- Groups contiguous spans of equal elements together in individual groups.
1995+--
1996+-- >>> S.toList $ S.groups FL.toList $ S.fromList [1,1,2,2]
1997+-- > [[1,1],[2,2]]
1998+--
1999+-- @since 0.7.0
2000+{-# INLINE groups #-}
2001+groups :: (IsStream t, Monad m, Eq a) => Fold m a b -> t m a -> t m b
2002+groups = groupsBy (==)
2003+
2004+------------------------------------------------------------------------------
2005+-- N-ary split on a predicate
2006+------------------------------------------------------------------------------
2007+
2008+-- TODO: Use a Splitter configuration similar to the "split" package to make it
2009+-- possible to express all splitting combinations. In general, we can have
2010+-- infix/suffix/prefix/condensing of separators, dropping both leading/trailing
2011+-- separators. We can have a single split operation taking the splitter config
2012+-- as argument.
2013+
2014+-- | Split on an infixed separator element, dropping the separator. Splits the
2015+-- stream on separator elements determined by the supplied predicate, separator
2016+-- is considered as infixed between two segments, if one side of the separator
2017+-- is missing then it is parsed as an empty stream. The supplied 'Fold' is
2018+-- applied on the split segments. With '-' representing non-separator elements
2019+-- and '.' as separator, 'splitOn' splits as follows:
2020+--
2021+-- @
2022+-- "--.--" => "--" "--"
2023+-- "--." => "--" ""
2024+-- ".--" => "" "--"
2025+-- @
2026+--
2027+-- @splitOn (== x)@ is an inverse of @intercalate (S.yield x)@
2028+--
2029+-- Let's use the following definition for illustration:
2030+--
2031+-- > splitOn' p xs = S.toList $ S.splitOn p (FL.toList) (S.fromList xs)
2032+--
2033+-- >>> splitOn' (== '.') ""
2034+-- [""]
2035+--
2036+-- >>> splitOn' (== '.') "."
2037+-- ["",""]
2038+--
2039+-- >>> splitOn' (== '.') ".a"
2040+-- > ["","a"]
2041+--
2042+-- >>> splitOn' (== '.') "a."
2043+-- > ["a",""]
2044+--
2045+-- >>> splitOn' (== '.') "a.b"
2046+-- > ["a","b"]
2047+--
2048+-- >>> splitOn' (== '.') "a..b"
2049+-- > ["a","","b"]
2050+--
2051+-- @since 0.7.0
2052+
2053+-- This can be considered as an n-fold version of 'breakOn' where we apply
2054+-- 'breakOn' successively on the input stream, dropping the first element
2055+-- of the second segment after each break.
2056+--
2057+{-# INLINE splitOn #-}
2058+splitOn
2059+ :: (IsStream t, Monad m)
2060+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
2061+splitOn predicate f = foldMany (FL.sliceSepBy predicate f)
2062+
2063+-- | Like 'splitOn' but the separator is considered as suffixed to the segments
2064+-- in the stream. A missing suffix at the end is allowed. A separator at the
2065+-- beginning is parsed as empty segment. With '-' representing elements and
2066+-- '.' as separator, 'splitOnSuffix' splits as follows:
2067+--
2068+-- @
2069+-- "--.--." => "--" "--"
2070+-- "--.--" => "--" "--"
2071+-- ".--." => "" "--"
2072+-- @
2073+--
2074+-- > splitOnSuffix' p xs = S.toList $ S.splitSuffixBy p (FL.toList) (S.fromList xs)
2075+--
2076+-- >>> splitOnSuffix' (== '.') ""
2077+-- []
2078+--
2079+-- >>> splitOnSuffix' (== '.') "."
2080+-- [""]
2081+--
2082+-- >>> splitOnSuffix' (== '.') "a"
2083+-- ["a"]
2084+--
2085+-- >>> splitOnSuffix' (== '.') ".a"
2086+-- > ["","a"]
2087+--
2088+-- >>> splitOnSuffix' (== '.') "a."
2089+-- > ["a"]
2090+--
2091+-- >>> splitOnSuffix' (== '.') "a.b"
2092+-- > ["a","b"]
2093+--
2094+-- >>> splitOnSuffix' (== '.') "a.b."
2095+-- > ["a","b"]
2096+--
2097+-- >>> splitOnSuffix' (== '.') "a..b.."
2098+-- > ["a","","b",""]
2099+--
2100+-- > lines = splitOnSuffix (== '\n')
2101+--
2102+-- @since 0.7.0
2103+
2104+-- This can be considered as an n-fold version of 'breakPost' where we apply
2105+-- 'breakPost' successively on the input stream, dropping the first element
2106+-- of the second segment after each break.
2107+--
2108+{-# INLINE splitOnSuffix #-}
2109+splitOnSuffix
2110+ :: (IsStream t, Monad m)
2111+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
2112+splitOnSuffix predicate f m =
2113+ D.fromStreamD $ D.foldMany1 (FL.sliceSepBy predicate f) (D.toStreamD m)
2114+
2115+-- | Like 'splitOn' after stripping leading, trailing, and repeated separators.
2116+-- Therefore, @".a..b."@ with '.' as the separator would be parsed as
2117+-- @["a","b"]@. In other words, its like parsing words from whitespace
2118+-- separated text.
2119+--
2120+-- > wordsBy' p xs = S.toList $ S.wordsBy p (FL.toList) (S.fromList xs)
2121+--
2122+-- >>> wordsBy' (== ',') ""
2123+-- > []
2124+--
2125+-- >>> wordsBy' (== ',') ","
2126+-- > []
2127+--
2128+-- >>> wordsBy' (== ',') ",a,,b,"
2129+-- > ["a","b"]
2130+--
2131+-- > words = wordsBy isSpace
2132+--
2133+-- @since 0.7.0
2134+
2135+-- It is equivalent to splitting in any of the infix/prefix/suffix styles
2136+-- followed by removal of empty segments.
2137+{-# INLINE wordsBy #-}
2138+wordsBy
2139+ :: (IsStream t, Monad m)
2140+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
2141+wordsBy predicate f m =
2142+ D.fromStreamD $ D.wordsBy predicate f (D.toStreamD m)
2143+
2144+-- | Like 'splitOnSuffix' but keeps the suffix attached to the resulting
2145+-- splits.
2146+--
2147+-- > splitWithSuffix' p xs = S.toList $ S.splitWithSuffix p (FL.toList) (S.fromList xs)
2148+--
2149+-- >>> splitWithSuffix' (== '.') ""
2150+-- []
2151+--
2152+-- >>> splitWithSuffix' (== '.') "."
2153+-- ["."]
2154+--
2155+-- >>> splitWithSuffix' (== '.') "a"
2156+-- ["a"]
2157+--
2158+-- >>> splitWithSuffix' (== '.') ".a"
2159+-- > [".","a"]
2160+--
2161+-- >>> splitWithSuffix' (== '.') "a."
2162+-- > ["a."]
2163+--
2164+-- >>> splitWithSuffix' (== '.') "a.b"
2165+-- > ["a.","b"]
2166+--
2167+-- >>> splitWithSuffix' (== '.') "a.b."
2168+-- > ["a.","b."]
2169+--
2170+-- >>> splitWithSuffix' (== '.') "a..b.."
2171+-- > ["a.",".","b.","."]
2172+--
2173+-- @since 0.7.0
2174+
2175+-- This can be considered as an n-fold version of 'breakPost' where we apply
2176+-- 'breakPost' successively on the input stream.
2177+--
2178+{-# INLINE splitWithSuffix #-}
2179+splitWithSuffix
2180+ :: (IsStream t, Monad m)
2181+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
2182+splitWithSuffix predicate f m =
2183+ D.fromStreamD $ D.foldMany1 (FL.sliceEndWith predicate f) (D.toStreamD m)
2184+
2185+------------------------------------------------------------------------------
2186+-- Split on a delimiter sequence
2187+------------------------------------------------------------------------------
2188+
2189+-- Int list examples for splitOn:
2190+--
2191+-- >>> splitList [] [1,2,3,3,4]
2192+-- > [[1],[2],[3],[3],[4]]
2193+--
2194+-- >>> splitList [5] [1,2,3,3,4]
2195+-- > [[1,2,3,3,4]]
2196+--
2197+-- >>> splitList [1] [1,2,3,3,4]
2198+-- > [[],[2,3,3,4]]
2199+--
2200+-- >>> splitList [4] [1,2,3,3,4]
2201+-- > [[1,2,3,3],[]]
2202+--
2203+-- >>> splitList [2] [1,2,3,3,4]
2204+-- > [[1],[3,3,4]]
2205+--
2206+-- >>> splitList [3] [1,2,3,3,4]
2207+-- > [[1,2],[],[4]]
2208+--
2209+-- >>> splitList [3,3] [1,2,3,3,4]
2210+-- > [[1,2],[4]]
2211+--
2212+-- >>> splitList [1,2,3,3,4] [1,2,3,3,4]
2213+-- > [[],[]]
2214+
2215+-- | Like 'splitOn' but the separator is a sequence of elements instead of a
2216+-- single element.
2217+--
2218+-- For illustration, let's define a function that operates on pure lists:
2219+--
2220+-- @
2221+-- splitOnSeq' pat xs = S.toList $ S.splitOnSeq (A.fromList pat) (FL.toList) (S.fromList xs)
2222+-- @
2223+--
2224+-- >>> splitOnSeq' "" "hello"
2225+-- > ["h","e","l","l","o"]
2226+--
2227+-- >>> splitOnSeq' "hello" ""
2228+-- > [""]
2229+--
2230+-- >>> splitOnSeq' "hello" "hello"
2231+-- > ["",""]
2232+--
2233+-- >>> splitOnSeq' "x" "hello"
2234+-- > ["hello"]
2235+--
2236+-- >>> splitOnSeq' "h" "hello"
2237+-- > ["","ello"]
2238+--
2239+-- >>> splitOnSeq' "o" "hello"
2240+-- > ["hell",""]
2241+--
2242+-- >>> splitOnSeq' "e" "hello"
2243+-- > ["h","llo"]
2244+--
2245+-- >>> splitOnSeq' "l" "hello"
2246+-- > ["he","","o"]
2247+--
2248+-- >>> splitOnSeq' "ll" "hello"
2249+-- > ["he","o"]
2250+--
2251+-- 'splitOnSeq' is an inverse of 'intercalate'. The following law always holds:
2252+--
2253+-- > intercalate . splitOn == id
2254+--
2255+-- The following law holds when the separator is non-empty and contains none of
2256+-- the elements present in the input lists:
2257+--
2258+-- > splitOn . intercalate == id
2259+--
2260+-- /Internal/
2261+
2262+-- XXX We can use a polymorphic vector implemented by Array# to represent the
2263+-- sequence, that way we can avoid the Storable constraint. If we still need
2264+-- Storable Array for performance, we can use a separate splitOnArray API for
2265+-- that. We can also have an API where the sequence itself is a lazy stream, so
2266+-- that we can search files in files for example.
2267+{-# INLINE splitOnSeq #-}
2268+splitOnSeq
2269+ :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
2270+ => Array a -> Fold m a b -> t m a -> t m b
2271+splitOnSeq patt f m = D.fromStreamD $ D.splitOnSeq patt f (D.toStreamD m)
2272+
2273+{-
2274+-- This can be implemented easily using Rabin Karp
2275+-- | Split on any one of the given patterns.
2276+{-# INLINE splitOnAny #-}
2277+splitOnAny
2278+ :: (IsStream t, Monad m, Storable a, Integral a)
2279+ => [Array a] -> Fold m a b -> t m a -> t m b
2280+splitOnAny subseq f m = undefined -- D.fromStreamD $ D.splitOnAny f subseq (D.toStreamD m)
2281+-}
2282+
2283+-- | Like 'splitSuffixBy' but the separator is a sequence of elements, instead
2284+-- of a predicate for a single element.
2285+--
2286+-- > splitOnSuffixSeq_ pat xs = S.toList $ S.splitOnSuffixSeq (A.fromList pat) (FL.toList) (S.fromList xs)
2287+--
2288+-- >>> splitOnSuffixSeq_ "." ""
2289+-- []
2290+--
2291+-- >>> splitOnSuffixSeq_ "." "."
2292+-- [""]
2293+--
2294+-- >>> splitOnSuffixSeq_ "." "a"
2295+-- ["a"]
2296+--
2297+-- >>> splitOnSuffixSeq_ "." ".a"
2298+-- > ["","a"]
2299+--
2300+-- >>> splitOnSuffixSeq_ "." "a."
2301+-- > ["a"]
2302+--
2303+-- >>> splitOnSuffixSeq_ "." "a.b"
2304+-- > ["a","b"]
2305+--
2306+-- >>> splitOnSuffixSeq_ "." "a.b."
2307+-- > ["a","b"]
2308+--
2309+-- >>> splitOnSuffixSeq_ "." "a..b.."
2310+-- > ["a","","b",""]
2311+--
2312+-- > lines = splitOnSuffixSeq "\n"
2313+--
2314+-- 'splitOnSuffixSeq' is an inverse of 'intercalateSuffix'. The following law
2315+-- always holds:
2316+--
2317+-- > intercalateSuffix . splitOnSuffixSeq == id
2318+--
2319+-- The following law holds when the separator is non-empty and contains none of
2320+-- the elements present in the input lists:
2321+--
2322+-- > splitSuffixOn . intercalateSuffix == id
2323+--
2324+-- /Internal/
2325+{-# INLINE splitOnSuffixSeq #-}
2326+splitOnSuffixSeq
2327+ :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
2328+ => Array a -> Fold m a b -> t m a -> t m b
2329+splitOnSuffixSeq patt f m =
2330+ D.fromStreamD $ D.splitOnSuffixSeq False patt f (D.toStreamD m)
2331+
2332+{-
2333+-- | Like 'splitOn' but drops any empty splits.
2334+--
2335+{-# INLINE wordsOn #-}
2336+wordsOn
2337+ :: (IsStream t, Monad m, Storable a, Eq a)
2338+ => Array a -> Fold m a b -> t m a -> t m b
2339+wordsOn subseq f m = undefined -- D.fromStreamD $ D.wordsOn f subseq (D.toStreamD m)
2340+-}
2341+
2342+-- | Like 'splitOnSuffixSeq' but keeps the suffix intact in the splits.
2343+--
2344+-- > splitWithSuffixSeq'_ pat xs = S.toList $ S.splitWithSuffixSeq (A.fromList pat) (FL.toList) (S.fromList xs)
2345+--
2346+-- >>> splitWithSuffixSeq' "." ""
2347+-- [""]
2348+--
2349+-- >>> splitWithSuffixSeq' "." "."
2350+-- ["."]
2351+--
2352+-- >>> splitWithSuffixSeq' "." "a"
2353+-- ["a"]
2354+--
2355+-- >>> splitWithSuffixSeq' "." ".a"
2356+-- > [".","a"]
2357+--
2358+-- >>> splitWithSuffixSeq' "." "a."
2359+-- > ["a."]
2360+--
2361+-- >>> splitWithSuffixSeq' "." "a.b"
2362+-- > ["a.","b"]
2363+--
2364+-- >>> splitWithSuffixSeq' "." "a.b."
2365+-- > ["a.","b."]
2366+--
2367+-- >>> splitWithSuffixSeq' "." "a..b.."
2368+-- > ["a.",".","b.","."]
2369+--
2370+-- /Internal/
2371+{-# INLINE splitWithSuffixSeq #-}
2372+splitWithSuffixSeq
2373+ :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
2374+ => Array a -> Fold m a b -> t m a -> t m b
2375+splitWithSuffixSeq patt f m =
2376+ D.fromStreamD $ D.splitOnSuffixSeq True patt f (D.toStreamD m)
2377+
2378+{-
2379+-- This can be implemented easily using Rabin Karp
2380+-- | Split post any one of the given patterns.
2381+{-# INLINE splitOnSuffixSeqAny #-}
2382+splitOnSuffixSeqAny
2383+ :: (IsStream t, Monad m, Storable a, Integral a)
2384+ => [Array a] -> Fold m a b -> t m a -> t m b
2385+splitOnSuffixSeqAny subseq f m = undefined
2386+ -- D.fromStreamD $ D.splitPostAny f subseq (D.toStreamD m)
2387+-}
2388+
2389+------------------------------------------------------------------------------
2390+-- Nested Split
2391+------------------------------------------------------------------------------
2392+
2393+-- | @splitInnerBy splitter joiner stream@ splits the inner containers @f a@ of
2394+-- an input stream @t m (f a)@ using the @splitter@ function. Container
2395+-- elements @f a@ are collected until a split occurs, then all the elements
2396+-- before the split are joined using the @joiner@ function.
2397+--
2398+-- For example, if we have a stream of @Array Word8@, we may want to split the
2399+-- stream into arrays representing lines separated by '\n' byte such that the
2400+-- resulting stream after a split would be one array for each line.
2401+--
2402+-- CAUTION! This is not a true streaming function as the container size after
2403+-- the split and merge may not be bounded.
2404+--
2405+-- /Internal/
2406+{-# INLINE splitInnerBy #-}
2407+splitInnerBy
2408+ :: (IsStream t, Monad m)
2409+ => (f a -> m (f a, Maybe (f a))) -- splitter
2410+ -> (f a -> f a -> m (f a)) -- joiner
2411+ -> t m (f a)
2412+ -> t m (f a)
2413+splitInnerBy splitter joiner xs =
2414+ D.fromStreamD $ D.splitInnerBy splitter joiner $ D.toStreamD xs
2415+
2416+-- | Like 'splitInnerBy' but splits assuming the separator joins the segment in
2417+-- a suffix style.
2418+--
2419+-- /Internal/
2420+{-# INLINE splitInnerBySuffix #-}
2421+splitInnerBySuffix
2422+ :: (IsStream t, Monad m, Eq (f a), Monoid (f a))
2423+ => (f a -> m (f a, Maybe (f a))) -- splitter
2424+ -> (f a -> f a -> m (f a)) -- joiner
2425+ -> t m (f a)
2426+ -> t m (f a)
2427+splitInnerBySuffix splitter joiner xs =
2428+ D.fromStreamD $ D.splitInnerBySuffix splitter joiner $ D.toStreamD xs
2429+
2430+------------------------------------------------------------------------------
2431+-- Reorder in sequence
2432+------------------------------------------------------------------------------
2433+
2434+{-
2435+-- Buffer until the next element in sequence arrives. The function argument
2436+-- determines the difference in sequence numbers. This could be useful in
2437+-- implementing sequenced streams, for example, TCP reassembly.
2438+{-# INLINE reassembleBy #-}
2439+reassembleBy
2440+ :: (IsStream t, Monad m)
2441+ => Fold m a b
2442+ -> (a -> a -> Int)
2443+ -> t m a
2444+ -> t m b
2445+reassembleBy = undefined
2446+-}
2447+
2448+------------------------------------------------------------------------------
2449+-- Distributing
2450+------------------------------------------------------------------------------
2451+
2452+-- | Tap the data flowing through a stream into a 'Fold'. For example, you may
2453+-- add a tap to log the contents flowing through the stream. The fold is used
2454+-- only for effects, its result is discarded.
2455+--
2456+-- @
2457+-- Fold m a b
2458+-- |
2459+-- -----stream m a ---------------stream m a-----
2460+--
2461+-- @
2462+--
2463+-- @
2464+-- > S.drain $ S.tap (FL.drainBy print) (S.enumerateFromTo 1 2)
2465+-- 1
2466+-- 2
2467+-- @
2468+--
2469+-- Compare with 'trace'.
2470+--
2471+-- @since 0.7.0
2472+{-# INLINE tap #-}
2473+tap :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> t m a
2474+tap f xs = D.fromStreamD $ D.tap f (D.toStreamD xs)
2475+
2476+-- | @tapOffsetEvery offset n@ taps every @n@th element in the stream
2477+-- starting at @offset@. @offset@ can be between @0@ and @n - 1@. Offset 0
2478+-- means start at the first element in the stream. If the offset is outside
2479+-- this range then @offset `mod` n@ is used as offset.
2480+--
2481+-- @
2482+-- >>> S.drain $ S.tapOffsetEvery 0 2 (FL.mapM print FL.toList) $ S.enumerateFromTo 0 10
2483+-- > [0,2,4,6,8,10]
2484+-- @
2485+--
2486+-- /Internal/
2487+--
2488+{-# INLINE tapOffsetEvery #-}
2489+tapOffsetEvery :: (IsStream t, Monad m)
2490+ => Int -> Int -> FL.Fold m a b -> t m a -> t m a
2491+tapOffsetEvery offset n f xs =
2492+ D.fromStreamD $ D.tapOffsetEvery offset n f (D.toStreamD xs)
2493+
2494+-- | Redirect a copy of the stream to a supplied fold and run it concurrently
2495+-- in an independent thread. The fold may buffer some elements. The buffer size
2496+-- is determined by the prevailing 'maxBuffer' setting.
2497+--
2498+-- @
2499+-- Stream m a -> m b
2500+-- |
2501+-- -----stream m a ---------------stream m a-----
2502+--
2503+-- @
2504+--
2505+-- @
2506+-- > S.drain $ S.tapAsync (S.mapM_ print) (S.enumerateFromTo 1 2)
2507+-- 1
2508+-- 2
2509+-- @
2510+--
2511+-- Exceptions from the concurrently running fold are propagated to the current
2512+-- computation. Note that, because of buffering in the fold, exceptions may be
2513+-- delayed and may not correspond to the current element being processed in the
2514+-- parent stream, but we guarantee that before the parent stream stops the tap
2515+-- finishes and all exceptions from it are drained.
2516+--
2517+--
2518+-- Compare with 'tap'.
2519+--
2520+-- /Internal/
2521+{-# INLINE tapAsync #-}
2522+tapAsync :: (IsStream t, MonadAsync m) => FL.Fold m a b -> t m a -> t m a
2523+tapAsync f xs = D.fromStreamD $ D.tapAsync f (D.toStreamD xs)
2524+
2525+-- | @pollCounts predicate transform fold stream@ counts those elements in the
2526+-- stream that pass the @predicate@. The resulting count stream is sent to
2527+-- another thread which transforms it using @transform@ and then folds it using
2528+-- @fold@. The thread is automatically cleaned up if the stream stops or
2529+-- aborts due to exception.
2530+--
2531+-- For example, to print the count of elements processed every second:
2532+--
2533+-- @
2534+-- > S.drain $ S.pollCounts (const True) (S.rollingMap (-) . S.delayPost 1) (FL.drainBy print)
2535+-- $ S.enumerateFrom 0
2536+-- @
2537+--
2538+-- Note: This may not work correctly on 32-bit machines.
2539+--
2540+-- /Internal/
2541+--
2542+{-# INLINE pollCounts #-}
2543+pollCounts ::
2544+ (IsStream t, MonadAsync m)
2545+ => (a -> Bool)
2546+ -> (t m Int -> t m Int)
2547+ -> Fold m Int b
2548+ -> t m a
2549+ -> t m a
2550+pollCounts predicate transf f xs =
2551+ D.fromStreamD
2552+ $ D.pollCounts predicate (D.toStreamD . transf . D.fromStreamD) f
2553+ $ D.toStreamD xs
2554+
2555+-- | Calls the supplied function with the number of elements consumed
2556+-- every @n@ seconds. The given function is run in a separate thread
2557+-- until the end of the stream. In case there is an exception in the
2558+-- stream the thread is killed during the next major GC.
2559+--
2560+-- Note: The action is not guaranteed to run if the main thread exits.
2561+--
2562+-- @
2563+-- > delay n = threadDelay (round $ n * 1000000) >> return n
2564+-- > S.drain $ S.tapRate 2 (\\n -> print $ show n ++ " elements processed") (delay 1 S.|: delay 0.5 S.|: delay 0.5 S.|: S.nil)
2565+-- 2 elements processed
2566+-- 1 elements processed
2567+-- @
2568+--
2569+-- Note: This may not work correctly on 32-bit machines.
2570+--
2571+-- /Internal/
2572+{-# INLINE tapRate #-}
2573+tapRate ::
2574+ (IsStream t, MonadAsync m, MonadCatch m)
2575+ => Double
2576+ -> (Int -> m b)
2577+ -> t m a
2578+ -> t m a
2579+tapRate n f xs = D.fromStreamD $ D.tapRate n f $ D.toStreamD xs
2580+
2581+-- | Apply a monadic function to each element flowing through the stream and
2582+-- discard the results.
2583+--
2584+-- @
2585+-- > S.drain $ S.trace print (S.enumerateFromTo 1 2)
2586+-- 1
2587+-- 2
2588+-- @
2589+--
2590+-- Compare with 'tap'.
2591+--
2592+-- @since 0.7.0
2593+{-# INLINE trace #-}
2594+trace :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m a
2595+trace f = mapM (\x -> void (f x) >> return x)
2596+
2597+-- | Perform a side effect before yielding each element of the stream and
2598+-- discard the results.
2599+--
2600+-- @
2601+-- > S.drain $ S.trace_ (print "got here") (S.enumerateFromTo 1 2)
2602+-- "got here"
2603+-- "got here"
2604+-- @
2605+--
2606+-- See also: 'trace', 'interspersePrefix_'
2607+--
2608+-- /Internal/
2609+{-# INLINE trace_ #-}
2610+trace_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
2611+trace_ eff = Serial.mapM (\x -> eff >> return x)
2612+
2613+
2614+------------------------------------------------------------------------------
2615+-- Generalize the underlying monad
2616+------------------------------------------------------------------------------
2617+
2618+-- | Transform the inner monad of a stream using a natural transformation.
2619+--
2620+-- / Internal/
2621+--
2622+{-# INLINE hoist #-}
2623+hoist :: (Monad m, Monad n)
2624+ => (forall x. m x -> n x) -> SerialT m a -> SerialT n a
2625+hoist f xs = fromStreamS $ S.hoist f (toStreamS xs)
2626+
2627+-- | Generalize the inner monad of the stream from 'Identity' to any monad.
2628+--
2629+-- / Internal/
2630+--
2631+{-# INLINE generally #-}
2632+generally :: (IsStream t, Monad m) => t Identity a -> t m a
2633+generally xs = fromStreamS $ S.hoist (return . runIdentity) (toStreamS xs)
2634+
2635+------------------------------------------------------------------------------
2636+-- Add and remove a monad transformer
2637+------------------------------------------------------------------------------
2638+
2639+-- | Lift the inner monad @m@ of a stream @t m a@ to @tr m@ using the monad
2640+-- transformer @tr@.
2641+--
2642+-- / Internal/
2643+--
2644+{-# INLINE liftInner #-}
2645+liftInner :: (Monad m, IsStream t, MonadTrans tr, Monad (tr m))
2646+ => t m a -> t (tr m) a
2647+liftInner xs = fromStreamD $ D.liftInner (toStreamD xs)
2648+
2649+------------------------------------------------------------------------------
2650+-- Sharing read only state in a stream
2651+------------------------------------------------------------------------------
2652+
2653+-- | Evaluate the inner monad of a stream as 'ReaderT'.
2654+--
2655+-- / Internal/
2656+--
2657+{-# INLINE runReaderT #-}
2658+runReaderT :: (IsStream t, Monad m) => m s -> t (ReaderT s m) a -> t m a
2659+runReaderT s xs = fromStreamD $ D.runReaderT s (toStreamD xs)
2660+
2661+-- | Run a stream transformation using a given environment.
2662+--
2663+-- See also: 'Serial.map'
2664+--
2665+-- / Internal/
2666+--
2667+{-# INLINE usingReaderT #-}
2668+usingReaderT
2669+ :: (Monad m, IsStream t)
2670+ => m r
2671+ -> (t (ReaderT r m) a -> t (ReaderT r m) a)
2672+ -> t m a
2673+ -> t m a
2674+usingReaderT r f xs = runReaderT r $ f $ liftInner xs
2675+
2676+------------------------------------------------------------------------------
2677+-- Sharing read write state in a stream
2678+------------------------------------------------------------------------------
2679+
2680+-- | Evaluate the inner monad of a stream as 'StateT'.
2681+--
2682+-- This is supported only for 'SerialT' as concurrent state updation may not be
2683+-- safe.
2684+--
2685+-- / Internal/
2686+--
2687+{-# INLINE evalStateT #-}
2688+evalStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m a
2689+evalStateT s xs = fromStreamD $ D.evalStateT s (toStreamD xs)
2690+
2691+-- | Run a stateful (StateT) stream transformation using a given state.
2692+--
2693+-- This is supported only for 'SerialT' as concurrent state updation may not be
2694+-- safe.
2695+--
2696+-- See also: 'scanl''
2697+--
2698+-- / Internal/
2699+--
2700+{-# INLINE usingStateT #-}
2701+usingStateT
2702+ :: Monad m
2703+ => m s
2704+ -> (SerialT (StateT s m) a -> SerialT (StateT s m) a)
2705+ -> SerialT m a
2706+ -> SerialT m a
2707+usingStateT s f xs = evalStateT s $ f $ liftInner xs
2708+
2709+-- | Evaluate the inner monad of a stream as 'StateT' and emit the resulting
2710+-- state and value pair after each step.
2711+--
2712+-- This is supported only for 'SerialT' as concurrent state updation may not be
2713+-- safe.
2714+--
2715+-- / Internal/
2716+--
2717+{-# INLINE runStateT #-}
2718+runStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m (s, a)
2719+runStateT s xs = fromStreamD $ D.runStateT s (toStreamD xs)
streamly.cabal+4
@@ -459,6 +459,10 @@ library
459459
460460 -- Higher level streams
461461 , Streamly.Internal.Data.Stream.IsStream
462+ , Streamly.Internal.Data.Stream.IsStream.Generate
463+ , Streamly.Internal.Data.Stream.IsStream.Eliminate
464+ , Streamly.Internal.Data.Stream.IsStream.Transform
465+ , Streamly.Internal.Data.Stream.IsStream.Exceptions
462466 , Streamly.Internal.Data.Stream.SVar
463467 , Streamly.Internal.Data.Stream.Serial
464468 , Streamly.Internal.Data.Stream.Async