@@ -598,75 +598,36 @@ module Streamly.Internal.Data.Stream.IsStream
598598 )
599599where
600600
601−import Control.Concurrent (threadDelay)
602−import Control.Exception (Exception, assert)
603−import Control.Monad (void)
604−import Control.Monad.Catch (MonadCatch, MonadThrow)
605−import 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 (..))
612−import Data.Kind (Type)
613−import Data.Heap (Entry(..))
614−import Data.Maybe (isJust, fromJust, isNothing)
615−import Data.Void (Void)
616−import Foreign.Storable (Storable)
617−import Streamly.Internal.BaseCompat (fromLeft, fromRight)
618−import Streamly.Internal.Data.Stream.Enumeration
619− (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)
601+import Streamly.Internal.Data.SVar (MonadAsync, Rate (..))
602+import Streamly.Internal.Data.Stream.Ahead (AheadT, Ahead, aheadly)
626603import Streamly.Internal.Data.Stream.Async
627− ( AsyncT, Async, WAsyncT, WAsync, mkAsync, async, asyncly, wAsync
604+ ( AsyncT, Async, WAsyncT, WAsync, mkAsync, asyncly
628605 , wAsyncly)
629606import Streamly.Internal.Data.Stream.Combinators
630− ( inspectMode, maxBuffer, maxThreads, maxYields, rate, avgRate, minRate
607+ ( inspectMode, maxBuffer, maxThreads, rate, avgRate, minRate
631608 , maxRate, constRate)
632609import 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)
638−import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM), adapt)
610+ ( ParallelT, Parallel, parallely)
611+import Streamly.Internal.Data.Stream.StreamK (IsStream(), adapt)
639612import Streamly.Internal.Data.Stream.Serial
640− ( SerialT, WSerialT, Serial, WSerial, serial, wSerial, serially
613+ ( SerialT, WSerialT, Serial, WSerial, serially
641614 , wSerially)
642615import Streamly.Internal.Data.Stream.Zip
643616 ( ZipSerialM, ZipSerial, ZipAsyncM, ZipAsync, zipSerially, zipAsyncly)
644−import Streamly.Internal.Data.Pipe.Types (Pipe (..))
645−import Streamly.Internal.Data.Time.Units
646− ( AbsTime, MilliSecond64(..), addToAbsTime, toRelTime
647− , toAbsTime, TimeUnit64, RelTime64, addToAbsTime64)
648−import Streamly.Internal.Data.IORef.Prim (Prim, IORef)
649−import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
650617
651−import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
652−import qualified Streamly.Internal.Data.Fold as FL
653618import qualified Streamly.Internal.Data.Stream.Prelude as P
654619import qualified Streamly.Internal.Data.Stream.StreamK as K
655620import qualified Streamly.Internal.Data.Stream.StreamD as D
656621import qualified Streamly.Internal.Data.Stream.Serial as Serial
657622import qualified Streamly.Internal.Data.Stream.Parallel as Par
658623import 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
661−import qualified Data.Heap as H
662−import 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
624+
625+import Streamly.Internal.Data.Stream.IsStream.Generate
626+import Streamly.Internal.Data.Stream.IsStream.Eliminate
627+import Streamly.Internal.Data.Stream.IsStream.Transform
628+import Streamly.Internal.Data.Stream.IsStream.Nesting
629+import Streamly.Internal.Data.Stream.IsStream.Exception
630+import Streamly.Internal.Data.Stream.IsStream.Lift
670631
671632import Prelude hiding
672633 ( filter, drop, dropWhile, take, takeWhile, zipWith, foldr
@@ -675,4756 +636,3 @@ import Prelude hiding
675636 , reverse, iterate, init, and, or, lookup, foldr1, (!!)
676637 , scanl, scanl1, replicate, concatMap, span, splitAt, break
677638 , repeat, concat, mconcat)
678−
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−
1010−------------------------------------------------------------------------------
1011−-- Conversions
1012−------------------------------------------------------------------------------
1013−
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−
1080−-- | Takes a callback setter function and provides it with a callback. The
1081−-- callback when invoked adds a value at the tail of the stream. Returns a
1082−-- stream of values generated by the callback.
1083−--
1084−-- /Internal/
1085−--
1086−{-# 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))
3954−
3955−------------------------------------------------------------------------------
3956−-- N-ary APIs
3957−------------------------------------------------------------------------------
3958−
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.
3965−--
3966−-- >>> S.toList $ S.groupsBy (>) FL.toList $ S.fromList [1,3,7,0,2,5]
3967−-- > [[1,3,7],[0,2,5]]
3968−--
3969−-- @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@.
3986−--
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]]
3989−--
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)
3999−
4000−-- |
4001−-- > groups = groupsBy (==)
4002−-- > groups = groupsByRolling (==)
4003−--
4004−-- Groups contiguous spans of equal elements together in individual groups.
4005−--
4006−-- >>> S.toList $ S.groups FL.toList $ S.fromList [1,1,2,2]
4007−-- > [[1,1],[2,2]]
4008−--
4009−-- @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 (==)
4013−
4014−------------------------------------------------------------------------------
4015−-- N-ary split on a predicate
4016−------------------------------------------------------------------------------
4017−
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:
4030−--
4031−-- @
4032−-- "--.--" => "--" "--"
4033−-- "--." => "--" ""
4034−-- ".--" => "" "--"
4035−-- @
4036−--
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−-- ["",""]
4048−--
4049−-- >>> splitOn' (== '.') ".a"
4050−-- > ["","a"]
4051−--
4052−-- >>> splitOn' (== '.') "a."
4053−-- > ["a",""]
4054−--
4055−-- >>> splitOn' (== '.') "a.b"
4056−-- > ["a","b"]
4057−--
4058−-- >>> splitOn' (== '.') "a..b"
4059−-- > ["a","","b"]
4060−--
4061−-- @since 0.7.0
4062−
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.
4066−--
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)
4072−
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:
4077−--
4078−-- @
4079−-- "--.--." => "--" "--"
4080−-- "--.--" => "--" "--"
4081−-- ".--." => "" "--"
4082−-- @
4083−--
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')
4111−--
4112−-- @since 0.7.0
4113−
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−-- > []
4137−--
4138−-- >>> wordsBy' (== ',') ",a,,b,"
4139−-- > ["a","b"]
4140−--
4141−-- > words = wordsBy isSpace
4142−--
4143−-- @since 0.7.0
4144−
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)
4153−
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."]
4179−--
4180−-- >>> splitWithSuffix' (== '.') "a..b.."
4181−-- > ["a.",".","b.","."]
4182−--
4183−-- @since 0.7.0
4184−
4185−-- This can be considered as an n-fold version of 'breakPost' where we apply
4186−-- 'breakPost' successively on the input stream.
4187−--
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)
4194−
4195−------------------------------------------------------------------------------
4196−-- Split on a delimiter sequence
4197−------------------------------------------------------------------------------
4198−
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]]
4209−--
4210−-- >>> splitList [4] [1,2,3,3,4]
4211−-- > [[1,2,3,3],[]]
4212−--
4213−-- >>> splitList [2] [1,2,3,3,4]
4214−-- > [[1],[3,3,4]]
4215−--
4216−-- >>> splitList [3] [1,2,3,3,4]
4217−-- > [[1,2],[],[4]]
4218−--
4219−-- >>> splitList [3,3] [1,2,3,3,4]
4220−-- > [[1,2],[4]]
4221−--
4222−-- >>> splitList [1,2,3,3,4] [1,2,3,3,4]
4223−-- > [[],[]]
4224−
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:
4229−--
4230−-- @
4231−-- splitOnSeq' pat xs = S.toList $ S.splitOnSeq (A.fromList pat) (FL.toList) (S.fromList xs)
4232−-- @
4233−--
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
4269−--
4270−-- /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−-- []
4300−--
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"
4323−--
4324−-- 'splitOnSuffixSeq' is an inverse of 'intercalateSuffix'. The following law
4325−-- always holds:
4326−--
4327−-- > intercalateSuffix . splitOnSuffixSeq == id
4328−--
4329−-- The following law holds when the separator is non-empty and contains none of
4330−-- the elements present in the input lists:
4331−--
4332−-- > splitSuffixOn . intercalateSuffix == id
4333−--
4334−-- /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)
4341−
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−-}
4351−
4352−-- XXX use a non-monadic intersperse to remove the MonadAsync constraint.
4353−--
4354−-- | Like 'splitOnSeq' but splits the separator as well, as an infix token.
4355−--
4356−-- > splitOn'_ pat xs = S.toList $ S.splitOn' (A.fromList pat) (FL.toList) (S.fromList xs)
4357−--
4358−-- >>> splitOn'_ "" "hello"
4359−-- > ["h","","e","","l","","l","","o"]
4360−--
4361−-- >>> splitOn'_ "hello" ""
4362−-- > [""]
4363−--
4364−-- >>> splitOn'_ "hello" "hello"
4365−-- > ["","hello",""]
4366−--
4367−-- >>> splitOn'_ "x" "hello"
4368−-- > ["hello"]
4369−--
4370−-- >>> splitOn'_ "h" "hello"
4371−-- > ["","h","ello"]
4372−--
4373−-- >>> splitOn'_ "o" "hello"
4374−-- > ["hell","o",""]
4375−--
4376−-- >>> splitOn'_ "e" "hello"
4377−-- > ["h","e","llo"]
4378−--
4379−-- >>> splitOn'_ "l" "hello"
4380−-- > ["he","l","","l","o"]
4381−--
4382−-- >>> splitOn'_ "ll" "hello"
4383−-- > ["he","ll","o"]
4384−--
4385−-- /Internal/
4386−{-# INLINE splitBySeq #-}
4387−splitBySeq
4388− :: (IsStream t, MonadAsync m, Storable a, Enum a, Eq a)
4389− => Array a -> Fold m a b -> t m a -> t m b
4390−splitBySeq patt f m =
4391− intersperseM (fold f (A.toStream patt)) $ splitOnSeq patt f m
4392−
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"]
4405−--
4406−-- >>> splitWithSuffixSeq' "." ".a"
4407−-- > [".","a"]
4408−--
4409−-- >>> splitWithSuffixSeq' "." "a."
4410−-- > ["a."]
4411−--
4412−-- >>> splitWithSuffixSeq' "." "a.b"
4413−-- > ["a.","b"]
4414−--
4415−-- >>> splitWithSuffixSeq' "." "a.b."
4416−-- > ["a.","b."]
4417−--
4418−-- >>> splitWithSuffixSeq' "." "a..b.."
4419−-- > ["a.",".","b.","."]
4420−--
4421−-- /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)
4428−
4429−{-
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)
4438−-}
4439−
4440−------------------------------------------------------------------------------
4441−-- Nested Split
4442−------------------------------------------------------------------------------
4443−
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.
4448−--
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.
4452−--
4453−-- CAUTION! This is not a true streaming function as the container size after
4454−-- the split and merge may not be bounded.
4455−--
4456−-- /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.
4469−--
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
4491− :: (IsStream t, Monad m)
4492− => Fold m a b
4493− -> (a -> a -> Int)
4494− -> t m a
4495− -> t m b
4496−reassembleBy = undefined
4497−-}
4498−
4499−------------------------------------------------------------------------------
4500−-- Distributing
4501−------------------------------------------------------------------------------
4502−
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.
4531−--
4532−-- @
4533−-- >>> S.drain $ S.tapOffsetEvery 0 2 (FL.mapM print FL.toList) $ S.enumerateFromTo 0 10
4534−-- > [0,2,4,6,8,10]
4535−-- @
4536−--
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.
4548−--
4549−-- @
4550−-- Stream m a -> m b
4551−-- |
4552−-- -----stream m a ---------------stream m a-----
4553−--
4554−-- @
4555−--
4556−-- @
4557−-- > S.drain $ S.tapAsync (S.mapM_ print) (S.enumerateFromTo 1 2)
4558−-- 1
4559−-- 2
4560−-- @
4561−--
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:
4583−--
4584−-- @
4585−-- > S.drain $ S.pollCounts (const True) (S.rollingMap (-) . S.delayPost 1) (FL.drainBy print)
4586−-- $ S.enumerateFrom 0
4587−-- @
4588−--
4589−-- Note: This may not work correctly on 32-bit machines.
4590−--
4591−-- /Internal/
4592−--
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
4631−
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)
4647−
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−-- @
4656−--
4657−-- See also: 'trace', 'interspersePrefix_'
4658−--
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)
4663−
4664−------------------------------------------------------------------------------
4665−-- Windowed classification
4666−------------------------------------------------------------------------------
4667−
4668−-- We divide the stream into windows or chunks in space or time and each window
4669−-- can be associated with a key, all events associated with a particular key in
4670−-- the window can be folded to a single result. The stream can be split into
4671−-- windows by size or by using a split predicate on the elements in the stream.
4672−-- For example, when we receive a closing flag, we can close the window.
4673−--
4674−-- A "chunk" is a space window and a "session" is a time window. Are there any
4675−-- other better short words to describe them. An alternative is to use
4676−-- "swindow" and "twindow". Another word for "session" could be "spell".
4677−--
4678−-- TODO: To mark the position in space or time we can have Indexed or
4679−-- TimeStamped types. That can make it easy to deal with the position indices
4680−-- or timestamps.
4681−
4682−------------------------------------------------------------------------------
4683−-- Keyed Sliding Windows
4684−------------------------------------------------------------------------------
4685−
4686−{-
4687−{-# INLINABLE classifySlidingChunks #-}
4688−classifySlidingChunks
4689− :: (IsStream t, MonadAsync m, Ord k)
4690− => Int -- ^ window size
4691− -> Int -- ^ window slide
4692− -> Fold m a b -- ^ Fold to be applied to window events
4693− -> t m (k, a, Bool) -- ^ window key, data, close event
4694− -> t m (k, b)
4695−classifySlidingChunks wsize wslide (Fold step initial extract) str
4696− = undefined
4697−
4698−-- XXX Another variant could be to slide the window on an event, e.g. in TCP we
4699−-- slide the send window when an ack is received and we slide the receive
4700−-- window when a sequence is complete. Sliding is stateful in case of TCP,
4701−-- sliding releases the send buffer or makes data available to the user from
4702−-- the receive buffer.
4703−{-# INLINABLE classifySlidingSessions #-}
4704−classifySlidingSessions
4705− :: (IsStream t, MonadAsync m, Ord k)
4706− => Double -- ^ timer tick in seconds
4707− -> Double -- ^ time window size
4708− -> Double -- ^ window slide
4709− -> Fold m a b -- ^ Fold to be applied to window events
4710− -> t m (k, a, Bool, AbsTime) -- ^ window key, data, close flag, timestamp
4711− -> t m (k, b)
4712−classifySlidingSessions tick interval slide (Fold step initial extract) str
4713− = undefined
4714−-}
4715−
4716−------------------------------------------------------------------------------
4717−-- Sliding Window Buffers
4718−------------------------------------------------------------------------------
4719−
4720−-- These buffered versions could be faster than concurrent incremental folds of
4721−-- all overlapping windows as in many cases we may not need all the values to
4722−-- compute the fold, we can just compute the result using the old value and new
4723−-- value. However, we may need the buffer once in a while, for example for
4724−-- string search we usually compute the hash incrementally but when the hash
4725−-- matches the hash of the pattern we need to compare the whole string.
4726−--
4727−-- XXX we should be able to implement sequence based splitting combinators
4728−-- using this combinator.
4729−
4730−{-
4731−-- | Buffer n elements of the input in a ring buffer. When t new elements are
4732−-- collected, slide the window to remove the same number of oldest elements,
4733−-- insert the new elements, and apply an incremental fold on the sliding
4734−-- window, supplying the outgoing elements, the new ring buffer as arguments.
4735−slidingChunkBuffer
4736− :: (IsStream t, Monad m, Ord a, Storable a)
4737− => Int -- window size
4738− -> Int -- window slide
4739− -> Fold m (Ring a, Array a) b
4740− -> t m a
4741− -> t m b
4742−slidingChunkBuffer = undefined
4743−
4744−-- Buffer n seconds worth of stream elements of the input in a radix tree.
4745−-- Every t seconds, remove the items that are older than n seconds, and apply
4746−-- an incremental fold on the sliding window, supplying the outgoing elements,
4747−-- and the new radix tree buffer as arguments.
4748−slidingSessionBuffer
4749− :: (IsStream t, Monad m, Ord a, Storable a)
4750− => Int -- window size
4751− -> Int -- tick size
4752− -> Fold m (RTree a, Array a) b
4753− -> t m a
4754− -> t m b
4755−slidingSessionBuffer = undefined
4756−-}
4757−
4758−------------------------------------------------------------------------------
4759−-- Keyed Session Windows
4760−------------------------------------------------------------------------------
4761−
4762−{-
4763−-- | Keyed variable size space windows. Close the window if we do not receive a
4764−-- window event in the next "spaceout" elements.
4765−{-# INLINABLE classifyChunksBy #-}
4766−classifyChunksBy
4767− :: (IsStream t, MonadAsync m, Ord k)
4768− => Int -- ^ window spaceout (spread)
4769− -> Bool -- ^ reset the spaceout when a chunk window element is received
4770− -> Fold m a b -- ^ Fold to be applied to chunk window elements
4771− -> t m (k, a, Bool) -- ^ chunk key, data, last element
4772− -> t m (k, b)
4773−classifyChunksBy spanout reset (Fold step initial extract) str = undefined
4774−
4775−-- | Like 'classifyChunksOf' but the chunk size is reset if an element is
4776−-- received within the chunk size window. The chunk gets closed only if no
4777−-- element is received within the chunk window.
4778−--
4779−{-# INLINABLE classifyKeepAliveChunks #-}
4780−classifyKeepAliveChunks
4781− :: (IsStream t, MonadAsync m, Ord k)
4782− => Int -- ^ window spaceout (spread)
4783− -> Fold m a b -- ^ Fold to be applied to chunk window elements
4784− -> t m (k, a, Bool) -- ^ chunk key, data, last element
4785− -> t m (k, b)
4786−classifyKeepAliveChunks spanout = classifyChunksBy spanout True
4787−-}
4788−
4789−data SessionState t m k a b = SessionState
4790− { sessionCurTime :: !AbsTime -- ^ time since last event
4791− , sessionEventTime :: !AbsTime -- ^ time as per last event
4792− , sessionCount :: !Int -- ^ total number sessions in progress
4793− , sessionTimerHeap :: H.Heap (H.Entry AbsTime k) -- ^ heap for timeouts
4794− , sessionKeyValueMap :: Map.Map k a -- ^ Stored sessions for keys
4795− , sessionOutputStream :: t (m :: Type -> Type) (k, b) -- ^ Completed sessions
4796− }
4797−
4798−#undef Type
4799−
4800−-- XXX Perhaps we should use an "Event a" type to represent timestamped data.
4801−-- | @classifySessionsBy tick timeout idle pred f stream@ groups timestamped
4802−-- events in an input event stream into sessions based on a session key. Each
4803−-- element in the input stream is an event consisting of a triple @(session key,
4804−-- sesssion data, timestamp)@. @session key@ is a key that uniquely identifies
4805−-- the session. All the events belonging to a session are folded using the fold
4806−-- @f@ until the fold terminates or a timeout has occurred. The session key and
4807−-- the result of the fold are emitted in the output stream when the session is
4808−-- purged.
4809−--
4810−-- When @idle@ is 'False', @timeout@ is the maximum lifetime of a session in
4811−-- seconds, measured from the @timestamp@ of the first event in that session.
4812−-- When @idle@ is 'True' then the timeout is an idle timeout, it is reset after
4813−-- every event received in the session.
4814−--
4815−-- @timestamp@ in an event characterizes the time when the input event was
4816−-- generated, this is an absolute time measured from some @Epoch@. The notion
4817−-- of current time is maintained by a monotonic event time clock using the
4818−-- timestamps seen in the input stream. The latest timestamp seen till now is
4819−-- used as the base for the current time. When no new events are seen, a timer
4820−-- is started with a tick duration specified by @tick@. This timer is used to
4821−-- detect session timeouts in the absence of new events.
4822−--
4823−-- The predicate @pred@ is invoked with the current session count, if it
4824−-- returns 'True' a session is ejected from the session cache before inserting
4825−-- a new session. This could be useful to alert or eject sessions when the
4826−-- number of sessions becomes too high.
4827−--
4828−-- /Internal/
4829−--
4830−{-# INLINABLE classifySessionsBy #-}
4831−classifySessionsBy
4832− :: (IsStream t, MonadAsync m, Ord k)
4833− => Double -- ^ timer tick in seconds
4834− -> Double -- ^ session timeout in seconds
4835− -> Bool -- ^ reset the timeout when an event is received
4836− -> (Int -> m Bool) -- ^ predicate to eject sessions based on session count
4837− -> Fold m a b -- ^ Fold to be applied to session events
4838− -> t m (k, a, AbsTime) -- ^ session key, data, timestamp
4839− -> t m (k, b) -- ^ session key, fold result
4840−classifySessionsBy tick tmout reset ejectPred
4841− (Fold step initial extract) str =
4842− concatMap sessionOutputStream $
4843− scanlMAfter' sstep (return szero) flush stream
4844−
4845− where
4846−
4847− timeoutMs = toRelTime (round (tmout * 1000) :: MilliSecond64)
4848− tickMs = toRelTime (round (tick * 1000) :: MilliSecond64)
4849− szero = SessionState
4850− { sessionCurTime = toAbsTime (0 :: MilliSecond64)
4851− , sessionEventTime = toAbsTime (0 :: MilliSecond64)
4852− , sessionCount = 0
4853− , sessionTimerHeap = H.empty
4854− , sessionKeyValueMap = Map.empty
4855− , sessionOutputStream = K.nil
4856− }
4857−
4858− -- We can eject sessions based on the current session count to limit
4859− -- memory consumption. There are two possible strategies:
4860− --
4861− -- 1) Eject old sessions or sessions beyond a certain/lower timeout
4862− -- threshold even before timeout, effectively reduce the timeout.
4863− -- 2) Drop creation of new sessions but keep accepting new events for the
4864− -- old ones.
4865− --
4866− -- We use the first strategy as of now.
4867−
4868− -- Got a new stream input element
4869− sstep session@SessionState{..} (Just (key, value, timestamp)) = do
4870− -- XXX we should use a heap in pinned memory to scale it to a large
4871− -- size
4872− --
4873− -- To detect session inactivity we keep a timestamp of the latest event
4874− -- in the Map along with the fold result. When we purge the session
4875− -- from the heap we match the timestamp in the heap with the timestamp
4876− -- in the Map, if the latest timestamp is newer and has not expired we
4877− -- reinsert the key in the heap.
4878− --
4879− -- XXX if the key is an Int, we can also use an IntMap for slightly
4880− -- better performance.
4881− --
4882− let curTime = max sessionEventTime timestamp
4883− mOld = Map.lookup key sessionKeyValueMap
4884−
4885− fs <-
4886− case mOld of
4887− Nothing -> initial
4888− Just (Tuple' _ acc) -> return acc
4889− res <- step fs value
4890− case res of
4891− FL.Done fb -> do
4892− -- deleting a key from the heap is expensive, so we never
4893− -- delete a key from heap, we just purge it from the Map and it
4894− -- gets purged from the heap on timeout. We just need an extra
4895− -- lookup in the Map when the key is purged from the heap, that
4896− -- should not be expensive.
4897− --
4898− let (mp, cnt) = case mOld of
4899− Nothing -> (sessionKeyValueMap, sessionCount)
4900− Just _ -> (Map.delete key sessionKeyValueMap
4901− , sessionCount - 1)
4902− return $ session
4903− { sessionCurTime = curTime
4904− , sessionEventTime = curTime
4905− , sessionCount = cnt
4906− , sessionKeyValueMap = mp
4907− , sessionOutputStream = yield (key, fb)
4908− }
4909− FL.Partial fs1 -> do
4910− let acc = Tuple' timestamp fs1
4911− (hp1, mp1, out1, cnt1) <- do
4912− let vars = (sessionTimerHeap, sessionKeyValueMap,
4913− K.nil, sessionCount)
4914− case mOld of
4915− -- inserting new entry
4916− Nothing -> do
4917− -- Eject a session from heap and map is needed
4918− eject <- ejectPred sessionCount
4919− (hp, mp, out, cnt) <-
4920− if eject
4921− then ejectOne vars
4922− else return vars
4923−
4924− -- Insert the new session in heap
4925− let expiry = addToAbsTime timestamp timeoutMs
4926− hp' = H.insert (Entry expiry key) hp
4927− in return (hp', mp, out, cnt + 1)
4928− -- updating old entry
4929− Just _ -> return vars
4930−
4931− let mp2 = Map.insert key acc mp1
4932− return $ SessionState
4933− { sessionCurTime = curTime
4934− , sessionEventTime = curTime
4935− , sessionCount = cnt1
4936− , sessionTimerHeap = hp1
4937− , sessionKeyValueMap = mp2
4938− , sessionOutputStream = out1
4939− }
4940−
4941− -- Got a timer tick event
4942− sstep sessionState@SessionState{..} Nothing =
4943− let curTime = addToAbsTime sessionCurTime tickMs
4944− in ejectExpired sessionState curTime
4945−
4946− flush session@SessionState{..} = do
4947− (hp', mp', out, count) <-
4948− ejectAll
4949− ( sessionTimerHeap
4950− , sessionKeyValueMap
4951− , K.nil
4952− , sessionCount
4953− )
4954− return $ session
4955− { sessionCount = count
4956− , sessionTimerHeap = hp'
4957− , sessionKeyValueMap = mp'
4958− , sessionOutputStream = out
4959− }
4960−
4961− -- delete from map and output the fold accumulator
4962− ejectEntry hp mp out cnt acc key = do
4963− sess <- extract acc
4964− let out1 = (key, sess) `K.cons` out
4965− let mp1 = Map.delete key mp
4966− return (hp, mp1, out1, cnt - 1)
4967−
4968− ejectAll (hp, mp, out, !cnt) = do
4969− let hres = H.uncons hp
4970− case hres of
4971− Just (Entry _ key, hp1) -> do
4972− r <- case Map.lookup key mp of
4973− Nothing -> return (hp1, mp, out, cnt)
4974− Just (Tuple' _ acc) -> ejectEntry hp1 mp out cnt acc key
4975− ejectAll r
4976− Nothing -> do
4977− assert (Map.null mp) (return ())
4978− return (hp, mp, out, cnt)
4979−
4980− ejectOne (hp, mp, out, !cnt) = do
4981− let hres = H.uncons hp
4982− case hres of
4983− Just (Entry expiry key, hp1) ->
4984− case Map.lookup key mp of
4985− Nothing -> ejectOne (hp1, mp, out, cnt)
4986− Just (Tuple' latestTS acc) -> do
4987− let expiry1 = addToAbsTime latestTS timeoutMs
4988− if not reset || expiry1 <= expiry
4989− then ejectEntry hp1 mp out cnt acc key
4990− else
4991− -- reset the session timeout and continue
4992− let hp2 = H.insert (Entry expiry1 key) hp1
4993− in ejectOne (hp2, mp, out, cnt)
4994− Nothing -> do
4995− assert (Map.null mp) (return ())
4996− return (hp, mp, out, cnt)
4997−
4998− ejectExpired session@SessionState{..} curTime = do
4999− (hp', mp', out, count) <-
5000− ejectLoop sessionTimerHeap sessionKeyValueMap K.nil sessionCount
5001− return $ session
5002− { sessionCurTime = curTime
5003− , sessionCount = count
5004− , sessionTimerHeap = hp'
5005− , sessionKeyValueMap = mp'
5006− , sessionOutputStream = out
5007− }
5008−
5009− where
5010−
5011− ejectLoop hp mp out !cnt = do
5012− let hres = H.uncons hp
5013− case hres of
5014− Just (Entry expiry key, hp1) -> do
5015− (eject, force) <-
5016− if curTime >= expiry
5017− then return (True, False)
5018− else do
5019− r <- ejectPred cnt
5020− return (r, r)
5021− if eject
5022− then
5023− case Map.lookup key mp of
5024− Nothing -> ejectLoop hp1 mp out cnt
5025− Just (Tuple' latestTS acc) -> do
5026− let expiry1 = addToAbsTime latestTS timeoutMs
5027− if expiry1 <= curTime || not reset || force
5028− then do
5029− (hp2,mp1,out1,cnt1) <-
5030− ejectEntry hp1 mp out cnt acc key
5031− ejectLoop hp2 mp1 out1 cnt1
5032− else
5033− -- reset the session timeout and continue
5034− let hp2 = H.insert (Entry expiry1 key) hp1
5035− in ejectLoop hp2 mp out cnt
5036− else return (hp, mp, out, cnt)
5037− Nothing -> do
5038− assert (Map.null mp) (return ())
5039− return (hp, mp, out, cnt)
5040−
5041− -- merge timer events in the stream
5042− stream = Serial.map Just str `Par.parallelFst` repeatM timer
5043− timer = do
5044− liftIO $ threadDelay (round $ tick * 1000000)
5045− return Nothing
5046−
5047−-- | Like 'classifySessionsOf' but the session is kept alive if an event is
5048−-- received within the session window. The session times out and gets closed
5049−-- only if no event is received within the specified session window size.
5050−--
5051−-- If the ejection predicate returns 'True', the session that was idle for
5052−-- the longest time is ejected before inserting a new session.
5053−--
5054−-- @
5055−-- classifyKeepAliveSessions timeout pred = classifySessionsBy 1 timeout True pred
5056−-- @
5057−--
5058−-- /Internal/
5059−--
5060−{-# INLINABLE classifyKeepAliveSessions #-}
5061−classifyKeepAliveSessions ::
5062− (IsStream t, MonadAsync m, Ord k)
5063− => Double -- ^ session inactive timeout
5064− -> (Int -> m Bool) -- ^ predicate to eject sessions on session count
5065− -> Fold m a b -- ^ Fold to be applied to session payload data
5066− -> t m (k, a, AbsTime) -- ^ session key, data, timestamp
5067− -> t m (k, b)
5068−classifyKeepAliveSessions tmout =
5069− classifySessionsBy 1 tmout True
5070−
5071−------------------------------------------------------------------------------
5072−-- Keyed tumbling windows
5073−------------------------------------------------------------------------------
5074−
5075−-- Tumbling windows is a special case of sliding windows where the window slide
5076−-- is the same as the window size. Or it can be a special case of session
5077−-- windows where the reset flag is set to False.
5078−
5079−-- XXX instead of using the early termination flag in the stream, we can use an
5080−-- early terminating fold instead.
5081−
5082−{-
5083−-- | Split the stream into fixed size chunks of specified size. Within each
5084−-- such chunk fold the elements in buckets identified by the keys. A particular
5085−-- bucket fold can be terminated early if a closing flag is encountered in an
5086−-- element for that key.
5087−--
5088−-- @since 0.7.0
5089−{-# INLINABLE classifyChunksOf #-}
5090−classifyChunksOf
5091− :: (IsStream t, MonadAsync m, Ord k)
5092− => Int -- ^ window size
5093− -> Fold m a b -- ^ Fold to be applied to window events
5094− -> t m (k, a, Bool) -- ^ window key, data, close event
5095− -> t m (k, b)
5096−classifyChunksOf wsize = classifyChunksBy wsize False
5097−-}
5098−
5099−-- | Split the stream into fixed size time windows of specified interval in
5100−-- seconds. Within each such window, fold the elements in sessions identified
5101−-- by the session keys. The fold result is emitted in the output stream if the
5102−-- fold returns a 'Left' result or if the time window ends.
5103−--
5104−-- Session @timestamp@ in the input stream is an absolute time from some epoch,
5105−-- characterizing the time when the input element was generated. To detect
5106−-- session window end, a monotonic event time clock is maintained synced with
5107−-- the timestamps with a clock resolution of 1 second.
5108−--
5109−-- If the ejection predicate returns 'True', the session with the longest
5110−-- lifetime is ejected before inserting a new session.
5111−--
5112−-- @
5113−-- classifySessionsOf interval pred = classifySessionsBy 1 interval False pred
5114−-- @
5115−--
5116−-- @
5117−-- >>> S.mapM_ print
5118−-- $ S.classifySessionsOf 3 (const (return False)) (fmap Right FL.toList)
5119−-- $ S.map (\(ts,(k,a)) -> (k, a, ts))
5120−-- $ S.timestamped
5121−-- $ S.delay 1
5122−-- $ (,) <$> S.fromList [1,2,3] <*> S.fromList [1,2,3]
5123−-- @
5124−--
5125−-- /Internal/
5126−--
5127−{-# INLINABLE classifySessionsOf #-}
5128−classifySessionsOf ::
5129− (IsStream t, MonadAsync m, Ord k)
5130− => Double -- ^ time window size
5131− -> (Int -> m Bool) -- ^ predicate to eject sessions on session count
5132− -> Fold m a b -- ^ Fold to be applied to session events
5133− -> t m (k, a, AbsTime) -- ^ session key, data, timestamp
5134− -> t m (k, b)
5135−classifySessionsOf interval =
5136− 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)