on master help sign in
Merge pull request #846 from composewell/refactor/IsStream

Break IsStream and StreamD into smaller modules.

commit4e48b52e8709390a47e99c107ebed2d1c9420076 authorHarendra Kumar <harendra@composewell.com> dateMon 11 Jan 2021, 12:25 (6 years ago) parentc671f2ee7ebd59
18 files changed+11412−9689
.hlint.ignore+6 src/Streamly/Internal/Data/Stream/IsStream.hs+14−4806 src/Streamly/Internal/Data/Stream/IsStream/Common.hs+502 src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs+1009 src/Streamly/Internal/Data/Stream/IsStream/Exception.hs+202 src/Streamly/Internal/Data/Stream/IsStream/Generate.hs+556 src/Streamly/Internal/Data/Stream/IsStream/Lift.hs+148 src/Streamly/Internal/Data/Stream/IsStream/Nesting.hs+2098 src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+1247 src/Streamly/Internal/Data/Stream/StreamD.hs+9−4644 src/Streamly/Internal/Data/Stream/StreamD/Eliminate.hs+494 src/Streamly/Internal/Data/Stream/StreamD/Exception.hs+425 src/Streamly/Internal/Data/Stream/StreamD/Generate.hs+491 src/Streamly/Internal/Data/Stream/StreamD/Lift.hs+112 src/Streamly/Internal/Data/Stream/StreamD/Nesting.hs+2183 src/Streamly/Internal/Data/Stream/StreamD/Transform.hs+1304 src/Streamly/Internal/Data/Stream/StreamD/Type.hs+598−238 streamly.cabal+14−1
.hlint.ignore+6
@@ -11,6 +11,12 @@ src/Streamly/Internal/Data/Stream/Ahead.hs
1111src/Streamly/Internal/Data/Stream/StreamD/Type.hs
1212src/Streamly/Internal/Data/Stream/StreamDK/Type.hs
1313src/Streamly/Internal/Data/Stream/StreamD.hs
14+src/Streamly/Internal/Data/Stream/StreamD/Generate.hs
15+src/Streamly/Internal/Data/Stream/StreamD/Eliminate.hs
16+src/Streamly/Internal/Data/Stream/StreamD/Transform.hs
17+src/Streamly/Internal/Data/Stream/StreamD/Exception.hs
18+src/Streamly/Internal/Data/Stream/StreamD/Lift.hs
19+src/Streamly/Internal/Data/Stream/StreamD/Nesting.hs
1420src/Streamly/Internal/Data/Pipe/Types.hs
1521src/Streamly/Internal/Data/SmallArray/Types.hs
1622src/Streamly/Internal/Unicode/Stream.hs
src/Streamly/Internal/Data/Stream/IsStream.hs+14−4806
@@ -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)
src/Streamly/Internal/Data/Stream/IsStream/Common.hsnew file+502
@@ -0,0 +1,502 @@
1+{-# OPTIONS_GHC -Wno-orphans #-}
2+
3+-- |
4+-- Module : Streamly.Internal.Data.Stream.IsStream.Common
5+-- Copyright : (c) 2017 Composewell Technologies
6+-- License : BSD-3-Clause
7+-- Maintainer : streamly@composewell.com
8+-- Stability : experimental
9+-- Portability : GHC
10+--
11+
12+module Streamly.Internal.Data.Stream.IsStream.Common
13+ (
14+ -- * Generation
15+ yield
16+ , yieldM
17+ , repeatM
18+ , timesWith
19+ , absTimesWith
20+ , relTimesWith
21+
22+ -- * Elimination
23+ , fold
24+
25+ -- * Transformation
26+ , scanlMAfter'
27+ , postscanlM'
28+ , smapM
29+ -- $smapM_Notes
30+ , take
31+ , takeWhile
32+ , drop
33+ , findIndices
34+ , intersperseM
35+ , interjectSuffix
36+ , reverse
37+ , reverse'
38+
39+ -- * Nesting
40+ , concatM
41+ , concatMapM
42+ , splitOnSeq
43+ )
44+where
45+
46+#include "inline.hs"
47+
48+import Control.Concurrent (threadDelay)
49+import Control.Monad.IO.Class (MonadIO(..))
50+import Foreign.Storable (Storable)
51+import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array)
52+import Streamly.Internal.Data.Fold.Types (Fold (..))
53+import Streamly.Internal.Data.Stream.Combinators (maxYields)
54+import Streamly.Internal.Data.Stream.Prelude (fromStreamS, toStreamS)
55+import Streamly.Internal.Data.Stream.Serial (SerialT)
56+import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
57+import Streamly.Internal.Data.Stream.StreamK (IsStream())
58+import Streamly.Internal.Data.SVar (MonadAsync)
59+import Streamly.Internal.Data.Time.Units (AbsTime, RelTime64, addToAbsTime64)
60+
61+import qualified Streamly.Internal.Data.Stream.Parallel as Par
62+import qualified Streamly.Internal.Data.Stream.Prelude as P
63+import qualified Streamly.Internal.Data.Stream.Serial as Serial
64+import qualified Streamly.Internal.Data.Stream.StreamK as K
65+import qualified Streamly.Internal.Data.Stream.StreamD as D
66+#ifdef USE_STREAMK_ONLY
67+import qualified Streamly.Internal.Data.Stream.StreamK as S
68+#else
69+import qualified Streamly.Internal.Data.Stream.StreamD as S
70+#endif
71+
72+import Prelude hiding (take, takeWhile, drop, reverse)
73+
74+------------------------------------------------------------------------------
75+-- Generation
76+------------------------------------------------------------------------------
77+
78+-- Faster than yieldM because there is no bind.
79+--
80+-- |
81+-- @
82+-- yield a = a \`cons` nil
83+-- @
84+--
85+-- Create a singleton stream from a pure value.
86+--
87+-- The following holds in monadic streams, but not in Zip streams:
88+--
89+-- @
90+-- yield = pure
91+-- yield = yieldM . pure
92+-- @
93+--
94+-- In Zip applicative streams 'yield' is not the same as 'pure' because in that
95+-- case 'pure' is equivalent to 'repeat' instead. 'yield' and 'pure' are
96+-- equally efficient, in other cases 'yield' may be slightly more efficient
97+-- than the other equivalent definitions.
98+--
99+-- @since 0.4.0
100+{-# INLINE yield #-}
101+yield :: IsStream t => a -> t m a
102+yield = K.yield
103+
104+-- |
105+-- @
106+-- yieldM m = m \`consM` nil
107+-- @
108+--
109+-- Create a singleton stream from a monadic action.
110+--
111+-- @
112+-- > toList $ yieldM getLine
113+-- hello
114+-- ["hello"]
115+-- @
116+--
117+-- @since 0.4.0
118+{-# INLINE yieldM #-}
119+yieldM :: (Monad m, IsStream t) => m a -> t m a
120+yieldM = K.yieldM
121+
122+-- |
123+-- @
124+-- repeatM = fix . consM
125+-- repeatM = cycle1 . yieldM
126+-- @
127+--
128+-- Generate a stream by repeatedly executing a monadic action forever.
129+--
130+-- @
131+-- drain $ serially $ S.take 10 $ S.repeatM $ (threadDelay 1000000 >> print 1)
132+-- drain $ asyncly $ S.take 10 $ S.repeatM $ (threadDelay 1000000 >> print 1)
133+-- @
134+--
135+-- /Concurrent, infinite (do not use with 'parallely')/
136+--
137+-- @since 0.2.0
138+{-# INLINE_EARLY repeatM #-}
139+repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
140+repeatM = K.repeatM
141+
142+{-# RULES "repeatM serial" repeatM = repeatMSerial #-}
143+{-# INLINE repeatMSerial #-}
144+repeatMSerial :: MonadAsync m => m a -> SerialT m a
145+repeatMSerial = fromStreamS . S.repeatM
146+
147+------------------------------------------------------------------------------
148+-- Generation - Time related
149+------------------------------------------------------------------------------
150+
151+-- | @timesWith g@ returns a stream of time value tuples. The first component
152+-- of the tuple is an absolute time reference (epoch) denoting the start of the
153+-- stream and the second component is a time relative to the reference.
154+--
155+-- The argument @g@ specifies the granularity of the relative time in seconds.
156+-- A lower granularity clock gives higher precision but is more expensive in
157+-- terms of CPU usage. Any granularity lower than 1 ms is treated as 1 ms.
158+--
159+-- @
160+-- >>> S.mapM_ (\x -> print x >> threadDelay 1000000) $ S.timesWith 0.01
161+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 0))
162+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1002028000))
163+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1996656000))
164+-- @
165+--
166+-- Note: This API is not safe on 32-bit machines.
167+--
168+-- /Internal/
169+--
170+{-# INLINE timesWith #-}
171+timesWith :: (IsStream t, MonadAsync m) => Double -> t m (AbsTime, RelTime64)
172+timesWith g = fromStreamD $ D.times g
173+
174+-- | @absTimesWith g@ returns a stream of absolute timestamps using a clock of
175+-- granularity @g@ specified in seconds. A low granularity clock is more
176+-- expensive in terms of CPU usage. Any granularity lower than 1 ms is treated
177+-- as 1 ms.
178+--
179+-- @
180+-- >>> S.mapM_ print $ S.delayPre 1 $ S.absTimesWith 0.01
181+-- @
182+--
183+-- Note: This API is not safe on 32-bit machines.
184+--
185+-- /Internal/
186+--
187+{-# INLINE absTimesWith #-}
188+absTimesWith :: (IsStream t, MonadAsync m, Functor (t m))
189+ => Double -> t m AbsTime
190+absTimesWith = fmap (uncurry addToAbsTime64) . timesWith
191+
192+-- | @relTimesWith g@ returns a stream of relative time values starting from 0,
193+-- using a clock of granularity @g@ specified in seconds. A low granularity
194+-- clock is more expensive in terms of CPU usage. Any granularity lower than 1
195+-- ms is treated as 1 ms.
196+--
197+-- @
198+-- >>> S.mapM_ print $ S.delayPre 1 $ S.relTimesWith 0.01
199+-- > RelTime64 (NanoSecond64 0)
200+-- > RelTime64 (NanoSecond64 91139000)
201+-- > RelTime64 (NanoSecond64 204052000)
202+-- @
203+--
204+-- Note: This API is not safe on 32-bit machines.
205+--
206+-- /Internal/
207+--
208+{-# INLINE relTimesWith #-}
209+relTimesWith :: (IsStream t, MonadAsync m, Functor (t m))
210+ => Double -> t m RelTime64
211+relTimesWith = fmap snd . timesWith
212+
213+------------------------------------------------------------------------------
214+-- Elimination - Running a Fold
215+------------------------------------------------------------------------------
216+
217+-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
218+-- expression strictly at each step. The behavior is similar to 'foldl''. A
219+-- 'Fold' can terminate early without consuming the full stream. See the
220+-- documentation of individual 'Fold's for termination behavior.
221+--
222+-- >>> S.fold FL.sum (S.enumerateFromTo 1 100)
223+-- 5050
224+--
225+-- @since 0.7.0
226+{-# INLINE fold #-}
227+fold :: Monad m => Fold m a b -> SerialT m a -> m b
228+fold = P.foldOnce
229+
230+------------------------------------------------------------------------------
231+-- Transformation
232+------------------------------------------------------------------------------
233+
234+-- | @scanlMAfter' accumulate initial done stream@ is like 'scanlM'' except
235+-- that it provides an additional @done@ function to be applied on the
236+-- accumulator when the stream stops. The result of @done@ is also emitted in
237+-- the stream.
238+--
239+-- This function can be used to allocate a resource in the beginning of the
240+-- scan and release it when the stream ends or to flush the internal state of
241+-- the scan at the end.
242+--
243+-- /Internal/
244+--
245+{-# INLINE scanlMAfter' #-}
246+scanlMAfter' :: (IsStream t, Monad m)
247+ => (b -> a -> m b) -> m b -> (b -> m b) -> t m a -> t m b
248+scanlMAfter' step initial done stream =
249+ fromStreamD $ D.scanlMAfter' step initial done $ toStreamD stream
250+
251+-- XXX this needs to be concurrent
252+-- | Like 'postscanl'' but with a monadic step function and a monadic seed.
253+--
254+-- /Since: 0.7.0/
255+--
256+-- /Since: 0.8.0 (signature change)/
257+{-# INLINE postscanlM' #-}
258+postscanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
259+postscanlM' step z m = fromStreamD $ D.postscanlM' step z $ toStreamD m
260+
261+-- $smapM_Notes
262+--
263+-- The stateful step function can be simplified to @(s -> a -> m b)@ to provide
264+-- a read-only environment. However, that would just be 'mapM'.
265+--
266+-- The initial action could be @m (s, Maybe b)@, and we can also add a final
267+-- action @s -> m (Maybe b)@. This can be used to get pre/post scan like
268+-- functionality and also to flush the state in the end like scanlMAfter'.
269+-- We can also use it along with a fusible version of bracket to get
270+-- scanlMAfter' like functionality. See issue #677.
271+--
272+-- This can be further generalized to a type similar to Fold/Parser, giving it
273+-- filtering and parsing capability as well (this is in fact equivalent to
274+-- parseMany):
275+--
276+-- smapM :: (s -> a -> m (Step s b)) -> m s -> t m a -> t m b
277+--
278+
279+-- | A stateful 'mapM', equivalent to a left scan, more like mapAccumL.
280+-- Hopefully, this is a better alternative to @scan@. Separation of state from
281+-- the output makes it easier to think in terms of a shared state, and also
282+-- makes it easier to keep the state fully strict and the output lazy.
283+--
284+-- See also: 'scanlM''
285+--
286+-- /Internal/
287+--
288+{-# INLINE smapM #-}
289+smapM :: (IsStream t, Monad m) =>
290+ (s -> a -> m (s, b))
291+ -> m s
292+ -> t m a
293+ -> t m b
294+smapM step initial stream =
295+ -- XXX implement this directly instead of using scanlM'
296+ -- Once we have postscanlM' with monadic initial we can use this code
297+ -- let r = postscanlM'
298+ -- (\(s, _) a -> step s a)
299+ -- (fmap (,undefined) initial)
300+ -- stream
301+ let r = postscanlM'
302+ (\(s, _) a -> step s a)
303+ (fmap (,undefined) initial)
304+ stream
305+ in Serial.map snd r
306+
307+------------------------------------------------------------------------------
308+-- Transformation - Trimming
309+------------------------------------------------------------------------------
310+
311+-- | Take first 'n' elements from the stream and discard the rest.
312+--
313+-- @since 0.1.0
314+{-# INLINE take #-}
315+take :: (IsStream t, Monad m) => Int -> t m a -> t m a
316+take n m = fromStreamS $ S.take n $ toStreamS
317+ (maxYields (Just (fromIntegral n)) m)
318+
319+-- | End the stream as soon as the predicate fails on an element.
320+--
321+-- @since 0.1.0
322+{-# INLINE takeWhile #-}
323+takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
324+takeWhile p m = fromStreamS $ S.takeWhile p $ toStreamS m
325+
326+-- | Discard first 'n' elements from the stream and take the rest.
327+--
328+-- @since 0.1.0
329+{-# INLINE drop #-}
330+drop :: (IsStream t, Monad m) => Int -> t m a -> t m a
331+drop n m = fromStreamS $ S.drop n $ toStreamS m
332+
333+------------------------------------------------------------------------------
334+-- Searching
335+------------------------------------------------------------------------------
336+
337+-- | Find all the indices where the element in the stream satisfies the given
338+-- predicate.
339+--
340+-- > findIndices = fold Fold.findIndices
341+--
342+-- @since 0.5.0
343+{-# INLINE findIndices #-}
344+findIndices :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m Int
345+findIndices p m = fromStreamS $ S.findIndices p (toStreamS m)
346+
347+------------------------------------------------------------------------------
348+-- Transformation by Inserting
349+------------------------------------------------------------------------------
350+
351+-- intersperseM = intersperseBySpan 1
352+
353+-- | Insert an effect and its output before consuming an element of a stream
354+-- except the first one.
355+--
356+-- @
357+-- >>> S.toList $ S.trace putChar $ S.intersperseM (putChar '.' >> return ',') $ S.fromList "hello"
358+-- > h.,e.,l.,l.,o"h,e,l,l,o"
359+-- @
360+--
361+-- @since 0.5.0
362+{-# INLINE intersperseM #-}
363+intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
364+intersperseM m = fromStreamS . S.intersperseM m . toStreamS
365+
366+-- | Intersperse a monadic action into the input stream after every @n@
367+-- seconds.
368+--
369+-- @
370+-- > S.drain $ S.interjectSuffix 1 (putChar ',') $ S.mapM (\\x -> threadDelay 1000000 >> putChar x) $ S.fromList "hello"
371+-- "h,e,l,l,o"
372+-- @
373+--
374+-- /Internal/
375+{-# INLINE interjectSuffix #-}
376+interjectSuffix
377+ :: (IsStream t, MonadAsync m)
378+ => Double -> m a -> t m a -> t m a
379+interjectSuffix n f xs = xs `Par.parallelFst` repeatM timed
380+ where timed = liftIO (threadDelay (round $ n * 1000000)) >> f
381+
382+------------------------------------------------------------------------------
383+-- Transformation by Reordering
384+------------------------------------------------------------------------------
385+
386+-- XXX Use a compact region list to temporarily store the list, in both reverse
387+-- as well as in reverse'.
388+--
389+-- /Note:/ 'reverse'' is much faster than this, use that when performance
390+-- matters.
391+--
392+-- > reverse = S.foldlT (flip S.cons) S.nil
393+--
394+-- | Returns the elements of the stream in reverse order. The stream must be
395+-- finite. Note that this necessarily buffers the entire stream in memory.
396+--
397+-- /Since 0.7.0 (Monad m constraint)/
398+--
399+-- /Since: 0.1.1/
400+{-# INLINE reverse #-}
401+reverse :: (IsStream t, Monad m) => t m a -> t m a
402+reverse s = fromStreamS $ S.reverse $ toStreamS s
403+
404+-- | Like 'reverse' but several times faster, requires a 'Storable' instance.
405+--
406+-- /Internal/
407+{-# INLINE reverse' #-}
408+reverse' :: (IsStream t, MonadIO m, Storable a) => t m a -> t m a
409+reverse' s = fromStreamD $ D.reverse' $ toStreamD s
410+
411+------------------------------------------------------------------------------
412+-- Combine streams and flatten
413+------------------------------------------------------------------------------
414+
415+-- | Map a stream producing monadic function on each element of the stream
416+-- and then flatten the results into a single stream. Since the stream
417+-- generation function is monadic, unlike 'concatMap', it can produce an
418+-- effect at the beginning of each iteration of the inner loop.
419+--
420+-- @since 0.6.0
421+{-# INLINE concatMapM #-}
422+concatMapM :: (IsStream t, Monad m) => (a -> m (t m b)) -> t m a -> t m b
423+concatMapM f m = fromStreamD $ D.concatMapM (fmap toStreamD . f) (toStreamD m)
424+
425+-- | Given a stream value in the underlying monad, lift and join the underlying
426+-- monad with the stream monad.
427+--
428+-- @
429+-- concatM = concat . yieldM
430+-- concatM = concat . lift -- requires @(MonadTrans t)@
431+-- concatM = join . lift -- requires @(MonadTrans t@, @Monad (t m))@
432+-- @
433+--
434+-- See also: 'concat', 'sequence'
435+--
436+-- /Internal/
437+--
438+{-# INLINE concatM #-}
439+concatM :: (IsStream t, Monad m) => m (t m a) -> t m a
440+concatM generator = concatMapM (\() -> generator) (yield ())
441+
442+------------------------------------------------------------------------------
443+-- Split stream and fold
444+------------------------------------------------------------------------------
445+
446+-- | Like 'splitOn' but the separator is a sequence of elements instead of a
447+-- single element.
448+--
449+-- For illustration, let's define a function that operates on pure lists:
450+--
451+-- @
452+-- splitOnSeq' pat xs = S.toList $ S.splitOnSeq (A.fromList pat) (FL.toList) (S.fromList xs)
453+-- @
454+--
455+-- >>> splitOnSeq' "" "hello"
456+-- > ["h","e","l","l","o"]
457+--
458+-- >>> splitOnSeq' "hello" ""
459+-- > [""]
460+--
461+-- >>> splitOnSeq' "hello" "hello"
462+-- > ["",""]
463+--
464+-- >>> splitOnSeq' "x" "hello"
465+-- > ["hello"]
466+--
467+-- >>> splitOnSeq' "h" "hello"
468+-- > ["","ello"]
469+--
470+-- >>> splitOnSeq' "o" "hello"
471+-- > ["hell",""]
472+--
473+-- >>> splitOnSeq' "e" "hello"
474+-- > ["h","llo"]
475+--
476+-- >>> splitOnSeq' "l" "hello"
477+-- > ["he","","o"]
478+--
479+-- >>> splitOnSeq' "ll" "hello"
480+-- > ["he","o"]
481+--
482+-- 'splitOnSeq' is an inverse of 'intercalate'. The following law always holds:
483+--
484+-- > intercalate . splitOn == id
485+--
486+-- The following law holds when the separator is non-empty and contains none of
487+-- the elements present in the input lists:
488+--
489+-- > splitOn . intercalate == id
490+--
491+-- /Internal/
492+
493+-- XXX We can use a polymorphic vector implemented by Array# to represent the
494+-- sequence, that way we can avoid the Storable constraint. If we still need
495+-- Storable Array for performance, we can use a separate splitOnArray API for
496+-- that. We can also have an API where the sequence itself is a lazy stream, so
497+-- that we can search files in files for example.
498+{-# INLINE splitOnSeq #-}
499+splitOnSeq
500+ :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
501+ => Array a -> Fold m a b -> t m a -> t m b
502+splitOnSeq patt f m = D.fromStreamD $ D.splitOnSeq patt f (D.toStreamD m)
src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hsnew file+1009
@@ -0,0 +1,1009 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.IsStream.Eliminate
3+-- Copyright : (c) 2020 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+--
9+-- This module contains functions ending in the shape:
10+--
11+-- @
12+-- t m a -> m b
13+-- @
14+--
15+-- We call them stream folding functions, they reduce a stream @t m a@ to a
16+-- monadic value @m b@.
17+
18+module Streamly.Internal.Data.Stream.IsStream.Eliminate
19+ (
20+ -- * Running a 'Fold'
21+ -- See "Streamly.Internal.Data.Fold".
22+ fold
23+
24+ -- * Running a 'Parser'
25+ -- "Streamly.Internal.Data.Parser".
26+ , parse
27+ , parseK
28+ , parseD
29+
30+ -- * Stream Deconstruction
31+ -- | foldr and foldl do not provide the remaining stream. 'uncons' is more
32+ -- general, as it can be used to implement those as well. It allows to use
33+ -- the stream one element at a time, and we have the remaining stream all
34+ -- the time.
35+ , uncons
36+
37+ -- * Right Folds
38+ , foldrM
39+ , foldr
40+
41+ -- * Left Folds
42+ , foldl'
43+ , foldl1'
44+ , foldlM'
45+
46+ -- * Specific 'Fold's
47+ -- XXX Move to Data.Fold?
48+ , toStream -- XXX rename to write? buffer?
49+ , toStreamRev -- XXX rename to writeRev? bufferRev?
50+
51+ -- * Specific Fold Functions
52+ -- | Folds as functions of the shape @t m a -> m b@.
53+ --
54+ -- These functions are good to run individually but they do not compose
55+ -- well. Prefer writing folds as the 'Fold' data type. Use folds from
56+ -- "Streamly.Internal.Data.Fold" instead of using the functions in this
57+ -- section.
58+ --
59+ -- This section can possibly be removed in future. Are these better in
60+ -- some case compared to 'Fold'? When the input stream is in CPS style
61+ -- (StreamK) we may want to rewrite the function call to CPS implementation
62+ -- of the fold through these definitions. Will that be more efficient for
63+ -- StreamK?
64+
65+ -- ** Full Folds
66+
67+ -- -- ** To Summary (Full Folds)
68+ , mapM_
69+ , drain
70+ , drainN
71+ , drainWhile
72+ , last
73+ , length
74+ , sum
75+ , product
76+ , mconcat
77+
78+ -- -- ** To Summary (Maybe) (Full Folds)
79+ , maximumBy
80+ , maximum
81+ , minimumBy
82+ , minimum
83+ , the
84+
85+ -- ** Partial Folds
86+
87+ -- -- ** To Elements (Partial Folds)
88+
89+ -- -- | Folds that extract selected elements of a stream or their properties.
90+ , (!!)
91+ , head
92+ , headElse
93+ , tail
94+ , init
95+ , findM
96+ , find
97+ , findIndex
98+ , elemIndex
99+ , lookup
100+
101+ -- -- ** To Boolean (Partial Folds)
102+ , null
103+ , elem
104+ , notElem
105+ , all
106+ , any
107+ , and
108+ , or
109+
110+ -- -- ** Lazy Folds
111+ -- ** To Containers
112+ , toList
113+ , toListRev
114+ , toPure -- XXX move toStream to Data.Fold and rename this to toStream?
115+ , toPureRev
116+
117+ -- * Concurrent Folds
118+ , foldAsync
119+ , (|$.)
120+ , (|&.)
121+
122+ -- * Multi-Stream folds
123+ -- Full equivalence
124+ , eqBy
125+ , cmpBy
126+
127+ -- finding subsequences
128+ , isPrefixOf
129+ , isInfixOf
130+ , isSuffixOf
131+ , isSubsequenceOf
132+
133+ -- trimming sequences
134+ , stripPrefix
135+ -- , stripInfix
136+ , stripSuffix
137+
138+ -- * Deprecated
139+ , foldx
140+ , foldxM
141+ , foldr1
142+ , runStream
143+ , runN
144+ , runWhile
145+ , toHandle
146+ )
147+where
148+
149+#include "inline.hs"
150+
151+import Control.Monad.Catch (MonadThrow)
152+import Control.Monad.IO.Class (MonadIO(..))
153+import Data.Functor.Identity (Identity (..))
154+import Foreign.Storable (Storable)
155+import Streamly.Internal.Data.Fold.Types (Fold (..))
156+import Streamly.Internal.Data.Parser (Parser (..))
157+import Streamly.Internal.Data.SVar (MonadAsync, defState)
158+import Streamly.Internal.Data.Stream.IsStream.Common
159+ (fold, drop, findIndices, reverse, splitOnSeq, take, takeWhile)
160+import Streamly.Internal.Data.Stream.Prelude (toStreamS)
161+import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
162+import Streamly.Internal.Data.Stream.StreamK (IsStream)
163+import Streamly.Internal.Data.Stream.Serial (SerialT)
164+
165+import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
166+import qualified Streamly.Internal.Data.Fold as FL
167+import qualified Streamly.Internal.Data.Stream.Prelude as P
168+import qualified Streamly.Internal.Data.Stream.StreamD as D
169+import qualified Streamly.Internal.Data.Stream.StreamK as K
170+import qualified Streamly.Internal.Data.Parser.ParserD as PRD
171+import qualified Streamly.Internal.Data.Parser.ParserK.Types as PRK
172+import qualified System.IO as IO
173+#ifdef USE_STREAMK_ONLY
174+import qualified Streamly.Internal.Data.Stream.StreamK as S
175+#else
176+import qualified Streamly.Internal.Data.Stream.StreamD as S
177+#endif
178+
179+import Prelude hiding
180+ ( drop, take, takeWhile, foldr , foldl, mapM_, sequence, all, any, sum
181+ , product, elem, notElem, maximum, minimum, head, last, tail, length
182+ , null , reverse, init, and, or, lookup, foldr1, (!!) , splitAt, break
183+ , mconcat)
184+
185+------------------------------------------------------------------------------
186+-- Deconstruction
187+------------------------------------------------------------------------------
188+
189+-- | Decompose a stream into its head and tail. If the stream is empty, returns
190+-- 'Nothing'. If the stream is non-empty, returns @Just (a, ma)@, where @a@ is
191+-- the head of the stream and @ma@ its tail.
192+--
193+-- This is a brute force primitive. Avoid using it as long as possible, use it
194+-- when no other combinator can do the job. This can be used to do pretty much
195+-- anything in an imperative manner, as it just breaks down the stream into
196+-- individual elements and we can loop over them as we deem fit. For example,
197+-- this can be used to convert a streamly stream into other stream types.
198+--
199+-- @since 0.1.0
200+{-# INLINE uncons #-}
201+uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a))
202+uncons m = K.uncons (K.adapt m)
203+
204+------------------------------------------------------------------------------
205+-- Right Folds
206+------------------------------------------------------------------------------
207+
208+-- | Right associative/lazy pull fold. @foldrM build final stream@ constructs
209+-- an output structure using the step function @build@. @build@ is invoked with
210+-- the next input element and the remaining (lazy) tail of the output
211+-- structure. It builds a lazy output expression using the two. When the "tail
212+-- structure" in the output expression is evaluated it calls @build@ again thus
213+-- lazily consuming the input @stream@ until either the output expression built
214+-- by @build@ is free of the "tail" or the input is exhausted in which case
215+-- @final@ is used as the terminating case for the output structure. For more
216+-- details see the description in the previous section.
217+--
218+-- Example, determine if any element is 'odd' in a stream:
219+--
220+-- >>> S.foldrM (\x xs -> if odd x then return True else xs) (return False) $ S.fromList (2:4:5:undefined)
221+-- > True
222+--
223+-- /Since: 0.7.0 (signature changed)/
224+--
225+-- /Since: 0.2.0 (signature changed)/
226+--
227+-- /Since: 0.1.0/
228+{-# INLINE foldrM #-}
229+foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b
230+foldrM = P.foldrM
231+
232+-- | Right fold, lazy for lazy monads and pure streams, and strict for strict
233+-- monads.
234+--
235+-- Please avoid using this routine in strict monads like IO unless you need a
236+-- strict right fold. This is provided only for use in lazy monads (e.g.
237+-- Identity) or pure streams. Note that with this signature it is not possible
238+-- to implement a lazy foldr when the monad @m@ is strict. In that case it
239+-- would be strict in its accumulator and therefore would necessarily consume
240+-- all its input.
241+--
242+-- @since 0.1.0
243+{-# INLINE foldr #-}
244+foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
245+foldr = P.foldr
246+
247+-- XXX This seems to be of limited use as it cannot be used to construct
248+-- recursive structures and for reduction foldl1' is better.
249+--
250+-- | Lazy right fold for non-empty streams, using first element as the starting
251+-- value. Returns 'Nothing' if the stream is empty.
252+--
253+-- @since 0.5.0
254+{-# INLINE foldr1 #-}
255+{-# DEPRECATED foldr1 "Use foldrM instead." #-}
256+foldr1 :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a)
257+foldr1 f m = S.foldr1 f (toStreamS m)
258+
259+------------------------------------------------------------------------------
260+-- Left Folds
261+------------------------------------------------------------------------------
262+
263+-- | Strict left fold with an extraction function. Like the standard strict
264+-- left fold, but applies a user supplied extraction function (the third
265+-- argument) to the folded value at the end. This is designed to work with the
266+-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
267+--
268+-- @since 0.2.0
269+{-# DEPRECATED foldx "Please use foldl' followed by fmap instead." #-}
270+{-# INLINE foldx #-}
271+foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
272+foldx = P.foldlx'
273+
274+-- | Left associative/strict push fold. @foldl' reduce initial stream@ invokes
275+-- @reduce@ with the accumulator and the next input in the input stream, using
276+-- @initial@ as the initial value of the current value of the accumulator. When
277+-- the input is exhausted the current value of the accumulator is returned.
278+-- Make sure to use a strict data structure for accumulator to not build
279+-- unnecessary lazy expressions unless that's what you want. See the previous
280+-- section for more details.
281+--
282+-- @since 0.2.0
283+{-# INLINE foldl' #-}
284+foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
285+foldl' = P.foldl'
286+
287+-- | Strict left fold, for non-empty streams, using first element as the
288+-- starting value. Returns 'Nothing' if the stream is empty.
289+--
290+-- @since 0.5.0
291+{-# INLINE foldl1' #-}
292+foldl1' :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a)
293+foldl1' step m = do
294+ r <- uncons m
295+ case r of
296+ Nothing -> return Nothing
297+ Just (h, t) -> do
298+ res <- foldl' step h t
299+ return $ Just res
300+
301+-- | Like 'foldx', but with a monadic step function.
302+--
303+-- @since 0.2.0
304+{-# DEPRECATED foldxM "Please use foldlM' followed by fmap instead." #-}
305+{-# INLINE foldxM #-}
306+foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
307+foldxM = P.foldlMx'
308+
309+-- | Like 'foldl'' but with a monadic step function.
310+--
311+-- /Since: 0.2.0/
312+--
313+-- /Since: 0.8.0 (signature change)/
314+{-# INLINE foldlM' #-}
315+foldlM' :: Monad m => (b -> a -> m b) -> m b -> SerialT m a -> m b
316+foldlM' step begin m = S.foldlM' step begin $ toStreamS m
317+
318+------------------------------------------------------------------------------
319+-- Running a sink
320+------------------------------------------------------------------------------
321+
322+{-
323+-- | Drain a stream to a 'Sink'.
324+{-# INLINE runSink #-}
325+runSink :: Monad m => Sink m a -> SerialT m a -> m ()
326+runSink = fold . toFold
327+-}
328+
329+------------------------------------------------------------------------------
330+-- Running a Parser
331+------------------------------------------------------------------------------
332+
333+-- | Parse a stream using the supplied 'Parser'.
334+--
335+-- /Internal/
336+--
337+{-# INLINE_NORMAL parseD #-}
338+parseD :: MonadThrow m => PRD.Parser m a b -> SerialT m a -> m b
339+parseD (PRD.Parser step initial extract) = P.parselMx' step initial extract
340+
341+{-# INLINE parseK #-}
342+parseK :: MonadThrow m => PRK.Parser m a b -> SerialT m a -> m b
343+parseK = parse
344+
345+-- | Parse a stream using the supplied 'Parser'.
346+--
347+-- /Internal/
348+--
349+{-# INLINE [3] parse #-}
350+parse :: MonadThrow m => Parser m a b -> SerialT m a -> m b
351+parse = parseD . PRK.fromParserK
352+
353+------------------------------------------------------------------------------
354+-- Specific Fold Functions
355+------------------------------------------------------------------------------
356+
357+-- XXX this can utilize parallel mapping if we implement it as drain . mapM
358+-- |
359+-- > mapM_ = drain . mapM
360+--
361+-- Apply a monadic action to each element of the stream and discard the output
362+-- of the action. This is not really a pure transformation operation but a
363+-- transformation followed by fold.
364+--
365+-- @since 0.1.0
366+{-# INLINE mapM_ #-}
367+mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
368+mapM_ f m = S.mapM_ f $ toStreamS m
369+
370+-- |
371+-- > drain = mapM_ (\_ -> return ())
372+-- > drain = fold Fold.drain
373+--
374+-- Run a stream, discarding the results. By default it interprets the stream
375+-- as 'SerialT', to run other types of streams use the type adapting
376+-- combinators for example @drain . 'asyncly'@.
377+--
378+-- @since 0.7.0
379+{-# INLINE drain #-}
380+drain :: Monad m => SerialT m a -> m ()
381+drain = P.drain
382+
383+-- |
384+-- > drainN n = drain . take n
385+-- > drainN n = fold (Fold.ltake n Fold.drain)
386+--
387+-- Run maximum up to @n@ iterations of a stream.
388+--
389+-- @since 0.7.0
390+{-# INLINE drainN #-}
391+drainN :: Monad m => Int -> SerialT m a -> m ()
392+drainN n = drain . take n
393+
394+-- |
395+-- > runN n = runStream . take n
396+--
397+-- Run maximum up to @n@ iterations of a stream.
398+--
399+-- @since 0.6.0
400+{-# DEPRECATED runN "Please use \"drainN\" instead" #-}
401+{-# INLINE runN #-}
402+runN :: Monad m => Int -> SerialT m a -> m ()
403+runN = drainN
404+
405+-- |
406+-- > drainWhile p = drain . takeWhile p
407+-- > drainWhile p = fold (Fold.sliceSepBy (not . p) Fold.drain)
408+--
409+-- Run a stream as long as the predicate holds true.
410+--
411+-- @since 0.7.0
412+{-# INLINE drainWhile #-}
413+drainWhile :: Monad m => (a -> Bool) -> SerialT m a -> m ()
414+drainWhile p = drain . takeWhile p
415+
416+-- |
417+-- > runWhile p = runStream . takeWhile p
418+--
419+-- Run a stream as long as the predicate holds true.
420+--
421+-- @since 0.6.0
422+{-# DEPRECATED runWhile "Please use \"drainWhile\" instead" #-}
423+{-# INLINE runWhile #-}
424+runWhile :: Monad m => (a -> Bool) -> SerialT m a -> m ()
425+runWhile = drainWhile
426+
427+-- | Run a stream, discarding the results. By default it interprets the stream
428+-- as 'SerialT', to run other types of streams use the type adapting
429+-- combinators for example @runStream . 'asyncly'@.
430+--
431+-- @since 0.2.0
432+{-# DEPRECATED runStream "Please use \"drain\" instead" #-}
433+{-# INLINE runStream #-}
434+runStream :: Monad m => SerialT m a -> m ()
435+runStream = drain
436+
437+-- | Determine whether the stream is empty.
438+--
439+-- > null = fold Fold.null
440+--
441+-- @since 0.1.1
442+{-# INLINE null #-}
443+null :: Monad m => SerialT m a -> m Bool
444+null = S.null . toStreamS
445+
446+-- | Extract the first element of the stream, if any.
447+--
448+-- > head = (!! 0)
449+-- > head = fold Fold.head
450+--
451+-- @since 0.1.0
452+{-# INLINE head #-}
453+head :: Monad m => SerialT m a -> m (Maybe a)
454+head = S.head . toStreamS
455+
456+-- | Extract the first element of the stream, if any, otherwise use the
457+-- supplied default value. It can help avoid one branch in high performance
458+-- code.
459+--
460+-- /Internal/
461+{-# INLINE headElse #-}
462+headElse :: Monad m => a -> SerialT m a -> m a
463+headElse x = D.headElse x . toStreamD
464+
465+-- |
466+-- > tail = fmap (fmap snd) . uncons
467+--
468+-- Extract all but the first element of the stream, if any.
469+--
470+-- @since 0.1.1
471+{-# INLINE tail #-}
472+tail :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
473+tail m = K.tail (K.adapt m)
474+
475+-- | Extract all but the last element of the stream, if any.
476+--
477+-- @since 0.5.0
478+{-# INLINE init #-}
479+init :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
480+init m = K.init (K.adapt m)
481+
482+-- | Extract the last element of the stream, if any.
483+--
484+-- > last xs = xs !! (length xs - 1)
485+-- > last = fold Fold.last
486+--
487+-- @since 0.1.1
488+{-# INLINE last #-}
489+last :: Monad m => SerialT m a -> m (Maybe a)
490+last m = S.last $ toStreamS m
491+
492+-- | Determine whether an element is present in the stream.
493+--
494+-- > elem = fold Fold.elem
495+--
496+-- @since 0.1.0
497+{-# INLINE elem #-}
498+elem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
499+elem e m = S.elem e (toStreamS m)
500+
501+-- | Determine whether an element is not present in the stream.
502+--
503+-- > notElem = fold Fold.length
504+--
505+-- @since 0.1.0
506+{-# INLINE notElem #-}
507+notElem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
508+notElem e m = S.notElem e (toStreamS m)
509+
510+-- | Determine the length of the stream.
511+--
512+-- @since 0.1.0
513+{-# INLINE length #-}
514+length :: Monad m => SerialT m a -> m Int
515+length = foldl' (\n _ -> n + 1) 0
516+
517+-- | Determine whether all elements of a stream satisfy a predicate.
518+--
519+-- > all = fold Fold.all
520+--
521+-- @since 0.1.0
522+{-# INLINE all #-}
523+all :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
524+all p m = S.all p (toStreamS m)
525+
526+-- | Determine whether any of the elements of a stream satisfy a predicate.
527+--
528+-- > any = fold Fold.any
529+--
530+-- @since 0.1.0
531+{-# INLINE any #-}
532+any :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
533+any p m = S.any p (toStreamS m)
534+
535+-- | Determines if all elements of a boolean stream are True.
536+--
537+-- > and = fold Fold.and
538+--
539+-- @since 0.5.0
540+{-# INLINE and #-}
541+and :: Monad m => SerialT m Bool -> m Bool
542+and = all (==True)
543+
544+-- | Determines whether at least one element of a boolean stream is True.
545+--
546+-- > or = fold Fold.or
547+--
548+-- @since 0.5.0
549+{-# INLINE or #-}
550+or :: Monad m => SerialT m Bool -> m Bool
551+or = any (==True)
552+
553+-- | Determine the sum of all elements of a stream of numbers. Returns @0@ when
554+-- the stream is empty. Note that this is not numerically stable for floating
555+-- point numbers.
556+--
557+-- > sum = fold Fold.sum
558+--
559+-- @since 0.1.0
560+{-# INLINE sum #-}
561+sum :: (Monad m, Num a) => SerialT m a -> m a
562+sum = foldl' (+) 0
563+
564+-- | Determine the product of all elements of a stream of numbers. Returns @1@
565+-- when the stream is empty.
566+--
567+-- > product = fold Fold.product
568+--
569+-- @since 0.1.1
570+{-# INLINE product #-}
571+product :: (Monad m, Num a) => SerialT m a -> m a
572+product = foldl' (*) 1
573+
574+-- | Fold a stream of monoid elements by appending them.
575+--
576+-- > mconcat = fold Fold.mconcat
577+--
578+-- /Internal/
579+{-# INLINE mconcat #-}
580+mconcat :: (Monad m, Monoid a) => SerialT m a -> m a
581+mconcat = foldr mappend mempty
582+
583+-- |
584+-- @
585+-- minimum = 'minimumBy' compare
586+ -- minimum = fold Fold.minimum
587+-- @
588+--
589+-- Determine the minimum element in a stream.
590+--
591+-- @since 0.1.0
592+{-# INLINE minimum #-}
593+minimum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
594+minimum m = S.minimum (toStreamS m)
595+
596+-- | Determine the minimum element in a stream using the supplied comparison
597+-- function.
598+--
599+-- > minimumBy = fold Fold.minimumBy
600+--
601+-- @since 0.6.0
602+{-# INLINE minimumBy #-}
603+minimumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
604+minimumBy cmp m = S.minimumBy cmp (toStreamS m)
605+
606+-- |
607+-- @
608+-- maximum = 'maximumBy' compare
609+-- maximum = fold Fold.maximum
610+-- @
611+--
612+-- Determine the maximum element in a stream.
613+--
614+-- @since 0.1.0
615+{-# INLINE maximum #-}
616+maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
617+maximum = P.maximum
618+
619+-- | Determine the maximum element in a stream using the supplied comparison
620+-- function.
621+--
622+-- > maximumBy = fold Fold.maximumBy
623+--
624+-- @since 0.6.0
625+{-# INLINE maximumBy #-}
626+maximumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a)
627+maximumBy cmp m = S.maximumBy cmp (toStreamS m)
628+
629+-- | Ensures that all the elements of the stream are identical and then returns
630+-- that unique element.
631+--
632+-- @since 0.6.0
633+{-# INLINE the #-}
634+the :: (Eq a, Monad m) => SerialT m a -> m (Maybe a)
635+the m = S.the (toStreamS m)
636+
637+------------------------------------------------------------------------------
638+-- Searching
639+------------------------------------------------------------------------------
640+
641+-- | Lookup the element at the given index.
642+--
643+-- @since 0.6.0
644+{-# INLINE (!!) #-}
645+(!!) :: Monad m => SerialT m a -> Int -> m (Maybe a)
646+m !! i = toStreamS m S.!! i
647+
648+-- | In a stream of (key-value) pairs @(a, b)@, return the value @b@ of the
649+-- first pair where the key equals the given value @a@.
650+--
651+-- > lookup = snd <$> find ((==) . fst)
652+-- > lookup = fold Fold.lookup
653+--
654+-- @since 0.5.0
655+{-# INLINE lookup #-}
656+lookup :: (Monad m, Eq a) => a -> SerialT m (a, b) -> m (Maybe b)
657+lookup a m = S.lookup a (toStreamS m)
658+
659+-- | Like 'findM' but with a non-monadic predicate.
660+--
661+-- > find p = findM (return . p)
662+-- > find = fold Fold.find
663+--
664+-- @since 0.5.0
665+{-# INLINE find #-}
666+find :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe a)
667+find p m = S.find p (toStreamS m)
668+
669+-- | Returns the first element that satisfies the given predicate.
670+--
671+-- > findM = fold Fold.findM
672+--
673+-- @since 0.6.0
674+{-# INLINE findM #-}
675+findM :: Monad m => (a -> m Bool) -> SerialT m a -> m (Maybe a)
676+findM p m = S.findM p (toStreamS m)
677+
678+-- | Returns the first index that satisfies the given predicate.
679+--
680+-- > findIndex = fold Fold.findIndex
681+--
682+-- @since 0.5.0
683+{-# INLINE findIndex #-}
684+findIndex :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe Int)
685+findIndex p = head . findIndices p
686+
687+-- | Returns the first index where a given value is found in the stream.
688+--
689+-- > elemIndex a = findIndex (== a)
690+--
691+-- @since 0.5.0
692+{-# INLINE elemIndex #-}
693+elemIndex :: (Monad m, Eq a) => a -> SerialT m a -> m (Maybe Int)
694+elemIndex a = findIndex (== a)
695+
696+------------------------------------------------------------------------------
697+-- To containers
698+------------------------------------------------------------------------------
699+
700+-- |
701+-- @
702+-- toList = S.foldr (:) []
703+-- @
704+--
705+-- Convert a stream into a list in the underlying monad. The list can be
706+-- consumed lazily in a lazy monad (e.g. 'Identity'). In a strict monad (e.g.
707+-- IO) the whole list is generated and buffered before it can be consumed.
708+--
709+-- /Warning!/ working on large lists accumulated as buffers in memory could be
710+-- very inefficient, consider using "Streamly.Array" instead.
711+--
712+-- @since 0.1.0
713+{-# INLINE toList #-}
714+toList :: Monad m => SerialT m a -> m [a]
715+toList = P.toList
716+
717+-- |
718+-- @
719+-- toListRev = S.foldl' (flip (:)) []
720+-- @
721+--
722+-- Convert a stream into a list in reverse order in the underlying monad.
723+--
724+-- /Warning!/ working on large lists accumulated as buffers in memory could be
725+-- very inefficient, consider using "Streamly.Array" instead.
726+--
727+-- /Internal/
728+{-# INLINE toListRev #-}
729+toListRev :: Monad m => SerialT m a -> m [a]
730+toListRev = D.toListRev . toStreamD
731+
732+-- |
733+-- @
734+-- toHandle h = S.mapM_ $ hPutStrLn h
735+-- @
736+--
737+-- Write a stream of Strings to an IO Handle.
738+--
739+-- @since 0.1.0
740+{-# DEPRECATED toHandle
741+ "Please use Streamly.FileSystem.Handle module (see the changelog)" #-}
742+toHandle :: MonadIO m => IO.Handle -> SerialT m String -> m ()
743+toHandle h = go
744+ where
745+ go m1 =
746+ let stop = return ()
747+ single a = liftIO (IO.hPutStrLn h a)
748+ yieldk a r = liftIO (IO.hPutStrLn h a) >> go r
749+ in K.foldStream defState yieldk single stop m1
750+
751+-- XXX rename these to write/writeRev to make the naming consistent with folds
752+-- in other modules.
753+--
754+-- | A fold that buffers its input to a pure stream.
755+--
756+-- /Warning!/ working on large streams accumulated as buffers in memory could
757+-- be very inefficient, consider using "Streamly.Data.Array" instead.
758+--
759+-- /Internal/
760+{-# INLINE toStream #-}
761+toStream :: Monad m => Fold m a (SerialT Identity a)
762+toStream = Fold (\f x -> return $ FL.Partial $ f . (x `K.cons`))
763+ (return id)
764+ (return . ($ K.nil))
765+
766+-- This is more efficient than 'toStream'. toStream is exactly the same as
767+-- reversing the stream after toStreamRev.
768+--
769+-- | Buffers the input stream to a pure stream in the reverse order of the
770+-- input.
771+--
772+-- /Warning!/ working on large streams accumulated as buffers in memory could
773+-- be very inefficient, consider using "Streamly.Data.Array" instead.
774+--
775+-- /Internal/
776+
777+-- xn : ... : x2 : x1 : []
778+{-# INLINABLE toStreamRev #-}
779+toStreamRev :: Monad m => Fold m a (SerialT Identity a)
780+toStreamRev = Fold (\xs x -> return $ FL.Partial $ x `K.cons` xs) (return K.nil) return
781+
782+-- | Convert a stream to a pure stream.
783+--
784+-- @
785+-- toPure = foldr cons nil
786+-- @
787+--
788+-- /Internal/
789+--
790+{-# INLINE toPure #-}
791+toPure :: Monad m => SerialT m a -> m (SerialT Identity a)
792+toPure = foldr K.cons K.nil
793+
794+-- | Convert a stream to a pure stream in reverse order.
795+--
796+-- @
797+-- toPureRev = foldl' (flip cons) nil
798+-- @
799+--
800+-- /Internal/
801+--
802+{-# INLINE toPureRev #-}
803+toPureRev :: Monad m => SerialT m a -> m (SerialT Identity a)
804+toPureRev = foldl' (flip K.cons) K.nil
805+
806+------------------------------------------------------------------------------
807+-- Concurrent Application
808+------------------------------------------------------------------------------
809+
810+-- | Parallel fold application operator; applies a fold function @t m a -> m b@
811+-- to a stream @t m a@ concurrently; The the input stream is evaluated
812+-- asynchronously in an independent thread yielding elements to a buffer and
813+-- the folding action runs in another thread consuming the input from the
814+-- buffer.
815+--
816+-- If you read the signature as @(t m a -> m b) -> (t m a -> m b)@ you can look
817+-- at it as a transformation that converts a fold function to a buffered
818+-- concurrent fold function.
819+--
820+-- The @.@ at the end of the operator is a mnemonic for termination of the
821+-- stream.
822+--
823+-- @
824+-- S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
825+-- |$. S.repeatM (threadDelay 1000000 >> return 1)
826+-- @
827+--
828+-- /Concurrent/
829+--
830+-- /Since: 0.3.0 ("Streamly")/
831+--
832+-- @since 0.8.0
833+{-# INLINE (|$.) #-}
834+(|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
835+-- (|$.) f = f . Async.mkAsync
836+(|$.) f = f . D.mkParallel
837+
838+infixr 0 |$.
839+
840+-- | Same as '|$.'.
841+--
842+-- /Internal/
843+--
844+{-# INLINE foldAsync #-}
845+foldAsync :: (IsStream t, MonadAsync m) => (t m a -> m b) -> (t m a -> m b)
846+foldAsync = (|$.)
847+
848+-- | Parallel reverse function application operator for applying a run or fold
849+-- functions to a stream. Just like '|$.' except that the operands are reversed.
850+--
851+-- @
852+-- S.repeatM (threadDelay 1000000 >> return 1)
853+-- |&. S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
854+-- @
855+--
856+-- /Concurrent/
857+--
858+-- /Since: 0.3.0 ("Streamly")/
859+--
860+-- @since 0.8.0
861+{-# INLINE (|&.) #-}
862+(|&.) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> m b) -> m b
863+x |&. f = f |$. x
864+
865+infixl 1 |&.
866+
867+------------------------------------------------------------------------------
868+-- Multi-stream folds
869+------------------------------------------------------------------------------
870+
871+-- | Returns 'True' if the first stream is the same as or a prefix of the
872+-- second. A stream is a prefix of itself.
873+--
874+-- @
875+-- > S.isPrefixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
876+-- True
877+-- @
878+--
879+-- @since 0.6.0
880+{-# INLINE isPrefixOf #-}
881+isPrefixOf :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m Bool
882+isPrefixOf m1 m2 = D.isPrefixOf (toStreamD m1) (toStreamD m2)
883+
884+-- | Returns 'True' if the first stream is an infix of the second. A stream is
885+-- considered an infix of itself.
886+--
887+-- @
888+-- > S.isInfixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
889+-- True
890+-- @
891+--
892+-- Space: @O(n)@ worst case where @n@ is the length of the infix.
893+--
894+-- /Internal/
895+--
896+-- /Requires 'Storable' constraint/ - Help wanted.
897+--
898+{-# INLINE isInfixOf #-}
899+isInfixOf :: (MonadIO m, Eq a, Enum a, Storable a)
900+ => SerialT m a -> SerialT m a -> m Bool
901+isInfixOf infx stream = do
902+ arr <- fold A.write infx
903+ -- XXX can use breakOnSeq instead (when available)
904+ r <- null $ drop 1 $ splitOnSeq arr FL.drain stream
905+ return (not r)
906+
907+-- Note: isPrefixOf uses the prefix stream only once. In contrast, isSuffixOf
908+-- may use the suffix stream many times. To run in optimal memory we do not
909+-- want to buffer the suffix stream in memory therefore we need an ability to
910+-- clone (or consume it multiple times) the suffix stream without any side
911+-- effects so that multiple potential suffix matches can proceed in parallel
912+-- without buffering the suffix stream. For example, we may create the suffix
913+-- stream from a file handle, however, if we evaluate the stream multiple
914+-- times, once for each match, we will need a different file handle each time
915+-- which may exhaust the file descriptors. Instead, we want to share the same
916+-- underlying file descriptor, use pread on it to generate the stream and clone
917+-- the stream for each match. Therefore the suffix stream should be built in
918+-- such a way that it can be consumed multiple times without any problems.
919+
920+-- XXX Can be implemented with better space/time complexity.
921+-- Space: @O(n)@ worst case where @n@ is the length of the suffix.
922+
923+-- | Returns 'True' if the first stream is a suffix of the second. A stream is
924+-- considered a suffix of itself.
925+--
926+-- @
927+-- > S.isSuffixOf (S.fromList "hello") (S.fromList "hello" :: SerialT IO Char)
928+-- True
929+-- @
930+--
931+-- Space: @O(n)@, buffers entire input stream and the suffix.
932+--
933+-- /Internal/
934+--
935+-- /Suboptimal/ - Help wanted.
936+--
937+{-# INLINE isSuffixOf #-}
938+isSuffixOf :: (Monad m, Eq a) => SerialT m a -> SerialT m a -> m Bool
939+isSuffixOf suffix stream = reverse suffix `isPrefixOf` reverse stream
940+
941+-- | Returns 'True' if all the elements of the first stream occur, in order, in
942+-- the second stream. The elements do not have to occur consecutively. A stream
943+-- is a subsequence of itself.
944+--
945+-- @
946+-- > S.isSubsequenceOf (S.fromList "hlo") (S.fromList "hello" :: SerialT IO Char)
947+-- True
948+-- @
949+--
950+-- @since 0.6.0
951+{-# INLINE isSubsequenceOf #-}
952+isSubsequenceOf :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m Bool
953+isSubsequenceOf m1 m2 = D.isSubsequenceOf (toStreamD m1) (toStreamD m2)
954+
955+-- Note: If we want to return a Maybe value to know whether the
956+-- suffix/infix was present or not along with the stripped stream then
957+-- we need to buffer the whole input stream.
958+--
959+-- | @stripPrefix prefix stream@ strips @prefix@ from @stream@ if it is a
960+-- prefix of stream. Returns 'Nothing' if the stream does not start with the
961+-- given prefix, stripped stream otherwise. Returns @Just nil@ when the prefix
962+-- is the same as the stream.
963+--
964+-- Space: @O(1)@
965+--
966+-- @since 0.6.0
967+{-# INLINE stripPrefix #-}
968+stripPrefix
969+ :: (Eq a, IsStream t, Monad m)
970+ => t m a -> t m a -> m (Maybe (t m a))
971+stripPrefix m1 m2 = fmap fromStreamD <$>
972+ D.stripPrefix (toStreamD m1) (toStreamD m2)
973+
974+-- | Drops the given suffix from a stream. Returns 'Nothing' if the stream does
975+-- not end with the given suffix. Returns @Just nil@ when the suffix is the
976+-- same as the stream.
977+--
978+-- It may be more efficient to convert the stream to an Array and use
979+-- stripSuffix on that especially if the elements have a Storable or Prim
980+-- instance.
981+--
982+-- Space: @O(n)@, buffers the entire input stream as well as the suffix
983+--
984+-- /Internal/
985+{-# INLINE stripSuffix #-}
986+stripSuffix
987+ :: (Monad m, Eq a)
988+ => SerialT m a -> SerialT m a -> m (Maybe (SerialT m a))
989+stripSuffix m1 m2 = fmap reverse <$> stripPrefix (reverse m1) (reverse m2)
990+
991+------------------------------------------------------------------------------
992+-- Comparison
993+------------------------------------------------------------------------------
994+
995+-- | Compare two streams for equality using an equality function.
996+--
997+-- @since 0.6.0
998+{-# INLINABLE eqBy #-}
999+eqBy :: (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> m Bool
1000+eqBy = P.eqBy
1001+
1002+-- | Compare two streams lexicographically using a comparison function.
1003+--
1004+-- @since 0.6.0
1005+{-# INLINABLE cmpBy #-}
1006+cmpBy
1007+ :: (IsStream t, Monad m)
1008+ => (a -> b -> Ordering) -> t m a -> t m b -> m Ordering
1009+cmpBy = P.cmpBy
src/Streamly/Internal/Data/Stream/IsStream/Exception.hsnew file+202
@@ -0,0 +1,202 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.IsStream.Exception
3+-- Copyright : (c) 2020 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+
9+module Streamly.Internal.Data.Stream.IsStream.Exception
10+ (
11+ before
12+ , after_
13+ , after
14+ , bracket_
15+ , bracket
16+ , onException
17+ , finally_
18+ , finally
19+ , ghandle
20+ , handle
21+ )
22+where
23+
24+import Control.Exception (Exception)
25+import Control.Monad.Catch (MonadCatch)
26+import Control.Monad.IO.Class (MonadIO(..))
27+import Control.Monad.Trans.Control (MonadBaseControl)
28+import Streamly.Internal.Data.Stream.StreamD (toStreamD)
29+import Streamly.Internal.Data.Stream.StreamK (IsStream)
30+import Streamly.Internal.Data.SVar (MonadAsync)
31+
32+import qualified Streamly.Internal.Data.Stream.StreamD as D
33+
34+------------------------------------------------------------------------------
35+-- Exceptions
36+------------------------------------------------------------------------------
37+
38+-- | Run the action @m b@ before the stream yields its first element.
39+--
40+-- > before action xs = 'nilM' action <> xs
41+--
42+-- @since 0.7.0
43+{-# INLINE before #-}
44+before :: (IsStream t, Monad m) => m b -> t m a -> t m a
45+before action xs = D.fromStreamD $ D.before action $ D.toStreamD xs
46+
47+-- | Like 'after', with following differences:
48+--
49+-- * action @m b@ won't run if the stream is garbage collected
50+-- after partial evaluation.
51+-- * Monad @m@ does not require any other constraints.
52+-- * has slightly better performance than 'after'.
53+--
54+-- Same as the following, but with stream fusion:
55+--
56+-- > after_ action xs = xs <> 'nilM' action
57+--
58+-- /Internal/
59+--
60+{-# INLINE after_ #-}
61+after_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
62+after_ action xs = D.fromStreamD $ D.after_ action $ D.toStreamD xs
63+
64+-- | Run the action @m b@ whenever the stream @t m a@ stops normally, or if it
65+-- is garbage collected after a partial lazy evaluation.
66+--
67+-- The semantics of the action @m b@ are similar to the semantics of cleanup
68+-- action in 'bracket'.
69+--
70+-- /See also 'after_'/
71+--
72+-- @since 0.7.0
73+--
74+{-# INLINE after #-}
75+after :: (IsStream t, MonadIO m, MonadBaseControl IO m)
76+ => m b -> t m a -> t m a
77+after action xs = D.fromStreamD $ D.after action $ D.toStreamD xs
78+
79+-- | Run the action @m b@ if the stream aborts due to an exception. The
80+-- exception is not caught, simply rethrown.
81+--
82+-- /Inhibits stream fusion/
83+--
84+-- @since 0.7.0
85+{-# INLINE onException #-}
86+onException :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a
87+onException action xs = D.fromStreamD $ D.onException action $ D.toStreamD xs
88+
89+-- | Like 'finally' with following differences:
90+--
91+-- * action @m b@ won't run if the stream is garbage collected
92+-- after partial evaluation.
93+-- * does not require a 'MonadAsync' constraint.
94+-- * has slightly better performance than 'finally'.
95+--
96+-- /Inhibits stream fusion/
97+--
98+-- /Internal/
99+--
100+{-# INLINE finally_ #-}
101+finally_ :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a
102+finally_ action xs = D.fromStreamD $ D.finally_ action $ D.toStreamD xs
103+
104+-- | Run the action @m b@ whenever the stream @t m a@ stops normally, aborts
105+-- due to an exception or if it is garbage collected after a partial lazy
106+-- evaluation.
107+--
108+-- The semantics of running the action @m b@ are similar to the cleanup action
109+-- semantics described in 'bracket'.
110+--
111+-- @
112+-- finally release = bracket (return ()) (const release)
113+-- @
114+--
115+-- /See also 'finally_'/
116+--
117+-- /Inhibits stream fusion/
118+--
119+-- @since 0.7.0
120+--
121+{-# INLINE finally #-}
122+finally :: (IsStream t, MonadAsync m, MonadCatch m) => m b -> t m a -> t m a
123+finally action xs = D.fromStreamD $ D.finally action $ D.toStreamD xs
124+
125+-- | Like 'bracket' but with following differences:
126+--
127+-- * alloc action @m b@ runs with async exceptions enabled
128+-- * cleanup action @b -> m c@ won't run if the stream is garbage collected
129+-- after partial evaluation.
130+-- * does not require a 'MonadAsync' constraint.
131+-- * has slightly better performance than 'bracket'.
132+--
133+-- /Inhibits stream fusion/
134+--
135+-- /Internal/
136+--
137+{-# INLINE bracket_ #-}
138+bracket_ :: (IsStream t, MonadCatch m)
139+ => m b -> (b -> m c) -> (b -> t m a) -> t m a
140+bracket_ bef aft bet = D.fromStreamD $
141+ D.bracket_ bef aft (toStreamD . bet)
142+
143+-- | Run the alloc action @m b@ with async exceptions disabled but keeping
144+-- blocking operations interruptible (see 'Control.Exception.mask'). Use the
145+-- output @b@ as input to @b -> t m a@ to generate an output stream.
146+--
147+-- @b@ is usually a resource under the state of monad @m@, e.g. a file
148+-- handle, that requires a cleanup after use. The cleanup action @b -> m c@,
149+-- runs whenever the stream ends normally, due to a sync or async exception or
150+-- if it gets garbage collected after a partial lazy evaluation.
151+--
152+-- 'bracket' only guarantees that the cleanup action runs, and it runs with
153+-- async exceptions enabled. The action must ensure that it can successfully
154+-- cleanup the resource in the face of sync or async exceptions.
155+--
156+-- When the stream ends normally or on a sync exception, cleanup action runs
157+-- immediately in the current thread context, whereas in other cases it runs in
158+-- the GC context, therefore, cleanup may be delayed until the GC gets to run.
159+--
160+-- /See also: 'bracket_'/
161+--
162+-- /Inhibits stream fusion/
163+--
164+-- @since 0.7.0
165+--
166+{-# INLINE bracket #-}
167+bracket :: (IsStream t, MonadAsync m, MonadCatch m)
168+ => m b -> (b -> m c) -> (b -> t m a) -> t m a
169+bracket bef aft bet = D.fromStreamD $
170+ D.bracket bef aft (toStreamD . bet)
171+
172+-- | Like 'handle' but the exception handler is also provided with the stream
173+-- that generated the exception as input. The exception handler can thus
174+-- re-evaluate the stream to retry the action that failed. The exception
175+-- handler can again call 'ghandle' on it to retry the action multiple times.
176+--
177+-- This is highly experimental. In a stream of actions we can map the stream
178+-- with a retry combinator to retry each action on failure.
179+--
180+-- /Inhibits stream fusion/
181+--
182+-- /Internal/
183+--
184+{-# INLINE ghandle #-}
185+ghandle :: (IsStream t, MonadCatch m, Exception e)
186+ => (e -> t m a -> t m a) -> t m a -> t m a
187+ghandle handler =
188+ D.fromStreamD
189+ . D.ghandle (\e xs -> D.toStreamD $ handler e (D.fromStreamD xs))
190+ . D.toStreamD
191+
192+-- | When evaluating a stream if an exception occurs, stream evaluation aborts
193+-- and the specified exception handler is run with the exception as argument.
194+--
195+-- /Inhibits stream fusion/
196+--
197+-- @since 0.7.0
198+{-# INLINE handle #-}
199+handle :: (IsStream t, MonadCatch m, Exception e)
200+ => (e -> t m a) -> t m a -> t m a
201+handle handler xs =
202+ D.fromStreamD $ D.handle (D.toStreamD . handler) $ D.toStreamD xs
src/Streamly/Internal/Data/Stream/IsStream/Generate.hsnew file+556
@@ -0,0 +1,556 @@
1+{-# OPTIONS_GHC -Wno-orphans #-}
2+
3+-- |
4+-- Module : Streamly.Internal.Data.Stream.IsStream.Generate
5+-- Copyright : (c) 2020 Composewell Technologies
6+-- License : BSD-3-Clause
7+-- Maintainer : streamly@composewell.com
8+-- Stability : experimental
9+-- Portability : GHC
10+--
11+-- Most of the combinators in this module can be implemented as unfolds. Some
12+-- of them however can only be expressed in terms StreamK e.g. cons/consM,
13+-- fromFoldable, mfix. We can possibly remove those from this module which can
14+-- be expressed as unfolds. Unless we want to use rewrite rules to rewrite them
15+-- as StreamK when StreamK is used, avoiding conversion to StreamD. Will that
16+-- help? Are there any other reasons to keep these and not use unfolds?
17+
18+module Streamly.Internal.Data.Stream.IsStream.Generate
19+ (
20+ -- * Primitives
21+ K.nil
22+ , K.nilM
23+ , K.cons
24+ , (K..:)
25+
26+ , consM
27+ , (|:)
28+
29+ -- * From 'Unfold'
30+ , unfold
31+ , unfold0
32+
33+ -- * Unfolding
34+ , unfoldr
35+ , unfoldrM
36+
37+ -- * From Values
38+ , yield
39+ , yieldM
40+ , repeat
41+ , repeatM
42+ , replicate
43+ , replicateM
44+
45+ -- * Enumeration
46+ , Enumerable (..)
47+ , enumerate
48+ , enumerateTo
49+
50+ -- * Time Enumeration
51+ , times
52+ , absTimes
53+ , absTimesWith
54+ , relTimes
55+ , relTimesWith
56+ , durations
57+ , ticks
58+ , timeout
59+
60+ -- * From Generators
61+ , fromIndices
62+ , fromIndicesM
63+ -- , generate
64+ -- , generateM
65+
66+ -- * Iteration
67+ , iterate
68+ , iterateM
69+
70+ -- * Cyclic Elements
71+ , K.mfix
72+
73+ -- * From Containers
74+ , P.fromList
75+ , fromListM
76+ , K.fromFoldable
77+ , fromFoldableM
78+ , fromPrimIORef
79+ , fromCallback
80+
81+ -- * Deprecated
82+ , each
83+ , fromHandle
84+ , currentTime
85+ )
86+where
87+
88+#include "inline.hs"
89+
90+import Control.Monad.IO.Class (MonadIO(..))
91+import Data.Void (Void)
92+import Streamly.Internal.Data.Unfold.Types (Unfold)
93+import Streamly.Internal.Data.SVar (MonadAsync, Rate (..))
94+import Streamly.Internal.Data.Stream.Enumeration
95+ (Enumerable(..), enumerate, enumerateTo)
96+import Streamly.Internal.Data.Stream.IsStream.Common
97+ (absTimesWith, concatM, relTimesWith, timesWith, yield, yieldM, repeatM)
98+import Streamly.Internal.Data.Stream.Prelude (fromStreamS)
99+import Streamly.Internal.Data.Stream.StreamD (fromStreamD)
100+import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM))
101+import Streamly.Internal.Data.Stream.Serial (SerialT, WSerialT)
102+import Streamly.Internal.Data.Stream.Zip (ZipSerialM)
103+import Streamly.Internal.Data.Time.Units (AbsTime , RelTime64, addToAbsTime64)
104+import Streamly.Internal.Data.IORef.Prim (Prim, IORef)
105+
106+import qualified Streamly.Internal.Data.Stream.Prelude as P
107+import qualified Streamly.Internal.Data.Stream.Serial as Serial
108+import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D
109+import qualified Streamly.Internal.Data.Stream.StreamK as K
110+#ifdef USE_STREAMK_ONLY
111+import qualified Streamly.Internal.Data.Stream.StreamK as S
112+#else
113+import qualified Streamly.Internal.Data.Stream.StreamD.Generate as S
114+#endif
115+import qualified System.IO as IO
116+
117+import Prelude hiding (iterate, replicate, repeat)
118+
119+------------------------------------------------------------------------------
120+-- From Unfold
121+------------------------------------------------------------------------------
122+
123+-- | Convert an 'Unfold' into a stream by supplying it an input seed.
124+--
125+-- >>> unfold (UF.replicateM 10) (putStrLn "hello")
126+--
127+-- /Since: 0.7.0/
128+{-# INLINE unfold #-}
129+unfold :: (IsStream t, Monad m) => Unfold m a b -> a -> t m b
130+unfold unf x = fromStreamD $ D.unfold unf x
131+
132+-- | Convert an 'Unfold' with a closed input end into a stream.
133+--
134+-- /Internal/
135+{-# INLINE unfold0 #-}
136+unfold0 :: (IsStream t, Monad m) => Unfold m Void b -> t m b
137+unfold0 unf = unfold unf (error "unfold0: unexpected void evaluation")
138+
139+------------------------------------------------------------------------------
140+-- Generation by Unfolding
141+------------------------------------------------------------------------------
142+
143+-- |
144+-- @
145+-- unfoldr step s =
146+-- case step s of
147+-- Nothing -> 'K.nil'
148+-- Just (a, b) -> a \`cons` unfoldr step b
149+-- @
150+--
151+-- Build a stream by unfolding a /pure/ step function @step@ starting from a
152+-- seed @s@. The step function returns the next element in the stream and the
153+-- next seed value. When it is done it returns 'Nothing' and the stream ends.
154+-- For example,
155+--
156+-- @
157+-- let f b =
158+-- if b > 3
159+-- then Nothing
160+-- else Just (b, b + 1)
161+-- in toList $ unfoldr f 0
162+-- @
163+-- @
164+-- [0,1,2,3]
165+-- @
166+--
167+-- @since 0.1.0
168+{-# INLINE_EARLY unfoldr #-}
169+unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a
170+unfoldr step seed = fromStreamS (S.unfoldr step seed)
171+{-# RULES "unfoldr fallback to StreamK" [1]
172+ forall a b. S.toStreamK (S.unfoldr a b) = K.unfoldr a b #-}
173+
174+-- | Build a stream by unfolding a /monadic/ step function starting from a
175+-- seed. The step function returns the next element in the stream and the next
176+-- seed value. When it is done it returns 'Nothing' and the stream ends. For
177+-- example,
178+--
179+-- @
180+-- let f b =
181+-- if b > 3
182+-- then return Nothing
183+-- else print b >> return (Just (b, b + 1))
184+-- in drain $ unfoldrM f 0
185+-- @
186+-- @
187+-- 0
188+-- 1
189+-- 2
190+-- 3
191+-- @
192+-- When run concurrently, the next unfold step can run concurrently with the
193+-- processing of the output of the previous step. Note that more than one step
194+-- cannot run concurrently as the next step depends on the output of the
195+-- previous step.
196+--
197+-- @
198+-- (asyncly $ S.unfoldrM (\\n -> liftIO (threadDelay 1000000) >> return (Just (n, n + 1))) 0)
199+-- & S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
200+-- @
201+--
202+-- /Concurrent/
203+--
204+-- /Since: 0.1.0/
205+{-# INLINE_EARLY unfoldrM #-}
206+unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
207+unfoldrM = K.unfoldrM
208+
209+{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
210+{-# INLINE_EARLY unfoldrMSerial #-}
211+unfoldrMSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
212+unfoldrMSerial = Serial.unfoldrM
213+
214+{-# RULES "unfoldrM wSerial" unfoldrM = unfoldrMWSerial #-}
215+{-# INLINE_EARLY unfoldrMWSerial #-}
216+unfoldrMWSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> WSerialT m a
217+unfoldrMWSerial = Serial.unfoldrM
218+
219+{-# RULES "unfoldrM zipSerial" unfoldrM = unfoldrMZipSerial #-}
220+{-# INLINE_EARLY unfoldrMZipSerial #-}
221+unfoldrMZipSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> ZipSerialM m a
222+unfoldrMZipSerial = Serial.unfoldrM
223+
224+------------------------------------------------------------------------------
225+-- From Values
226+------------------------------------------------------------------------------
227+
228+-- |
229+-- Generate an infinite stream by repeating a pure value.
230+--
231+-- @since 0.4.0
232+{-# INLINE_NORMAL repeat #-}
233+repeat :: (IsStream t, Monad m) => a -> t m a
234+repeat = fromStreamS . S.repeat
235+
236+-- |
237+-- @
238+-- replicate = take n . repeat
239+-- @
240+--
241+-- Generate a stream of length @n@ by repeating a value @n@ times.
242+--
243+-- @since 0.6.0
244+{-# INLINE_NORMAL replicate #-}
245+replicate :: (IsStream t, Monad m) => Int -> a -> t m a
246+replicate n = fromStreamS . S.replicate n
247+
248+-- |
249+-- @
250+-- replicateM = take n . repeatM
251+-- @
252+--
253+-- Generate a stream by performing a monadic action @n@ times. Same as:
254+--
255+-- @
256+-- drain $ serially $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
257+-- drain $ asyncly $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
258+-- @
259+--
260+-- /Concurrent/
261+--
262+-- @since 0.1.1
263+{-# INLINE_EARLY replicateM #-}
264+replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
265+replicateM = K.replicateM
266+
267+{-# RULES "replicateM serial" replicateM = replicateMSerial #-}
268+{-# INLINE replicateMSerial #-}
269+replicateMSerial :: MonadAsync m => Int -> m a -> SerialT m a
270+replicateMSerial n = fromStreamS . S.replicateM n
271+
272+------------------------------------------------------------------------------
273+-- Time Enumeration
274+------------------------------------------------------------------------------
275+
276+-- | @times@ returns a stream of time value tuples with clock of 10 ms
277+-- granularity. The first component of the tuple is an absolute time reference
278+-- (epoch) denoting the start of the stream and the second component is a time
279+-- relative to the reference.
280+--
281+-- @
282+-- >>> S.mapM_ (\x -> print x >> threadDelay 1000000) $ S.times
283+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 0))
284+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1002028000))
285+-- > (AbsTime (TimeSpec {sec = 2496295, nsec = 536223000}),RelTime64 (NanoSecond64 1996656000))
286+-- @
287+--
288+-- Note: This API is not safe on 32-bit machines.
289+--
290+-- /Internal/
291+--
292+{-# INLINE times #-}
293+times :: (IsStream t, MonadAsync m) => t m (AbsTime, RelTime64)
294+times = timesWith 0.01
295+
296+-- | @absTimes@ returns a stream of absolute timestamps using a clock of 10 ms
297+-- granularity.
298+--
299+-- @
300+-- >>> S.mapM_ print $ S.delayPre 1 $ S.absTimes
301+-- @
302+--
303+-- Note: This API is not safe on 32-bit machines.
304+--
305+-- /Internal/
306+--
307+{-# INLINE absTimes #-}
308+absTimes :: (IsStream t, MonadAsync m, Functor (t m)) => t m AbsTime
309+absTimes = fmap (uncurry addToAbsTime64) times
310+
311+{-# DEPRECATED currentTime "Please use absTimes instead" #-}
312+{-# INLINE currentTime #-}
313+currentTime :: (IsStream t, MonadAsync m, Functor (t m))
314+ => Double -> t m AbsTime
315+currentTime = absTimesWith
316+
317+-- | @relTimes@ returns a stream of relative time values starting from 0,
318+-- using a clock of granularity 10 ms.
319+--
320+-- @
321+-- >>> S.mapM_ print $ S.delayPre 1 $ S.relTimes
322+-- @
323+--
324+-- Note: This API is not safe on 32-bit machines.
325+--
326+-- /Internal/
327+--
328+{-# INLINE relTimes #-}
329+relTimes :: (IsStream t, MonadAsync m, Functor (t m)) => t m RelTime64
330+relTimes = fmap snd times
331+
332+-- | @durations g@ returns a stream of relative time values measuring the time
333+-- elapsed since the immediate predecessor element of the stream was generated.
334+-- The first element of the stream is always 0. @durations@ uses a clock of
335+-- granularity @g@ specified in seconds. A low granularity clock is more
336+-- expensive in terms of CPU usage. The minimum granularity is 1 millisecond.
337+-- Durations lower than 1 ms will be 0.
338+--
339+-- Note: This API is not safe on 32-bit machines.
340+--
341+-- /Unimplemented/
342+--
343+{-# INLINE durations #-}
344+durations :: -- (IsStream t, MonadAsync m) =>
345+ Double -> t m RelTime64
346+durations = undefined
347+
348+-- | Generate ticks at the specified rate. The rate is adaptive, the tick
349+-- generation speed can be increased or decreased at different times to achieve
350+-- the specified rate. The specific behavior for different styles of 'Rate'
351+-- specifications is documented under 'Rate'. The effective maximum rate
352+-- achieved by a stream is governed by the processor speed.
353+--
354+-- /Unimplemented/
355+--
356+{-# INLINE ticks #-}
357+ticks :: -- (IsStream t, MonadAsync m) =>
358+ Rate -> t m ()
359+ticks = undefined
360+
361+-- | Generate a singleton event at or after the specified absolute time. Note
362+-- that this is different from a threadDelay, a threadDelay starts from the
363+-- time when the action is evaluated, whereas if we use AbsTime based timeout
364+-- it will immediately expire if the action is evaluated too late.
365+--
366+-- /Unimplemented/
367+--
368+{-# INLINE timeout #-}
369+timeout :: -- (IsStream t, MonadAsync m) =>
370+ AbsTime -> t m ()
371+timeout = undefined
372+
373+------------------------------------------------------------------------------
374+-- From Generator functions
375+------------------------------------------------------------------------------
376+
377+-- |
378+-- @
379+-- fromIndices f = let g i = f i \`cons` g (i + 1) in g 0
380+-- @
381+--
382+-- Generate an infinite stream, whose values are the output of a function @f@
383+-- applied on the corresponding index. Index starts at 0.
384+--
385+-- @
386+-- > S.toList $ S.take 5 $ S.fromIndices id
387+-- [0,1,2,3,4]
388+-- @
389+--
390+-- @since 0.6.0
391+{-# INLINE fromIndices #-}
392+fromIndices :: (IsStream t, Monad m) => (Int -> a) -> t m a
393+fromIndices = fromStreamS . S.fromIndices
394+
395+--
396+-- |
397+-- @
398+-- fromIndicesM f = let g i = f i \`consM` g (i + 1) in g 0
399+-- @
400+--
401+-- Generate an infinite stream, whose values are the output of a monadic
402+-- function @f@ applied on the corresponding index. Index starts at 0.
403+--
404+-- /Concurrent/
405+--
406+-- @since 0.6.0
407+{-# INLINE_EARLY fromIndicesM #-}
408+fromIndicesM :: (IsStream t, MonadAsync m) => (Int -> m a) -> t m a
409+fromIndicesM = K.fromIndicesM
410+
411+{-# RULES "fromIndicesM serial" fromIndicesM = fromIndicesMSerial #-}
412+{-# INLINE fromIndicesMSerial #-}
413+fromIndicesMSerial :: MonadAsync m => (Int -> m a) -> SerialT m a
414+fromIndicesMSerial = fromStreamS . S.fromIndicesM
415+
416+------------------------------------------------------------------------------
417+-- Iterating functions
418+------------------------------------------------------------------------------
419+
420+-- |
421+-- @
422+-- iterate f x = x \`cons` iterate f x
423+-- @
424+--
425+-- Generate an infinite stream with @x@ as the first element and each
426+-- successive element derived by applying the function @f@ on the previous
427+-- element.
428+--
429+-- @
430+-- > S.toList $ S.take 5 $ S.iterate (+1) 1
431+-- [1,2,3,4,5]
432+-- @
433+--
434+-- @since 0.1.2
435+{-# INLINE_NORMAL iterate #-}
436+iterate :: (IsStream t, Monad m) => (a -> a) -> a -> t m a
437+iterate step = fromStreamS . S.iterate step
438+
439+-- |
440+-- @
441+-- iterateM f m = m >>= \a -> return a \`consM` iterateM f (f a)
442+-- @
443+--
444+-- Generate an infinite stream with the first element generated by the action
445+-- @m@ and each successive element derived by applying the monadic function
446+-- @f@ on the previous element.
447+--
448+-- When run concurrently, the next iteration can run concurrently with the
449+-- processing of the previous iteration. Note that more than one iteration
450+-- cannot run concurrently as the next iteration depends on the output of the
451+-- previous iteration.
452+--
453+-- @
454+-- drain $ serially $ S.take 10 $ S.iterateM
455+-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) (return 0)
456+--
457+-- drain $ asyncly $ S.take 10 $ S.iterateM
458+-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) (return 0)
459+-- @
460+--
461+-- /Concurrent/
462+--
463+-- /Since: 0.1.2/
464+--
465+-- /Since: 0.7.0 (signature change)/
466+{-# INLINE_EARLY iterateM #-}
467+iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
468+iterateM = K.iterateM
469+
470+{-# RULES "iterateM serial" iterateM = iterateMSerial #-}
471+{-# INLINE iterateMSerial #-}
472+iterateMSerial :: MonadAsync m => (a -> m a) -> m a -> SerialT m a
473+iterateMSerial step = fromStreamS . S.iterateM step
474+
475+------------------------------------------------------------------------------
476+-- Conversions
477+------------------------------------------------------------------------------
478+
479+-- |
480+-- @
481+-- fromFoldableM = 'Prelude.foldr' 'consM' 'K.nil'
482+-- @
483+--
484+-- Construct a stream from a 'Foldable' containing monadic actions.
485+--
486+-- @
487+-- drain $ serially $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
488+-- drain $ asyncly $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
489+-- @
490+--
491+-- /Concurrent (do not use with 'parallely' on infinite containers)/
492+--
493+-- @since 0.3.0
494+{-# INLINE fromFoldableM #-}
495+fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a
496+fromFoldableM = Prelude.foldr consM K.nil
497+
498+-- |
499+-- @
500+-- fromListM = 'Prelude.foldr' 'K.consM' 'K.nil'
501+-- @
502+--
503+-- Construct a stream from a list of monadic actions. This is more efficient
504+-- than 'fromFoldableM' for serial streams.
505+--
506+-- @since 0.4.0
507+{-# INLINE_EARLY fromListM #-}
508+fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a
509+fromListM = fromStreamD . D.fromListM
510+{-# RULES "fromListM fallback to StreamK" [1]
511+ forall a. D.toStreamK (D.fromListM a) = fromFoldableM a #-}
512+
513+-- | Same as 'fromFoldable'.
514+--
515+-- @since 0.1.0
516+{-# DEPRECATED each "Please use fromFoldable instead." #-}
517+{-# INLINE each #-}
518+each :: (IsStream t, Foldable f) => f a -> t m a
519+each = K.fromFoldable
520+
521+-- | Read lines from an IO Handle into a stream of Strings.
522+--
523+-- @since 0.1.0
524+{-# DEPRECATED fromHandle
525+ "Please use Streamly.FileSystem.Handle module (see the changelog)" #-}
526+fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
527+fromHandle h = go
528+ where
529+ go = K.mkStream $ \_ yld _ stp -> do
530+ eof <- liftIO $ IO.hIsEOF h
531+ if eof
532+ then stp
533+ else do
534+ str <- liftIO $ IO.hGetLine h
535+ yld str go
536+
537+-- | Construct a stream by reading a 'Prim' 'IORef' repeatedly.
538+--
539+-- /Internal/
540+--
541+{-# INLINE fromPrimIORef #-}
542+fromPrimIORef :: (IsStream t, MonadIO m, Prim a) => IORef a -> t m a
543+fromPrimIORef = fromStreamD . D.fromPrimIORef
544+
545+-- | Takes a callback setter function and provides it with a callback. The
546+-- callback when invoked adds a value at the tail of the stream. Returns a
547+-- stream of values generated by the callback.
548+--
549+-- /Internal/
550+--
551+{-# INLINE fromCallback #-}
552+fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> SerialT m a
553+fromCallback setCallback = concatM $ do
554+ (callback, stream) <- D.newCallbackStream
555+ setCallback callback
556+ return stream
src/Streamly/Internal/Data/Stream/IsStream/Lift.hsnew file+148
@@ -0,0 +1,148 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.IsStream.Lift
3+-- Copyright : (c) 2020 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+
9+module Streamly.Internal.Data.Stream.IsStream.Lift
10+ (
11+ -- * Generalize Inner Monad
12+ hoist
13+ , generally
14+
15+ -- * Transform Inner Monad
16+ , liftInner
17+ , usingReaderT
18+ , runReaderT
19+ , evalStateT
20+ , usingStateT
21+ , runStateT
22+ )
23+where
24+
25+#include "inline.hs"
26+
27+import Control.Monad.Trans.Reader (ReaderT)
28+import Control.Monad.Trans.State.Strict (StateT)
29+import Control.Monad.Trans.Class (MonadTrans(..))
30+import Data.Functor.Identity (Identity (..))
31+import Streamly.Internal.Data.Stream.Prelude (fromStreamS, toStreamS)
32+import Streamly.Internal.Data.Stream.Serial (SerialT)
33+import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
34+import Streamly.Internal.Data.Stream.StreamK (IsStream)
35+
36+import qualified Streamly.Internal.Data.Stream.StreamD as D
37+#ifdef USE_STREAMK_ONLY
38+import qualified Streamly.Internal.Data.Stream.StreamK as S
39+#else
40+import qualified Streamly.Internal.Data.Stream.StreamD as S
41+#endif
42+
43+------------------------------------------------------------------------------
44+-- Generalize the underlying monad
45+------------------------------------------------------------------------------
46+
47+-- | Transform the inner monad of a stream using a natural transformation.
48+--
49+-- / Internal/
50+--
51+{-# INLINE hoist #-}
52+hoist :: (Monad m, Monad n)
53+ => (forall x. m x -> n x) -> SerialT m a -> SerialT n a
54+hoist f xs = fromStreamS $ S.hoist f (toStreamS xs)
55+
56+-- | Generalize the inner monad of the stream from 'Identity' to any monad.
57+--
58+-- / Internal/
59+--
60+{-# INLINE generally #-}
61+generally :: (IsStream t, Monad m) => t Identity a -> t m a
62+generally xs = fromStreamS $ S.hoist (return . runIdentity) (toStreamS xs)
63+
64+------------------------------------------------------------------------------
65+-- Add and remove a monad transformer
66+------------------------------------------------------------------------------
67+
68+-- | Lift the inner monad @m@ of a stream @t m a@ to @tr m@ using the monad
69+-- transformer @tr@.
70+--
71+-- / Internal/
72+--
73+{-# INLINE liftInner #-}
74+liftInner :: (Monad m, IsStream t, MonadTrans tr, Monad (tr m))
75+ => t m a -> t (tr m) a
76+liftInner xs = fromStreamD $ D.liftInner (toStreamD xs)
77+
78+------------------------------------------------------------------------------
79+-- Sharing read only state in a stream
80+------------------------------------------------------------------------------
81+
82+-- | Evaluate the inner monad of a stream as 'ReaderT'.
83+--
84+-- / Internal/
85+--
86+{-# INLINE runReaderT #-}
87+runReaderT :: (IsStream t, Monad m) => m s -> t (ReaderT s m) a -> t m a
88+runReaderT s xs = fromStreamD $ D.runReaderT s (toStreamD xs)
89+
90+-- | Run a stream transformation using a given environment.
91+--
92+-- See also: 'Serial.map'
93+--
94+-- / Internal/
95+--
96+{-# INLINE usingReaderT #-}
97+usingReaderT
98+ :: (Monad m, IsStream t)
99+ => m r
100+ -> (t (ReaderT r m) a -> t (ReaderT r m) a)
101+ -> t m a
102+ -> t m a
103+usingReaderT r f xs = runReaderT r $ f $ liftInner xs
104+
105+------------------------------------------------------------------------------
106+-- Sharing read write state in a stream
107+------------------------------------------------------------------------------
108+
109+-- | Evaluate the inner monad of a stream as 'StateT'.
110+--
111+-- This is supported only for 'SerialT' as concurrent state updation may not be
112+-- safe.
113+--
114+-- / Internal/
115+--
116+{-# INLINE evalStateT #-}
117+evalStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m a
118+evalStateT s xs = fromStreamD $ D.evalStateT s (toStreamD xs)
119+
120+-- | Run a stateful (StateT) stream transformation using a given state.
121+--
122+-- This is supported only for 'SerialT' as concurrent state updation may not be
123+-- safe.
124+--
125+-- See also: 'scanl''
126+--
127+-- / Internal/
128+--
129+{-# INLINE usingStateT #-}
130+usingStateT
131+ :: Monad m
132+ => m s
133+ -> (SerialT (StateT s m) a -> SerialT (StateT s m) a)
134+ -> SerialT m a
135+ -> SerialT m a
136+usingStateT s f xs = evalStateT s $ f $ liftInner xs
137+
138+-- | Evaluate the inner monad of a stream as 'StateT' and emit the resulting
139+-- state and value pair after each step.
140+--
141+-- This is supported only for 'SerialT' as concurrent state updation may not be
142+-- safe.
143+--
144+-- / Internal/
145+--
146+{-# INLINE runStateT #-}
147+runStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m (s, a)
148+runStateT s xs = fromStreamD $ D.runStateT s (toStreamD xs)
src/Streamly/Internal/Data/Stream/IsStream/Nesting.hsnew file+2098
@@ -0,0 +1,2098 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.IsStream.Nesting
3+-- Copyright : (c) 2020 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+--
9+-- Transformations involving multiple streams, streams and unfolds or streams
10+-- and folds.
11+
12+module Streamly.Internal.Data.Stream.IsStream.Nesting
13+ (
14+ -- * Generate
15+ -- | Combining streams to generate streams.
16+
17+ -- ** Combine Two Streams
18+ -- | Functions ending in the shape:
19+ --
20+ -- @t m a -> t m a -> t m a@.
21+
22+ -- *** Appending
23+ serial
24+ , append
25+
26+ -- *** Interleaving
27+ , interleave
28+ , interleaveMin
29+ , interleaveSuffix
30+ , interleaveInfix
31+
32+ , wSerial
33+ , Serial.wSerialFst
34+ , Serial.wSerialMin
35+
36+ -- *** Scheduling
37+ , ahead
38+ , async
39+ , wAsync
40+ , roundrobin
41+
42+ -- *** Parallel
43+ , parallel
44+ , Par.parallelFst
45+ , Par.parallelMin
46+
47+ -- *** Zipping
48+ , Z.zipWith
49+ , Z.zipWithM
50+ , Z.zipAsyncWith
51+ , Z.zipAsyncWithM
52+
53+ -- *** Merging
54+ -- , merge
55+ , mergeBy
56+ , mergeByM
57+ , mergeAsyncBy
58+ , mergeAsyncByM
59+
60+ -- ** Combine N Streams
61+ -- | Functions generally ending in these shapes:
62+ --
63+ -- @
64+ -- concat: f (t m a) -> t m a
65+ -- concatMap: (a -> t m b) -> t m a -> t m b
66+ -- concatUnfold: Unfold m a b -> t m a -> t m b
67+ -- @
68+
69+ -- *** Flatten Containers of Streams
70+ , concatM
71+ , concat
72+ , concatFoldableWith
73+
74+ -- *** ConcatMap
75+ -- | Map and flatten streams.
76+ , concatMapFoldableWith
77+ , concatForFoldableWith
78+ , concatMap
79+ , concatMapM
80+ , concatMapWith
81+ , concatSmapMWith
82+ -- , bindWith
83+
84+ -- *** ConcatUnfold
85+ -- | Unfold and flatten streams.
86+ , concatUnfold
87+ , concatUnfoldInterleave
88+ , concatUnfoldRoundrobin
89+
90+ -- *** Interpose
91+ -- | Insert effects between streams. Like concatUnfold but intersperses an
92+ -- effect between the streams. A
93+ -- special case of gintercalate.
94+ , interpose
95+ , interposeSuffix
96+ -- , interposeBy
97+
98+ -- *** Intercalate
99+ -- | Insert Streams between Streams.
100+ -- Like concatUnfold but intersperses streams from another source between
101+ -- the streams from the first source.
102+ , intercalate
103+ , intercalateSuffix
104+ , gintercalate
105+ , gintercalateSuffix
106+
107+ -- *** IterateMap
108+ -- | Map and flatten Trees of Streams
109+ , iterateMapWith
110+ , iterateSmapMWith
111+ , iterateMapLeftsWith
112+
113+ -- * Eliminate
114+ -- | Folding and Parsing chunks of streams to eliminate nested streams.
115+ -- Functions generally ending in these shapes:
116+ --
117+ -- @
118+ -- f (Fold m a b) -> t m a -> t m b
119+ -- f (Parser m a b) -> t m a -> t m b
120+ -- @
121+
122+ -- ** Folding
123+ -- | Apply folds on a stream.
124+ , foldMany
125+ , foldSequence
126+ , foldIterate
127+
128+ -- ** Parsing
129+ -- | Apply parsers on a stream.
130+ , parseMany
131+ , parseManyD
132+ , parseManyTill
133+ , parseSequence
134+ , parseIterate
135+
136+ -- ** Chunking
137+ -- | Element unaware grouping.
138+ , chunksOf
139+ , chunksOf2
140+ , arraysOf
141+ , intervalsOf
142+
143+ -- ** Trimming
144+ , dropPrefix
145+ , dropInfix
146+ , dropSuffix
147+
148+ -- ** Grouping
149+ -- In imperative terms, grouped folding can be considered as a nested loop
150+ -- where we loop over the stream to group elements and then loop over
151+ -- individual groups to fold them to a single value that is yielded in the
152+ -- output stream.
153+
154+ , groups
155+ , groupsBy
156+ , groupsByRolling
157+
158+ -- -- *** Searching Sequences
159+ -- , seqIndices -- search a sequence in the stream
160+
161+ -- -- *** Searching Multiple Sequences
162+ -- , seqIndicesAny -- search any of the given sequence in the stream
163+
164+ -- -- -- ** Searching Streams
165+ -- -- | Finding a stream within another stream.
166+
167+ -- ** Splitting
168+ -- | Streams can be sliced into segments in space or in time. We use the
169+ -- term @chunk@ to refer to a spatial length of the stream (spatial window)
170+ -- and the term @session@ to refer to a length in time (time window).
171+
172+ -- -- *** Using Element Separators
173+ , splitOn
174+ , splitOnSuffix
175+ -- , splitOnPrefix
176+
177+ -- , splitBy
178+ , splitWithSuffix
179+ -- , splitByPrefix
180+ , wordsBy -- stripAndCompactBy
181+
182+ -- -- *** Splitting By Sequences
183+ , splitBySeq
184+ , splitOnSeq
185+ , splitOnSuffixSeq
186+ -- , splitOnPrefixSeq
187+
188+ -- Keeping the delimiters
189+ , splitWithSuffixSeq
190+ -- , splitByPrefixSeq
191+ -- , wordsBySeq
192+
193+ -- Splitting using multiple sequence separators
194+ -- , splitOnAnySeq
195+ -- , splitOnAnySuffixSeq
196+ -- , splitOnAnyPrefixSeq
197+
198+ -- -- *** Splitting By Streams
199+ -- -- | Splitting a stream using another stream as separator.
200+
201+ -- ** Classifying
202+ -- | De-interleaving groups.
203+ , classifySessionsOf
204+ , classifyKeepAliveSessions
205+ , classifySessionsBy
206+
207+ -- * Transform (Nested Containers)
208+ -- Nested splitting
209+ , splitInnerBy
210+ , splitInnerBySuffix
211+ )
212+where
213+
214+#include "inline.hs"
215+
216+import Control.Concurrent (threadDelay)
217+import Control.Exception (assert)
218+import Control.Monad.Catch (MonadThrow)
219+import Control.Monad.IO.Class (MonadIO(..))
220+import Data.Heap (Entry(..))
221+import Data.Kind (Type)
222+import Data.Maybe (isNothing)
223+import Foreign.Storable (Storable)
224+import Streamly.Internal.Data.Fold.Types (Fold (..), Fold2 (..))
225+import Streamly.Internal.Data.Parser (Parser (..))
226+import Streamly.Internal.Data.Unfold.Types (Unfold)
227+import Streamly.Internal.Data.Array.Storable.Foreign.Types
228+ (Array, writeNUnsafe)
229+import Streamly.Internal.Data.SVar (MonadAsync)
230+import Streamly.Internal.Data.Stream.Ahead (ahead)
231+import Streamly.Internal.Data.Stream.Async (async, wAsync)
232+import Streamly.Internal.Data.Stream.IsStream.Common
233+ ( concatM
234+ , concatMapM
235+ , fold
236+ , interjectSuffix
237+ , intersperseM
238+ , repeatM
239+ , scanlMAfter'
240+ , smapM
241+ , splitOnSeq
242+ , yield
243+ , yieldM)
244+import Streamly.Internal.Data.Stream.Parallel (parallel)
245+import Streamly.Internal.Data.Stream.Prelude
246+ ( fromStreamS, toStreamS, concatFoldableWith, concatMapFoldableWith
247+ , concatForFoldableWith)
248+import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
249+import Streamly.Internal.Data.Stream.StreamK (IsStream)
250+import Streamly.Internal.Data.Stream.Serial (serial, wSerial)
251+import Streamly.Internal.Data.Time.Units
252+ ( AbsTime, MilliSecond64(..), addToAbsTime, toRelTime
253+ , toAbsTime)
254+import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
255+
256+import qualified Data.Heap as H
257+import qualified Data.Map.Strict as Map
258+import qualified Streamly.Internal.Data.Array.Storable.Foreign as A
259+import qualified Streamly.Internal.Data.Fold as FL
260+import qualified Streamly.Internal.Data.Parser.ParserK.Types as PRK
261+import qualified Streamly.Internal.Data.Parser.ParserD as PRD
262+import qualified Streamly.Internal.Data.Stream.Parallel as Par
263+import qualified Streamly.Internal.Data.Stream.Serial as Serial
264+import qualified Streamly.Internal.Data.Stream.StreamD as D
265+import qualified Streamly.Internal.Data.Stream.StreamK as K
266+import qualified Streamly.Internal.Data.Stream.Zip as Z
267+#ifdef USE_STREAMK_ONLY
268+import qualified Streamly.Internal.Data.Stream.StreamK as S
269+#else
270+import qualified Streamly.Internal.Data.Stream.StreamD as S
271+#endif
272+
273+import Prelude hiding (zipWith, concatMap, concat)
274+
275+-------------------------------------------------------------------------------
276+-- Appending
277+-------------------------------------------------------------------------------
278+
279+-- | Append the outputs of two streams, yielding all the elements from the
280+-- first stream and then yielding all the elements from the second stream.
281+--
282+-- IMPORTANT NOTE: This could be 100x faster than @serial/<>@ for appending a
283+-- few (say 100) streams because it can fuse via stream fusion. However, it
284+-- does not scale for a large number of streams (say 1000s) and becomes
285+-- qudartically slow. Therefore use this for custom appending of a few streams
286+-- but use 'concatMap' or 'concatMapWith serial' for appending @n@ streams or
287+-- infinite containers of streams.
288+--
289+-- /Internal/
290+{-# INLINE append #-}
291+append ::(IsStream t, Monad m) => t m b -> t m b -> t m b
292+append m1 m2 = fromStreamD $ D.append (toStreamD m1) (toStreamD m2)
293+
294+-------------------------------------------------------------------------------
295+-- Interleaving
296+-------------------------------------------------------------------------------
297+
298+-- XXX Same as 'wSerial'. We should perhaps rename wSerial to interleave.
299+-- XXX Document the interleaving behavior of side effects in all the
300+-- interleaving combinators.
301+-- XXX Write time-domain equivalents of these. In the time domain we can
302+-- interleave two streams such that the value of second stream is always taken
303+-- from its last value even if no new value is being yielded, like
304+-- zipWithLatest. It would be something like interleaveWithLatest.
305+--
306+-- | Interleaves the outputs of two streams, yielding elements from each stream
307+-- alternately, starting from the first stream. If any of the streams finishes
308+-- early the other stream continues alone until it too finishes.
309+--
310+-- >>> :set -XOverloadedStrings
311+-- >>> interleave "ab" ",,,," :: SerialT Identity Char
312+-- fromList "a,b,,,"
313+-- >>> interleave "abcd" ",," :: SerialT Identity Char
314+-- fromList "a,b,cd"
315+--
316+-- 'interleave' is dual to 'interleaveMin', it can be called @interleaveMax@.
317+--
318+-- Do not use at scale in concatMapWith.
319+--
320+-- /Internal/
321+{-# INLINE interleave #-}
322+interleave ::(IsStream t, Monad m) => t m b -> t m b -> t m b
323+interleave m1 m2 = fromStreamD $ D.interleave (toStreamD m1) (toStreamD m2)
324+
325+-- | Interleaves the outputs of two streams, yielding elements from each stream
326+-- alternately, starting from the first stream. As soon as the first stream
327+-- finishes, the output stops, discarding the remaining part of the second
328+-- stream. In this case, the last element in the resulting stream would be from
329+-- the second stream. If the second stream finishes early then the first stream
330+-- still continues to yield elements until it finishes.
331+--
332+-- >>> :set -XOverloadedStrings
333+-- >>> interleaveSuffix "abc" ",,,," :: SerialT Identity Char
334+-- fromList "a,b,c,"
335+-- >>> interleaveSuffix "abc" "," :: SerialT Identity Char
336+-- fromList "a,bc"
337+--
338+-- 'interleaveSuffix' is a dual of 'interleaveInfix'.
339+--
340+-- Do not use at scale in concatMapWith.
341+--
342+-- /Internal/
343+{-# INLINE interleaveSuffix #-}
344+interleaveSuffix ::(IsStream t, Monad m) => t m b -> t m b -> t m b
345+interleaveSuffix m1 m2 =
346+ fromStreamD $ D.interleaveSuffix (toStreamD m1) (toStreamD m2)
347+
348+-- | Interleaves the outputs of two streams, yielding elements from each stream
349+-- alternately, starting from the first stream and ending at the first stream.
350+-- If the second stream is longer than the first, elements from the second
351+-- stream are infixed with elements from the first stream. If the first stream
352+-- is longer then it continues yielding elements even after the second stream
353+-- has finished.
354+--
355+-- >>> :set -XOverloadedStrings
356+-- >>> interleaveInfix "abc" ",,,," :: SerialT Identity Char
357+-- fromList "a,b,c"
358+-- >>> interleaveInfix "abc" "," :: SerialT Identity Char
359+-- fromList "a,bc"
360+--
361+-- 'interleaveInfix' is a dual of 'interleaveSuffix'.
362+--
363+-- Do not use at scale in concatMapWith.
364+--
365+-- /Internal/
366+{-# INLINE interleaveInfix #-}
367+interleaveInfix ::(IsStream t, Monad m) => t m b -> t m b -> t m b
368+interleaveInfix m1 m2 =
369+ fromStreamD $ D.interleaveInfix (toStreamD m1) (toStreamD m2)
370+
371+-- | Interleaves the outputs of two streams, yielding elements from each stream
372+-- alternately, starting from the first stream. The output stops as soon as any
373+-- of the two streams finishes, discarding the remaining part of the other
374+-- stream. The last element of the resulting stream would be from the longer
375+-- stream.
376+--
377+-- >>> :set -XOverloadedStrings
378+-- >>> interleaveMin "ab" ",,,," :: SerialT Identity Char
379+-- fromList "a,b,"
380+-- >>> interleaveMin "abcd" ",," :: SerialT Identity Char
381+-- fromList "a,b,c"
382+--
383+-- 'interleaveMin' is dual to 'interleave'.
384+--
385+-- Do not use at scale in concatMapWith.
386+--
387+-- /Internal/
388+{-# INLINE interleaveMin #-}
389+interleaveMin ::(IsStream t, Monad m) => t m b -> t m b -> t m b
390+interleaveMin m1 m2 = fromStreamD $ D.interleaveMin (toStreamD m1) (toStreamD m2)
391+
392+-------------------------------------------------------------------------------
393+-- Scheduling
394+-------------------------------------------------------------------------------
395+
396+-- | Schedule the execution of two streams in a fair round-robin manner,
397+-- executing each stream once, alternately. Execution of a stream may not
398+-- necessarily result in an output, a stream may chose to @Skip@ producing an
399+-- element until later giving the other stream a chance to run. Therefore, this
400+-- combinator fairly interleaves the execution of two streams rather than
401+-- fairly interleaving the output of the two streams. This can be useful in
402+-- co-operative multitasking without using explicit threads. This can be used
403+-- as an alternative to `async`.
404+--
405+-- Do not use at scale in concatMapWith.
406+--
407+-- /Internal/
408+{-# INLINE roundrobin #-}
409+roundrobin ::(IsStream t, Monad m) => t m b -> t m b -> t m b
410+roundrobin m1 m2 = fromStreamD $ D.roundRobin (toStreamD m1) (toStreamD m2)
411+
412+------------------------------------------------------------------------------
413+-- Merging
414+------------------------------------------------------------------------------
415+
416+-- | Merge two streams using a comparison function. The head elements of both
417+-- the streams are compared and the smaller of the two elements is emitted, if
418+-- both elements are equal then the element from the first stream is used
419+-- first.
420+--
421+-- If the streams are sorted in ascending order, the resulting stream would
422+-- also remain sorted in ascending order.
423+--
424+-- @
425+-- > S.toList $ S.mergeBy compare (S.fromList [1,3,5]) (S.fromList [2,4,6,8])
426+-- [1,2,3,4,5,6,8]
427+-- @
428+--
429+-- @since 0.6.0
430+{-# INLINABLE mergeBy #-}
431+mergeBy ::
432+ (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> t m a -> t m a
433+mergeBy f m1 m2 = fromStreamS $ S.mergeBy f (toStreamS m1) (toStreamS m2)
434+
435+-- | Like 'mergeBy' but with a monadic comparison function.
436+--
437+-- Merge two streams randomly:
438+--
439+-- @
440+-- > randomly _ _ = randomIO >>= \x -> return $ if x then LT else GT
441+-- > S.toList $ S.mergeByM randomly (S.fromList [1,1,1,1]) (S.fromList [2,2,2,2])
442+-- [2,1,2,2,2,1,1,1]
443+-- @
444+--
445+-- Merge two streams in a proportion of 2:1:
446+--
447+-- @
448+-- proportionately m n = do
449+-- ref <- newIORef $ cycle $ concat [replicate m LT, replicate n GT]
450+-- return $ \\_ _ -> do
451+-- r <- readIORef ref
452+-- writeIORef ref $ tail r
453+-- return $ head r
454+--
455+-- main = do
456+-- f <- proportionately 2 1
457+-- xs <- S.toList $ S.mergeByM f (S.fromList [1,1,1,1,1,1]) (S.fromList [2,2,2])
458+-- print xs
459+-- @
460+-- @
461+-- [1,1,2,1,1,2,1,1,2]
462+-- @
463+--
464+-- @since 0.6.0
465+{-# INLINABLE mergeByM #-}
466+mergeByM
467+ :: (IsStream t, Monad m)
468+ => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
469+mergeByM f m1 m2 = fromStreamS $ S.mergeByM f (toStreamS m1) (toStreamS m2)
470+
471+{-
472+-- | Like 'mergeByM' but stops merging as soon as any of the two streams stops.
473+{-# INLINABLE mergeEndByAny #-}
474+mergeEndByAny
475+ :: (IsStream t, Monad m)
476+ => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
477+mergeEndByAny f m1 m2 = fromStreamD $
478+ D.mergeEndByAny f (toStreamD m1) (toStreamD m2)
479+
480+-- Like 'mergeByM' but stops merging as soon as the first stream stops.
481+{-# INLINABLE mergeEndByFirst #-}
482+mergeEndByFirst
483+ :: (IsStream t, Monad m)
484+ => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
485+mergeEndByFirst f m1 m2 = fromStreamS $
486+ D.mergeEndByFirst f (toStreamD m1) (toStreamD m2)
487+
488+-- Holding this back for now, we may want to use the name "merge" differently
489+-- | Same as @'mergeBy' 'compare'@.
490+--
491+-- @
492+-- > S.toList $ S.merge (S.fromList [1,3,5]) (S.fromList [2,4,6,8])
493+-- [1,2,3,4,5,6,8]
494+-- @
495+--
496+-- @since 0.6.0
497+{-# INLINABLE merge #-}
498+merge ::
499+ (IsStream t, Monad m, Ord a) => t m a -> t m a -> t m a
500+merge = mergeBy compare
501+-}
502+
503+-- | Like 'mergeBy' but merges concurrently (i.e. both the elements being
504+-- merged are generated concurrently).
505+--
506+-- @since 0.6.0
507+{-# INLINE mergeAsyncBy #-}
508+mergeAsyncBy :: (IsStream t, MonadAsync m)
509+ => (a -> a -> Ordering) -> t m a -> t m a -> t m a
510+mergeAsyncBy f = mergeAsyncByM (\a b -> return $ f a b)
511+
512+-- | Like 'mergeByM' but merges concurrently (i.e. both the elements being
513+-- merged are generated concurrently).
514+--
515+-- @since 0.6.0
516+{-# INLINE mergeAsyncByM #-}
517+mergeAsyncByM :: (IsStream t, MonadAsync m)
518+ => (a -> a -> m Ordering) -> t m a -> t m a -> t m a
519+mergeAsyncByM f m1 m2 = fromStreamD $
520+ D.mergeByM f (D.mkParallelD $ toStreamD m1) (D.mkParallelD $ toStreamD m2)
521+
522+------------------------------------------------------------------------------
523+-- Combine N Streams - concatMap
524+------------------------------------------------------------------------------
525+
526+-- | @concatMapWith merge map stream@ is a two dimensional looping combinator.
527+-- The first argument specifies a merge or concat function that is used to
528+-- merge the streams generated by applying the second argument i.e. the @map@
529+-- function to each element of the input stream. The concat function could be
530+-- 'serial', 'parallel', 'async', 'ahead' or any other zip or merge function
531+-- and the second argument could be any stream generation function using a
532+-- seed.
533+--
534+-- /Compare 'foldMapWith'/
535+--
536+-- /Since: 0.7.0/
537+--
538+-- /Since: 0.8.0 (signature change)/
539+{-# INLINE concatMapWith #-}
540+concatMapWith
541+ :: IsStream t
542+ => (t m b -> t m b -> t m b)
543+ -> (a -> t m b)
544+ -> t m a
545+ -> t m b
546+concatMapWith = K.concatMapBy
547+
548+-- | Like 'concatMapWith' but carries a state which can be used to share
549+-- information across multiple steps of concat.
550+--
551+-- @
552+-- concatSmapMWith combine f initial = concatMapWith combine id . smapM f initial
553+-- @
554+--
555+-- /Internal/
556+--
557+{-# INLINE concatSmapMWith #-}
558+concatSmapMWith
559+ :: (IsStream t, Monad m)
560+ => (t m b -> t m b -> t m b)
561+ -> (s -> a -> m (s, t m b))
562+ -> m s
563+ -> t m a
564+ -> t m b
565+concatSmapMWith combine f initial = concatMapWith combine id . smapM f initial
566+
567+-- | Map a stream producing function on each element of the stream and then
568+-- flatten the results into a single stream.
569+--
570+-- @
571+-- concatMap f = 'concat . map f'
572+-- concatMap = 'concatMapWith' 'Serial.serial'
573+-- concatMap f = 'concatMapM' (return . f)
574+-- concatMap f = 'concatUnfold' (UF.lmap f UF.fromStream)
575+-- @
576+--
577+-- @since 0.6.0
578+{-# INLINE concatMap #-}
579+concatMap ::(IsStream t, Monad m) => (a -> t m b) -> t m a -> t m b
580+concatMap f m = fromStreamD $ D.concatMap (toStreamD . f) (toStreamD m)
581+
582+-- | Flatten a stream of streams to a single stream.
583+--
584+-- @
585+-- concat = concatMap id
586+-- @
587+--
588+-- /Internal/
589+{-# INLINE concat #-}
590+concat :: (IsStream t, Monad m) => t m (t m a) -> t m a
591+concat = concatMap id
592+
593+-- Keep concating either streams as long as rights are generated, stop as soon
594+-- as a left is generated and concat the left stream.
595+--
596+-- See also: 'handle'
597+--
598+-- /Unimplemented/
599+--
600+{-
601+concatMapEitherWith
602+ :: -- (IsStream t, MonadAsync m) =>
603+ (forall x. t m x -> t m x -> t m x)
604+ -> (a -> t m (Either (t m b) b))
605+ -> t m a
606+ -> t m b
607+concatMapEitherWith = undefined
608+-}
609+
610+------------------------------------------------------------------------------
611+-- Combine N Streams - concatUnfold
612+------------------------------------------------------------------------------
613+
614+-- | Like 'concatMap' but uses an 'Unfold' for stream generation. Unlike
615+-- 'concatMap' this can fuse the 'Unfold' code with the inner loop and
616+-- therefore provide many times better performance.
617+--
618+-- @since 0.7.0
619+{-# INLINE concatUnfold #-}
620+concatUnfold ::(IsStream t, Monad m) => Unfold m a b -> t m a -> t m b
621+concatUnfold u m = fromStreamD $ D.concatMapU u (toStreamD m)
622+
623+-- | Like 'concatUnfold' but interleaves the streams in the same way as
624+-- 'interleave' behaves instead of appending them.
625+--
626+-- /Internal/
627+{-# INLINE concatUnfoldInterleave #-}
628+concatUnfoldInterleave ::(IsStream t, Monad m)
629+ => Unfold m a b -> t m a -> t m b
630+concatUnfoldInterleave u m =
631+ fromStreamD $ D.concatUnfoldInterleave u (toStreamD m)
632+
633+-- | Like 'concatUnfold' but executes the streams in the same way as
634+-- 'roundrobin'.
635+--
636+-- /Internal/
637+{-# INLINE concatUnfoldRoundrobin #-}
638+concatUnfoldRoundrobin ::(IsStream t, Monad m)
639+ => Unfold m a b -> t m a -> t m b
640+concatUnfoldRoundrobin u m =
641+ fromStreamD $ D.concatUnfoldRoundrobin u (toStreamD m)
642+
643+------------------------------------------------------------------------------
644+-- Combine N Streams - interpose
645+------------------------------------------------------------------------------
646+
647+-- > interpose x unf str = gintercalate unf str UF.identity (repeat x)
648+--
649+-- | Unfold the elements of a stream, intersperse the given element between the
650+-- unfolded streams and then concat them into a single stream.
651+--
652+-- > unwords = S.interpose ' '
653+--
654+-- /Internal/
655+{-# INLINE interpose #-}
656+interpose :: (IsStream t, Monad m)
657+ => c -> Unfold m b c -> t m b -> t m c
658+interpose x unf str =
659+ D.fromStreamD $ D.interpose (return x) unf (D.toStreamD str)
660+
661+-- interposeSuffix x unf str = gintercalateSuffix unf str UF.identity (repeat x)
662+--
663+-- | Unfold the elements of a stream, append the given element after each
664+-- unfolded stream and then concat them into a single stream.
665+--
666+-- > unlines = S.interposeSuffix '\n'
667+--
668+-- /Internal/
669+{-# INLINE interposeSuffix #-}
670+interposeSuffix :: (IsStream t, Monad m)
671+ => c -> Unfold m b c -> t m b -> t m c
672+interposeSuffix x unf str =
673+ D.fromStreamD $ D.interposeSuffix (return x) unf (D.toStreamD str)
674+
675+------------------------------------------------------------------------------
676+-- Combine N Streams - intercalate
677+------------------------------------------------------------------------------
678+
679+-- XXX we can swap the order of arguments to gintercalate so that the
680+-- definition of concatUnfold becomes simpler? The first stream should be
681+-- infixed inside the second one. However, if we change the order in
682+-- "interleave" as well similarly, then that will make it a bit unintuitive.
683+--
684+-- > concatUnfold unf str =
685+-- > gintercalate unf str (UF.nilM (\_ -> return ())) (repeat ())
686+--
687+-- | 'interleaveInfix' followed by unfold and concat.
688+--
689+-- /Internal/
690+{-# INLINE gintercalate #-}
691+gintercalate
692+ :: (IsStream t, Monad m)
693+ => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
694+gintercalate unf1 str1 unf2 str2 =
695+ D.fromStreamD $ D.gintercalate
696+ unf1 (D.toStreamD str1)
697+ unf2 (D.toStreamD str2)
698+
699+-- XXX The order of arguments in "intercalate" is consistent with the list
700+-- intercalate but inconsistent with gintercalate and other stream interleaving
701+-- combinators. We can change the order of the arguments in other combinators
702+-- but then 'interleave' combinator may become a bit unintuitive because we
703+-- will be starting with the second stream.
704+
705+-- > intercalate seed unf str = gintercalate unf str unf (repeatM seed)
706+-- > intercalate a unf str = concatUnfold unf $ intersperse a str
707+--
708+-- | 'intersperse' followed by unfold and concat.
709+--
710+-- > unwords = intercalate " " UF.fromList
711+--
712+-- >>> intercalate " " UF.fromList ["abc", "def", "ghi"]
713+-- > "abc def ghi"
714+--
715+-- /Internal/
716+{-# INLINE intercalate #-}
717+intercalate :: (IsStream t, Monad m)
718+ => b -> Unfold m b c -> t m b -> t m c
719+intercalate seed unf str = D.fromStreamD $
720+ D.concatMapU unf $ D.intersperse seed (toStreamD str)
721+
722+-- | 'interleaveSuffix' followed by unfold and concat.
723+--
724+-- /Internal/
725+{-# INLINE gintercalateSuffix #-}
726+gintercalateSuffix
727+ :: (IsStream t, Monad m)
728+ => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c
729+gintercalateSuffix unf1 str1 unf2 str2 =
730+ D.fromStreamD $ D.gintercalateSuffix
731+ unf1 (D.toStreamD str1)
732+ unf2 (D.toStreamD str2)
733+
734+-- > intercalateSuffix seed unf str = gintercalateSuffix unf str unf (repeatM seed)
735+-- > intercalateSuffix a unf str = concatUnfold unf $ intersperseSuffix a str
736+--
737+-- | 'intersperseSuffix' followed by unfold and concat.
738+--
739+-- > unlines = intercalateSuffix "\n" UF.fromList
740+--
741+-- >>> intercalate "\n" UF.fromList ["abc", "def", "ghi"]
742+-- > "abc\ndef\nghi\n"
743+--
744+-- /Internal/
745+{-# INLINE intercalateSuffix #-}
746+intercalateSuffix :: (IsStream t, Monad m)
747+ => b -> Unfold m b c -> t m b -> t m c
748+intercalateSuffix seed unf str = fromStreamD $ D.concatMapU unf
749+ $ D.intersperseSuffix (return seed) (D.toStreamD str)
750+
751+------------------------------------------------------------------------------
752+-- IterateMap - Map and flatten Trees of Streams
753+------------------------------------------------------------------------------
754+
755+-- | Like 'iterateM' but iterates after mapping a stream generator on the
756+-- output.
757+--
758+-- Yield an input element in the output stream, map a stream generator on it
759+-- and then do the same on the resulting stream. This can be used for a depth
760+-- first traversal of a tree like structure.
761+--
762+-- Note that 'iterateM' is a special case of 'iterateMapWith':
763+--
764+-- @
765+-- iterateM f = iterateMapWith serial (yieldM . f) . yieldM
766+-- @
767+--
768+-- It can be used to traverse a tree structure. For example, to list a
769+-- directory tree:
770+--
771+-- @
772+-- Stream.iterateMapWith Stream.serial
773+-- (either Dir.toEither (const nil))
774+-- (yield (Left "tmp"))
775+-- @
776+--
777+-- /Internal/
778+--
779+{-# INLINE iterateMapWith #-}
780+iterateMapWith
781+ :: IsStream t
782+ => (t m a -> t m a -> t m a)
783+ -> (a -> t m a)
784+ -> t m a
785+ -> t m a
786+iterateMapWith combine f = concatMapWith combine go
787+ where
788+ go x = yield x `combine` concatMapWith combine go (f x)
789+
790+{-
791+{-# INLINE iterateUnfold #-}
792+iterateUnfold :: (IsStream t, MonadAsync m)
793+ => Unfold m a a -> t m a -> t m a
794+iterateUnfold unf xs = undefined
795+-}
796+
797+------------------------------------------------------------------------------
798+-- Flattening Graphs
799+------------------------------------------------------------------------------
800+
801+-- To traverse graphs we need a state to be carried around in the traversal.
802+-- For example, we can use a hashmap to store the visited status of nodes.
803+
804+-- | Like 'iterateMap' but carries a state in the stream generation function.
805+-- This can be used to traverse graph like structures, we can remember the
806+-- visited nodes in the state to avoid cycles.
807+--
808+-- Note that a combination of 'iterateMap' and 'usingState' can also be used to
809+-- traverse graphs. However, this function provides a more localized state
810+-- instead of using a global state.
811+--
812+-- See also: 'mfix'
813+--
814+-- /Internal/
815+--
816+{-# INLINE iterateSmapMWith #-}
817+iterateSmapMWith
818+ :: (IsStream t, Monad m)
819+ => (t m a -> t m a -> t m a)
820+ -> (b -> a -> m (b, t m a))
821+ -> m b
822+ -> t m a
823+ -> t m a
824+iterateSmapMWith combine f initial stream =
825+ concatMap (\b -> concatMapWith combine (go b) stream) (yieldM initial)
826+
827+ where
828+
829+ go b a = yield a `combine` feedback b a
830+
831+ feedback b a =
832+ concatMap
833+ (\(b1, s) -> concatMapWith combine (go b1) s)
834+ (yieldM $ f b a)
835+
836+------------------------------------------------------------------------------
837+-- iterateMap - Either streams
838+------------------------------------------------------------------------------
839+
840+-- | In an 'Either' stream iterate on 'Left's. This is a special case of
841+-- 'iterateMapWith':
842+--
843+-- @
844+-- iterateMapLeftsWith combine f = iterateMapWith combine (either f (const nil))
845+-- @
846+--
847+-- To traverse a directory tree:
848+--
849+-- @
850+-- iterateMapLeftsWith serial Dir.toEither (yield (Left "tmp"))
851+-- @
852+--
853+-- /Internal/
854+--
855+{-# INLINE iterateMapLeftsWith #-}
856+iterateMapLeftsWith
857+ :: IsStream t
858+ => (t m (Either a b) -> t m (Either a b) -> t m (Either a b))
859+ -> (a -> t m (Either a b))
860+ -> t m (Either a b)
861+ -> t m (Either a b)
862+iterateMapLeftsWith combine f = iterateMapWith combine (either f (const K.nil))
863+
864+------------------------------------------------------------------------------
865+-- Folding
866+------------------------------------------------------------------------------
867+
868+-- Splitting operations that take a predicate and a Fold can be
869+-- expressed using parseMany. Operations like chunksOf, intervalsOf, split*,
870+-- can be expressed using parseMany when used with an appropriate Parser.
871+--
872+-- XXX We need takeGE/takeBetween to implement "some" using "many".
873+
874+-- | Apply a 'Fold' repeatedly on a stream and emit the parsed values in the
875+-- output stream.
876+--
877+-- This is the streaming dual of the 'Streamly.Internal.Data.Fold.many'
878+-- parse combinator.
879+--
880+-- >>> f = Fold.ltake 2 Fold.sum
881+-- >>> Stream.toList $ Stream.foldMany f $ Stream.fromList [1..10]
882+-- > [3,7,11,15,19]
883+--
884+-- >>> f = Fold.sliceEndWith Fold.toList
885+-- >>> Stream.toList $ Stream.foldMany f $ Stream.fromList "hello\nworld"
886+-- > ["hello\n","world"]
887+--
888+-- /Internal/
889+--
890+{-# INLINE foldMany #-}
891+foldMany
892+ :: (IsStream t, Monad m)
893+ => Fold m a b
894+ -> t m a
895+ -> t m b
896+foldMany f m = D.fromStreamD $ D.foldMany f (D.toStreamD m)
897+
898+-- | Apply a stream of folds to an input stream and emit the results in the
899+-- output stream.
900+--
901+-- /Internal/
902+--
903+{-# INLINE foldSequence #-}
904+foldSequence
905+ :: -- (IsStream t, Monad m) =>
906+ t m (Fold m a b)
907+ -> t m a
908+ -> t m b
909+foldSequence _f _m = undefined
910+
911+-- | Iterate a fold generator on a stream. The initial value @b@ is used to
912+-- generate the first fold, the fold is applied on the stream and the result of
913+-- the fold is used to generate the next fold and so on.
914+--
915+-- >>> f x = Fold.ltake 2 (Fold.mconcatTo x)
916+-- >>> s = Stream.map Sum $ Stream.fromList [1..10]
917+-- >>> Stream.toList $ Stream.map getSum $ Stream.foldIterate f 0 s
918+-- > [3,10,21,36,55,55]
919+--
920+-- This is the streaming equivalent of monad like sequenced application of
921+-- folds where next fold is dependent on the previous fold.
922+--
923+-- /Internal/
924+--
925+{-# INLINE foldIterate #-}
926+foldIterate
927+ :: -- (IsStream t, Monad m) =>
928+ (b -> Fold m a b)
929+ -> b
930+ -> t m a
931+ -> t m b
932+foldIterate _f _i _m = undefined
933+-- D.fromStreamD $ D.foldIterate f i (D.toStreamD m)
934+
935+------------------------------------------------------------------------------
936+-- Parsing
937+------------------------------------------------------------------------------
938+
939+-- | Apply a 'Parser' repeatedly on a stream and emit the parsed values in the
940+-- output stream.
941+--
942+-- This is the streaming equivalent of the 'Streamly.Internal.Data.Parser.many'
943+-- parse combinator.
944+--
945+-- >>> S.toList $ S.parseMany (PR.take 2 $ PR.fromFold FL.sum) $ S.fromList [1..10]
946+-- > [3,7,11,15,19]
947+--
948+-- >>> S.toList $ S.parseMany (PR.line FL.toList) $ S.fromList "hello\nworld"
949+-- > ["hello\n","world"]
950+--
951+-- /Internal/
952+--
953+{-# INLINE parseMany #-}
954+parseMany
955+ :: (IsStream t, MonadThrow m)
956+ => Parser m a b
957+ -> t m a
958+ -> t m b
959+parseMany p m =
960+ D.fromStreamD $ D.parseMany (PRK.fromParserK p) (D.toStreamD m)
961+
962+{-# INLINE parseManyD #-}
963+parseManyD
964+ :: (IsStream t, MonadThrow m)
965+ => PRD.Parser m a b
966+ -> t m a
967+ -> t m b
968+parseManyD p m =
969+ D.fromStreamD $ D.parseMany p (D.toStreamD m)
970+
971+-- | Apply a stream of parsers to an input stream and emit the results in the
972+-- output stream.
973+--
974+-- /Internal/
975+--
976+{-# INLINE parseSequence #-}
977+parseSequence
978+ :: -- (IsStream t, Monad m) =>
979+ t m (Parser m a b)
980+ -> t m a
981+ -> t m b
982+parseSequence _f _m = undefined
983+
984+-- | @parseManyTill collect test stream@ tries the parser @test@ on the input,
985+-- if @test@ fails it backtracks and tries @collect@, after @collect@ succeeds
986+-- @test@ is tried again and so on. The parser stops when @test@ succeeds. The
987+-- output of @test@ is discarded and the output of @collect@ is emitted in the
988+-- output stream. The parser fails if @collect@ fails.
989+--
990+-- /Unimplemented/
991+--
992+{-# INLINE parseManyTill #-}
993+parseManyTill ::
994+ -- (IsStream t, MonadThrow m) =>
995+ Parser m a b
996+ -> Parser m a x
997+ -> t m a
998+ -> t m b
999+parseManyTill = undefined
1000+
1001+-- | Iterate a parser generating function on a stream. The initial value @b@ is
1002+-- used to generate the first parser, the parser is applied on the stream and
1003+-- the result is used to generate the next parser and so on.
1004+--
1005+-- >>> S.toList $ S.map getSum $ S.parseIterate (\b -> PR.take 2 (FL.mconcatTo b)) 0 $ S.map Sum $ S.fromList [1..10]
1006+-- > [3,10,21,36,55,55]
1007+--
1008+-- This is the streaming equivalent of monad like sequenced application of
1009+-- parsers where next parser is dependent on the previous parser.
1010+--
1011+-- /Internal/
1012+--
1013+{-# INLINE parseIterate #-}
1014+parseIterate
1015+ :: (IsStream t, MonadThrow m)
1016+ => (b -> Parser m a b)
1017+ -> b
1018+ -> t m a
1019+ -> t m b
1020+parseIterate f i m = D.fromStreamD $
1021+ D.parseIterate (PRK.fromParserK . f) i (D.toStreamD m)
1022+
1023+------------------------------------------------------------------------------
1024+-- Trimming
1025+------------------------------------------------------------------------------
1026+
1027+-- | Drop prefix from the input stream if present.
1028+--
1029+-- Space: @O(1)@
1030+--
1031+-- /Unimplemented/ - Help wanted.
1032+{-# INLINE dropPrefix #-}
1033+dropPrefix ::
1034+ -- (Eq a, IsStream t, Monad m) =>
1035+ t m a -> t m a -> t m a
1036+dropPrefix = error "Not implemented yet!"
1037+
1038+-- | Drop all matching infix from the input stream if present. Infix stream
1039+-- may be consumed multiple times.
1040+--
1041+-- Space: @O(n)@ where n is the length of the infix.
1042+--
1043+-- /Unimplemented/ - Help wanted.
1044+{-# INLINE dropInfix #-}
1045+dropInfix ::
1046+ -- (Eq a, IsStream t, Monad m) =>
1047+ t m a -> t m a -> t m a
1048+dropInfix = error "Not implemented yet!"
1049+
1050+-- | Drop suffix from the input stream if present. Suffix stream may be
1051+-- consumed multiple times.
1052+--
1053+-- Space: @O(n)@ where n is the length of the suffix.
1054+--
1055+-- /Unimplemented/ - Help wanted.
1056+{-# INLINE dropSuffix #-}
1057+dropSuffix ::
1058+ -- (Eq a, IsStream t, Monad m) =>
1059+ t m a -> t m a -> t m a
1060+dropSuffix = error "Not implemented yet!"
1061+
1062+------------------------------------------------------------------------------
1063+-- Generalized grouping
1064+------------------------------------------------------------------------------
1065+
1066+-- This combinator is the most general grouping combinator and can be used to
1067+-- implement all other grouping combinators.
1068+--
1069+-- XXX check if this can implement the splitOn combinator i.e. we can slide in
1070+-- new elements, slide out old elements and incrementally compute the hash.
1071+-- Also, can we implement the windowed classification combinators using this?
1072+--
1073+-- In fact this is a parse. Instead of using a special return value in the fold
1074+-- we are using a mapping function.
1075+--
1076+-- Note that 'scanl'' (usually followed by a map to extract the desired value
1077+-- from the accumulator) can be used to realize many implementations e.g. a
1078+-- sliding window implementation. A scan followed by a mapMaybe is also a good
1079+-- pattern to express many problems where we want to emit a filtered output and
1080+-- not emit an output on every input.
1081+--
1082+-- Passing on of the initial accumulator value to the next fold is equivalent
1083+-- to returning the leftover concept.
1084+
1085+{-
1086+-- | @groupScan splitter fold stream@ folds the input stream using @fold@.
1087+-- @splitter@ is applied on the accumulator of the fold every time an item is
1088+-- consumed by the fold. The fold continues until @splitter@ returns a 'Just'
1089+-- value. A 'Just' result from the @splitter@ specifies a result to be emitted
1090+-- in the output stream and the initial value of the accumulator for the next
1091+-- group's fold. This allows us to control whether to start fresh for the next
1092+-- fold or to continue from the previous fold's output.
1093+--
1094+{-# INLINE groupScan #-}
1095+groupScan
1096+ :: (IsStream t, Monad m)
1097+ => (x -> m (Maybe (b, x))) -> Fold m a x -> t m a -> t m b
1098+groupScan split fold m = undefined
1099+-}
1100+
1101+------------------------------------------------------------------------------
1102+-- Grouping
1103+------------------------------------------------------------------------------
1104+
1105+-- | @groupsBy cmp f $ S.fromList [a,b,c,...]@ assigns the element @a@ to the
1106+-- first group, if @b \`cmp` a@ is 'True' then @b@ is also assigned to the same
1107+-- group. If @c \`cmp` a@ is 'True' then @c@ is also assigned to the same
1108+-- group and so on. When the comparison fails a new group is started. Each
1109+-- group is folded using the fold @f@ and the result of the fold is emitted in
1110+-- the output stream.
1111+--
1112+-- >>> S.toList $ S.groupsBy (>) FL.toList $ S.fromList [1,3,7,0,2,5]
1113+-- > [[1,3,7],[0,2,5]]
1114+--
1115+-- @since 0.7.0
1116+{-# INLINE groupsBy #-}
1117+groupsBy
1118+ :: (IsStream t, Monad m)
1119+ => (a -> a -> Bool)
1120+ -> Fold m a b
1121+ -> t m a
1122+ -> t m b
1123+groupsBy cmp f m = D.fromStreamD $ D.groupsBy cmp f (D.toStreamD m)
1124+
1125+-- | Unlike @groupsBy@ this function performs a rolling comparison of two
1126+-- successive elements in the input stream. @groupsByRolling cmp f $ S.fromList
1127+-- [a,b,c,...]@ assigns the element @a@ to the first group, if @a \`cmp` b@ is
1128+-- 'True' then @b@ is also assigned to the same group. If @b \`cmp` c@ is
1129+-- 'True' then @c@ is also assigned to the same group and so on. When the
1130+-- comparison fails a new group is started. Each group is folded using the fold
1131+-- @f@.
1132+--
1133+-- >>> S.toList $ S.groupsByRolling (\a b -> a + 1 == b) FL.toList $ S.fromList [1,2,3,7,8,9]
1134+-- > [[1,2,3],[7,8,9]]
1135+--
1136+-- @since 0.7.0
1137+{-# INLINE groupsByRolling #-}
1138+groupsByRolling
1139+ :: (IsStream t, Monad m)
1140+ => (a -> a -> Bool)
1141+ -> Fold m a b
1142+ -> t m a
1143+ -> t m b
1144+groupsByRolling cmp f m = D.fromStreamD $ D.groupsRollingBy cmp f (D.toStreamD m)
1145+
1146+-- |
1147+-- > groups = groupsBy (==)
1148+-- > groups = groupsByRolling (==)
1149+--
1150+-- Groups contiguous spans of equal elements together in individual groups.
1151+--
1152+-- >>> S.toList $ S.groups FL.toList $ S.fromList [1,1,2,2]
1153+-- > [[1,1],[2,2]]
1154+--
1155+-- @since 0.7.0
1156+{-# INLINE groups #-}
1157+groups :: (IsStream t, Monad m, Eq a) => Fold m a b -> t m a -> t m b
1158+groups = groupsBy (==)
1159+
1160+------------------------------------------------------------------------------
1161+-- Splitting - by a predicate
1162+------------------------------------------------------------------------------
1163+
1164+-- TODO: Use a Splitter configuration similar to the "split" package to make it
1165+-- possible to express all splitting combinations. In general, we can have
1166+-- infix/suffix/prefix/condensing of separators, dropping both leading/trailing
1167+-- separators. We can have a single split operation taking the splitter config
1168+-- as argument.
1169+
1170+-- | Split on an infixed separator element, dropping the separator. Splits the
1171+-- stream on separator elements determined by the supplied predicate, separator
1172+-- is considered as infixed between two segments, if one side of the separator
1173+-- is missing then it is parsed as an empty stream. The supplied 'Fold' is
1174+-- applied on the split segments. With '-' representing non-separator elements
1175+-- and '.' as separator, 'splitOn' splits as follows:
1176+--
1177+-- @
1178+-- "--.--" => "--" "--"
1179+-- "--." => "--" ""
1180+-- ".--" => "" "--"
1181+-- @
1182+--
1183+-- @splitOn (== x)@ is an inverse of @intercalate (S.yield x)@
1184+--
1185+-- Let's use the following definition for illustration:
1186+--
1187+-- > splitOn' p xs = S.toList $ S.splitOn p (FL.toList) (S.fromList xs)
1188+--
1189+-- >>> splitOn' (== '.') ""
1190+-- [""]
1191+--
1192+-- >>> splitOn' (== '.') "."
1193+-- ["",""]
1194+--
1195+-- >>> splitOn' (== '.') ".a"
1196+-- > ["","a"]
1197+--
1198+-- >>> splitOn' (== '.') "a."
1199+-- > ["a",""]
1200+--
1201+-- >>> splitOn' (== '.') "a.b"
1202+-- > ["a","b"]
1203+--
1204+-- >>> splitOn' (== '.') "a..b"
1205+-- > ["a","","b"]
1206+--
1207+-- @since 0.7.0
1208+
1209+-- This can be considered as an n-fold version of 'breakOn' where we apply
1210+-- 'breakOn' successively on the input stream, dropping the first element
1211+-- of the second segment after each break.
1212+--
1213+{-# INLINE splitOn #-}
1214+splitOn
1215+ :: (IsStream t, Monad m)
1216+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
1217+splitOn predicate f = foldMany (FL.sliceSepBy predicate f)
1218+
1219+-- | Like 'splitOn' but the separator is considered as suffixed to the segments
1220+-- in the stream. A missing suffix at the end is allowed. A separator at the
1221+-- beginning is parsed as empty segment. With '-' representing elements and
1222+-- '.' as separator, 'splitOnSuffix' splits as follows:
1223+--
1224+-- @
1225+-- "--.--." => "--" "--"
1226+-- "--.--" => "--" "--"
1227+-- ".--." => "" "--"
1228+-- @
1229+--
1230+-- > splitOnSuffix' p xs = S.toList $ S.splitSuffixBy p (FL.toList) (S.fromList xs)
1231+--
1232+-- >>> splitOnSuffix' (== '.') ""
1233+-- []
1234+--
1235+-- >>> splitOnSuffix' (== '.') "."
1236+-- [""]
1237+--
1238+-- >>> splitOnSuffix' (== '.') "a"
1239+-- ["a"]
1240+--
1241+-- >>> splitOnSuffix' (== '.') ".a"
1242+-- > ["","a"]
1243+--
1244+-- >>> splitOnSuffix' (== '.') "a."
1245+-- > ["a"]
1246+--
1247+-- >>> splitOnSuffix' (== '.') "a.b"
1248+-- > ["a","b"]
1249+--
1250+-- >>> splitOnSuffix' (== '.') "a.b."
1251+-- > ["a","b"]
1252+--
1253+-- >>> splitOnSuffix' (== '.') "a..b.."
1254+-- > ["a","","b",""]
1255+--
1256+-- > lines = splitOnSuffix (== '\n')
1257+--
1258+-- @since 0.7.0
1259+
1260+-- This can be considered as an n-fold version of 'breakPost' where we apply
1261+-- 'breakPost' successively on the input stream, dropping the first element
1262+-- of the second segment after each break.
1263+--
1264+{-# INLINE splitOnSuffix #-}
1265+splitOnSuffix
1266+ :: (IsStream t, Monad m)
1267+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
1268+splitOnSuffix predicate f m =
1269+ D.fromStreamD $ D.foldMany1 (FL.sliceSepBy predicate f) (D.toStreamD m)
1270+
1271+-- | Like 'splitOn' after stripping leading, trailing, and repeated separators.
1272+-- Therefore, @".a..b."@ with '.' as the separator would be parsed as
1273+-- @["a","b"]@. In other words, its like parsing words from whitespace
1274+-- separated text.
1275+--
1276+-- > wordsBy' p xs = S.toList $ S.wordsBy p (FL.toList) (S.fromList xs)
1277+--
1278+-- >>> wordsBy' (== ',') ""
1279+-- > []
1280+--
1281+-- >>> wordsBy' (== ',') ","
1282+-- > []
1283+--
1284+-- >>> wordsBy' (== ',') ",a,,b,"
1285+-- > ["a","b"]
1286+--
1287+-- > words = wordsBy isSpace
1288+--
1289+-- @since 0.7.0
1290+
1291+-- It is equivalent to splitting in any of the infix/prefix/suffix styles
1292+-- followed by removal of empty segments.
1293+{-# INLINE wordsBy #-}
1294+wordsBy
1295+ :: (IsStream t, Monad m)
1296+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
1297+wordsBy predicate f m =
1298+ D.fromStreamD $ D.wordsBy predicate f (D.toStreamD m)
1299+
1300+-- | Like 'splitOnSuffix' but keeps the suffix attached to the resulting
1301+-- splits.
1302+--
1303+-- > splitWithSuffix' p xs = S.toList $ S.splitWithSuffix p (FL.toList) (S.fromList xs)
1304+--
1305+-- >>> splitWithSuffix' (== '.') ""
1306+-- []
1307+--
1308+-- >>> splitWithSuffix' (== '.') "."
1309+-- ["."]
1310+--
1311+-- >>> splitWithSuffix' (== '.') "a"
1312+-- ["a"]
1313+--
1314+-- >>> splitWithSuffix' (== '.') ".a"
1315+-- > [".","a"]
1316+--
1317+-- >>> splitWithSuffix' (== '.') "a."
1318+-- > ["a."]
1319+--
1320+-- >>> splitWithSuffix' (== '.') "a.b"
1321+-- > ["a.","b"]
1322+--
1323+-- >>> splitWithSuffix' (== '.') "a.b."
1324+-- > ["a.","b."]
1325+--
1326+-- >>> splitWithSuffix' (== '.') "a..b.."
1327+-- > ["a.",".","b.","."]
1328+--
1329+-- @since 0.7.0
1330+
1331+-- This can be considered as an n-fold version of 'breakPost' where we apply
1332+-- 'breakPost' successively on the input stream.
1333+--
1334+{-# INLINE splitWithSuffix #-}
1335+splitWithSuffix
1336+ :: (IsStream t, Monad m)
1337+ => (a -> Bool) -> Fold m a b -> t m a -> t m b
1338+splitWithSuffix predicate f m =
1339+ D.fromStreamD $ D.foldMany1 (FL.sliceEndWith predicate f) (D.toStreamD m)
1340+
1341+------------------------------------------------------------------------------
1342+-- Splitting - on a delimiter sequence
1343+------------------------------------------------------------------------------
1344+
1345+-- Int list examples for splitOn:
1346+--
1347+-- >>> splitList [] [1,2,3,3,4]
1348+-- > [[1],[2],[3],[3],[4]]
1349+--
1350+-- >>> splitList [5] [1,2,3,3,4]
1351+-- > [[1,2,3,3,4]]
1352+--
1353+-- >>> splitList [1] [1,2,3,3,4]
1354+-- > [[],[2,3,3,4]]
1355+--
1356+-- >>> splitList [4] [1,2,3,3,4]
1357+-- > [[1,2,3,3],[]]
1358+--
1359+-- >>> splitList [2] [1,2,3,3,4]
1360+-- > [[1],[3,3,4]]
1361+--
1362+-- >>> splitList [3] [1,2,3,3,4]
1363+-- > [[1,2],[],[4]]
1364+--
1365+-- >>> splitList [3,3] [1,2,3,3,4]
1366+-- > [[1,2],[4]]
1367+--
1368+-- >>> splitList [1,2,3,3,4] [1,2,3,3,4]
1369+-- > [[],[]]
1370+
1371+{-
1372+-- This can be implemented easily using Rabin Karp
1373+-- | Split on any one of the given patterns.
1374+{-# INLINE splitOnAny #-}
1375+splitOnAny
1376+ :: (IsStream t, Monad m, Storable a, Integral a)
1377+ => [Array a] -> Fold m a b -> t m a -> t m b
1378+splitOnAny subseq f m = undefined -- D.fromStreamD $ D.splitOnAny f subseq (D.toStreamD m)
1379+-}
1380+
1381+-- XXX use a non-monadic intersperse to remove the MonadAsync constraint.
1382+--
1383+-- | Like 'splitOnSeq' but splits the separator as well, as an infix token.
1384+--
1385+-- > splitOn'_ pat xs = S.toList $ S.splitOn' (A.fromList pat) (FL.toList) (S.fromList xs)
1386+--
1387+-- >>> splitOn'_ "" "hello"
1388+-- > ["h","","e","","l","","l","","o"]
1389+--
1390+-- >>> splitOn'_ "hello" ""
1391+-- > [""]
1392+--
1393+-- >>> splitOn'_ "hello" "hello"
1394+-- > ["","hello",""]
1395+--
1396+-- >>> splitOn'_ "x" "hello"
1397+-- > ["hello"]
1398+--
1399+-- >>> splitOn'_ "h" "hello"
1400+-- > ["","h","ello"]
1401+--
1402+-- >>> splitOn'_ "o" "hello"
1403+-- > ["hell","o",""]
1404+--
1405+-- >>> splitOn'_ "e" "hello"
1406+-- > ["h","e","llo"]
1407+--
1408+-- >>> splitOn'_ "l" "hello"
1409+-- > ["he","l","","l","o"]
1410+--
1411+-- >>> splitOn'_ "ll" "hello"
1412+-- > ["he","ll","o"]
1413+--
1414+-- /Internal/
1415+{-# INLINE splitBySeq #-}
1416+splitBySeq
1417+ :: (IsStream t, MonadAsync m, Storable a, Enum a, Eq a)
1418+ => Array a -> Fold m a b -> t m a -> t m b
1419+splitBySeq patt f m =
1420+ intersperseM (fold f (A.toStream patt)) $ splitOnSeq patt f m
1421+
1422+-- | Like 'splitSuffixBy' but the separator is a sequence of elements, instead
1423+-- of a predicate for a single element.
1424+--
1425+-- > splitOnSuffixSeq_ pat xs = S.toList $ S.splitOnSuffixSeq (A.fromList pat) (FL.toList) (S.fromList xs)
1426+--
1427+-- >>> splitOnSuffixSeq_ "." ""
1428+-- []
1429+--
1430+-- >>> splitOnSuffixSeq_ "." "."
1431+-- [""]
1432+--
1433+-- >>> splitOnSuffixSeq_ "." "a"
1434+-- ["a"]
1435+--
1436+-- >>> splitOnSuffixSeq_ "." ".a"
1437+-- > ["","a"]
1438+--
1439+-- >>> splitOnSuffixSeq_ "." "a."
1440+-- > ["a"]
1441+--
1442+-- >>> splitOnSuffixSeq_ "." "a.b"
1443+-- > ["a","b"]
1444+--
1445+-- >>> splitOnSuffixSeq_ "." "a.b."
1446+-- > ["a","b"]
1447+--
1448+-- >>> splitOnSuffixSeq_ "." "a..b.."
1449+-- > ["a","","b",""]
1450+--
1451+-- > lines = splitOnSuffixSeq "\n"
1452+--
1453+-- 'splitOnSuffixSeq' is an inverse of 'intercalateSuffix'. The following law
1454+-- always holds:
1455+--
1456+-- > intercalateSuffix . splitOnSuffixSeq == id
1457+--
1458+-- The following law holds when the separator is non-empty and contains none of
1459+-- the elements present in the input lists:
1460+--
1461+-- > splitSuffixOn . intercalateSuffix == id
1462+--
1463+-- /Internal/
1464+{-# INLINE splitOnSuffixSeq #-}
1465+splitOnSuffixSeq
1466+ :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
1467+ => Array a -> Fold m a b -> t m a -> t m b
1468+splitOnSuffixSeq patt f m =
1469+ D.fromStreamD $ D.splitOnSuffixSeq False patt f (D.toStreamD m)
1470+
1471+{-
1472+-- | Like 'splitOn' but drops any empty splits.
1473+--
1474+{-# INLINE wordsOn #-}
1475+wordsOn
1476+ :: (IsStream t, Monad m, Storable a, Eq a)
1477+ => Array a -> Fold m a b -> t m a -> t m b
1478+wordsOn subseq f m = undefined -- D.fromStreamD $ D.wordsOn f subseq (D.toStreamD m)
1479+-}
1480+
1481+-- | Like 'splitOnSuffixSeq' but keeps the suffix intact in the splits.
1482+--
1483+-- > splitWithSuffixSeq'_ pat xs = S.toList $ S.splitWithSuffixSeq (A.fromList pat) (FL.toList) (S.fromList xs)
1484+--
1485+-- >>> splitWithSuffixSeq' "." ""
1486+-- [""]
1487+--
1488+-- >>> splitWithSuffixSeq' "." "."
1489+-- ["."]
1490+--
1491+-- >>> splitWithSuffixSeq' "." "a"
1492+-- ["a"]
1493+--
1494+-- >>> splitWithSuffixSeq' "." ".a"
1495+-- > [".","a"]
1496+--
1497+-- >>> splitWithSuffixSeq' "." "a."
1498+-- > ["a."]
1499+--
1500+-- >>> splitWithSuffixSeq' "." "a.b"
1501+-- > ["a.","b"]
1502+--
1503+-- >>> splitWithSuffixSeq' "." "a.b."
1504+-- > ["a.","b."]
1505+--
1506+-- >>> splitWithSuffixSeq' "." "a..b.."
1507+-- > ["a.",".","b.","."]
1508+--
1509+-- /Internal/
1510+{-# INLINE splitWithSuffixSeq #-}
1511+splitWithSuffixSeq
1512+ :: (IsStream t, MonadIO m, Storable a, Enum a, Eq a)
1513+ => Array a -> Fold m a b -> t m a -> t m b
1514+splitWithSuffixSeq patt f m =
1515+ D.fromStreamD $ D.splitOnSuffixSeq True patt f (D.toStreamD m)
1516+
1517+{-
1518+-- This can be implemented easily using Rabin Karp
1519+-- | Split post any one of the given patterns.
1520+{-# INLINE splitOnSuffixSeqAny #-}
1521+splitOnSuffixSeqAny
1522+ :: (IsStream t, Monad m, Storable a, Integral a)
1523+ => [Array a] -> Fold m a b -> t m a -> t m b
1524+splitOnSuffixSeqAny subseq f m = undefined
1525+ -- D.fromStreamD $ D.splitPostAny f subseq (D.toStreamD m)
1526+-}
1527+
1528+------------------------------------------------------------------------------
1529+-- Chunking
1530+------------------------------------------------------------------------------
1531+
1532+-- | Group the input stream into groups of @n@ elements each and then fold each
1533+-- group using the provided fold function.
1534+--
1535+-- >> S.toList $ S.chunksOf 2 FL.sum (S.enumerateFromTo 1 10)
1536+-- > [3,7,11,15,19]
1537+--
1538+-- This can be considered as an n-fold version of 'ltake' where we apply
1539+-- 'ltake' repeatedly on the leftover stream until the stream exhausts.
1540+--
1541+-- @since 0.7.0
1542+{-# INLINE chunksOf #-}
1543+chunksOf
1544+ :: (IsStream t, Monad m)
1545+ => Int -> Fold m a b -> t m a -> t m b
1546+chunksOf n f = foldMany (FL.ltake n f)
1547+
1548+-- |
1549+--
1550+-- /Internal/
1551+{-# INLINE chunksOf2 #-}
1552+chunksOf2
1553+ :: (IsStream t, Monad m)
1554+ => Int -> m c -> Fold2 m c a b -> t m a -> t m b
1555+chunksOf2 n action f m = D.fromStreamD $ D.groupsOf2 n action f (D.toStreamD m)
1556+
1557+-- | @arraysOf n stream@ groups the elements in the input stream into arrays of
1558+-- @n@ elements each.
1559+--
1560+-- Same as the following but may be more efficient:
1561+--
1562+-- > arraysOf n = S.chunksOf n (A.writeN n)
1563+--
1564+-- /Internal/
1565+{-# INLINE arraysOf #-}
1566+arraysOf :: (IsStream t, MonadIO m, Storable a)
1567+ => Int -> t m a -> t m (Array a)
1568+arraysOf n = chunksOf n (writeNUnsafe n)
1569+
1570+-- XXX we can implement this by repeatedly applying the 'lrunFor' fold.
1571+-- XXX add this example after fixing the serial stream rate control
1572+-- >>> S.toList $ S.take 5 $ intervalsOf 1 FL.sum $ constRate 2 $ S.enumerateFrom 1
1573+-- > [3,7,11,15,19]
1574+--
1575+-- | Group the input stream into windows of @n@ second each and then fold each
1576+-- group using the provided fold function.
1577+--
1578+-- @since 0.7.0
1579+{-# INLINE intervalsOf #-}
1580+intervalsOf
1581+ :: (IsStream t, MonadAsync m)
1582+ => Double -> Fold m a b -> t m a -> t m b
1583+intervalsOf n f xs =
1584+ splitWithSuffix isNothing (FL.lcatMaybes f)
1585+ (interjectSuffix n (return Nothing) (Serial.map Just xs))
1586+
1587+------------------------------------------------------------------------------
1588+-- Windowed classification
1589+------------------------------------------------------------------------------
1590+
1591+-- We divide the stream into windows or chunks in space or time and each window
1592+-- can be associated with a key, all events associated with a particular key in
1593+-- the window can be folded to a single result. The stream can be split into
1594+-- windows by size or by using a split predicate on the elements in the stream.
1595+-- For example, when we receive a closing flag, we can close the window.
1596+--
1597+-- A "chunk" is a space window and a "session" is a time window. Are there any
1598+-- other better short words to describe them. An alternative is to use
1599+-- "swindow" and "twindow". Another word for "session" could be "spell".
1600+--
1601+-- TODO: To mark the position in space or time we can have Indexed or
1602+-- TimeStamped types. That can make it easy to deal with the position indices
1603+-- or timestamps.
1604+
1605+------------------------------------------------------------------------------
1606+-- Keyed Sliding Windows
1607+------------------------------------------------------------------------------
1608+
1609+{-
1610+{-# INLINABLE classifySlidingChunks #-}
1611+classifySlidingChunks
1612+ :: (IsStream t, MonadAsync m, Ord k)
1613+ => Int -- ^ window size
1614+ -> Int -- ^ window slide
1615+ -> Fold m a b -- ^ Fold to be applied to window events
1616+ -> t m (k, a, Bool) -- ^ window key, data, close event
1617+ -> t m (k, b)
1618+classifySlidingChunks wsize wslide (Fold step initial extract) str
1619+ = undefined
1620+
1621+-- XXX Another variant could be to slide the window on an event, e.g. in TCP we
1622+-- slide the send window when an ack is received and we slide the receive
1623+-- window when a sequence is complete. Sliding is stateful in case of TCP,
1624+-- sliding releases the send buffer or makes data available to the user from
1625+-- the receive buffer.
1626+{-# INLINABLE classifySlidingSessions #-}
1627+classifySlidingSessions
1628+ :: (IsStream t, MonadAsync m, Ord k)
1629+ => Double -- ^ timer tick in seconds
1630+ -> Double -- ^ time window size
1631+ -> Double -- ^ window slide
1632+ -> Fold m a b -- ^ Fold to be applied to window events
1633+ -> t m (k, a, Bool, AbsTime) -- ^ window key, data, close flag, timestamp
1634+ -> t m (k, b)
1635+classifySlidingSessions tick interval slide (Fold step initial extract) str
1636+ = undefined
1637+-}
1638+
1639+------------------------------------------------------------------------------
1640+-- Sliding Window Buffers
1641+------------------------------------------------------------------------------
1642+
1643+-- These buffered versions could be faster than concurrent incremental folds of
1644+-- all overlapping windows as in many cases we may not need all the values to
1645+-- compute the fold, we can just compute the result using the old value and new
1646+-- value. However, we may need the buffer once in a while, for example for
1647+-- string search we usually compute the hash incrementally but when the hash
1648+-- matches the hash of the pattern we need to compare the whole string.
1649+--
1650+-- XXX we should be able to implement sequence based splitting combinators
1651+-- using this combinator.
1652+
1653+{-
1654+-- | Buffer n elements of the input in a ring buffer. When t new elements are
1655+-- collected, slide the window to remove the same number of oldest elements,
1656+-- insert the new elements, and apply an incremental fold on the sliding
1657+-- window, supplying the outgoing elements, the new ring buffer as arguments.
1658+slidingChunkBuffer
1659+ :: (IsStream t, Monad m, Ord a, Storable a)
1660+ => Int -- window size
1661+ -> Int -- window slide
1662+ -> Fold m (Ring a, Array a) b
1663+ -> t m a
1664+ -> t m b
1665+slidingChunkBuffer = undefined
1666+
1667+-- Buffer n seconds worth of stream elements of the input in a radix tree.
1668+-- Every t seconds, remove the items that are older than n seconds, and apply
1669+-- an incremental fold on the sliding window, supplying the outgoing elements,
1670+-- and the new radix tree buffer as arguments.
1671+slidingSessionBuffer
1672+ :: (IsStream t, Monad m, Ord a, Storable a)
1673+ => Int -- window size
1674+ -> Int -- tick size
1675+ -> Fold m (RTree a, Array a) b
1676+ -> t m a
1677+ -> t m b
1678+slidingSessionBuffer = undefined
1679+-}
1680+
1681+------------------------------------------------------------------------------
1682+-- Keyed Session Windows
1683+------------------------------------------------------------------------------
1684+
1685+{-
1686+-- | Keyed variable size space windows. Close the window if we do not receive a
1687+-- window event in the next "spaceout" elements.
1688+{-# INLINABLE classifyChunksBy #-}
1689+classifyChunksBy
1690+ :: (IsStream t, MonadAsync m, Ord k)
1691+ => Int -- ^ window spaceout (spread)
1692+ -> Bool -- ^ reset the spaceout when a chunk window element is received
1693+ -> Fold m a b -- ^ Fold to be applied to chunk window elements
1694+ -> t m (k, a, Bool) -- ^ chunk key, data, last element
1695+ -> t m (k, b)
1696+classifyChunksBy spanout reset (Fold step initial extract) str = undefined
1697+
1698+-- | Like 'classifyChunksOf' but the chunk size is reset if an element is
1699+-- received within the chunk size window. The chunk gets closed only if no
1700+-- element is received within the chunk window.
1701+--
1702+{-# INLINABLE classifyKeepAliveChunks #-}
1703+classifyKeepAliveChunks
1704+ :: (IsStream t, MonadAsync m, Ord k)
1705+ => Int -- ^ window spaceout (spread)
1706+ -> Fold m a b -- ^ Fold to be applied to chunk window elements
1707+ -> t m (k, a, Bool) -- ^ chunk key, data, last element
1708+ -> t m (k, b)
1709+classifyKeepAliveChunks spanout = classifyChunksBy spanout True
1710+-}
1711+
1712+data SessionState t m k a b = SessionState
1713+ { sessionCurTime :: !AbsTime -- ^ time since last event
1714+ , sessionEventTime :: !AbsTime -- ^ time as per last event
1715+ , sessionCount :: !Int -- ^ total number sessions in progress
1716+ , sessionTimerHeap :: H.Heap (H.Entry AbsTime k) -- ^ heap for timeouts
1717+ , sessionKeyValueMap :: Map.Map k a -- ^ Stored sessions for keys
1718+ , sessionOutputStream :: t (m :: Type -> Type) (k, b) -- ^ Completed sessions
1719+ }
1720+
1721+-- XXX Perhaps we should use an "Event a" type to represent timestamped data.
1722+-- | @classifySessionsBy tick timeout idle pred f stream@ groups timestamped
1723+-- events in an input event stream into sessions based on a session key. Each
1724+-- element in the input stream is an event consisting of a triple @(session key,
1725+-- sesssion data, timestamp)@. @session key@ is a key that uniquely identifies
1726+-- the session. All the events belonging to a session are folded using the fold
1727+-- @f@ until the fold terminates or a timeout has occurred. The session key and
1728+-- the result of the fold are emitted in the output stream when the session is
1729+-- purged.
1730+--
1731+-- When @idle@ is 'False', @timeout@ is the maximum lifetime of a session in
1732+-- seconds, measured from the @timestamp@ of the first event in that session.
1733+-- When @idle@ is 'True' then the timeout is an idle timeout, it is reset after
1734+-- every event received in the session.
1735+--
1736+-- @timestamp@ in an event characterizes the time when the input event was
1737+-- generated, this is an absolute time measured from some @Epoch@. The notion
1738+-- of current time is maintained by a monotonic event time clock using the
1739+-- timestamps seen in the input stream. The latest timestamp seen till now is
1740+-- used as the base for the current time. When no new events are seen, a timer
1741+-- is started with a tick duration specified by @tick@. This timer is used to
1742+-- detect session timeouts in the absence of new events.
1743+--
1744+-- The predicate @pred@ is invoked with the current session count, if it
1745+-- returns 'True' a session is ejected from the session cache before inserting
1746+-- a new session. This could be useful to alert or eject sessions when the
1747+-- number of sessions becomes too high.
1748+--
1749+-- /Internal/
1750+--
1751+{-# INLINABLE classifySessionsBy #-}
1752+classifySessionsBy
1753+ :: (IsStream t, MonadAsync m, Ord k)
1754+ => Double -- ^ timer tick in seconds
1755+ -> Double -- ^ session timeout in seconds
1756+ -> Bool -- ^ reset the timeout when an event is received
1757+ -> (Int -> m Bool) -- ^ predicate to eject sessions based on session count
1758+ -> Fold m a b -- ^ Fold to be applied to session events
1759+ -> t m (k, a, AbsTime) -- ^ session key, data, timestamp
1760+ -> t m (k, b) -- ^ session key, fold result
1761+classifySessionsBy tick tmout reset ejectPred
1762+ (Fold step initial extract) str =
1763+ concatMap sessionOutputStream $
1764+ scanlMAfter' sstep (return szero) flush stream
1765+
1766+ where
1767+
1768+ timeoutMs = toRelTime (round (tmout * 1000) :: MilliSecond64)
1769+ tickMs = toRelTime (round (tick * 1000) :: MilliSecond64)
1770+ szero = SessionState
1771+ { sessionCurTime = toAbsTime (0 :: MilliSecond64)
1772+ , sessionEventTime = toAbsTime (0 :: MilliSecond64)
1773+ , sessionCount = 0
1774+ , sessionTimerHeap = H.empty
1775+ , sessionKeyValueMap = Map.empty
1776+ , sessionOutputStream = K.nil
1777+ }
1778+
1779+ -- We can eject sessions based on the current session count to limit
1780+ -- memory consumption. There are two possible strategies:
1781+ --
1782+ -- 1) Eject old sessions or sessions beyond a certain/lower timeout
1783+ -- threshold even before timeout, effectively reduce the timeout.
1784+ -- 2) Drop creation of new sessions but keep accepting new events for the
1785+ -- old ones.
1786+ --
1787+ -- We use the first strategy as of now.
1788+
1789+ -- Got a new stream input element
1790+ sstep session@SessionState{..} (Just (key, value, timestamp)) = do
1791+ -- XXX we should use a heap in pinned memory to scale it to a large
1792+ -- size
1793+ --
1794+ -- To detect session inactivity we keep a timestamp of the latest event
1795+ -- in the Map along with the fold result. When we purge the session
1796+ -- from the heap we match the timestamp in the heap with the timestamp
1797+ -- in the Map, if the latest timestamp is newer and has not expired we
1798+ -- reinsert the key in the heap.
1799+ --
1800+ -- XXX if the key is an Int, we can also use an IntMap for slightly
1801+ -- better performance.
1802+ --
1803+ let curTime = max sessionEventTime timestamp
1804+ mOld = Map.lookup key sessionKeyValueMap
1805+
1806+ fs <-
1807+ case mOld of
1808+ Nothing -> initial
1809+ Just (Tuple' _ acc) -> return acc
1810+ res <- step fs value
1811+ case res of
1812+ FL.Done fb -> do
1813+ -- deleting a key from the heap is expensive, so we never
1814+ -- delete a key from heap, we just purge it from the Map and it
1815+ -- gets purged from the heap on timeout. We just need an extra
1816+ -- lookup in the Map when the key is purged from the heap, that
1817+ -- should not be expensive.
1818+ --
1819+ let (mp, cnt) = case mOld of
1820+ Nothing -> (sessionKeyValueMap, sessionCount)
1821+ Just _ -> (Map.delete key sessionKeyValueMap
1822+ , sessionCount - 1)
1823+ return $ session
1824+ { sessionCurTime = curTime
1825+ , sessionEventTime = curTime
1826+ , sessionCount = cnt
1827+ , sessionKeyValueMap = mp
1828+ , sessionOutputStream = yield (key, fb)
1829+ }
1830+ FL.Partial fs1 -> do
1831+ let acc = Tuple' timestamp fs1
1832+ (hp1, mp1, out1, cnt1) <- do
1833+ let vars = (sessionTimerHeap, sessionKeyValueMap,
1834+ K.nil, sessionCount)
1835+ case mOld of
1836+ -- inserting new entry
1837+ Nothing -> do
1838+ -- Eject a session from heap and map is needed
1839+ eject <- ejectPred sessionCount
1840+ (hp, mp, out, cnt) <-
1841+ if eject
1842+ then ejectOne vars
1843+ else return vars
1844+
1845+ -- Insert the new session in heap
1846+ let expiry = addToAbsTime timestamp timeoutMs
1847+ hp' = H.insert (Entry expiry key) hp
1848+ in return (hp', mp, out, cnt + 1)
1849+ -- updating old entry
1850+ Just _ -> return vars
1851+
1852+ let mp2 = Map.insert key acc mp1
1853+ return $ SessionState
1854+ { sessionCurTime = curTime
1855+ , sessionEventTime = curTime
1856+ , sessionCount = cnt1
1857+ , sessionTimerHeap = hp1
1858+ , sessionKeyValueMap = mp2
1859+ , sessionOutputStream = out1
1860+ }
1861+
1862+ -- Got a timer tick event
1863+ sstep sessionState@SessionState{..} Nothing =
1864+ let curTime = addToAbsTime sessionCurTime tickMs
1865+ in ejectExpired sessionState curTime
1866+
1867+ flush session@SessionState{..} = do
1868+ (hp', mp', out, count) <-
1869+ ejectAll
1870+ ( sessionTimerHeap
1871+ , sessionKeyValueMap
1872+ , K.nil
1873+ , sessionCount
1874+ )
1875+ return $ session
1876+ { sessionCount = count
1877+ , sessionTimerHeap = hp'
1878+ , sessionKeyValueMap = mp'
1879+ , sessionOutputStream = out
1880+ }
1881+
1882+ -- delete from map and output the fold accumulator
1883+ ejectEntry hp mp out cnt acc key = do
1884+ sess <- extract acc
1885+ let out1 = (key, sess) `K.cons` out
1886+ let mp1 = Map.delete key mp
1887+ return (hp, mp1, out1, cnt - 1)
1888+
1889+ ejectAll (hp, mp, out, !cnt) = do
1890+ let hres = H.uncons hp
1891+ case hres of
1892+ Just (Entry _ key, hp1) -> do
1893+ r <- case Map.lookup key mp of
1894+ Nothing -> return (hp1, mp, out, cnt)
1895+ Just (Tuple' _ acc) -> ejectEntry hp1 mp out cnt acc key
1896+ ejectAll r
1897+ Nothing -> do
1898+ assert (Map.null mp) (return ())
1899+ return (hp, mp, out, cnt)
1900+
1901+ ejectOne (hp, mp, out, !cnt) = do
1902+ let hres = H.uncons hp
1903+ case hres of
1904+ Just (Entry expiry key, hp1) ->
1905+ case Map.lookup key mp of
1906+ Nothing -> ejectOne (hp1, mp, out, cnt)
1907+ Just (Tuple' latestTS acc) -> do
1908+ let expiry1 = addToAbsTime latestTS timeoutMs
1909+ if not reset || expiry1 <= expiry
1910+ then ejectEntry hp1 mp out cnt acc key
1911+ else
1912+ -- reset the session timeout and continue
1913+ let hp2 = H.insert (Entry expiry1 key) hp1
1914+ in ejectOne (hp2, mp, out, cnt)
1915+ Nothing -> do
1916+ assert (Map.null mp) (return ())
1917+ return (hp, mp, out, cnt)
1918+
1919+ ejectExpired session@SessionState{..} curTime = do
1920+ (hp', mp', out, count) <-
1921+ ejectLoop sessionTimerHeap sessionKeyValueMap K.nil sessionCount
1922+ return $ session
1923+ { sessionCurTime = curTime
1924+ , sessionCount = count
1925+ , sessionTimerHeap = hp'
1926+ , sessionKeyValueMap = mp'
1927+ , sessionOutputStream = out
1928+ }
1929+
1930+ where
1931+
1932+ ejectLoop hp mp out !cnt = do
1933+ let hres = H.uncons hp
1934+ case hres of
1935+ Just (Entry expiry key, hp1) -> do
1936+ (eject, force) <-
1937+ if curTime >= expiry
1938+ then return (True, False)
1939+ else do
1940+ r <- ejectPred cnt
1941+ return (r, r)
1942+ if eject
1943+ then
1944+ case Map.lookup key mp of
1945+ Nothing -> ejectLoop hp1 mp out cnt
1946+ Just (Tuple' latestTS acc) -> do
1947+ let expiry1 = addToAbsTime latestTS timeoutMs
1948+ if expiry1 <= curTime || not reset || force
1949+ then do
1950+ (hp2,mp1,out1,cnt1) <-
1951+ ejectEntry hp1 mp out cnt acc key
1952+ ejectLoop hp2 mp1 out1 cnt1
1953+ else
1954+ -- reset the session timeout and continue
1955+ let hp2 = H.insert (Entry expiry1 key) hp1
1956+ in ejectLoop hp2 mp out cnt
1957+ else return (hp, mp, out, cnt)
1958+ Nothing -> do
1959+ assert (Map.null mp) (return ())
1960+ return (hp, mp, out, cnt)
1961+
1962+ -- merge timer events in the stream
1963+ stream = Serial.map Just str `Par.parallelFst` repeatM timer
1964+ timer = do
1965+ liftIO $ threadDelay (round $ tick * 1000000)
1966+ return Nothing
1967+
1968+-- | Like 'classifySessionsOf' but the session is kept alive if an event is
1969+-- received within the session window. The session times out and gets closed
1970+-- only if no event is received within the specified session window size.
1971+--
1972+-- If the ejection predicate returns 'True', the session that was idle for
1973+-- the longest time is ejected before inserting a new session.
1974+--
1975+-- @
1976+-- classifyKeepAliveSessions timeout pred = classifySessionsBy 1 timeout True pred
1977+-- @
1978+--
1979+-- /Internal/
1980+--
1981+{-# INLINABLE classifyKeepAliveSessions #-}
1982+classifyKeepAliveSessions ::
1983+ (IsStream t, MonadAsync m, Ord k)
1984+ => Double -- ^ session inactive timeout
1985+ -> (Int -> m Bool) -- ^ predicate to eject sessions on session count
1986+ -> Fold m a b -- ^ Fold to be applied to session payload data
1987+ -> t m (k, a, AbsTime) -- ^ session key, data, timestamp
1988+ -> t m (k, b)
1989+classifyKeepAliveSessions tmout =
1990+ classifySessionsBy 1 tmout True
1991+
1992+------------------------------------------------------------------------------
1993+-- Keyed tumbling windows
1994+------------------------------------------------------------------------------
1995+
1996+-- Tumbling windows is a special case of sliding windows where the window slide
1997+-- is the same as the window size. Or it can be a special case of session
1998+-- windows where the reset flag is set to False.
1999+
2000+-- XXX instead of using the early termination flag in the stream, we can use an
2001+-- early terminating fold instead.
2002+
2003+{-
2004+-- | Split the stream into fixed size chunks of specified size. Within each
2005+-- such chunk fold the elements in buckets identified by the keys. A particular
2006+-- bucket fold can be terminated early if a closing flag is encountered in an
2007+-- element for that key.
2008+--
2009+-- @since 0.7.0
2010+{-# INLINABLE classifyChunksOf #-}
2011+classifyChunksOf
2012+ :: (IsStream t, MonadAsync m, Ord k)
2013+ => Int -- ^ window size
2014+ -> Fold m a b -- ^ Fold to be applied to window events
2015+ -> t m (k, a, Bool) -- ^ window key, data, close event
2016+ -> t m (k, b)
2017+classifyChunksOf wsize = classifyChunksBy wsize False
2018+-}
2019+
2020+-- | Split the stream into fixed size time windows of specified interval in
2021+-- seconds. Within each such window, fold the elements in sessions identified
2022+-- by the session keys. The fold result is emitted in the output stream if the
2023+-- fold returns a 'Left' result or if the time window ends.
2024+--
2025+-- Session @timestamp@ in the input stream is an absolute time from some epoch,
2026+-- characterizing the time when the input element was generated. To detect
2027+-- session window end, a monotonic event time clock is maintained synced with
2028+-- the timestamps with a clock resolution of 1 second.
2029+--
2030+-- If the ejection predicate returns 'True', the session with the longest
2031+-- lifetime is ejected before inserting a new session.
2032+--
2033+-- @
2034+-- classifySessionsOf interval pred = classifySessionsBy 1 interval False pred
2035+-- @
2036+--
2037+-- @
2038+-- >>> S.mapM_ print
2039+-- $ S.classifySessionsOf 3 (const (return False)) (fmap Right FL.toList)
2040+-- $ S.map (\(ts,(k,a)) -> (k, a, ts))
2041+-- $ S.timestamped
2042+-- $ S.delay 1
2043+-- $ (,) <$> S.fromList [1,2,3] <*> S.fromList [1,2,3]
2044+-- @
2045+--
2046+-- /Internal/
2047+--
2048+{-# INLINABLE classifySessionsOf #-}
2049+classifySessionsOf ::
2050+ (IsStream t, MonadAsync m, Ord k)
2051+ => Double -- ^ time window size
2052+ -> (Int -> m Bool) -- ^ predicate to eject sessions on session count
2053+ -> Fold m a b -- ^ Fold to be applied to session events
2054+ -> t m (k, a, AbsTime) -- ^ session key, data, timestamp
2055+ -> t m (k, b)
2056+classifySessionsOf interval =
2057+ classifySessionsBy 1 interval False
2058+
2059+------------------------------------------------------------------------------
2060+-- Nested Split
2061+------------------------------------------------------------------------------
2062+
2063+-- | @splitInnerBy splitter joiner stream@ splits the inner containers @f a@ of
2064+-- an input stream @t m (f a)@ using the @splitter@ function. Container
2065+-- elements @f a@ are collected until a split occurs, then all the elements
2066+-- before the split are joined using the @joiner@ function.
2067+--
2068+-- For example, if we have a stream of @Array Word8@, we may want to split the
2069+-- stream into arrays representing lines separated by '\n' byte such that the
2070+-- resulting stream after a split would be one array for each line.
2071+--
2072+-- CAUTION! This is not a true streaming function as the container size after
2073+-- the split and merge may not be bounded.
2074+--
2075+-- /Internal/
2076+{-# INLINE splitInnerBy #-}
2077+splitInnerBy
2078+ :: (IsStream t, Monad m)
2079+ => (f a -> m (f a, Maybe (f a))) -- splitter
2080+ -> (f a -> f a -> m (f a)) -- joiner
2081+ -> t m (f a)
2082+ -> t m (f a)
2083+splitInnerBy splitter joiner xs =
2084+ D.fromStreamD $ D.splitInnerBy splitter joiner $ D.toStreamD xs
2085+
2086+-- | Like 'splitInnerBy' but splits assuming the separator joins the segment in
2087+-- a suffix style.
2088+--
2089+-- /Internal/
2090+{-# INLINE splitInnerBySuffix #-}
2091+splitInnerBySuffix
2092+ :: (IsStream t, Monad m, Eq (f a), Monoid (f a))
2093+ => (f a -> m (f a, Maybe (f a))) -- splitter
2094+ -> (f a -> f a -> m (f a)) -- joiner
2095+ -> t m (f a)
2096+ -> t m (f a)
2097+splitInnerBySuffix splitter joiner xs =
2098+ D.fromStreamD $ D.splitInnerBySuffix splitter joiner $ D.toStreamD xs
src/Streamly/Internal/Data/Stream/IsStream/Transform.hsnew file+1247
@@ -0,0 +1,1247 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.IsStream.Transform
3+-- Copyright : (c) 2020 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+
9+module Streamly.Internal.Data.Stream.IsStream.Transform
10+ (
11+ -- * Piping
12+ -- | Pass through a 'Pipe'.
13+ transform
14+
15+ -- * Folding
16+ , foldrS
17+ , foldrT
18+
19+ -- * Mapping
20+ -- | Stateless one-to-one maps.
21+ , Serial.map
22+ , sequence
23+ , mapM
24+ , smapM
25+
26+ -- * Mapping Side Effects
27+ , trace
28+ , trace_
29+ , tap
30+ , tapOffsetEvery
31+ , tapAsync
32+ , tapRate
33+ , pollCounts
34+
35+ -- * Scanning By 'Fold'
36+ , scan
37+ , postscan
38+
39+ -- * Scanning
40+ -- | Left scans. Stateful, mostly one-to-one maps.
41+ , scanl'
42+ , scanlM'
43+ , scanlMAfter'
44+ , postscanl'
45+ , postscanlM'
46+ , prescanl'
47+ , prescanlM'
48+ , scanl1'
49+ , scanl1M'
50+
51+ -- XXX Once we have pipes the contravariant transformations can be
52+ -- represented by attaching pipes before a transformation.
53+ --
54+ -- , lscanl'
55+ -- , lscanlM'
56+ -- , lscanl1'
57+ -- , lscanl1M'
58+ --
59+ -- , lpostscanl'
60+ -- , lpostscanlM'
61+ -- , lprescanl'
62+ -- , lprescanlM'
63+
64+ -- * Filtering
65+ -- | Produce a subset of the stream.
66+
67+ , filter
68+ , filterM
69+ , deleteBy
70+ , uniq
71+ -- , uniqBy -- by predicate e.g. to remove duplicate "/" in a path
72+ -- , uniqOn -- to remove duplicate sequences
73+ -- , pruneBy -- dropAround + uniqBy - like words
74+
75+ -- * Trimming
76+ -- | Produce a subset of the stream trimmed at ends.
77+
78+ , take
79+ -- , takeGE
80+ -- , takeBetween
81+ , takeByTime
82+ -- , takeEnd
83+ , takeWhile
84+ , takeWhileM
85+ -- , takeWhileEnd
86+ , drop
87+ , dropByTime
88+ -- , dropEnd
89+ , dropWhile
90+ , dropWhileM
91+ -- , dropWhileEnd
92+ -- , dropAround
93+
94+ -- * Inserting Elements
95+ -- | Produce a superset of the stream.
96+
97+ , insertBy
98+ , intersperse
99+ , intersperseM -- XXX naming
100+ , intersperseSuffix
101+ , intersperseSuffixBySpan
102+ -- , intersperseBySpan
103+ -- , intersperseByIndices -- using an index function/stream
104+
105+ -- * Inserting Side Effects
106+ , intersperseM_ -- XXX naming
107+ , intersperseSuffix_
108+ , interspersePrefix_
109+
110+ -- * Inserting Time
111+ -- , intersperseByTime
112+ -- , intersperseByEvent
113+ , interjectSuffix
114+ , delay
115+ , delayPost
116+ , delayPre
117+
118+ -- * Reordering
119+ , reverse
120+ , reverse'
121+ , reassembleBy
122+
123+ -- * Position Indexing
124+ , indexed
125+ , indexedR
126+
127+ -- * Time Indexing
128+ , timestamped
129+ , timestampWith
130+ -- , timestampedR -- timer
131+ , timeIndexed
132+ , timeIndexWith
133+
134+ -- * Searching
135+ , findIndices -- XXX indicesBy
136+ , elemIndices -- XXX indicesOf
137+
138+ -- * Rolling map
139+ -- | Map using the previous element.
140+ , rollingMapM
141+ , rollingMap
142+
143+ -- * Maybe Streams
144+ , catMaybes -- XXX justs (like lefts/rights)
145+ , mapMaybe
146+ , mapMaybeM
147+
148+ -- * Either Streams
149+ , lefts
150+ , rights
151+
152+ -- * Threading
153+ -- | Run streaming stages concurrently.
154+
155+ , D.mkParallel
156+ -- Par.mkParallel
157+ , applyAsync
158+ , (|$)
159+ , (|&)
160+
161+ -- * Deprecated
162+ , scanx
163+ )
164+where
165+
166+#include "inline.hs"
167+
168+import Control.Concurrent (threadDelay)
169+import Control.Monad (void)
170+import Control.Monad.Catch (MonadCatch)
171+import Control.Monad.IO.Class (MonadIO(..))
172+import Control.Monad.Trans.Class (MonadTrans(..))
173+import Data.Either (isLeft, isRight)
174+import Data.Maybe (isJust, fromJust)
175+import Streamly.Internal.BaseCompat (fromLeft, fromRight)
176+import Streamly.Internal.Data.Fold.Types (Fold (..))
177+import Streamly.Internal.Data.SVar (MonadAsync)
178+import Streamly.Internal.Data.Stream.IsStream.Common
179+ ( absTimesWith
180+ , drop
181+ , findIndices
182+ , postscanlM'
183+ , relTimesWith
184+ , reverse
185+ , reverse'
186+ , scanlMAfter'
187+ , smapM
188+ , take
189+ , takeWhile
190+ , interjectSuffix
191+ , intersperseM
192+ )
193+import Streamly.Internal.Data.Stream.Prelude (fromStreamS, toStreamS)
194+import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
195+import Streamly.Internal.Data.Stream.StreamK (IsStream)
196+import Streamly.Internal.Data.Stream.Serial (SerialT)
197+import Streamly.Internal.Data.Pipe.Types (Pipe (..))
198+import Streamly.Internal.Data.Time.Units ( TimeUnit64, AbsTime, RelTime64)
199+
200+import qualified Streamly.Internal.Data.Fold as FL
201+import qualified Streamly.Internal.Data.Stream.Prelude as P
202+import qualified Streamly.Internal.Data.Stream.Serial as Serial
203+import qualified Streamly.Internal.Data.Stream.StreamD as D
204+import qualified Streamly.Internal.Data.Stream.StreamK as K
205+import qualified Streamly.Internal.Data.Stream.Zip as Z
206+#ifdef USE_STREAMK_ONLY
207+import qualified Streamly.Internal.Data.Stream.StreamK as S
208+#else
209+import qualified Streamly.Internal.Data.Stream.StreamD as S
210+#endif
211+
212+import Prelude hiding
213+ ( filter, drop, dropWhile, take, takeWhile, foldr, map, mapM, sequence
214+ , reverse, foldr1 , scanl, scanl1)
215+
216+------------------------------------------------------------------------------
217+-- Piping
218+------------------------------------------------------------------------------
219+
220+-- | Use a 'Pipe' to transform a stream.
221+--
222+-- /Internal/
223+--
224+{-# INLINE transform #-}
225+transform :: (IsStream t, Monad m) => Pipe m a b -> t m a -> t m b
226+transform pipe xs = fromStreamD $ D.transform pipe (toStreamD xs)
227+
228+------------------------------------------------------------------------------
229+-- Transformation Folds
230+------------------------------------------------------------------------------
231+
232+-- | Right fold to a streaming monad.
233+--
234+-- > foldrS S.cons S.nil === id
235+--
236+-- 'foldrS' can be used to perform stateless stream to stream transformations
237+-- like map and filter in general. It can be coupled with a scan to perform
238+-- stateful transformations. However, note that the custom map and filter
239+-- routines can be much more efficient than this due to better stream fusion.
240+--
241+-- >>> S.toList $ S.foldrS S.cons S.nil $ S.fromList [1..5]
242+-- > [1,2,3,4,5]
243+--
244+-- Find if any element in the stream is 'True':
245+--
246+-- >>> 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)
247+-- > [True]
248+--
249+-- Map (+2) on odd elements and filter out the even elements:
250+--
251+-- >>> 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)
252+-- > [3,5,7]
253+--
254+-- 'foldrM' can also be represented in terms of 'foldrS', however, the former
255+-- is much more efficient:
256+--
257+-- > foldrM f z s = runIdentityT $ foldrS (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
258+--
259+-- /Internal/
260+{-# INLINE foldrS #-}
261+foldrS :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b
262+foldrS = K.foldrS
263+
264+-- | Right fold to a transformer monad. This is the most general right fold
265+-- function. 'foldrS' is a special case of 'foldrT', however 'foldrS'
266+-- implementation can be more efficient:
267+--
268+-- > foldrS = foldrT
269+-- > foldrM f z s = runIdentityT $ foldrT (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
270+--
271+-- 'foldrT' can be used to translate streamly streams to other transformer
272+-- monads e.g. to a different streaming type.
273+--
274+-- /Internal/
275+{-# INLINE foldrT #-}
276+foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s)
277+ => (a -> s m b -> s m b) -> s m b -> t m a -> s m b
278+foldrT f z s = S.foldrT f z (toStreamS s)
279+
280+------------------------------------------------------------------------------
281+-- Transformation by Mapping
282+------------------------------------------------------------------------------
283+
284+-- |
285+-- @
286+-- mapM f = sequence . map f
287+-- @
288+--
289+-- Apply a monadic function to each element of the stream and replace it with
290+-- the output of the resulting action.
291+--
292+-- @
293+-- > drain $ S.mapM putStr $ S.fromList ["a", "b", "c"]
294+-- abc
295+--
296+-- drain $ S.replicateM 10 (return 1)
297+-- & (serially . S.mapM (\\x -> threadDelay 1000000 >> print x))
298+--
299+-- drain $ S.replicateM 10 (return 1)
300+-- & (asyncly . S.mapM (\\x -> threadDelay 1000000 >> print x))
301+-- @
302+--
303+-- /Concurrent (do not use with 'parallely' on infinite streams)/
304+--
305+-- @since 0.1.0
306+{-# INLINE_EARLY mapM #-}
307+mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
308+mapM = K.mapM
309+
310+{-# RULES "mapM serial" mapM = mapMSerial #-}
311+{-# INLINE mapMSerial #-}
312+mapMSerial :: Monad m => (a -> m b) -> SerialT m a -> SerialT m b
313+mapMSerial = Serial.mapM
314+
315+-- |
316+-- @
317+-- sequence = mapM id
318+-- @
319+--
320+-- Replace the elements of a stream of monadic actions with the outputs of
321+-- those actions.
322+--
323+-- @
324+-- > drain $ S.sequence $ S.fromList [putStr "a", putStr "b", putStrLn "c"]
325+-- abc
326+--
327+-- drain $ S.replicateM 10 (return $ threadDelay 1000000 >> print 1)
328+-- & (serially . S.sequence)
329+--
330+-- drain $ S.replicateM 10 (return $ threadDelay 1000000 >> print 1)
331+-- & (asyncly . S.sequence)
332+-- @
333+--
334+-- /Concurrent (do not use with 'parallely' on infinite streams)/
335+--
336+-- @since 0.1.0
337+{-# INLINE sequence #-}
338+sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
339+sequence m = fromStreamS $ S.sequence (toStreamS m)
340+
341+------------------------------------------------------------------------------
342+-- Mapping side effects
343+------------------------------------------------------------------------------
344+
345+-- | Tap the data flowing through a stream into a 'Fold'. For example, you may
346+-- add a tap to log the contents flowing through the stream. The fold is used
347+-- only for effects, its result is discarded.
348+--
349+-- @
350+-- Fold m a b
351+-- |
352+-- -----stream m a ---------------stream m a-----
353+--
354+-- @
355+--
356+-- @
357+-- > S.drain $ S.tap (FL.drainBy print) (S.enumerateFromTo 1 2)
358+-- 1
359+-- 2
360+-- @
361+--
362+-- Compare with 'trace'.
363+--
364+-- @since 0.7.0
365+{-# INLINE tap #-}
366+tap :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> t m a
367+tap f xs = D.fromStreamD $ D.tap f (D.toStreamD xs)
368+
369+-- | @tapOffsetEvery offset n@ taps every @n@th element in the stream
370+-- starting at @offset@. @offset@ can be between @0@ and @n - 1@. Offset 0
371+-- means start at the first element in the stream. If the offset is outside
372+-- this range then @offset `mod` n@ is used as offset.
373+--
374+-- @
375+-- >>> S.drain $ S.tapOffsetEvery 0 2 (FL.mapM print FL.toList) $ S.enumerateFromTo 0 10
376+-- > [0,2,4,6,8,10]
377+-- @
378+--
379+-- /Internal/
380+--
381+{-# INLINE tapOffsetEvery #-}
382+tapOffsetEvery :: (IsStream t, Monad m)
383+ => Int -> Int -> FL.Fold m a b -> t m a -> t m a
384+tapOffsetEvery offset n f xs =
385+ D.fromStreamD $ D.tapOffsetEvery offset n f (D.toStreamD xs)
386+
387+-- | Redirect a copy of the stream to a supplied fold and run it concurrently
388+-- in an independent thread. The fold may buffer some elements. The buffer size
389+-- is determined by the prevailing 'maxBuffer' setting.
390+--
391+-- @
392+-- Stream m a -> m b
393+-- |
394+-- -----stream m a ---------------stream m a-----
395+--
396+-- @
397+--
398+-- @
399+-- > S.drain $ S.tapAsync (S.mapM_ print) (S.enumerateFromTo 1 2)
400+-- 1
401+-- 2
402+-- @
403+--
404+-- Exceptions from the concurrently running fold are propagated to the current
405+-- computation. Note that, because of buffering in the fold, exceptions may be
406+-- delayed and may not correspond to the current element being processed in the
407+-- parent stream, but we guarantee that before the parent stream stops the tap
408+-- finishes and all exceptions from it are drained.
409+--
410+--
411+-- Compare with 'tap'.
412+--
413+-- /Internal/
414+{-# INLINE tapAsync #-}
415+tapAsync :: (IsStream t, MonadAsync m) => FL.Fold m a b -> t m a -> t m a
416+tapAsync f xs = D.fromStreamD $ D.tapAsync f (D.toStreamD xs)
417+
418+-- | @pollCounts predicate transform fold stream@ counts those elements in the
419+-- stream that pass the @predicate@. The resulting count stream is sent to
420+-- another thread which transforms it using @transform@ and then folds it using
421+-- @fold@. The thread is automatically cleaned up if the stream stops or
422+-- aborts due to exception.
423+--
424+-- For example, to print the count of elements processed every second:
425+--
426+-- @
427+-- > S.drain $ S.pollCounts (const True) (S.rollingMap (-) . S.delayPost 1) (FL.drainBy print)
428+-- $ S.enumerateFrom 0
429+-- @
430+--
431+-- Note: This may not work correctly on 32-bit machines.
432+--
433+-- /Internal/
434+--
435+{-# INLINE pollCounts #-}
436+pollCounts ::
437+ (IsStream t, MonadAsync m)
438+ => (a -> Bool)
439+ -> (t m Int -> t m Int)
440+ -> Fold m Int b
441+ -> t m a
442+ -> t m a
443+pollCounts predicate transf f xs =
444+ D.fromStreamD
445+ $ D.pollCounts predicate (D.toStreamD . transf . D.fromStreamD) f
446+ $ D.toStreamD xs
447+
448+-- | Calls the supplied function with the number of elements consumed
449+-- every @n@ seconds. The given function is run in a separate thread
450+-- until the end of the stream. In case there is an exception in the
451+-- stream the thread is killed during the next major GC.
452+--
453+-- Note: The action is not guaranteed to run if the main thread exits.
454+--
455+-- @
456+-- > delay n = threadDelay (round $ n * 1000000) >> return n
457+-- > S.drain $ S.tapRate 2 (\\n -> print $ show n ++ " elements processed") (delay 1 S.|: delay 0.5 S.|: delay 0.5 S.|: S.nil)
458+-- 2 elements processed
459+-- 1 elements processed
460+-- @
461+--
462+-- Note: This may not work correctly on 32-bit machines.
463+--
464+-- /Internal/
465+{-# INLINE tapRate #-}
466+tapRate ::
467+ (IsStream t, MonadAsync m, MonadCatch m)
468+ => Double
469+ -> (Int -> m b)
470+ -> t m a
471+ -> t m a
472+tapRate n f xs = D.fromStreamD $ D.tapRate n f $ D.toStreamD xs
473+
474+-- | Apply a monadic function to each element flowing through the stream and
475+-- discard the results.
476+--
477+-- @
478+-- > S.drain $ S.trace print (S.enumerateFromTo 1 2)
479+-- 1
480+-- 2
481+-- @
482+--
483+-- Compare with 'tap'.
484+--
485+-- @since 0.7.0
486+{-# INLINE trace #-}
487+trace :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m a
488+trace f = mapM (\x -> void (f x) >> return x)
489+
490+-- | Perform a side effect before yielding each element of the stream and
491+-- discard the results.
492+--
493+-- @
494+-- > S.drain $ S.trace_ (print "got here") (S.enumerateFromTo 1 2)
495+-- "got here"
496+-- "got here"
497+-- @
498+--
499+-- See also: 'trace', 'interspersePrefix_'
500+--
501+-- /Internal/
502+{-# INLINE trace_ #-}
503+trace_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
504+trace_ eff = Serial.mapM (\x -> eff >> return x)
505+
506+------------------------------------------------------------------------------
507+-- Scanning with a Fold
508+------------------------------------------------------------------------------
509+
510+-- | Scan a stream using the given monadic fold.
511+--
512+-- @since 0.7.0
513+{-# INLINE scan #-}
514+scan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
515+scan = P.scanOnce
516+
517+-- | Postscan a stream using the given monadic fold.
518+--
519+-- @since 0.7.0
520+{-# INLINE postscan #-}
521+postscan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b
522+postscan = P.postscanOnce
523+
524+------------------------------------------------------------------------------
525+-- Scanning - Transformation by Folding
526+------------------------------------------------------------------------------
527+
528+-- XXX It may be useful to have a version of scan where we can keep the
529+-- accumulator independent of the value emitted. So that we do not necessarily
530+-- have to keep a value in the accumulator which we are not using. We can pass
531+-- an extraction function that will take the accumulator and the current value
532+-- of the element and emit the next value in the stream. That will also make it
533+-- possible to modify the accumulator after using it. In fact, the step function
534+-- can return new accumulator and the value to be emitted. The signature would
535+-- be more like mapAccumL. Or we can change the signature of scanx to
536+-- accommodate this.
537+--
538+-- | Strict left scan with an extraction function. Like 'scanl'', but applies a
539+-- user supplied extraction function (the third argument) at each step. This is
540+-- designed to work with the @foldl@ library. The suffix @x@ is a mnemonic for
541+-- extraction.
542+--
543+-- /Since 0.2.0/
544+--
545+-- /Since: 0.7.0 (Monad m constraint)/
546+{-# DEPRECATED scanx "Please use scanl followed by map instead." #-}
547+{-# INLINE scanx #-}
548+scanx :: (IsStream t, Monad m) => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
549+scanx = P.scanlx'
550+
551+-- XXX this needs to be concurrent
552+-- XXX because of the use of D.cons for appending, scanlM' has quadratic
553+-- complexity when iterated over a stream. We should use StreamK style scanlM'
554+-- for linear performance on iteration.
555+--
556+-- | Like 'scanl'' but with a monadic step function and a monadic seed.
557+--
558+-- /Since: 0.4.0/
559+--
560+-- /Since: 0.8.0 (signature change)/
561+{-# INLINE scanlM' #-}
562+scanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
563+scanlM' step begin m = fromStreamD $ D.scanlM' step begin $ toStreamD m
564+
565+-- XXX because of the use of D.cons for appending, scanl' has quadratic
566+-- complexity when iterated over a stream. We should use StreamK style scanlM'
567+-- for linear performance on iteration.
568+
569+-- | Strict left scan. Like 'map', 'scanl'' too is a one to one transformation,
570+-- however it adds an extra element.
571+--
572+-- @
573+-- > S.toList $ S.scanl' (+) 0 $ fromList [1,2,3,4]
574+-- [0,1,3,6,10]
575+-- @
576+--
577+-- @
578+-- > S.toList $ S.scanl' (flip (:)) [] $ S.fromList [1,2,3,4]
579+-- [[],[1],[2,1],[3,2,1],[4,3,2,1]]
580+-- @
581+--
582+-- The output of 'scanl'' is the initial value of the accumulator followed by
583+-- all the intermediate steps and the final result of 'foldl''.
584+--
585+-- By streaming the accumulated state after each fold step, we can share the
586+-- state across multiple stages of stream composition. Each stage can modify or
587+-- extend the state, do some processing with it and emit it for the next stage,
588+-- thus modularizing the stream processing. This can be useful in
589+-- stateful or event-driven programming.
590+--
591+-- Consider the following monolithic example, computing the sum and the product
592+-- of the elements in a stream in one go using a @foldl'@:
593+--
594+-- @
595+-- > S.foldl' (\\(s, p) x -> (s + x, p * x)) (0,1) $ S.fromList \[1,2,3,4]
596+-- (10,24)
597+-- @
598+--
599+-- Using @scanl'@ we can make it modular by computing the sum in the first
600+-- stage and passing it down to the next stage for computing the product:
601+--
602+-- @
603+-- > S.foldl' (\\(_, p) (s, x) -> (s, p * x)) (0,1)
604+-- $ S.scanl' (\\(s, _) x -> (s + x, x)) (0,1)
605+-- $ S.fromList \[1,2,3,4]
606+-- (10,24)
607+-- @
608+--
609+-- IMPORTANT: 'scanl'' evaluates the accumulator to WHNF. To avoid building
610+-- lazy expressions inside the accumulator, it is recommended that a strict
611+-- data structure is used for accumulator.
612+--
613+-- See also: 'usingStateT'
614+--
615+-- @since 0.2.0
616+{-# INLINE scanl' #-}
617+scanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
618+scanl' step z m = fromStreamS $ S.scanl' step z $ toStreamS m
619+
620+-- | Like 'scanl'' but does not stream the initial value of the accumulator.
621+--
622+-- > postscanl' f z xs = S.drop 1 $ S.scanl' f z xs
623+--
624+-- @since 0.7.0
625+{-# INLINE postscanl' #-}
626+postscanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
627+postscanl' step z m = fromStreamD $ D.postscanl' step z $ toStreamD m
628+
629+-- XXX prescanl does not sound very useful, enable only if there is a
630+-- compelling use case.
631+--
632+-- | Like scanl' but does not stream the final value of the accumulator.
633+--
634+-- /Internal/
635+{-# INLINE prescanl' #-}
636+prescanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
637+prescanl' step z m = fromStreamD $ D.prescanl' step z $ toStreamD m
638+
639+-- XXX this needs to be concurrent
640+-- | Like prescanl' but with a monadic step function and a monadic seed.
641+--
642+-- /Internal/
643+{-# INLINE prescanlM' #-}
644+prescanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b
645+prescanlM' step z m = fromStreamD $ D.prescanlM' step z $ toStreamD m
646+
647+-- XXX this needs to be concurrent
648+-- | Like 'scanl1'' but with a monadic step function.
649+--
650+-- @since 0.6.0
651+{-# INLINE scanl1M' #-}
652+scanl1M' :: (IsStream t, Monad m) => (a -> a -> m a) -> t m a -> t m a
653+scanl1M' step m = fromStreamD $ D.scanl1M' step $ toStreamD m
654+
655+-- | Like 'scanl'' but for a non-empty stream. The first element of the stream
656+-- is used as the initial value of the accumulator. Does nothing if the stream
657+-- is empty.
658+--
659+-- @
660+-- > S.toList $ S.scanl1 (+) $ fromList [1,2,3,4]
661+-- [1,3,6,10]
662+-- @
663+--
664+-- @since 0.6.0
665+{-# INLINE scanl1' #-}
666+scanl1' :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> t m a
667+scanl1' step m = fromStreamD $ D.scanl1' step $ toStreamD m
668+
669+------------------------------------------------------------------------------
670+-- Filtering
671+------------------------------------------------------------------------------
672+
673+-- | Include only those elements that pass a predicate.
674+--
675+-- @since 0.1.0
676+{-# INLINE filter #-}
677+#if __GLASGOW_HASKELL__ != 802
678+-- GHC 8.2.2 crashes with this code, when used with "stack"
679+filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
680+filter p m = fromStreamS $ S.filter p $ toStreamS m
681+#else
682+filter :: IsStream t => (a -> Bool) -> t m a -> t m a
683+filter = K.filter
684+#endif
685+
686+-- | Same as 'filter' but with a monadic predicate.
687+--
688+-- @since 0.4.0
689+{-# INLINE filterM #-}
690+filterM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
691+filterM p m = fromStreamD $ D.filterM p $ toStreamD m
692+
693+-- | Drop repeated elements that are adjacent to each other.
694+--
695+-- @since 0.6.0
696+{-# INLINE uniq #-}
697+uniq :: (Eq a, IsStream t, Monad m) => t m a -> t m a
698+uniq = fromStreamD . D.uniq . toStreamD
699+
700+-- | Deletes the first occurrence of the element in the stream that satisfies
701+-- the given equality predicate.
702+--
703+-- @
704+-- > S.toList $ S.deleteBy (==) 3 $ S.fromList [1,3,3,5]
705+-- [1,3,5]
706+-- @
707+--
708+-- @since 0.6.0
709+{-# INLINE deleteBy #-}
710+deleteBy :: (IsStream t, Monad m) => (a -> a -> Bool) -> a -> t m a -> t m a
711+deleteBy cmp x m = fromStreamS $ S.deleteBy cmp x (toStreamS m)
712+
713+------------------------------------------------------------------------------
714+-- Trimming
715+------------------------------------------------------------------------------
716+
717+-- | Same as 'takeWhile' but with a monadic predicate.
718+--
719+-- @since 0.4.0
720+{-# INLINE takeWhileM #-}
721+takeWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
722+takeWhileM p m = fromStreamD $ D.takeWhileM p $ toStreamD m
723+
724+-- | @takeByTime duration@ yields stream elements upto specified time
725+-- @duration@. The duration starts when the stream is evaluated for the first
726+-- time, before the first element is yielded. The time duration is checked
727+-- before generating each element, if the duration has expired the stream
728+-- stops.
729+--
730+-- The total time taken in executing the stream is guaranteed to be /at least/
731+-- @duration@, however, because the duration is checked before generating an
732+-- element, the upper bound is indeterminate and depends on the time taken in
733+-- generating and processing the last element.
734+--
735+-- No element is yielded if the duration is zero. At least one element is
736+-- yielded if the duration is non-zero.
737+--
738+-- /Internal/
739+--
740+{-# INLINE takeByTime #-}
741+takeByTime ::(MonadIO m, IsStream t, TimeUnit64 d) => d -> t m a -> t m a
742+takeByTime d = fromStreamD . D.takeByTime d . toStreamD
743+
744+-- | Drop elements in the stream as long as the predicate succeeds and then
745+-- take the rest of the stream.
746+--
747+-- @since 0.1.0
748+{-# INLINE dropWhile #-}
749+dropWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
750+dropWhile p m = fromStreamS $ S.dropWhile p $ toStreamS m
751+
752+-- | Same as 'dropWhile' but with a monadic predicate.
753+--
754+-- @since 0.4.0
755+{-# INLINE dropWhileM #-}
756+dropWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
757+dropWhileM p m = fromStreamD $ D.dropWhileM p $ toStreamD m
758+
759+-- | @dropByTime duration@ drops stream elements until specified @duration@ has
760+-- passed. The duration begins when the stream is evaluated for the first
761+-- time. The time duration is checked /after/ generating a stream element, the
762+-- element is yielded if the duration has expired otherwise it is dropped.
763+--
764+-- The time elapsed before starting to generate the first element is /at most/
765+-- @duration@, however, because the duration expiry is checked after the
766+-- element is generated, the lower bound is indeterminate and depends on the
767+-- time taken in generating an element.
768+--
769+-- All elements are yielded if the duration is zero.
770+--
771+-- /Internal/
772+--
773+{-# INLINE dropByTime #-}
774+dropByTime ::(MonadIO m, IsStream t, TimeUnit64 d) => d -> t m a -> t m a
775+dropByTime d = fromStreamD . D.dropByTime d . toStreamD
776+
777+------------------------------------------------------------------------------
778+-- Inserting Elements
779+------------------------------------------------------------------------------
780+
781+-- | @insertBy cmp elem stream@ inserts @elem@ before the first element in
782+-- @stream@ that is less than @elem@ when compared using @cmp@.
783+--
784+-- @
785+-- insertBy cmp x = 'mergeBy' cmp ('yield' x)
786+-- @
787+--
788+-- @
789+-- > S.toList $ S.insertBy compare 2 $ S.fromList [1,3,5]
790+-- [1,2,3,5]
791+-- @
792+--
793+-- @since 0.6.0
794+{-# INLINE insertBy #-}
795+insertBy ::
796+ (IsStream t, Monad m) => (a -> a -> Ordering) -> a -> t m a -> t m a
797+insertBy cmp x m = fromStreamS $ S.insertBy cmp x (toStreamS m)
798+
799+-- | Insert a pure value between successive elements of a stream.
800+--
801+-- @
802+-- > S.toList $ S.intersperse ',' $ S.fromList "hello"
803+-- "h,e,l,l,o"
804+-- @
805+--
806+-- @since 0.7.0
807+{-# INLINE intersperse #-}
808+intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a
809+intersperse a = fromStreamS . S.intersperse a . toStreamS
810+
811+-- | Insert a side effect before consuming an element of a stream except the
812+-- first one.
813+--
814+-- @
815+-- >>> S.drain $ S.trace putChar $ S.intersperseM_ (putChar '.') $ S.fromList "hello"
816+-- > h.e.l.l.o
817+-- @
818+--
819+-- /Internal/
820+{-# INLINE intersperseM_ #-}
821+intersperseM_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
822+intersperseM_ m = fromStreamD . D.intersperseM_ m . toStreamD
823+
824+{-
825+-- | Intersperse a monadic action into the input stream after every @n@
826+-- elements.
827+--
828+-- @
829+-- > S.toList $ S.intersperseBySpan 2 (return ',') $ S.fromList "hello"
830+-- "he,ll,o"
831+-- @
832+--
833+-- @since 0.7.0
834+{-# INLINE intersperseBySpan #-}
835+intersperseBySpan :: IsStream t => Int -> m a -> t m a -> t m a
836+intersperseBySpan _n _f _xs = undefined
837+-}
838+
839+-- | Insert an effect and its output after consuming an element of a stream.
840+--
841+-- @
842+-- >>> S.toList $ S.trace putChar $ S.intersperseSuffix (putChar '.' >> return ',') $ S.fromList "hello"
843+-- > h.,e.,l.,l.,o.,"h,e,l,l,o,"
844+-- @
845+--
846+-- /Internal/
847+{-# INLINE intersperseSuffix #-}
848+intersperseSuffix :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
849+intersperseSuffix m = fromStreamD . D.intersperseSuffix m . toStreamD
850+
851+-- | Insert a side effect after consuming an element of a stream.
852+--
853+-- @
854+-- > S.mapM_ putChar $ S.intersperseSuffix_ (threadDelay 1000000) $ S.fromList "hello"
855+-- @
856+--
857+-- /Internal/
858+--
859+{-# INLINE intersperseSuffix_ #-}
860+intersperseSuffix_ :: (IsStream t, Monad m) => m b -> t m a -> t m a
861+intersperseSuffix_ m = fromStreamD . D.intersperseSuffix_ m . toStreamD
862+
863+-- | Like 'intersperseSuffix' but intersperses an effectful action into the
864+-- input stream after every @n@ elements and after the last element.
865+--
866+-- @
867+-- > S.toList $ S.intersperseSuffixBySpan 2 (return ',') $ S.fromList "hello"
868+-- "he,ll,o,"
869+-- @
870+--
871+-- /Internal/
872+--
873+{-# INLINE intersperseSuffixBySpan #-}
874+intersperseSuffixBySpan :: (IsStream t, MonadAsync m)
875+ => Int -> m a -> t m a -> t m a
876+intersperseSuffixBySpan n eff =
877+ fromStreamD . D.intersperseSuffixBySpan n eff . toStreamD
878+
879+-- | Insert a side effect before consuming an element of a stream.
880+--
881+-- @
882+-- >>> S.toList $ S.trace putChar $ S.interspersePrefix_ (putChar '.' >> return ',') $ S.fromList "hello"
883+-- > .h.e.l.l.o"hello"
884+-- @
885+--
886+-- See also: 'trace_'
887+--
888+-- /Concurrent/
889+--
890+-- /Internal/
891+--
892+{-# INLINE interspersePrefix_ #-}
893+interspersePrefix_ :: (IsStream t, MonadAsync m) => m b -> t m a -> t m a
894+interspersePrefix_ m = mapM (\x -> void m >> return x)
895+
896+------------------------------------------------------------------------------
897+-- Inserting Time
898+------------------------------------------------------------------------------
899+
900+-- Note: delay must be serial.
901+--
902+-- | Introduce a delay of specified seconds before consuming an element of the
903+-- stream except the first one.
904+--
905+-- @
906+-- >>> S.mapM_ print $ S.timestamped $ S.delay 1 $ S.enumerateFromTo 1 3
907+-- > (AbsTime (TimeSpec {sec = 2502706, nsec = 751137000}),1)
908+-- > (AbsTime (TimeSpec {sec = 2502707, nsec = 743535000}),2)
909+-- > (AbsTime (TimeSpec {sec = 2502708, nsec = 749758000}),3)
910+-- @
911+--
912+-- /Internal/
913+--
914+{-# INLINE delay #-}
915+delay :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
916+delay n = intersperseM_ $ liftIO $ threadDelay $ round $ n * 1000000
917+
918+-- Note: delay must be serial.
919+--
920+-- | Introduce a delay of specified seconds after consuming an element of a
921+-- stream.
922+--
923+-- @
924+-- >>> S.mapM_ print $ S.timestamped $ S.delayPost 1 $ S.enumerateFromTo 1 3
925+-- > (AbsTime (TimeSpec {sec = 2502826, nsec = 119030000}),1)
926+-- > (AbsTime (TimeSpec {sec = 2502827, nsec = 111393000}),2)
927+-- > (AbsTime (TimeSpec {sec = 2502828, nsec = 112221000}),3)
928+-- @
929+--
930+-- /Internal/
931+--
932+{-# INLINE delayPost #-}
933+delayPost :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
934+delayPost n = intersperseSuffix_ $ liftIO $ threadDelay $ round $ n * 1000000
935+
936+-- Note: delay must be serial, that's why 'trace_' is used.
937+--
938+-- | Introduce a delay of specified seconds before consuming an element of a
939+-- stream.
940+--
941+-- @
942+-- >>> S.mapM_ print $ S.timestamped $ S.delayPre 1 $ S.enumerateFromTo 1 3
943+-- > (AbsTime (TimeSpec {sec = 2502207, nsec = 533177000}),1)
944+-- > (AbsTime (TimeSpec {sec = 2502208, nsec = 530859000}),2)
945+-- > (AbsTime (TimeSpec {sec = 2502209, nsec = 531619000}),3)
946+-- @
947+--
948+-- /Internal/
949+--
950+{-# INLINE delayPre #-}
951+delayPre :: (IsStream t, MonadIO m) => Double -> t m a -> t m a
952+delayPre n = trace_ $ liftIO $ threadDelay $ round $ n * 1000000
953+
954+------------------------------------------------------------------------------
955+-- Reorder in sequence
956+------------------------------------------------------------------------------
957+
958+-- | Buffer until the next element in sequence arrives. The function argument
959+-- determines the difference in sequence numbers. This could be useful in
960+-- implementing sequenced streams, for example, TCP reassembly.
961+--
962+-- /Unimplemented/
963+--
964+{-# INLINE reassembleBy #-}
965+reassembleBy
966+ :: -- (IsStream t, Monad m) =>
967+ Fold m a b
968+ -> (a -> a -> Int)
969+ -> t m a
970+ -> t m b
971+reassembleBy = undefined
972+
973+------------------------------------------------------------------------------
974+-- Position Indexing
975+------------------------------------------------------------------------------
976+
977+-- |
978+-- > indexed = S.postscanl' (\(i, _) x -> (i + 1, x)) (-1,undefined)
979+-- > indexed = S.zipWith (,) (S.enumerateFrom 0)
980+--
981+-- Pair each element in a stream with its index, starting from index 0.
982+--
983+-- @
984+-- > S.toList $ S.indexed $ S.fromList "hello"
985+-- [(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')]
986+-- @
987+--
988+-- @since 0.6.0
989+{-# INLINE indexed #-}
990+indexed :: (IsStream t, Monad m) => t m a -> t m (Int, a)
991+indexed = fromStreamD . D.indexed . toStreamD
992+
993+-- |
994+-- > indexedR n = S.postscanl' (\(i, _) x -> (i - 1, x)) (n + 1,undefined)
995+-- > indexedR n = S.zipWith (,) (S.enumerateFromThen n (n - 1))
996+--
997+-- Pair each element in a stream with its index, starting from the
998+-- given index @n@ and counting down.
999+--
1000+-- @
1001+-- > S.toList $ S.indexedR 10 $ S.fromList "hello"
1002+-- [(10,'h'),(9,'e'),(8,'l'),(7,'l'),(6,'o')]
1003+-- @
1004+--
1005+-- @since 0.6.0
1006+{-# INLINE indexedR #-}
1007+indexedR :: (IsStream t, Monad m) => Int -> t m a -> t m (Int, a)
1008+indexedR n = fromStreamD . D.indexedR n . toStreamD
1009+
1010+-------------------------------------------------------------------------------
1011+-- Time Indexing
1012+-------------------------------------------------------------------------------
1013+
1014+-- Note: The timestamp stream must be the second stream in the zip so that the
1015+-- timestamp is generated after generating the stream element and not before.
1016+-- If we do not do that then the following example will generate the same
1017+-- timestamp for first two elements:
1018+--
1019+-- S.mapM_ print $ S.timestamped $ S.delay $ S.enumerateFromTo 1 3
1020+--
1021+-- | Pair each element in a stream with an absolute timestamp, using a clock of
1022+-- specified granularity. The timestamp is generated just before the element
1023+-- is consumed.
1024+--
1025+-- @
1026+-- >>> S.mapM_ print $ S.timestampWith 0.01 $ S.delay 1 $ S.enumerateFromTo 1 3
1027+-- @
1028+--
1029+-- /Internal/
1030+--
1031+{-# INLINE timestampWith #-}
1032+timestampWith :: (IsStream t, MonadAsync m, Functor (t m))
1033+ => Double -> t m a -> t m (AbsTime, a)
1034+timestampWith g stream = Z.zipWith (flip (,)) stream (absTimesWith g)
1035+
1036+-- TBD: check performance vs a custom implementation without using zipWith.
1037+--
1038+-- /Internal/
1039+--
1040+{-# INLINE timestamped #-}
1041+timestamped :: (IsStream t, MonadAsync m, Functor (t m))
1042+ => t m a -> t m (AbsTime, a)
1043+timestamped = timestampWith 0.01
1044+
1045+-- | Pair each element in a stream with relative times starting from 0, using a
1046+-- clock with the specified granularity. The time is measured just before the
1047+-- element is consumed.
1048+--
1049+-- @
1050+-- >>> S.mapM_ print $ S.timeIndexWith 0.01 $ S.delay 1 $ S.enumerateFromTo 1 3
1051+-- @
1052+--
1053+-- /Internal/
1054+--
1055+{-# INLINE timeIndexWith #-}
1056+timeIndexWith :: (IsStream t, MonadAsync m, Functor (t m))
1057+ => Double -> t m a -> t m (RelTime64, a)
1058+timeIndexWith g stream = Z.zipWith (flip (,)) stream (relTimesWith g)
1059+
1060+-- | Pair each element in a stream with relative times starting from 0, using a
1061+-- 10 ms granularity clock. The time is measured just before the element is
1062+-- consumed.
1063+--
1064+-- @
1065+-- >>> S.mapM_ print $ S.timeIndexed $ S.delay 1 $ S.enumerateFromTo 1 3
1066+-- (RelTime64 (NanoSecond64 0),1)
1067+-- (RelTime64 (NanoSecond64 996239000),2)
1068+-- (RelTime64 (NanoSecond64 1996712000),3)
1069+-- @
1070+--
1071+-- /Internal/
1072+--
1073+{-# INLINE timeIndexed #-}
1074+timeIndexed :: (IsStream t, MonadAsync m, Functor (t m))
1075+ => t m a -> t m (RelTime64, a)
1076+timeIndexed = timeIndexWith 0.01
1077+
1078+------------------------------------------------------------------------------
1079+-- Searching
1080+------------------------------------------------------------------------------
1081+
1082+-- | Find all the indices where the value of the element in the stream is equal
1083+-- to the given value.
1084+--
1085+-- > elemIndices a = findIndices (== a)
1086+--
1087+-- @since 0.5.0
1088+{-# INLINE elemIndices #-}
1089+elemIndices :: (IsStream t, Eq a, Monad m) => a -> t m a -> t m Int
1090+elemIndices a = findIndices (== a)
1091+
1092+------------------------------------------------------------------------------
1093+-- Rolling map
1094+------------------------------------------------------------------------------
1095+
1096+-- XXX this is not a one-to-one map so calling it map may not be right.
1097+-- We can perhaps call it zipWithTail or rollWith.
1098+--
1099+-- | Apply a function on every two successive elements of a stream. If the
1100+-- stream consists of a single element the output is an empty stream.
1101+--
1102+-- This is the stream equivalent of the list idiom @zipWith f xs (tail xs)@.
1103+--
1104+-- /Internal/
1105+--
1106+{-# INLINE rollingMap #-}
1107+rollingMap :: (IsStream t, Monad m) => (a -> a -> b) -> t m a -> t m b
1108+rollingMap f m = fromStreamD $ D.rollingMap f $ toStreamD m
1109+
1110+-- | Like 'rollingMap' but with an effectful map function.
1111+--
1112+-- /Internal/
1113+--
1114+{-# INLINE rollingMapM #-}
1115+rollingMapM :: (IsStream t, Monad m) => (a -> a -> m b) -> t m a -> t m b
1116+rollingMapM f m = fromStreamD $ D.rollingMapM f $ toStreamD m
1117+
1118+------------------------------------------------------------------------------
1119+-- Maybe Streams
1120+------------------------------------------------------------------------------
1121+
1122+-- | Map a 'Maybe' returning function to a stream, filter out the 'Nothing'
1123+-- elements, and return a stream of values extracted from 'Just'.
1124+--
1125+-- Equivalent to:
1126+--
1127+-- @
1128+-- mapMaybe f = S.map 'fromJust' . S.filter 'isJust' . S.map f
1129+-- @
1130+--
1131+-- @since 0.3.0
1132+{-# INLINE mapMaybe #-}
1133+mapMaybe :: (IsStream t, Monad m) => (a -> Maybe b) -> t m a -> t m b
1134+mapMaybe f m = fromStreamS $ S.mapMaybe f $ toStreamS m
1135+
1136+-- | Like 'mapMaybe' but maps a monadic function.
1137+--
1138+-- Equivalent to:
1139+--
1140+-- @
1141+-- mapMaybeM f = S.map 'fromJust' . S.filter 'isJust' . S.mapM f
1142+-- @
1143+--
1144+-- /Concurrent (do not use with 'parallely' on infinite streams)/
1145+--
1146+-- @since 0.3.0
1147+{-# INLINE_EARLY mapMaybeM #-}
1148+mapMaybeM :: (IsStream t, MonadAsync m, Functor (t m))
1149+ => (a -> m (Maybe b)) -> t m a -> t m b
1150+mapMaybeM f = fmap fromJust . filter isJust . K.mapM f
1151+
1152+{-# RULES "mapMaybeM serial" mapMaybeM = mapMaybeMSerial #-}
1153+{-# INLINE mapMaybeMSerial #-}
1154+mapMaybeMSerial :: Monad m => (a -> m (Maybe b)) -> SerialT m a -> SerialT m b
1155+mapMaybeMSerial f m = fromStreamD $ D.mapMaybeM f $ toStreamD m
1156+
1157+-- | In a stream of 'Maybe's, discard 'Nothing's and unwrap 'Just's.
1158+--
1159+-- /Internal/
1160+--
1161+catMaybes :: (IsStream t, Monad m, Functor (t m)) => t m (Maybe a) -> t m a
1162+catMaybes = fmap fromJust . filter isJust
1163+
1164+------------------------------------------------------------------------------
1165+-- Either streams
1166+------------------------------------------------------------------------------
1167+
1168+-- | Discard 'Right's and unwrap 'Left's in an 'Either' stream.
1169+--
1170+-- /Internal/
1171+--
1172+lefts :: (IsStream t, Monad m, Functor (t m)) => t m (Either a b) -> t m a
1173+lefts = fmap (fromLeft undefined) . filter isLeft
1174+
1175+-- | Discard 'Left's and unwrap 'Right's in an 'Either' stream.
1176+--
1177+-- /Internal/
1178+--
1179+rights :: (IsStream t, Monad m, Functor (t m)) => t m (Either a b) -> t m b
1180+rights = fmap (fromRight undefined) . filter isRight
1181+
1182+------------------------------------------------------------------------------
1183+-- Concurrent Application
1184+------------------------------------------------------------------------------
1185+
1186+-- | Parallel transform application operator; applies a stream transformation
1187+-- function @t m a -> t m b@ to a stream @t m a@ concurrently; the input stream
1188+-- is evaluated asynchronously in an independent thread yielding elements to a
1189+-- buffer and the transformation function runs in another thread consuming the
1190+-- input from the buffer. '|$' is just like regular function application
1191+-- operator '$' except that it is concurrent.
1192+--
1193+-- If you read the signature as @(t m a -> t m b) -> (t m a -> t m b)@ you can
1194+-- look at it as a transformation that converts a transform function to a
1195+-- buffered concurrent transform function.
1196+--
1197+-- The following code prints a value every second even though each stage adds a
1198+-- 1 second delay.
1199+--
1200+--
1201+-- @
1202+-- drain $
1203+-- S.mapM (\\x -> threadDelay 1000000 >> print x)
1204+-- |$ S.repeatM (threadDelay 1000000 >> return 1)
1205+-- @
1206+--
1207+-- /Concurrent/
1208+--
1209+-- /Since: 0.3.0 ("Streamly")/
1210+--
1211+-- @since 0.8.0
1212+{-# INLINE (|$) #-}
1213+(|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> (t m a -> t m b)
1214+-- (|$) f = f . Async.mkAsync
1215+(|$) f = f . D.mkParallel
1216+
1217+infixr 0 |$
1218+
1219+-- | Same as '|$'.
1220+--
1221+-- /Internal/
1222+--
1223+{-# INLINE applyAsync #-}
1224+applyAsync :: (IsStream t, MonadAsync m)
1225+ => (t m a -> t m b) -> (t m a -> t m b)
1226+applyAsync = (|$)
1227+
1228+-- | Parallel reverse function application operator for streams; just like the
1229+-- regular reverse function application operator '&' except that it is
1230+-- concurrent.
1231+--
1232+-- @
1233+-- drain $
1234+-- S.repeatM (threadDelay 1000000 >> return 1)
1235+-- |& S.mapM (\\x -> threadDelay 1000000 >> print x)
1236+-- @
1237+--
1238+-- /Concurrent/
1239+--
1240+-- /Since: 0.3.0 ("Streamly")/
1241+--
1242+-- @since 0.8.0
1243+{-# INLINE (|&) #-}
1244+(|&) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> t m b) -> t m b
1245+x |& f = f |$ x
1246+
1247+infixl 1 |&
src/Streamly/Internal/Data/Stream/StreamD.hs+9−4644
@@ -3,10 +3,7 @@
33-- |
44-- Module : Streamly.Internal.Data.Stream.StreamD
55-- Copyright : (c) 2018 Composewell Technologies
6−-- (c) Roman Leshchinskiy 2008-2010
7−-- (c) The University of Glasgow, 2009
8−--
9−-- License : BSD3
6+-- License : BSD-3-Clause
107-- Maintainer : streamly@composewell.com
118-- Stability : experimental
129-- Portability : GHC
@@ -302,4650 +299,18 @@ module Streamly.Internal.Data.Stream.StreamD
302299 )
303300where
304301
305−import Control.Concurrent (killThread, myThreadId, takeMVar, threadDelay)
306−import Control.Exception
307− (assert, Exception, SomeException, AsyncException, fromException, mask_)
308−import Control.Monad (void, when, forever)
309−import Control.Monad.Catch (MonadCatch, MonadThrow, throwM)
310−import Control.Monad.IO.Class (MonadIO(..))
311−import Control.Monad.Trans.Reader (ReaderT)
312−import Control.Monad.Trans.State.Strict (StateT)
313−import Control.Monad.Trans.Class (MonadTrans(lift))
314−import Control.Monad.Trans.Control (MonadBaseControl, liftBaseOp_, control)
315−import Data.Bits (shiftR, shiftL, (.|.), (.&.))
316−import Data.Functor.Identity (Identity(..))
317−import Data.Int (Int64)
318−import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef, IORef)
319−import Data.Maybe (fromJust, isJust, isNothing)
320−import Data.Word (Word32)
321−import Foreign.Storable (Storable(..))
322−import GHC.Exts (SpecConstrAnnotation(..))
323−import GHC.Types (SPEC(..))
324−import System.Mem (performMajorGC)
325−import Fusion.Plugin.Types (Fuse(..))
326−import Streamly.Internal.Data.IORef.Prim (Prim)
327−import Streamly.Internal.Data.Time.Units
328− (TimeUnit64, toRelTime64, diffAbsTime64, RelTime64)
329−import Streamly.Internal.Data.Atomics (atomicModifyIORefCAS_)
330−import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array(..))
331−import Streamly.Internal.Data.Fold.Types (Fold(..))
332−import Streamly.Internal.Data.Parser (ParseError(..))
333−import Streamly.Internal.Data.Pipe.Types (Pipe(..), PipeState(..))
334−import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
335−import Streamly.Internal.Data.Time.Units
336− (MicroSecond64(..), fromAbsTime, toAbsTime, AbsTime)
337−import Streamly.Internal.Data.Unfold.Types (Unfold(..))
338−import Streamly.Internal.Data.Stream.SVar (fromConsumer, pushToFold)
339−
340−import qualified Streamly.Internal.Data.IORef.Prim as Prim
341−import qualified Streamly.Internal.Data.Pipe.Types as Pipe
342−import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as A
343−import qualified Streamly.Internal.Data.Fold as FL
344−import qualified Streamly.Memory.Ring as RB
345−import qualified Streamly.Internal.Data.Stream.StreamK as K
346−import qualified Streamly.Internal.Data.Parser as PR
347−import qualified Streamly.Internal.Data.Parser.ParserD as PRD
348−import qualified Control.Monad.Catch as MC
349−import qualified Control.Monad.Trans.Reader as Reader
350−import qualified Control.Monad.Trans.State.Strict as State
351−import qualified Prelude
352−
353302import Prelude hiding
354303 ( map, mapM, mapM_, repeat, foldr, last, take, filter
355304 , takeWhile, drop, dropWhile, all, any, maximum, minimum, elem
356305 , notElem, null, head, tail, zipWith, lookup, foldr1, sequence
357306 , (!!), scanl, scanl1, concatMap, replicate, enumFromTo, concat
358307 , reverse, iterate, splitAt)
359−import Streamly.Internal.Data.Stream.StreamD.Type
360−import Streamly.Internal.Data.SVar
361−
362−------------------------------------------------------------------------------
363−-- Construction
364−------------------------------------------------------------------------------
365−
366−-- | An empty 'Stream'.
367−{-# INLINE_NORMAL nil #-}
368−nil :: Monad m => Stream m a
369−nil = Stream (\_ _ -> return Stop) ()
370−
371−-- | An empty 'Stream' with a side effect.
372−{-# INLINE_NORMAL nilM #-}
373−nilM :: Monad m => m b -> Stream m a
374−nilM m = Stream (\_ _ -> m >> return Stop) ()
375−
376−{-# INLINE_NORMAL consM #-}
377−consM :: Monad m => m a -> Stream m a -> Stream m a
378−consM m (Stream step state) = Stream step1 Nothing
379− where
380− {-# INLINE_LATE step1 #-}
381− step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
382− step1 gst (Just st) = do
383− r <- step gst st
384− return $
385− case r of
386− Yield a s -> Yield a (Just s)
387− Skip s -> Skip (Just s)
388− Stop -> Stop
389−
390−-- XXX implement in terms of consM?
391−-- cons x = consM (return x)
392−--
393−-- | Can fuse but has O(n^2) complexity.
394−{-# INLINE_NORMAL cons #-}
395−cons :: Monad m => a -> Stream m a -> Stream m a
396−cons x (Stream step state) = Stream step1 Nothing
397− where
398− {-# INLINE_LATE step1 #-}
399− step1 _ Nothing = return $ Yield x (Just state)
400− step1 gst (Just st) = do
401− r <- step gst st
402− return $
403− case r of
404− Yield a s -> Yield a (Just s)
405− Skip s -> Skip (Just s)
406− Stop -> Stop
407−
408−-------------------------------------------------------------------------------
409−-- Deconstruction
410−-------------------------------------------------------------------------------
411−
412−-- Does not fuse, has the same performance as the StreamK version.
413−{-# INLINE_NORMAL uncons #-}
414−uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
415−uncons (UnStream step state) = go state
416− where
417− go st = do
418− r <- step defState st
419− case r of
420− Yield x s -> return $ Just (x, Stream step s)
421− Skip s -> go s
422− Stop -> return Nothing
423−
424−------------------------------------------------------------------------------
425−-- Generation by unfold
426−------------------------------------------------------------------------------
427−
428−{-# INLINE_NORMAL unfoldrM #-}
429−unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
430−unfoldrM next state = Stream step state
431− where
432− {-# INLINE_LATE step #-}
433− step _ st = do
434− r <- next st
435− return $ case r of
436− Just (x, s) -> Yield x s
437− Nothing -> Stop
438−
439−{-# INLINE_LATE unfoldr #-}
440−unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
441−unfoldr f = unfoldrM (return . f)
442−
443−data UnfoldState s = UnfoldNothing | UnfoldJust s
444−
445−-- | Convert an 'Unfold' into a 'Stream' by supplying it a seed.
446−--
447−{-# INLINE_NORMAL unfold #-}
448−unfold :: Monad m => Unfold m a b -> a -> Stream m b
449−unfold (Unfold ustep inject) seed = Stream step UnfoldNothing
450− where
451− {-# INLINE_LATE step #-}
452− step _ UnfoldNothing = inject seed >>= return . Skip . UnfoldJust
453− step _ (UnfoldJust st) = do
454− r <- ustep st
455− return $ case r of
456− Yield x s -> Yield x (UnfoldJust s)
457− Skip s -> Skip (UnfoldJust s)
458− Stop -> Stop
459−
460−------------------------------------------------------------------------------
461−-- Specialized Generation
462−------------------------------------------------------------------------------
463−
464−{-# INLINE_NORMAL repeatM #-}
465−repeatM :: Monad m => m a -> Stream m a
466−repeatM x = Stream (\_ _ -> x >>= \r -> return $ Yield r ()) ()
467−
468−{-# INLINE_NORMAL repeat #-}
469−repeat :: Monad m => a -> Stream m a
470−repeat x = Stream (\_ _ -> return $ Yield x ()) ()
471−
472−{-# INLINE_NORMAL iterateM #-}
473−iterateM :: Monad m => (a -> m a) -> m a -> Stream m a
474−iterateM step = Stream (\_ st -> st >>= \x -> return $ Yield x (step x))
475−
476−{-# INLINE_NORMAL iterate #-}
477−iterate :: Monad m => (a -> a) -> a -> Stream m a
478−iterate step st = iterateM (return . step) (return st)
479−
480−{-# INLINE_NORMAL replicateM #-}
481−replicateM :: forall m a. Monad m => Int -> m a -> Stream m a
482−replicateM n p = Stream step n
483− where
484− {-# INLINE_LATE step #-}
485− step _ (i :: Int)
486− | i <= 0 = return Stop
487− | otherwise = do
488− x <- p
489− return $ Yield x (i - 1)
490−
491−{-# INLINE_NORMAL replicate #-}
492−replicate :: Monad m => Int -> a -> Stream m a
493−replicate n x = replicateM n (return x)
494−
495−-- This would not work properly for floats, therefore we put an Integral
496−-- constraint.
497−-- | Can be used to enumerate unbounded integrals. This does not check for
498−-- overflow or underflow for bounded integrals.
499−{-# INLINE_NORMAL enumerateFromStepIntegral #-}
500−enumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
501−enumerateFromStepIntegral from stride =
502− from `seq` stride `seq` Stream step from
503− where
504− {-# INLINE_LATE step #-}
505− step _ !x = return $ Yield x $! (x + stride)
506−
507−-- We are assuming that "to" is constrained by the type to be within
508−-- max/min bounds.
509−{-# INLINE enumerateFromToIntegral #-}
510−enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
511−enumerateFromToIntegral from to =
512− takeWhile (<= to) $ enumerateFromStepIntegral from 1
513−
514−{-# INLINE enumerateFromIntegral #-}
515−enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
516−enumerateFromIntegral from = enumerateFromToIntegral from maxBound
517−
518−data EnumState a = EnumInit | EnumYield a a a | EnumStop
519−
520−{-# INLINE_NORMAL enumerateFromThenToIntegralUp #-}
521−enumerateFromThenToIntegralUp
522− :: (Monad m, Integral a)
523− => a -> a -> a -> Stream m a
524−enumerateFromThenToIntegralUp from next to = Stream step EnumInit
525− where
526− {-# INLINE_LATE step #-}
527− step _ EnumInit =
528− return $
529− if to < next
530− then if to < from
531− then Stop
532− else Yield from EnumStop
533− else -- from <= next <= to
534− let stride = next - from
535− in Skip $ EnumYield from stride (to - stride)
536−
537− step _ (EnumYield x stride toMinus) =
538− return $
539− if x > toMinus
540− then Yield x EnumStop
541− else Yield x $ EnumYield (x + stride) stride toMinus
542−
543− step _ EnumStop = return Stop
544−
545−{-# INLINE_NORMAL enumerateFromThenToIntegralDn #-}
546−enumerateFromThenToIntegralDn
547− :: (Monad m, Integral a)
548− => a -> a -> a -> Stream m a
549−enumerateFromThenToIntegralDn from next to = Stream step EnumInit
550− where
551− {-# INLINE_LATE step #-}
552− step _ EnumInit =
553− return $ if to > next
554− then if to > from
555− then Stop
556− else Yield from EnumStop
557− else -- from >= next >= to
558− let stride = next - from
559− in Skip $ EnumYield from stride (to - stride)
560−
561− step _ (EnumYield x stride toMinus) =
562− return $
563− if x < toMinus
564− then Yield x EnumStop
565− else Yield x $ EnumYield (x + stride) stride toMinus
566−
567− step _ EnumStop = return Stop
568−
569−{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
570−enumerateFromThenToIntegral
571− :: (Monad m, Integral a)
572− => a -> a -> a -> Stream m a
573−enumerateFromThenToIntegral from next to
574− | next >= from = enumerateFromThenToIntegralUp from next to
575− | otherwise = enumerateFromThenToIntegralDn from next to
576−
577−{-# INLINE_NORMAL enumerateFromThenIntegral #-}
578−enumerateFromThenIntegral
579− :: (Monad m, Integral a, Bounded a)
580− => a -> a -> Stream m a
581−enumerateFromThenIntegral from next =
582− if next > from
583− then enumerateFromThenToIntegralUp from next maxBound
584− else enumerateFromThenToIntegralDn from next minBound
585−
586−-- For floating point numbers if the increment is less than the precision then
587−-- it just gets lost. Therefore we cannot always increment it correctly by just
588−-- repeated addition.
589−-- 9007199254740992 + 1 + 1 :: Double => 9.007199254740992e15
590−-- 9007199254740992 + 2 :: Double => 9.007199254740994e15
591−
592−-- Instead we accumulate the increment counter and compute the increment
593−-- every time before adding it to the starting number.
594−--
595−-- This works for Integrals as well as floating point numbers, but
596−-- enumerateFromStepIntegral is faster for integrals.
597−{-# INLINE_NORMAL enumerateFromStepNum #-}
598−enumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
599−enumerateFromStepNum from stride = Stream step 0
600− where
601− {-# INLINE_LATE step #-}
602− step _ !i = return $ (Yield $! (from + i * stride)) $! (i + 1)
603−
604−{-# INLINE_NORMAL numFrom #-}
605−numFrom :: (Monad m, Num a) => a -> Stream m a
606−numFrom from = enumerateFromStepNum from 1
607−
608−{-# INLINE_NORMAL numFromThen #-}
609−numFromThen :: (Monad m, Num a) => a -> a -> Stream m a
610−numFromThen from next = enumerateFromStepNum from (next - from)
611−
612−-- We cannot write a general function for Num. The only way to write code
613−-- portable between the two is to use a 'Real' constraint and convert between
614−-- Fractional and Integral using fromRational which is horribly slow.
615−{-# INLINE_NORMAL enumerateFromToFractional #-}
616−enumerateFromToFractional
617− :: (Monad m, Fractional a, Ord a)
618− => a -> a -> Stream m a
619−enumerateFromToFractional from to =
620− takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
621−
622−{-# INLINE_NORMAL enumerateFromThenToFractional #-}
623−enumerateFromThenToFractional
624− :: (Monad m, Fractional a, Ord a)
625− => a -> a -> a -> Stream m a
626−enumerateFromThenToFractional from next to =
627− takeWhile predicate $ numFromThen from next
628− where
629− mid = (next - from) / 2
630− predicate | next >= from = (<= to + mid)
631− | otherwise = (>= to + mid)
632−
633−-------------------------------------------------------------------------------
634−-- Generation by Conversion
635−-------------------------------------------------------------------------------
636−
637−{-# INLINE_NORMAL fromIndicesM #-}
638−fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
639−fromIndicesM gen = Stream step 0
640− where
641− {-# INLINE_LATE step #-}
642− step _ i = do
643− x <- gen i
644− return $ Yield x (i + 1)
645−
646−{-# INLINE fromIndices #-}
647−fromIndices :: Monad m => (Int -> a) -> Stream m a
648−fromIndices gen = fromIndicesM (return . gen)
649−
650−{-# INLINE_NORMAL generateM #-}
651−generateM :: Monad m => Int -> (Int -> m a) -> Stream m a
652−generateM n gen = n `seq` Stream step 0
653− where
654− {-# INLINE_LATE step #-}
655− step _ i | i < n = do
656− x <- gen i
657− return $ Yield x (i + 1)
658− | otherwise = return Stop
659−
660−{-# INLINE generate #-}
661−generate :: Monad m => Int -> (Int -> a) -> Stream m a
662−generate n gen = generateM n (return . gen)
663−
664−-- XXX we need the MonadAsync constraint because of a rewrite rule.
665−-- | Convert a list of monadic actions to a 'Stream'
666−{-# INLINE_LATE fromListM #-}
667−fromListM :: MonadAsync m => [m a] -> Stream m a
668−fromListM = Stream step
669− where
670− {-# INLINE_LATE step #-}
671− step _ (m:ms) = m >>= \x -> return $ Yield x ms
672− step _ [] = return Stop
673−
674−{-# INLINE toStreamD #-}
675−toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
676−toStreamD = fromStreamK . K.toStream
677−
678−{-# INLINE_NORMAL fromPrimIORef #-}
679−fromPrimIORef :: (MonadIO m, Prim a) => Prim.IORef a -> Stream m a
680−fromPrimIORef var = Stream step ()
681− where
682− {-# INLINE_LATE step #-}
683− step _ () = liftIO (Prim.readIORef var) >>= \x -> return $ Yield x ()
684−
685−-------------------------------------------------------------------------------
686−-- Generation from SVar
687−-------------------------------------------------------------------------------
688−
689−data FromSVarState t m a =
690− FromSVarInit
691− | FromSVarRead (SVar t m a)
692− | FromSVarLoop (SVar t m a) [ChildEvent a]
693− | FromSVarDone (SVar t m a)
694−
695−{-# INLINE_NORMAL fromSVar #-}
696−fromSVar :: (MonadAsync m) => SVar t m a -> Stream m a
697−fromSVar svar = Stream step FromSVarInit
698− where
699−
700− {-# INLINE_LATE step #-}
701− step _ FromSVarInit = do
702− ref <- liftIO $ newIORef ()
703− _ <- liftIO $ mkWeakIORef ref hook
704− -- when this copy of svar gets garbage collected "ref" will get
705− -- garbage collected and our GC hook will be called.
706− let sv = svar{svarRef = Just ref}
707− return $ Skip (FromSVarRead sv)
708−
709− where
710−
711− {-# NOINLINE hook #-}
712− hook = do
713− when (svarInspectMode svar) $ do
714− r <- liftIO $ readIORef (svarStopTime (svarStats svar))
715− when (isNothing r) $
716− printSVar svar "SVar Garbage Collected"
717− cleanupSVar svar
718− -- If there are any SVars referenced by this SVar a GC will prompt
719− -- them to be cleaned up quickly.
720− when (svarInspectMode svar) performMajorGC
721−
722− step _ (FromSVarRead sv) = do
723− list <- readOutputQ sv
724− -- Reversing the output is important to guarantee that we process the
725− -- outputs in the same order as they were generated by the constituent
726− -- streams.
727− return $ Skip $ FromSVarLoop sv (Prelude.reverse list)
728−
729− step _ (FromSVarLoop sv []) = do
730− done <- postProcess sv
731− return $ Skip $ if done
732− then (FromSVarDone sv)
733− else (FromSVarRead sv)
734−
735− step _ (FromSVarLoop sv (ev : es)) = do
736− case ev of
737− ChildYield a -> return $ Yield a (FromSVarLoop sv es)
738− ChildStop tid e -> do
739− accountThread sv tid
740− case e of
741− Nothing -> do
742− stop <- shouldStop tid
743− if stop
744− then do
745− liftIO (cleanupSVar sv)
746− return $ Skip (FromSVarDone sv)
747− else return $ Skip (FromSVarLoop sv es)
748− Just ex ->
749− case fromException ex of
750− Just ThreadAbort ->
751− return $ Skip (FromSVarLoop sv es)
752− Nothing -> liftIO (cleanupSVar sv) >> throwM ex
753− where
754−
755− shouldStop tid =
756− case svarStopStyle sv of
757− StopNone -> return False
758− StopAny -> return True
759− StopBy -> do
760− sid <- liftIO $ readIORef (svarStopBy sv)
761− return $ if tid == sid then True else False
762−
763− step _ (FromSVarDone sv) = do
764− when (svarInspectMode sv) $ do
765− t <- liftIO $ getTime Monotonic
766− liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
767− liftIO $ printSVar sv "SVar Done"
768− return Stop
769−
770−-------------------------------------------------------------------------------
771−-- Process events received by a fold consumer from a stream producer
772−-------------------------------------------------------------------------------
773−
774−{-# INLINE_NORMAL fromProducer #-}
775−fromProducer :: (MonadAsync m) => SVar t m a -> Stream m a
776−fromProducer svar = Stream step (FromSVarRead svar)
777− where
778−
779− {-# INLINE_LATE step #-}
780− step _ (FromSVarRead sv) = do
781− list <- readOutputQ sv
782− -- Reversing the output is important to guarantee that we process the
783− -- outputs in the same order as they were generated by the constituent
784− -- streams.
785− return $ Skip $ FromSVarLoop sv (Prelude.reverse list)
786−
787− step _ (FromSVarLoop sv []) = return $ Skip $ FromSVarRead sv
788− step _ (FromSVarLoop sv (ev : es)) = do
789− case ev of
790− ChildYield a -> return $ Yield a (FromSVarLoop sv es)
791− ChildStop tid e -> do
792− accountThread sv tid
793− case e of
794− Nothing -> do
795− sendStopToProducer sv
796− return $ Skip (FromSVarDone sv)
797− Just _ -> error "Bug: fromProducer: received exception"
798−
799− step _ (FromSVarDone sv) = do
800− when (svarInspectMode sv) $ do
801− t <- liftIO $ getTime Monotonic
802− liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
803− liftIO $ printSVar sv "SVar Done"
804− return Stop
805−
806− step _ FromSVarInit = undefined
807−
808−-------------------------------------------------------------------------------
809−-- Hoisting the inner monad
810−-------------------------------------------------------------------------------
811−
812−{-# INLINE_NORMAL hoist #-}
813−hoist :: Monad n => (forall x. m x -> n x) -> Stream m a -> Stream n a
814−hoist f (Stream step state) = (Stream step' state)
815− where
816− {-# INLINE_LATE step' #-}
817− step' gst st = do
818− r <- f $ step (adaptState gst) st
819− return $ case r of
820− Yield x s -> Yield x s
821− Skip s -> Skip s
822− Stop -> Stop
823−
824−{-# INLINE generally #-}
825−generally :: Monad m => Stream Identity a -> Stream m a
826−generally = hoist (return . runIdentity)
827−
828−{-# INLINE_NORMAL liftInner #-}
829−liftInner :: (Monad m, MonadTrans t, Monad (t m))
830− => Stream m a -> Stream (t m) a
831−liftInner (Stream step state) = Stream step' state
832− where
833− {-# INLINE_LATE step' #-}
834− step' gst st = do
835− r <- lift $ step (adaptState gst) st
836− return $ case r of
837− Yield x s -> Yield x s
838− Skip s -> Skip s
839− Stop -> Stop
840−
841−{-# INLINE_NORMAL runReaderT #-}
842−runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
843−runReaderT env (Stream step state) = Stream step' (state, env)
844− where
845− {-# INLINE_LATE step' #-}
846− step' gst (st, action) = do
847− sv <- action
848− r <- Reader.runReaderT (step (adaptState gst) st) sv
849− return $ case r of
850− Yield x s -> Yield x (s, return sv)
851− Skip s -> Skip (s, return sv)
852− Stop -> Stop
853−
854−{-# INLINE_NORMAL evalStateT #-}
855−evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
856−evalStateT initial (Stream step state) = Stream step' (state, initial)
857− where
858− {-# INLINE_LATE step' #-}
859− step' gst (st, action) = do
860− sv <- action
861− (r, sv') <- State.runStateT (step (adaptState gst) st) sv
862− return $ case r of
863− Yield x s -> Yield x (s, return sv')
864− Skip s -> Skip (s, return sv')
865− Stop -> Stop
866−
867−{-# INLINE_NORMAL runStateT #-}
868−runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
869−runStateT initial (Stream step state) = Stream step' (state, initial)
870− where
871− {-# INLINE_LATE step' #-}
872− step' gst (st, action) = do
873− sv <- action
874− (r, sv') <- State.runStateT (step (adaptState gst) st) sv
875− return $ case r of
876− Yield x s -> Yield (sv', x) (s, return sv')
877− Skip s -> Skip (s, return sv')
878− Stop -> Stop
879−
880−------------------------------------------------------------------------------
881−-- Elimination by Folds
882−------------------------------------------------------------------------------
883−
884−------------------------------------------------------------------------------
885−-- Right Folds
886−------------------------------------------------------------------------------
887−
888−{-# INLINE_NORMAL foldr1 #-}
889−foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
890−foldr1 f m = do
891− r <- uncons m
892− case r of
893− Nothing -> return Nothing
894− Just (h, t) -> fmap Just (foldr f h t)
895−
896−------------------------------------------------------------------------------
897−-- Left Folds
898−------------------------------------------------------------------------------
899−
900−{-# INLINE_NORMAL foldlT #-}
901−foldlT :: (Monad m, Monad (s m), MonadTrans s)
902− => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
903−foldlT fstep begin (Stream step state) = go SPEC begin state
904− where
905− go !_ acc st = do
906− r <- lift $ step defState st
907− case r of
908− Yield x s -> go SPEC (fstep acc x) s
909− Skip s -> go SPEC acc s
910− Stop -> acc
911−
912−-- Note, this is going to have horrible performance, because of the nature of
913−-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
914−-- likely be practically unusable.
915−{-# INLINE_NORMAL foldlS #-}
916−foldlS :: Monad m
917− => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
918−foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
919− where
920− step' gst (Left (st, acc)) = do
921− r <- step (adaptState gst) st
922− return $ case r of
923− Yield x s -> Skip (Left (s, fstep acc x))
924− Skip s -> Skip (Left (s, acc))
925− Stop -> Skip (Right acc)
926−
927− step' gst (Right (Stream stp stt)) = do
928− r <- stp (adaptState gst) stt
929− return $ case r of
930− Yield x s -> Yield x (Right (Stream stp s))
931− Skip s -> Skip (Right (Stream stp s))
932− Stop -> Stop
933−
934−------------------------------------------------------------------------------
935−-- Parses
936−------------------------------------------------------------------------------
937−
938−-- Inlined definition. Without the inline "serially/parser/take" benchmark
939−-- degrades and parseMany does not fuse. Even using "inline" at the callsite
940−-- does not help.
941−{-# INLINE splitAt #-}
942−splitAt :: Int -> [a] -> ([a],[a])
943−splitAt n ls
944− | n <= 0 = ([], ls)
945− | otherwise = splitAt' n ls
946− where
947− splitAt' :: Int -> [a] -> ([a], [a])
948− splitAt' _ [] = ([], [])
949− splitAt' 1 (x:xs) = ([x], xs)
950− splitAt' m (x:xs) = (x:xs', xs'')
951− where
952− (xs', xs'') = splitAt' (m - 1) xs
953−
954−-- GHC parser does not accept {-# ANN type [] NoSpecConstr #-}, so we need
955−-- to make a newtype.
956−{-# ANN type List NoSpecConstr #-}
957−newtype List a = List {getList :: [a]}
958−
959−-- | Run a 'Parse' over a stream.
960−{-# INLINE_NORMAL parselMx' #-}
961−parselMx'
962− :: MonadThrow m
963− => (s -> a -> m (PR.Step s b))
964− -> m s
965− -> (s -> m b)
966− -> Stream m a
967− -> m b
968−parselMx' pstep initial extract (Stream step state) = do
969− initial >>= go SPEC state (List [])
970−
971− where
972−
973− -- XXX currently we are using a dumb list based approach for backtracking
974− -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
975− -- That will allow us more efficient random back and forth movement.
976− {-# INLINE go #-}
977− go !_ st buf !pst = do
978− r <- step defState st
979− case r of
980− Yield x s -> do
981− pRes <- pstep pst x
982− case pRes of
983− PR.Partial 0 pst1 -> go SPEC s (List []) pst1
984− PR.Partial n pst1 -> do
985− assert (n <= length (x:getList buf)) (return ())
986− let src0 = Prelude.take n (x:getList buf)
987− src = Prelude.reverse src0
988− gobuf SPEC s (List []) (List src) pst1
989− PR.Continue 0 pst1 -> go SPEC s (List (x:getList buf)) pst1
990− PR.Continue n pst1 -> do
991− assert (n <= length (x:getList buf)) (return ())
992− let (src0, buf1) = splitAt n (x:getList buf)
993− src = Prelude.reverse src0
994− gobuf SPEC s (List buf1) (List src) pst1
995− PR.Done _ b -> return b
996− PR.Error err -> throwM $ ParseError err
997− Skip s -> go SPEC s buf pst
998− Stop -> extract pst
999−
1000− gobuf !_ s buf (List []) !pst = go SPEC s buf pst
1001− gobuf !_ s buf (List (x:xs)) !pst = do
1002− pRes <- pstep pst x
1003− case pRes of
1004− PR.Partial 0 pst1 ->
1005− gobuf SPEC s (List []) (List xs) pst1
1006− PR.Partial n pst1 -> do
1007− assert (n <= length (x:getList buf)) (return ())
1008− let src0 = Prelude.take n (x:getList buf)
1009− src = Prelude.reverse src0 ++ xs
1010− gobuf SPEC s (List []) (List src) pst1
1011− PR.Continue 0 pst1 ->
1012− gobuf SPEC s (List (x:getList buf)) (List xs) pst1
1013− PR.Continue n pst1 -> do
1014− assert (n <= length (x:getList buf)) (return ())
1015− let (src0, buf1) = splitAt n (x:getList buf)
1016− src = Prelude.reverse src0 ++ xs
1017− gobuf SPEC s (List buf1) (List src) pst1
1018− PR.Done _ b -> return b
1019− PR.Error err -> throwM $ ParseError err
1020−
1021−------------------------------------------------------------------------------
1022−-- Repeated parsing
1023−------------------------------------------------------------------------------
1024−
1025−{-# ANN type ParseChunksState Fuse #-}
1026−data ParseChunksState x inpBuf st pst =
1027− ParseChunksInit inpBuf st
1028− | ParseChunksInitLeftOver inpBuf
1029− | ParseChunksStream st inpBuf !pst
1030− | ParseChunksBuf inpBuf st inpBuf !pst
1031− | ParseChunksYield x (ParseChunksState x inpBuf st pst)
1032−
1033−{-# INLINE_NORMAL parseMany #-}
1034−parseMany
1035− :: MonadThrow m
1036− => PRD.Parser m a b
1037− -> Stream m a
1038− -> Stream m b
1039−parseMany (PRD.Parser pstep initial extract) (Stream step state) =
1040− Stream stepOuter (ParseChunksInit [] state)
1041−
1042− where
1043−
1044− {-# INLINE_LATE stepOuter #-}
1045− -- Buffer is empty, get the first element from the stream, initialize the
1046− -- fold and then go to stream processing loop.
1047− stepOuter gst (ParseChunksInit [] st) = do
1048− r <- step (adaptState gst) st
1049− case r of
1050− Yield x s -> initial >>= return . Skip . ParseChunksBuf [x] s []
1051− Skip s -> return $ Skip $ ParseChunksInit [] s
1052− Stop -> return Stop
1053−
1054− -- Buffer is not empty, go to buffered processing loop
1055− stepOuter _ (ParseChunksInit src st) = do
1056− initial >>= return . Skip . ParseChunksBuf src st []
1057−
1058− -- XXX we just discard any leftover input at the end
1059− stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1060−
1061− -- Buffer is empty, process elements from the stream
1062− stepOuter gst (ParseChunksStream st buf pst) = do
1063− r <- step (adaptState gst) st
1064− case r of
1065− Yield x s -> do
1066− pRes <- pstep pst x
1067− case pRes of
1068− PR.Partial 0 pst1 ->
1069− return $ Skip $ ParseChunksStream s [] pst1
1070− PR.Partial n pst1 -> do
1071− assert (n <= length (x:buf)) (return ())
1072− let src0 = Prelude.take n (x:buf)
1073− src = Prelude.reverse src0
1074− return $ Skip $ ParseChunksBuf src s [] pst1
1075− PR.Continue 0 pst1 ->
1076− return $ Skip $ ParseChunksStream s (x:buf) pst1
1077− PR.Continue n pst1 -> do
1078− assert (n <= length (x:buf)) (return ())
1079− let (src0, buf1) = splitAt n (x:buf)
1080− src = Prelude.reverse src0
1081− return $ Skip $ ParseChunksBuf src s buf1 pst1
1082− PR.Done 0 b -> do
1083− return $ Skip $
1084− ParseChunksYield b (ParseChunksInit [] s)
1085− PR.Done n b -> do
1086− assert (n <= length (x:buf)) (return ())
1087− let src = Prelude.reverse (Prelude.take n (x:buf))
1088− return $ Skip $
1089− ParseChunksYield b (ParseChunksInit src s)
1090− PR.Error err -> throwM $ ParseError err
1091− Skip s -> return $ Skip $ ParseChunksStream s buf pst
1092− Stop -> do
1093− b <- extract pst
1094− let src = Prelude.reverse buf
1095− return $ Skip $
1096− ParseChunksYield b (ParseChunksInitLeftOver src)
1097−
1098− -- go back to stream processing mode
1099− stepOuter _ (ParseChunksBuf [] s buf pst) =
1100− return $ Skip $ ParseChunksStream s buf pst
1101−
1102− -- buffered processing loop
1103− stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1104− pRes <- pstep pst x
1105− case pRes of
1106− PR.Partial 0 pst1 ->
1107− return $ Skip $ ParseChunksBuf xs s [] pst1
1108− PR.Partial n pst1 -> do
1109− assert (n <= length (x:buf)) (return ())
1110− let src0 = Prelude.take n (x:buf)
1111− src = Prelude.reverse src0 ++ xs
1112− return $ Skip $ ParseChunksBuf src s [] pst1
1113− PR.Continue 0 pst1 ->
1114− return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1115− PR.Continue n pst1 -> do
1116− assert (n <= length (x:buf)) (return ())
1117− let (src0, buf1) = splitAt n (x:buf)
1118− src = Prelude.reverse src0 ++ xs
1119− return $ Skip $ ParseChunksBuf src s buf1 pst1
1120− PR.Done 0 b ->
1121− return $ Skip $ ParseChunksYield b (ParseChunksInit xs s)
1122− PR.Done n b -> do
1123− assert (n <= length (x:buf)) (return ())
1124− let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1125− return $ Skip $ ParseChunksYield b (ParseChunksInit src s)
1126− PR.Error err -> throwM $ ParseError err
1127−
1128− stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1129−
1130−{-# ANN type ConcatParseState Fuse #-}
1131−data ConcatParseState x inpBuf st p =
1132− ConcatParseInit inpBuf st p
1133− | ConcatParseInitLeftOver inpBuf
1134− | ConcatParseStream st inpBuf p
1135− | ConcatParseBuf inpBuf st inpBuf p
1136− | ConcatParseYield x (ConcatParseState x inpBuf st p)
1137−
1138−{-# INLINE_NORMAL parseIterate #-}
1139−parseIterate
1140− :: MonadThrow m
1141− => (b -> PRD.Parser m a b)
1142− -> b
1143− -> Stream m a
1144− -> Stream m b
1145−parseIterate func seed (Stream step state) =
1146− Stream stepOuter (ConcatParseInit [] state (func seed))
1147−
1148− where
1149−
1150− {-# INLINE_LATE stepOuter #-}
1151− -- Buffer is empty, go to stream processing loop
1152− stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1153− initial >>= \r -> return $ Skip $ ConcatParseStream st []
1154− (PRD.Parser pstep (return r) extract)
1155−
1156− -- Buffer is not empty, go to buffered processing loop
1157− stepOuter _ (ConcatParseInit src st
1158− (PRD.Parser pstep initial extract)) = do
1159− initial >>= \r -> return $ Skip $ ConcatParseBuf src st []
1160− (PRD.Parser pstep (return r) extract)
1161−
1162− -- XXX we just discard any leftover input at the end
1163− stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1164−
1165− -- Buffer is empty process elements from the stream
1166− stepOuter gst (ConcatParseStream st buf
1167− p@(PRD.Parser pstep initial extract)) = do
1168− r <- step (adaptState gst) st
1169− case r of
1170− Yield x s -> do
1171− pst <- initial
1172− pRes <- pstep pst x
1173− case pRes of
1174− PR.Partial 0 pst1 ->
1175− return $ Skip $ ConcatParseStream s []
1176− (PRD.Parser pstep (return pst1) extract)
1177− PR.Partial n pst1 -> do
1178− assert (n <= length (x:buf)) (return ())
1179− let src0 = Prelude.take n (x:buf)
1180− src = Prelude.reverse src0
1181− return $ Skip $ ConcatParseBuf src s []
1182− (PRD.Parser pstep (return pst1) extract)
1183− -- PR.Continue 0 pst1 ->
1184− -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1185− PR.Continue n pst1 -> do
1186− assert (n <= length (x:buf)) (return ())
1187− let (src0, buf1) = splitAt n (x:buf)
1188− src = Prelude.reverse src0
1189− return $ Skip $ ConcatParseBuf src s buf1
1190− (PRD.Parser pstep (return pst1) extract)
1191− -- XXX Specialize for Stop 0 common case?
1192− PR.Done n b -> do
1193− assert (n <= length (x:buf)) (return ())
1194− let src = Prelude.reverse (Prelude.take n (x:buf))
1195− return $ Skip $
1196− ConcatParseYield b (ConcatParseInit src s (func b))
1197− PR.Error err -> throwM $ ParseError err
1198− Skip s -> return $ Skip $ ConcatParseStream s buf p
1199− Stop -> do
1200− pst <- initial
1201− b <- extract pst
1202− let src = Prelude.reverse buf
1203− return $ Skip $
1204− ConcatParseYield b (ConcatParseInitLeftOver src)
1205−
1206− -- go back to stream processing mode
1207− stepOuter _ (ConcatParseBuf [] s buf p) =
1208− return $ Skip $ ConcatParseStream s buf p
1209−
1210− -- buffered processing loop
1211− stepOuter _ (ConcatParseBuf (x:xs) s buf
1212− (PRD.Parser pstep initial extract)) = do
1213− pst <- initial
1214− pRes <- pstep pst x
1215− case pRes of
1216− PR.Partial 0 pst1 ->
1217− return $ Skip $ ConcatParseBuf xs s []
1218− (PRD.Parser pstep (return pst1) extract)
1219− PR.Partial n pst1 -> do
1220− assert (n <= length (x:buf)) (return ())
1221− let src0 = Prelude.take n (x:buf)
1222− src = Prelude.reverse src0 ++ xs
1223− return $ Skip $ ConcatParseBuf src s []
1224− (PRD.Parser pstep (return pst1) extract)
1225− -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1226− PR.Continue n pst1 -> do
1227− assert (n <= length (x:buf)) (return ())
1228− let (src0, buf1) = splitAt n (x:buf)
1229− src = Prelude.reverse src0 ++ xs
1230− return $ Skip $ ConcatParseBuf src s buf1
1231− (PRD.Parser pstep (return pst1) extract)
1232− -- XXX Specialize for Stop 0 common case?
1233− PR.Done n b -> do
1234− assert (n <= length (x:buf)) (return ())
1235− let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1236− return $ Skip $ ConcatParseYield b
1237− (ConcatParseInit src s (func b))
1238− PR.Error err -> throwM $ ParseError err
1239−
1240− stepOuter _ (ConcatParseYield a next) = return $ Yield a next
1241−
1242−------------------------------------------------------------------------------
1243−-- Specialized Folds
1244−------------------------------------------------------------------------------
1245−
1246−-- | Run a streaming composition, discard the results.
1247−{-# INLINE_LATE drain #-}
1248−drain :: Monad m => Stream m a -> m ()
1249−-- drain = foldrM (\_ xs -> xs) (return ())
1250−drain (Stream step state) = go SPEC state
1251− where
1252− go !_ st = do
1253− r <- step defState st
1254− case r of
1255− Yield _ s -> go SPEC s
1256− Skip s -> go SPEC s
1257− Stop -> return ()
1258−
1259−{-# INLINE_NORMAL null #-}
1260−null :: Monad m => Stream m a -> m Bool
1261−null m = foldrM (\_ _ -> return False) (return True) m
1262−
1263−{-# INLINE_NORMAL head #-}
1264−head :: Monad m => Stream m a -> m (Maybe a)
1265−head m = foldrM (\x _ -> return (Just x)) (return Nothing) m
1266−
1267−{-# INLINE_NORMAL headElse #-}
1268−headElse :: Monad m => a -> Stream m a -> m a
1269−headElse a m = foldrM (\x _ -> return x) (return a) m
1270−
1271−-- Does not fuse, has the same performance as the StreamK version.
1272−{-# INLINE_NORMAL tail #-}
1273−tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
1274−tail (UnStream step state) = go state
1275− where
1276− go st = do
1277− r <- step defState st
1278− case r of
1279− Yield _ s -> return (Just $ Stream step s)
1280− Skip s -> go s
1281− Stop -> return Nothing
1282−
1283−-- XXX will it fuse? need custom impl?
1284−{-# INLINE_NORMAL last #-}
1285−last :: Monad m => Stream m a -> m (Maybe a)
1286−last = foldl' (\_ y -> Just y) Nothing
1287−
1288−{-# INLINE_NORMAL elem #-}
1289−elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
1290−-- elem e m = foldrM (\x xs -> if x == e then return True else xs) (return False) m
1291−elem e (Stream step state) = go state
1292− where
1293− go st = do
1294− r <- step defState st
1295− case r of
1296− Yield x s
1297− | x == e -> return True
1298− | otherwise -> go s
1299− Skip s -> go s
1300− Stop -> return False
1301−
1302−{-# INLINE_NORMAL notElem #-}
1303−notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
1304−notElem e s = fmap not (elem e s)
1305−
1306−{-# INLINE_NORMAL all #-}
1307−all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
1308−-- all p m = foldrM (\x xs -> if p x then xs else return False) (return True) m
1309−all p (Stream step state) = go state
1310− where
1311− go st = do
1312− r <- step defState st
1313− case r of
1314− Yield x s
1315− | p x -> go s
1316− | otherwise -> return False
1317− Skip s -> go s
1318− Stop -> return True
1319−
1320−{-# INLINE_NORMAL any #-}
1321−any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
1322−-- any p m = foldrM (\x xs -> if p x then return True else xs) (return False) m
1323−any p (Stream step state) = go state
1324− where
1325− go st = do
1326− r <- step defState st
1327− case r of
1328− Yield x s
1329− | p x -> return True
1330− | otherwise -> go s
1331− Skip s -> go s
1332− Stop -> return False
1333−
1334−{-# INLINE_NORMAL maximum #-}
1335−maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
1336−maximum (Stream step state) = go Nothing state
1337− where
1338− go Nothing st = do
1339− r <- step defState st
1340− case r of
1341− Yield x s -> go (Just x) s
1342− Skip s -> go Nothing s
1343− Stop -> return Nothing
1344− go (Just acc) st = do
1345− r <- step defState st
1346− case r of
1347− Yield x s
1348− | acc <= x -> go (Just x) s
1349− | otherwise -> go (Just acc) s
1350− Skip s -> go (Just acc) s
1351− Stop -> return (Just acc)
1352−
1353−{-# INLINE_NORMAL maximumBy #-}
1354−maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
1355−maximumBy cmp (Stream step state) = go Nothing state
1356− where
1357− go Nothing st = do
1358− r <- step defState st
1359− case r of
1360− Yield x s -> go (Just x) s
1361− Skip s -> go Nothing s
1362− Stop -> return Nothing
1363− go (Just acc) st = do
1364− r <- step defState st
1365− case r of
1366− Yield x s -> case cmp acc x of
1367− GT -> go (Just acc) s
1368− _ -> go (Just x) s
1369− Skip s -> go (Just acc) s
1370− Stop -> return (Just acc)
1371−
1372−{-# INLINE_NORMAL minimum #-}
1373−minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
1374−minimum (Stream step state) = go Nothing state
1375− where
1376− go Nothing st = do
1377− r <- step defState st
1378− case r of
1379− Yield x s -> go (Just x) s
1380− Skip s -> go Nothing s
1381− Stop -> return Nothing
1382− go (Just acc) st = do
1383− r <- step defState st
1384− case r of
1385− Yield x s
1386− | acc <= x -> go (Just acc) s
1387− | otherwise -> go (Just x) s
1388− Skip s -> go (Just acc) s
1389− Stop -> return (Just acc)
1390−
1391−{-# INLINE_NORMAL minimumBy #-}
1392−minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
1393−minimumBy cmp (Stream step state) = go Nothing state
1394− where
1395− go Nothing st = do
1396− r <- step defState st
1397− case r of
1398− Yield x s -> go (Just x) s
1399− Skip s -> go Nothing s
1400− Stop -> return Nothing
1401− go (Just acc) st = do
1402− r <- step defState st
1403− case r of
1404− Yield x s -> case cmp acc x of
1405− GT -> go (Just x) s
1406− _ -> go (Just acc) s
1407− Skip s -> go (Just acc) s
1408− Stop -> return (Just acc)
1409−
1410−{-# INLINE_NORMAL (!!) #-}
1411−(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
1412−(Stream step state) !! i = go i state
1413− where
1414− go n st = do
1415− r <- step defState st
1416− case r of
1417− Yield x s | n < 0 -> return Nothing
1418− | n == 0 -> return $ Just x
1419− | otherwise -> go (n - 1) s
1420− Skip s -> go n s
1421− Stop -> return Nothing
1422−
1423−{-# INLINE_NORMAL lookup #-}
1424−lookup :: (Monad m, Eq a) => a -> Stream m (a, b) -> m (Maybe b)
1425−lookup e m = foldrM (\(a, b) xs -> if e == a then return (Just b) else xs)
1426− (return Nothing) m
1427308
1428−{-# INLINE_NORMAL findM #-}
1429−findM :: Monad m => (a -> m Bool) -> Stream m a -> m (Maybe a)
1430−findM p m = foldrM (\x xs -> p x >>= \r -> if r then return (Just x) else xs)
1431− (return Nothing) m
1432−
1433−{-# INLINE find #-}
1434−find :: Monad m => (a -> Bool) -> Stream m a -> m (Maybe a)
1435−find p = findM (return . p)
1436−
1437−{-# INLINE_NORMAL findIndices #-}
1438−findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
1439−findIndices p (Stream step state) = Stream step' (state, 0)
1440− where
1441− {-# INLINE_LATE step' #-}
1442− step' gst (st, i) = i `seq` do
1443− r <- step (adaptState gst) st
1444− return $ case r of
1445− Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
1446− Skip s -> Skip (s, i)
1447− Stop -> Stop
1448−
1449−{-# INLINE toListRev #-}
1450−toListRev :: Monad m => Stream m a -> m [a]
1451−toListRev = foldl' (flip (:)) []
1452−
1453−-- We can implement reverse as:
1454−--
1455−-- > reverse = foldlS (flip cons) nil
1456−--
1457−-- However, this implementation is unusable because of the horrible performance
1458−-- of cons. So we just convert it to a list first and then stream from the
1459−-- list.
1460−--
1461−-- XXX Maybe we can use an Array instead of a list here?
1462−{-# INLINE_NORMAL reverse #-}
1463−reverse :: Monad m => Stream m a -> Stream m a
1464−reverse m = Stream step Nothing
1465− where
1466− {-# INLINE_LATE step #-}
1467− step _ Nothing = do
1468− xs <- toListRev m
1469− return $ Skip (Just xs)
1470− step _ (Just (x:xs)) = return $ Yield x (Just xs)
1471− step _ (Just []) = return Stop
1472−
1473−-- Much faster reverse for Storables
1474−{-# INLINE_NORMAL reverse' #-}
1475−reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
1476−{-
1477−-- This commented implementation copies the whole stream into one single array
1478−-- and then streams from that array, this is 3-4x faster than the chunked code
1479−-- that follows. Though this could be problematic due to unbounded large
1480−-- allocations. We need to figure out why the chunked code is slower and if we
1481−-- can optimize the chunked code to work as fast as this one. It may be a
1482−-- fusion issue?
1483−import Foreign.ForeignPtr (touchForeignPtr)
1484−import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
1485−import Foreign.Ptr (Ptr, plusPtr)
1486−reverse' m = Stream step Nothing
1487− where
1488− {-# INLINE_LATE step #-}
1489− step _ Nothing = do
1490− arr <- A.fromStreamD m
1491− let p = aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
1492− return $ Skip $ Just (aStart arr, p)
1493−
1494− step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
1495−
1496− step _ (Just (start, p)) = do
1497− let !x = A.unsafeInlineIO $ do
1498− r <- peek p
1499− touchForeignPtr start
1500− return r
1501− next = p `plusPtr` negate (sizeOf (undefined :: a))
1502− return $ Yield x (Just (start, next))
1503−-}
1504−reverse' m =
1505− A.flattenArraysRev
1506− $ fromStreamK
1507− $ K.reverse
1508− $ toStreamK
1509− $ A.fromStreamDArraysOf A.defaultChunkSize m
1510−
1511−
1512−------------------------------------------------------------------------------
1513−-- Grouping/Splitting
1514−------------------------------------------------------------------------------
1515−
1516−{-# INLINE_NORMAL groupsBy #-}
1517−groupsBy :: Monad m
1518− => (a -> a -> Bool)
1519− -> Fold m a b
1520− -> Stream m a
1521− -> Stream m b
1522−groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
1523−
1524− where
1525−
1526− {-# INLINE_LATE stepOuter #-}
1527− stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1528− res <- step (adaptState gst) st
1529− case res of
1530− Yield x s -> do
1531− fs <- initial
1532− r <- fstep fs x
1533− case r of
1534− FL.Partial fs1 -> go SPEC x s fs1
1535− FL.Done b -> return $ Yield b (Just s, Just x)
1536− Skip s -> return $ Skip (Just s, Nothing)
1537− Stop -> return Stop
1538−
1539− where
1540−
1541− go !_ prev stt !acc = do
1542− res <- step (adaptState gst) stt
1543− case res of
1544− Yield x s -> do
1545− if cmp x prev
1546− then do
1547− r <- fstep acc x
1548− case r of
1549− FL.Partial fs1 -> go SPEC prev s fs1
1550− FL.Done b -> return $ Yield b (Just s, Just x)
1551− else done acc >>= \r -> return $ Yield r (Just s, Just x)
1552− Skip s -> go SPEC prev s acc
1553− Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1554− stepOuter (Fold fstep initial done) gst (Just st, Just prev) = do
1555− fs <- initial
1556− r <- fstep fs prev
1557− case r of
1558− FL.Partial fs1 -> go SPEC st fs1
1559− FL.Done b -> return $ Yield b (Just st, Nothing)
1560−
1561− where
1562−
1563− -- XXX code duplicated from the previous equation
1564− go !_ stt !acc = do
1565− res <- step (adaptState gst) stt
1566− case res of
1567− Yield x s -> do
1568− if cmp x prev
1569− then do
1570− r <- fstep acc x
1571− case r of
1572− FL.Partial fs1 -> go SPEC s fs1
1573− FL.Done b -> return $ Yield b (Just s, Just x)
1574− else done acc >>= \r -> return $ Yield r (Just s, Just x)
1575− Skip s -> go SPEC s acc
1576− Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1577− stepOuter _ _ (Nothing, _) = return Stop
1578−
1579−{-# INLINE_NORMAL groupsRollingBy #-}
1580−groupsRollingBy :: Monad m
1581− => (a -> a -> Bool)
1582− -> Fold m a b
1583− -> Stream m a
1584− -> Stream m b
1585−groupsRollingBy cmp f (Stream step state) =
1586− Stream (stepOuter f) (Just state, Nothing)
1587−
1588− where
1589−
1590− {-# INLINE_LATE stepOuter #-}
1591− stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1592− res <- step (adaptState gst) st
1593− case res of
1594− Yield x s -> do
1595− fs <- initial
1596− r <- fstep fs x
1597− case r of
1598− FL.Partial fs1 -> go SPEC x s fs1
1599− FL.Done b -> return $ Yield b (Just s, Just x)
1600− Skip s -> return $ Skip $ (Just s, Nothing)
1601− Stop -> return Stop
1602−
1603− where
1604−
1605− go !_ prev stt !acc = do
1606− res <- step (adaptState gst) stt
1607− case res of
1608− Yield x s -> do
1609− if cmp prev x
1610− then do
1611− r <- fstep acc x
1612− case r of
1613− FL.Partial fs1 -> go SPEC x s fs1
1614− FL.Done b -> return $ Yield b (Just s, Just x)
1615− else done acc >>= \r -> return $ Yield r (Just s, Just x)
1616− Skip s -> go SPEC prev s acc
1617− Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1618− stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1619− fs <- initial
1620− r <- fstep fs prev'
1621− case r of
1622− FL.Partial fs1 -> go SPEC prev' st fs1
1623− FL.Done b -> return $ Yield b (Just st, Nothing)
1624−
1625− where
1626−
1627− go !_ prevv stt !acc = do
1628− res <- step (adaptState gst) stt
1629− case res of
1630− Yield x s -> do
1631− if cmp prevv x
1632− then do
1633− r <- fstep acc x
1634− case r of
1635− FL.Partial fs1 -> go SPEC x s fs1
1636− FL.Done b -> return $ Yield b (Just s, Just x)
1637− else done acc >>= \r -> return $ Yield r (Just s, Just x)
1638− Skip s -> go SPEC prevv s acc
1639− Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1640− stepOuter _ _ (Nothing, _) = return Stop
1641−
1642−data WordsByState s = WordsByJust s | WordsByNothing
1643−
1644−{-# INLINE_NORMAL wordsBy #-}
1645−wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1646−wordsBy predicate f (Stream step state) =
1647− Stream (stepOuter f) (WordsByJust state)
1648−
1649− where
1650−
1651− {-# INLINE_LATE stepOuter #-}
1652− stepOuter (Fold fstep initial done) gst (WordsByJust st) = do
1653− res <- step (adaptState gst) st
1654− case res of
1655− Yield x s -> do
1656− if predicate x
1657− then return $ Skip (WordsByJust s)
1658− else do
1659− fs <- initial
1660− r <- fstep fs x
1661− case r of
1662− FL.Partial fs1 -> go SPEC s fs1
1663− FL.Done b -> return $ Yield b (WordsByJust s)
1664−
1665− Skip s -> return $ Skip $ WordsByJust s
1666− Stop -> return Stop
1667−
1668− where
1669−
1670− go !_ stt !acc = do
1671− res <- step (adaptState gst) stt
1672− case res of
1673− Yield x s -> do
1674− if predicate x
1675− then done acc >>= \r -> return $ Yield r (WordsByJust s)
1676− else do
1677− r <- fstep acc x
1678− case r of
1679− FL.Partial fs1 -> go SPEC s fs1
1680− FL.Done b -> return $ Yield b (WordsByJust s)
1681− Skip s -> go SPEC s acc
1682− Stop -> done acc >>= \r -> return $ Yield r WordsByNothing
1683−
1684− stepOuter _ _ WordsByNothing = return Stop
1685−
1686−-- String search algorithms:
1687−-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1688−
1689−{-
1690−-- TODO can we unify the splitting operations using a splitting configuration
1691−-- like in the split package.
1692−--
1693−data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1694−
1695−data SplitOptions = SplitOptions
1696− { style :: SplitStyle
1697− , withSep :: Bool -- ^ keep the separators in output
1698− -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1699− -- , trimHead :: Bool -- ^ drop blank at head
1700− -- , trimTail :: Bool -- ^ drop blank at tail
1701− }
1702−-}
1703−
1704−{-# ANN type SplitOnSeqState Fuse #-}
1705−data SplitOnSeqState rb rh ck w fs s b x =
1706− SplitOnSeqInit
1707− | SplitOnSeqYield b (SplitOnSeqState rb rh ck w fs s b x)
1708− | SplitOnSeqDone
1709−
1710− | SplitOnSeqEmpty s
1711−
1712− | SplitOnSeqSingle !fs s x
1713−
1714− | SplitOnSeqWordInit s
1715− | SplitOnSeqWordLoop !w s !fs
1716− | SplitOnSeqWordDone Int !fs !w
1717−
1718− | SplitOnSeqKRInit Int s rb !rh
1719− | SplitOnSeqKRLoop fs s rb !rh !ck
1720− | SplitOnSeqKRCheck fs s rb !rh
1721− | SplitOnSeqKRDone Int !fs rb !rh
1722−
1723−{-# INLINE_NORMAL splitOnSeq #-}
1724−splitOnSeq
1725− :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1726− => Array a
1727− -> Fold m a b
1728− -> Stream m a
1729− -> Stream m b
1730−splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1731− Stream stepOuter SplitOnSeqInit
1732−
1733− where
1734−
1735− patLen = A.length patArr
1736− maxIndex = patLen - 1
1737− elemBits = sizeOf (undefined :: a) * 8
1738−
1739− -- For word pattern case
1740− wordMask :: Word
1741− wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1742−
1743− elemMask :: Word
1744− elemMask = (1 `shiftL` elemBits) - 1
1745−
1746− wordPat :: Word
1747− wordPat = wordMask .&. A.foldl' addToWord 0 patArr
1748−
1749− addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1750−
1751− -- For Rabin-Karp search
1752− k = 2891336453 :: Word32
1753− coeff = k ^ patLen
1754−
1755− addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1756−
1757− deltaCksum cksum old new =
1758− addCksum cksum new - coeff * fromIntegral (fromEnum old)
1759−
1760− -- XXX shall we use a random starting hash or 1 instead of 0?
1761− patHash = A.foldl' addCksum 0 patArr
1762−
1763− skip = return . Skip
1764−
1765− {-# INLINE_LATE stepOuter #-}
1766− stepOuter _ SplitOnSeqInit =
1767− if patLen == 0
1768− then return $ Skip $ SplitOnSeqEmpty state
1769− else if patLen == 1
1770− then do
1771− acc <- initial
1772− pat <- liftIO $ A.unsafeIndexIO patArr 0
1773− return $ Skip $ SplitOnSeqSingle acc state pat
1774− else if sizeOf (undefined :: a) * patLen
1775− <= sizeOf (undefined :: Word)
1776− then return $ Skip $ SplitOnSeqWordInit state
1777− else do
1778− (rb, rhead) <- liftIO $ RB.new patLen
1779− skip $ SplitOnSeqKRInit 0 state rb rhead
1780−
1781− stepOuter _ (SplitOnSeqYield x next) = return $ Yield x next
1782−
1783− ---------------------------
1784− -- Empty pattern
1785− ---------------------------
1786−
1787− stepOuter gst (SplitOnSeqEmpty st) = do
1788− res <- step (adaptState gst) st
1789− case res of
1790− Yield x s -> do
1791− fs <- initial
1792− r <- fstep fs x
1793− case r of
1794− FL.Partial fs1 -> do
1795− b <- done fs1
1796− skip $ SplitOnSeqYield b (SplitOnSeqEmpty s)
1797− FL.Done b -> skip $ SplitOnSeqYield b (SplitOnSeqEmpty s)
1798−
1799− Skip s -> return $ Skip (SplitOnSeqEmpty s)
1800− Stop -> return Stop
1801−
1802− -----------------
1803− -- Done
1804− -----------------
1805−
1806− stepOuter _ SplitOnSeqDone = return Stop
1807−
1808− -----------------
1809− -- Single Pattern
1810− -----------------
1811−
1812− stepOuter gst (SplitOnSeqSingle fs st pat) = do
1813− res <- step (adaptState gst) st
1814− case res of
1815− Yield x s -> do
1816− if pat == x
1817− then do
1818− r <- done fs
1819− fs1 <- initial
1820− return $ Skip $ SplitOnSeqYield r (SplitOnSeqSingle fs1 s pat)
1821− else do
1822− r <- fstep fs x
1823− case r of
1824− FL.Partial fs1 -> skip $ SplitOnSeqSingle fs1 s pat
1825− FL.Done b -> do
1826− fs1 <- initial
1827− skip $ SplitOnSeqYield b (SplitOnSeqSingle fs1 s pat)
1828− Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
1829− Stop -> do
1830− r <- done fs
1831− return $ Skip $ SplitOnSeqYield r SplitOnSeqDone
1832−
1833− ---------------------------
1834− -- Short Pattern - Shift Or
1835− ---------------------------
1836−
1837− stepOuter _ (SplitOnSeqWordDone 0 fs _) = do
1838− r <- done fs
1839− skip $ SplitOnSeqYield r SplitOnSeqDone
1840− stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
1841− let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1842− r <- fstep fs (toEnum $ fromIntegral old)
1843− case r of
1844− FL.Partial fs1 -> skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
1845− FL.Done b -> do
1846− fs1 <- initial
1847− let next = SplitOnSeqWordDone (n - 1) fs1 wrd
1848− skip $ SplitOnSeqYield b next
1849−
1850− stepOuter gst (SplitOnSeqWordInit st0) =
1851− go SPEC 0 0 st0
1852−
1853− where
1854−
1855− {-# INLINE go #-}
1856− go !_ !idx !wrd !st = do
1857− res <- step (adaptState gst) st
1858− case res of
1859− Yield x s -> do
1860− let wrd1 = addToWord wrd x
1861− if idx == maxIndex
1862− then do
1863− fs <- initial
1864− if wrd1 .&. wordMask == wordPat
1865− then do
1866− r <- done fs
1867− let next = SplitOnSeqWordInit s
1868− skip $ SplitOnSeqYield r next
1869− else skip $ SplitOnSeqWordLoop wrd1 s fs
1870− else go SPEC (idx + 1) wrd1 s
1871− Skip s -> go SPEC idx wrd s
1872− Stop -> do
1873− fs <- initial
1874− if idx /= 0
1875− then skip $ SplitOnSeqWordDone idx fs wrd
1876− else do
1877− r <- done fs
1878− skip $ SplitOnSeqYield r SplitOnSeqDone
1879−
1880− stepOuter gst (SplitOnSeqWordLoop wrd0 st0 fs0) =
1881− go SPEC wrd0 st0 fs0
1882−
1883− where
1884−
1885− {-# INLINE go #-}
1886− go !_ !wrd !st !fs = do
1887− res <- step (adaptState gst) st
1888− case res of
1889− Yield x s -> do
1890− let wrd1 = addToWord wrd x
1891− old = (wordMask .&. wrd)
1892− `shiftR` (elemBits * (patLen - 1))
1893− r <- fstep fs (toEnum $ fromIntegral old)
1894− case r of
1895− FL.Partial fs1 -> do
1896− if wrd1 .&. wordMask == wordPat
1897− then do
1898− b <- done fs1
1899− let next = SplitOnSeqWordInit s
1900− skip $ SplitOnSeqYield b next
1901− else go SPEC wrd1 s fs1
1902− FL.Done b ->
1903− let next = SplitOnSeqWordInit s
1904− in skip $ SplitOnSeqYield b next
1905− Skip s -> go SPEC wrd s fs
1906− Stop -> skip $ SplitOnSeqWordDone patLen fs wrd
1907−
1908− -------------------------------
1909− -- General Pattern - Karp Rabin
1910− -------------------------------
1911−
1912− stepOuter gst (SplitOnSeqKRInit idx st rb rh) = do
1913− res <- step (adaptState gst) st
1914− case res of
1915− Yield x s -> do
1916− rh1 <- liftIO $ RB.unsafeInsert rb rh x
1917− if idx == maxIndex
1918− then do
1919− let fold = RB.unsafeFoldRing (RB.ringBound rb)
1920− let !ringHash = fold addCksum 0 rb
1921− fs <- initial
1922− if ringHash == patHash
1923− then skip $ SplitOnSeqKRCheck fs s rb rh1
1924− else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
1925− else skip $ SplitOnSeqKRInit (idx + 1) s rb rh1
1926− Skip s -> skip $ SplitOnSeqKRInit idx s rb rh
1927− Stop -> do
1928− fs <- initial
1929− skip $ SplitOnSeqKRDone idx fs rb (RB.startOf rb)
1930−
1931− -- XXX The recursive "go" is more efficient than the state based recursion
1932− -- code commented out below. Perhaps its more efficient because of
1933− -- factoring out "rb" outside the loop.
1934− --
1935− stepOuter gst (SplitOnSeqKRLoop fs0 st0 rb rh0 cksum0) =
1936− go SPEC fs0 st0 rh0 cksum0
1937−
1938− where
1939−
1940− go !_ !fs !st !rh !cksum = do
1941− res <- step (adaptState gst) st
1942− case res of
1943− Yield x s -> do
1944− old <- liftIO $ peek rh
1945− let cksum1 = deltaCksum cksum old x
1946− r <- fstep fs old
1947− case r of
1948− FL.Partial fs1 -> do
1949− rh1 <- liftIO (RB.unsafeInsert rb rh x)
1950− if cksum1 == patHash
1951− then skip $ SplitOnSeqKRCheck fs1 s rb rh1
1952− else go SPEC fs1 s rh1 cksum1
1953− FL.Done b ->
1954− let next = SplitOnSeqKRInit 0 s rb (RB.startOf rb)
1955− in skip $ SplitOnSeqYield b next
1956− Skip s -> go SPEC fs s rh cksum
1957− Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1958−
1959− -- XXX The following code is 5 times slower compared to the recursive loop
1960− -- based code above. Need to investigate why. One possibility is that the
1961− -- go loop above does not thread around the ring buffer (rb). This code may
1962− -- be causing the state to bloat and getting allocated on each iteration.
1963− -- We can check the cmm/asm code to confirm. If so a good GHC solution to
1964− -- such problem is needed. One way to avoid this could be to use unboxed
1965− -- mutable state?
1966− {-
1967− stepOuter gst (SplitOnSeqKRLoop fs st rb rh cksum) = do
1968− res <- step (adaptState gst) st
1969− case res of
1970− Yield x s -> do
1971− old <- liftIO $ peek rh
1972− let cksum1 = deltaCksum cksum old x
1973− fs1 <- fstep fs old
1974− if (cksum1 == patHash)
1975− then do
1976− r <- done fs1
1977− skip $ SplitOnSeqYield r $ SplitOnSeqKRInit 0 s rb rh
1978− else do
1979− rh1 <- liftIO (RB.unsafeInsert rb rh x)
1980− skip $ SplitOnSeqKRLoop fs1 s rb rh1 cksum1
1981− Skip s -> skip $ SplitOnSeqKRLoop fs s rb rh cksum
1982− Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1983− -}
1984−
1985− stepOuter _ (SplitOnSeqKRCheck fs st rb rh) = do
1986− if RB.unsafeEqArray rb rh patArr
1987− then do
1988− r <- done fs
1989− let next = SplitOnSeqKRInit 0 st rb (RB.startOf rb)
1990− skip $ SplitOnSeqYield r next
1991− else skip $ SplitOnSeqKRLoop fs st rb rh patHash
1992− stepOuter _ (SplitOnSeqKRDone 0 fs _ _) = do
1993− r <- done fs
1994− skip $ SplitOnSeqYield r SplitOnSeqDone
1995− stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
1996− old <- liftIO $ peek rh
1997− let rh1 = RB.advance rb rh
1998− r <- fstep fs old
1999− case r of
2000− FL.Partial fs1 -> skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
2001− FL.Done b -> do
2002− fs1 <- initial
2003− let next = SplitOnSeqKRDone (n - 1) fs1 rb rh1
2004− skip $ SplitOnSeqYield b next
2005−
2006−{-# ANN type SplitOnSuffixSeqState Fuse #-}
2007−data SplitOnSuffixSeqState rb rh ck w fs s b x =
2008− SplitOnSuffixSeqInit
2009− | SplitOnSuffixSeqYield b (SplitOnSuffixSeqState rb rh ck w fs s b x)
2010− | SplitOnSuffixSeqDone
2011−
2012− | SplitOnSuffixSeqEmpty s
2013−
2014− | SplitOnSuffixSeqSingleInit s x
2015− | SplitOnSuffixSeqSingle !fs s x
2016−
2017− | SplitOnSuffixSeqWordInit s
2018− | SplitOnSuffixSeqWordLoop !w s !fs
2019− | SplitOnSuffixSeqWordDone Int !fs !w
2020−
2021− | SplitOnSuffixSeqKRInit Int s rb !rh
2022− | SplitOnSuffixSeqKRInit1 !fs s rb !rh
2023− | SplitOnSuffixSeqKRLoop fs s rb !rh !ck
2024− | SplitOnSuffixSeqKRCheck fs s rb !rh
2025− | SplitOnSuffixSeqKRDone Int !fs rb !rh
2026−
2027−{-# INLINE_NORMAL splitOnSuffixSeq #-}
2028−splitOnSuffixSeq
2029− :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
2030− => Bool
2031− -> Array a
2032− -> Fold m a b
2033− -> Stream m a
2034− -> Stream m b
2035−splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
2036− Stream stepOuter SplitOnSuffixSeqInit
2037−
2038− where
2039−
2040− patLen = A.length patArr
2041− maxIndex = patLen - 1
2042− elemBits = sizeOf (undefined :: a) * 8
2043−
2044− -- For word pattern case
2045− wordMask :: Word
2046− wordMask = (1 `shiftL` (elemBits * patLen)) - 1
2047−
2048− elemMask :: Word
2049− elemMask = (1 `shiftL` elemBits) - 1
2050−
2051− wordPat :: Word
2052− wordPat = wordMask .&. A.foldl' addToWord 0 patArr
2053−
2054− addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
2055−
2056− -- For single element pattern case
2057− {-# INLINE processYieldSingle #-}
2058− processYieldSingle pat x s fs =
2059− if pat == x
2060− then do
2061− r <- if withSep then fstep fs x else return $ FL.Partial fs
2062− case r of
2063− FL.Partial fs1 -> do
2064− b <- done fs1
2065− let next = SplitOnSuffixSeqSingleInit s pat
2066− skip $ SplitOnSuffixSeqYield b next
2067− FL.Done b ->
2068− let next = SplitOnSuffixSeqSingleInit s pat
2069− in skip $ SplitOnSuffixSeqYield b next
2070− else do
2071− r <- fstep fs x
2072− case r of
2073− FL.Partial fs1 -> skip $ SplitOnSuffixSeqSingle fs1 s pat
2074− FL.Done b ->
2075− let next = SplitOnSuffixSeqSingleInit s pat
2076− in skip $ SplitOnSuffixSeqYield b next
2077−
2078− -- For Rabin-Karp search
2079− k = 2891336453 :: Word32
2080− coeff = k ^ patLen
2081−
2082− addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
2083−
2084− deltaCksum cksum old new =
2085− addCksum cksum new - coeff * fromIntegral (fromEnum old)
2086−
2087− -- XXX shall we use a random starting hash or 1 instead of 0?
2088− patHash = A.foldl' addCksum 0 patArr
2089−
2090− skip = return . Skip
2091−
2092− {-# INLINE_LATE stepOuter #-}
2093− stepOuter _ SplitOnSuffixSeqInit =
2094− if patLen == 0
2095− then skip $ SplitOnSuffixSeqEmpty state
2096− else if patLen == 1
2097− then do
2098− pat <- liftIO $ A.unsafeIndexIO patArr 0
2099− skip $ SplitOnSuffixSeqSingleInit state pat
2100− else if sizeOf (undefined :: a) * patLen
2101− <= sizeOf (undefined :: Word)
2102− then skip $ SplitOnSuffixSeqWordInit state
2103− else do
2104− (rb, rhead) <- liftIO $ RB.new patLen
2105− skip $ SplitOnSuffixSeqKRInit 0 state rb rhead
2106−
2107− stepOuter _ (SplitOnSuffixSeqYield x next) = return $ Yield x next
2108−
2109− ---------------------------
2110− -- Empty pattern
2111− ---------------------------
2112−
2113− stepOuter gst (SplitOnSuffixSeqEmpty st) = do
2114− res <- step (adaptState gst) st
2115− case res of
2116− Yield x s -> do
2117− acc <- initial
2118− r <- fstep acc x
2119− case r of
2120− FL.Partial fs -> do
2121− b <- done fs
2122− skip $ SplitOnSuffixSeqYield b (SplitOnSuffixSeqEmpty s)
2123− FL.Done b ->
2124− skip $ SplitOnSuffixSeqYield b (SplitOnSuffixSeqEmpty s)
2125− Skip s -> skip (SplitOnSuffixSeqEmpty s)
2126− Stop -> return Stop
2127−
2128− -----------------
2129− -- Done
2130− -----------------
2131−
2132− stepOuter _ SplitOnSuffixSeqDone = return Stop
2133−
2134− -----------------
2135− -- Single Pattern
2136− -----------------
2137−
2138− stepOuter gst (SplitOnSuffixSeqSingleInit st pat) = do
2139− res <- step (adaptState gst) st
2140− case res of
2141− Yield x s -> initial >>= processYieldSingle pat x s
2142− Skip s -> skip $ SplitOnSuffixSeqSingleInit s pat
2143− Stop -> return Stop
2144−
2145− stepOuter gst (SplitOnSuffixSeqSingle fs st pat) = do
2146− res <- step (adaptState gst) st
2147− case res of
2148− Yield x s -> processYieldSingle pat x s fs
2149− Skip s -> skip $ SplitOnSuffixSeqSingle fs s pat
2150− Stop -> do
2151− r <- done fs
2152− skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2153−
2154− ---------------------------
2155− -- Short Pattern - Shift Or
2156− ---------------------------
2157−
2158− stepOuter _ (SplitOnSuffixSeqWordDone 0 fs _) = do
2159− r <- done fs
2160− skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2161− stepOuter _ (SplitOnSuffixSeqWordDone n fs wrd) = do
2162− let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
2163− r <- fstep fs (toEnum $ fromIntegral old)
2164− case r of
2165− FL.Partial fs1 -> skip $ SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2166− FL.Done b -> do
2167− fs1 <- initial
2168− let next = SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
2169− skip $ SplitOnSuffixSeqYield b next
2170−
2171− stepOuter gst (SplitOnSuffixSeqWordInit st0) = do
2172− res <- step (adaptState gst) st0
2173− case res of
2174− Yield x s -> do
2175− fs <- initial
2176− let wrd = addToWord 0 x
2177− r <- if withSep then fstep fs x else return $ FL.Partial fs
2178− case r of
2179− FL.Partial fs1 -> go SPEC 1 wrd s fs1
2180− FL.Done b -> do
2181− let next = SplitOnSuffixSeqWordInit s
2182− in skip $ SplitOnSuffixSeqYield b next
2183− Skip s -> skip (SplitOnSuffixSeqWordInit s)
2184− Stop -> return Stop
2185−
2186− where
2187−
2188− {-# INLINE go #-}
2189− go !_ !idx !wrd !st !fs = do
2190− res <- step (adaptState gst) st
2191− case res of
2192− Yield x s -> do
2193− let wrd1 = addToWord wrd x
2194− r <- if withSep then fstep fs x else return $ FL.Partial fs
2195− case r of
2196− FL.Partial fs1 ->
2197− if idx /= maxIndex
2198− then go SPEC (idx + 1) wrd1 s fs1
2199− else if wrd1 .&. wordMask /= wordPat
2200− then skip $ SplitOnSuffixSeqWordLoop wrd1 s fs1
2201− else do
2202− b <- done fs
2203− let next = SplitOnSuffixSeqWordInit s
2204− skip $ SplitOnSuffixSeqYield b next
2205− FL.Done b ->
2206− let next = SplitOnSuffixSeqWordInit s
2207− in skip $ SplitOnSuffixSeqYield b next
2208− Skip s -> go SPEC idx wrd s fs
2209− Stop -> skip $ SplitOnSuffixSeqWordDone idx fs wrd
2210−
2211− stepOuter gst (SplitOnSuffixSeqWordLoop wrd0 st0 fs0) =
2212− go SPEC wrd0 st0 fs0
2213−
2214− where
2215−
2216− {-# INLINE go #-}
2217− go !_ !wrd !st !fs = do
2218− res <- step (adaptState gst) st
2219− case res of
2220− Yield x s -> do
2221− let wrd1 = addToWord wrd x
2222− old = (wordMask .&. wrd)
2223− `shiftR` (elemBits * (patLen - 1))
2224− r <-
2225− if withSep
2226− then fstep fs x
2227− else fstep fs (toEnum $ fromIntegral old)
2228− case r of
2229− FL.Partial fs1 ->
2230− if wrd1 .&. wordMask == wordPat
2231− then do
2232− b <- done fs1
2233− let next = SplitOnSuffixSeqWordInit s
2234− skip $ SplitOnSuffixSeqYield b next
2235− else go SPEC wrd1 s fs1
2236− FL.Done b ->
2237− let next = SplitOnSuffixSeqWordInit s
2238− in skip $ SplitOnSuffixSeqYield b next
2239− Skip s -> go SPEC wrd s fs
2240− Stop ->
2241− if wrd .&. wordMask == wordPat
2242− then return Stop
2243− else if withSep
2244− then do
2245− r <- done fs
2246− skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2247− else skip $ SplitOnSuffixSeqWordDone patLen fs wrd
2248−
2249− -------------------------------
2250− -- General Pattern - Karp Rabin
2251− -------------------------------
2252−
2253− stepOuter gst (SplitOnSuffixSeqKRInit idx0 st0 rb rh0) = do
2254− res <- step (adaptState gst) st0
2255− case res of
2256− Yield x s -> do
2257− rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
2258− fs <- initial
2259− r <- if withSep then fstep fs x else return $ FL.Partial fs
2260− case r of
2261− FL.Partial fs1 ->
2262− skip $ SplitOnSuffixSeqKRInit1 fs1 s rb rh1
2263− FL.Done b ->
2264− let next = SplitOnSuffixSeqKRInit 0 s rb (RB.startOf rb)
2265− in skip $ SplitOnSuffixSeqYield b next
2266− Skip s -> skip $ SplitOnSuffixSeqKRInit idx0 s rb rh0
2267− Stop -> return Stop
2268−
2269− stepOuter gst (SplitOnSuffixSeqKRInit1 fs0 st0 rb rh0) = do
2270− go SPEC 1 rh0 st0 fs0
2271−
2272− where
2273−
2274− go !_ !idx !rh st !fs = do
2275− res <- step (adaptState gst) st
2276− case res of
2277− Yield x s -> do
2278− rh1 <- liftIO (RB.unsafeInsert rb rh x)
2279− r <- if withSep then fstep fs x else return $ FL.Partial fs
2280− case r of
2281− FL.Partial fs1 ->
2282− if idx /= maxIndex
2283− then go SPEC (idx + 1) rh1 s fs1
2284− else skip $
2285− let fold = RB.unsafeFoldRing (RB.ringBound rb)
2286− !ringHash = fold addCksum 0 rb
2287− in if ringHash == patHash
2288− then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2289− else SplitOnSuffixSeqKRLoop
2290− fs1 s rb rh1 ringHash
2291− FL.Done b ->
2292− let next = SplitOnSuffixSeqKRInit
2293− 0 st rb (RB.startOf rb)
2294− in skip $ SplitOnSuffixSeqYield b next
2295− Skip s -> go SPEC idx rh s fs
2296− Stop -> do
2297− -- do not issue a blank segment when we end at pattern
2298− if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
2299− then return Stop
2300− else if withSep
2301− then do
2302− r <- done fs
2303− skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2304− else skip $ SplitOnSuffixSeqKRDone idx fs rb (RB.startOf rb)
2305−
2306− stepOuter gst (SplitOnSuffixSeqKRLoop fs0 st0 rb rh0 cksum0) =
2307− go SPEC fs0 st0 rh0 cksum0
2308−
2309− where
2310−
2311− go !_ !fs !st !rh !cksum = do
2312− res <- step (adaptState gst) st
2313− case res of
2314− Yield x s -> do
2315− old <- liftIO $ peek rh
2316− rh1 <- liftIO (RB.unsafeInsert rb rh x)
2317− let cksum1 = deltaCksum cksum old x
2318− r <- if withSep then fstep fs x else fstep fs old
2319− case r of
2320− FL.Partial fs1 ->
2321− if (cksum1 /= patHash)
2322− then go SPEC fs1 s rh1 cksum1
2323− else skip $ SplitOnSuffixSeqKRCheck fs1 s rb rh1
2324− FL.Done b ->
2325− let next = SplitOnSuffixSeqKRInit
2326− 0 st rb (RB.startOf rb)
2327− in skip $ SplitOnSuffixSeqYield b next
2328− Skip s -> go SPEC fs s rh cksum
2329− Stop ->
2330− if RB.unsafeEqArray rb rh patArr
2331− then return Stop
2332− else if withSep
2333− then do
2334− r <- done fs
2335− skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2336− else skip $ SplitOnSuffixSeqKRDone patLen fs rb rh
2337−
2338− stepOuter _ (SplitOnSuffixSeqKRCheck fs st rb rh) = do
2339− if RB.unsafeEqArray rb rh patArr
2340− then do
2341− r <- done fs
2342− let next = SplitOnSuffixSeqKRInit 0 st rb (RB.startOf rb)
2343− skip $ SplitOnSuffixSeqYield r next
2344− else skip $ SplitOnSuffixSeqKRLoop fs st rb rh patHash
2345−
2346− stepOuter _ (SplitOnSuffixSeqKRDone 0 fs _ _) = do
2347− r <- done fs
2348− skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2349− stepOuter _ (SplitOnSuffixSeqKRDone n fs rb rh) = do
2350− old <- liftIO $ peek rh
2351− let rh1 = RB.advance rb rh
2352− r <- fstep fs old
2353− case r of
2354− FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2355− FL.Done b -> do
2356− fs1 <- initial
2357− let next = SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2358− skip $ SplitOnSuffixSeqYield b next
2359−
2360−{-# ANN type SplitState Fuse #-}
2361−data SplitState s arr
2362− = SplitInitial s
2363− | SplitBuffering s arr
2364− | SplitSplitting s arr
2365− | SplitYielding arr (SplitState s arr)
2366− | SplitFinishing
2367−
2368−-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
2369−-- split using a splitBy like combinator. The Fold would consume upto the
2370−-- separator and return any leftover which can then be fed to the next fold.
2371−--
2372−-- We can revisit this once we have partial folds/parsers.
2373−--
2374−-- | Performs infix separator style splitting.
2375−{-# INLINE_NORMAL splitInnerBy #-}
2376−splitInnerBy
2377− :: Monad m
2378− => (f a -> m (f a, Maybe (f a))) -- splitter
2379− -> (f a -> f a -> m (f a)) -- joiner
2380− -> Stream m (f a)
2381− -> Stream m (f a)
2382−splitInnerBy splitter joiner (Stream step1 state1) =
2383− (Stream step (SplitInitial state1))
2384−
2385− where
2386−
2387− {-# INLINE_LATE step #-}
2388− step gst (SplitInitial st) = do
2389− r <- step1 gst st
2390− case r of
2391− Yield x s -> do
2392− (x1, mx2) <- splitter x
2393− return $ case mx2 of
2394− Nothing -> Skip (SplitBuffering s x1)
2395− Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2396− Skip s -> return $ Skip (SplitInitial s)
2397− Stop -> return $ Stop
2398−
2399− step gst (SplitBuffering st buf) = do
2400− r <- step1 gst st
2401− case r of
2402− Yield x s -> do
2403− (x1, mx2) <- splitter x
2404− buf' <- joiner buf x1
2405− return $ case mx2 of
2406− Nothing -> Skip (SplitBuffering s buf')
2407− Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2408− Skip s -> return $ Skip (SplitBuffering s buf)
2409− Stop -> return $ Skip (SplitYielding buf SplitFinishing)
2410−
2411− step _ (SplitSplitting st buf) = do
2412− (x1, mx2) <- splitter buf
2413− return $ case mx2 of
2414− Nothing -> Skip $ SplitBuffering st x1
2415− Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2416−
2417− step _ (SplitYielding x next) = return $ Yield x next
2418− step _ SplitFinishing = return $ Stop
2419−
2420−-- | Performs infix separator style splitting.
2421−{-# INLINE_NORMAL splitInnerBySuffix #-}
2422−splitInnerBySuffix
2423− :: (Monad m, Eq (f a), Monoid (f a))
2424− => (f a -> m (f a, Maybe (f a))) -- splitter
2425− -> (f a -> f a -> m (f a)) -- joiner
2426− -> Stream m (f a)
2427− -> Stream m (f a)
2428−splitInnerBySuffix splitter joiner (Stream step1 state1) =
2429− (Stream step (SplitInitial state1))
2430−
2431− where
2432−
2433− {-# INLINE_LATE step #-}
2434− step gst (SplitInitial st) = do
2435− r <- step1 gst st
2436− case r of
2437− Yield x s -> do
2438− (x1, mx2) <- splitter x
2439− return $ case mx2 of
2440− Nothing -> Skip (SplitBuffering s x1)
2441− Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2442− Skip s -> return $ Skip (SplitInitial s)
2443− Stop -> return $ Stop
2444−
2445− step gst (SplitBuffering st buf) = do
2446− r <- step1 gst st
2447− case r of
2448− Yield x s -> do
2449− (x1, mx2) <- splitter x
2450− buf' <- joiner buf x1
2451− return $ case mx2 of
2452− Nothing -> Skip (SplitBuffering s buf')
2453− Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2454− Skip s -> return $ Skip (SplitBuffering s buf)
2455− Stop -> return $
2456− if buf == mempty
2457− then Stop
2458− else Skip (SplitYielding buf SplitFinishing)
2459−
2460− step _ (SplitSplitting st buf) = do
2461− (x1, mx2) <- splitter buf
2462− return $ case mx2 of
2463− Nothing -> Skip $ SplitBuffering st x1
2464− Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2465−
2466− step _ (SplitYielding x next) = return $ Yield x next
2467− step _ SplitFinishing = return $ Stop
2468−
2469−------------------------------------------------------------------------------
2470−-- Substreams
2471−------------------------------------------------------------------------------
2472−
2473−{-# INLINE_NORMAL isPrefixOf #-}
2474−isPrefixOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
2475−isPrefixOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
2476− where
2477− go (sa, sb, Nothing) = do
2478− r <- stepa defState sa
2479− case r of
2480− Yield x sa' -> go (sa', sb, Just x)
2481− Skip sa' -> go (sa', sb, Nothing)
2482− Stop -> return True
2483−
2484− go (sa, sb, Just x) = do
2485− r <- stepb defState sb
2486− case r of
2487− Yield y sb' ->
2488− if x == y
2489− then go (sa, sb', Nothing)
2490− else return False
2491− Skip sb' -> go (sa, sb', Just x)
2492− Stop -> return False
2493−
2494−{-# INLINE_NORMAL isSubsequenceOf #-}
2495−isSubsequenceOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
2496−isSubsequenceOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
2497− where
2498− go (sa, sb, Nothing) = do
2499− r <- stepa defState sa
2500− case r of
2501− Yield x sa' -> go (sa', sb, Just x)
2502− Skip sa' -> go (sa', sb, Nothing)
2503− Stop -> return True
2504−
2505− go (sa, sb, Just x) = do
2506− r <- stepb defState sb
2507− case r of
2508− Yield y sb' ->
2509− if x == y
2510− then go (sa, sb', Nothing)
2511− else go (sa, sb', Just x)
2512− Skip sb' -> go (sa, sb', Just x)
2513− Stop -> return False
2514−
2515−{-# INLINE_NORMAL stripPrefix #-}
2516−stripPrefix
2517− :: (Eq a, Monad m)
2518− => Stream m a -> Stream m a -> m (Maybe (Stream m a))
2519−stripPrefix (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
2520− where
2521− go (sa, sb, Nothing) = do
2522− r <- stepa defState sa
2523− case r of
2524− Yield x sa' -> go (sa', sb, Just x)
2525− Skip sa' -> go (sa', sb, Nothing)
2526− Stop -> return $ Just (Stream stepb sb)
2527−
2528− go (sa, sb, Just x) = do
2529− r <- stepb defState sb
2530− case r of
2531− Yield y sb' ->
2532− if x == y
2533− then go (sa, sb', Nothing)
2534− else return Nothing
2535− Skip sb' -> go (sa, sb', Just x)
2536− Stop -> return Nothing
2537−
2538−------------------------------------------------------------------------------
2539−-- Map and Fold
2540−------------------------------------------------------------------------------
2541−
2542−-- | Execute a monadic action for each element of the 'Stream'
2543−{-# INLINE_NORMAL mapM_ #-}
2544−mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
2545−mapM_ m = drain . mapM m
2546−
2547−-------------------------------------------------------------------------------
2548−-- Stream transformations using Unfolds
2549−-------------------------------------------------------------------------------
2550−
2551−-- Define a unique structure to use in inspection testing
2552−data ConcatMapUState o i =
2553− ConcatMapUOuter o
2554− | ConcatMapUInner o i
2555−
2556−-- | @concatMapU unfold stream@ uses @unfold@ to map the input stream elements
2557−-- to streams and then flattens the generated streams into a single output
2558−-- stream.
2559−
2560−-- This is like 'concatMap' but uses an unfold with an explicit state to
2561−-- generate the stream instead of a 'Stream' type generator. This allows better
2562−-- optimization via fusion. This can be many times more efficient than
2563−-- 'concatMap'.
2564−
2565−{-# INLINE_NORMAL concatMapU #-}
2566−concatMapU :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2567−concatMapU (Unfold istep inject) (Stream ostep ost) =
2568− Stream step (ConcatMapUOuter ost)
2569− where
2570− {-# INLINE_LATE step #-}
2571− step gst (ConcatMapUOuter o) = do
2572− r <- ostep (adaptState gst) o
2573− case r of
2574− Yield a o' -> do
2575− i <- inject a
2576− i `seq` return (Skip (ConcatMapUInner o' i))
2577− Skip o' -> return $ Skip (ConcatMapUOuter o')
2578− Stop -> return $ Stop
2579−
2580− step _ (ConcatMapUInner o i) = do
2581− r <- istep i
2582− return $ case r of
2583− Yield x i' -> Yield x (ConcatMapUInner o i')
2584− Skip i' -> Skip (ConcatMapUInner o i')
2585− Stop -> Skip (ConcatMapUOuter o)
2586−
2587−data ConcatUnfoldInterleaveState o i =
2588− ConcatUnfoldInterleaveOuter o [i]
2589− | ConcatUnfoldInterleaveInner o [i]
2590− | ConcatUnfoldInterleaveInnerL [i] [i]
2591− | ConcatUnfoldInterleaveInnerR [i] [i]
2592−
2593−-- XXX use arrays to store state instead of lists.
2594−-- XXX In general we can use different scheduling strategies e.g. how to
2595−-- schedule the outer vs inner loop or assigning weights to different streams
2596−-- or outer and inner loops.
2597−
2598−-- After a yield, switch to the next stream. Do not switch streams on Skip.
2599−-- Yield from outer stream switches to the inner stream.
2600−--
2601−-- There are two choices here, (1) exhaust the outer stream first and then
2602−-- start yielding from the inner streams, this is much simpler to implement,
2603−-- (2) yield at least one element from an inner stream before going back to
2604−-- outer stream and opening the next stream from it.
2605−--
2606−-- Ideally, we need some scheduling bias to inner streams vs outer stream.
2607−-- Maybe we can configure the behavior.
2608−--
2609−{-# INLINE_NORMAL concatUnfoldInterleave #-}
2610−concatUnfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2611−concatUnfoldInterleave (Unfold istep inject) (Stream ostep ost) =
2612− Stream step (ConcatUnfoldInterleaveOuter ost [])
2613− where
2614− {-# INLINE_LATE step #-}
2615− step gst (ConcatUnfoldInterleaveOuter o ls) = do
2616− r <- ostep (adaptState gst) o
2617− case r of
2618− Yield a o' -> do
2619− i <- inject a
2620− i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
2621− Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
2622− Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2623−
2624− step _ (ConcatUnfoldInterleaveInner _ []) = undefined
2625− step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
2626− r <- istep st
2627− return $ case r of
2628− Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
2629− Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
2630− Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
2631−
2632− step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
2633− step _ (ConcatUnfoldInterleaveInnerL [] rs) =
2634− return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
2635−
2636− step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
2637− r <- istep st
2638− return $ case r of
2639− Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
2640− Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
2641− Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
2642−
2643− step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
2644− step _ (ConcatUnfoldInterleaveInnerR ls []) =
2645− return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2646−
2647− step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
2648− r <- istep st
2649− return $ case r of
2650− Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2651− Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
2652− Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
2653−
2654−-- XXX In general we can use different scheduling strategies e.g. how to
2655−-- schedule the outer vs inner loop or assigning weights to different streams
2656−-- or outer and inner loops.
2657−--
2658−-- This could be inefficient if the tasks are too small.
2659−--
2660−-- Compared to concatUnfoldInterleave this one switches streams on Skips.
2661−--
2662−{-# INLINE_NORMAL concatUnfoldRoundrobin #-}
2663−concatUnfoldRoundrobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2664−concatUnfoldRoundrobin (Unfold istep inject) (Stream ostep ost) =
2665− Stream step (ConcatUnfoldInterleaveOuter ost [])
2666− where
2667− {-# INLINE_LATE step #-}
2668− step gst (ConcatUnfoldInterleaveOuter o ls) = do
2669− r <- ostep (adaptState gst) o
2670− case r of
2671− Yield a o' -> do
2672− i <- inject a
2673− i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
2674− Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
2675− Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2676−
2677− step _ (ConcatUnfoldInterleaveInner o []) =
2678− return $ Skip (ConcatUnfoldInterleaveOuter o [])
2679−
2680− step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
2681− r <- istep st
2682− return $ case r of
2683− Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
2684− Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
2685− Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
2686−
2687− step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
2688− step _ (ConcatUnfoldInterleaveInnerL [] rs) =
2689− return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
2690−
2691− step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
2692− r <- istep st
2693− return $ case r of
2694− Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
2695− Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
2696− Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
2697−
2698− step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
2699− step _ (ConcatUnfoldInterleaveInnerR ls []) =
2700− return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2701−
2702− step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
2703− r <- istep st
2704− return $ case r of
2705− Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2706− Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2707− Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
2708−
2709−data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
2710−
2711−-- Note that this could be much faster compared to the CPS stream. However, as
2712−-- the number of streams being composed increases this may become expensive.
2713−-- Need to see where the breaking point is between the two.
2714−--
2715−{-# INLINE_NORMAL append #-}
2716−append :: Monad m => Stream m a -> Stream m a -> Stream m a
2717−append (Stream step1 state1) (Stream step2 state2) =
2718− Stream step (AppendFirst state1)
2719−
2720− where
2721−
2722− {-# INLINE_LATE step #-}
2723− step gst (AppendFirst st) = do
2724− r <- step1 gst st
2725− return $ case r of
2726− Yield a s -> Yield a (AppendFirst s)
2727− Skip s -> Skip (AppendFirst s)
2728− Stop -> Skip (AppendSecond state2)
2729−
2730− step gst (AppendSecond st) = do
2731− r <- step2 gst st
2732− return $ case r of
2733− Yield a s -> Yield a (AppendSecond s)
2734− Skip s -> Skip (AppendSecond s)
2735− Stop -> Stop
2736−
2737−data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
2738− | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
2739−
2740−{-# INLINE_NORMAL interleave #-}
2741−interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
2742−interleave (Stream step1 state1) (Stream step2 state2) =
2743− Stream step (InterleaveFirst state1 state2)
2744−
2745− where
2746−
2747− {-# INLINE_LATE step #-}
2748− step gst (InterleaveFirst st1 st2) = do
2749− r <- step1 gst st1
2750− return $ case r of
2751− Yield a s -> Yield a (InterleaveSecond s st2)
2752− Skip s -> Skip (InterleaveFirst s st2)
2753− Stop -> Skip (InterleaveSecondOnly st2)
2754−
2755− step gst (InterleaveSecond st1 st2) = do
2756− r <- step2 gst st2
2757− return $ case r of
2758− Yield a s -> Yield a (InterleaveFirst st1 s)
2759− Skip s -> Skip (InterleaveSecond st1 s)
2760− Stop -> Skip (InterleaveFirstOnly st1)
2761−
2762− step gst (InterleaveFirstOnly st1) = do
2763− r <- step1 gst st1
2764− return $ case r of
2765− Yield a s -> Yield a (InterleaveFirstOnly s)
2766− Skip s -> Skip (InterleaveFirstOnly s)
2767− Stop -> Stop
2768−
2769− step gst (InterleaveSecondOnly st2) = do
2770− r <- step2 gst st2
2771− return $ case r of
2772− Yield a s -> Yield a (InterleaveSecondOnly s)
2773− Skip s -> Skip (InterleaveSecondOnly s)
2774− Stop -> Stop
2775−
2776−{-# INLINE_NORMAL interleaveMin #-}
2777−interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
2778−interleaveMin (Stream step1 state1) (Stream step2 state2) =
2779− Stream step (InterleaveFirst state1 state2)
2780−
2781− where
2782−
2783− {-# INLINE_LATE step #-}
2784− step gst (InterleaveFirst st1 st2) = do
2785− r <- step1 gst st1
2786− return $ case r of
2787− Yield a s -> Yield a (InterleaveSecond s st2)
2788− Skip s -> Skip (InterleaveFirst s st2)
2789− Stop -> Stop
2790−
2791− step gst (InterleaveSecond st1 st2) = do
2792− r <- step2 gst st2
2793− return $ case r of
2794− Yield a s -> Yield a (InterleaveFirst st1 s)
2795− Skip s -> Skip (InterleaveSecond st1 s)
2796− Stop -> Stop
2797−
2798− step _ (InterleaveFirstOnly _) = undefined
2799− step _ (InterleaveSecondOnly _) = undefined
2800−
2801−{-# INLINE_NORMAL interleaveSuffix #-}
2802−interleaveSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
2803−interleaveSuffix (Stream step1 state1) (Stream step2 state2) =
2804− Stream step (InterleaveFirst state1 state2)
2805−
2806− where
2807−
2808− {-# INLINE_LATE step #-}
2809− step gst (InterleaveFirst st1 st2) = do
2810− r <- step1 gst st1
2811− return $ case r of
2812− Yield a s -> Yield a (InterleaveSecond s st2)
2813− Skip s -> Skip (InterleaveFirst s st2)
2814− Stop -> Stop
2815−
2816− step gst (InterleaveSecond st1 st2) = do
2817− r <- step2 gst st2
2818− return $ case r of
2819− Yield a s -> Yield a (InterleaveFirst st1 s)
2820− Skip s -> Skip (InterleaveSecond st1 s)
2821− Stop -> Skip (InterleaveFirstOnly st1)
2822−
2823− step gst (InterleaveFirstOnly st1) = do
2824− r <- step1 gst st1
2825− return $ case r of
2826− Yield a s -> Yield a (InterleaveFirstOnly s)
2827− Skip s -> Skip (InterleaveFirstOnly s)
2828− Stop -> Stop
2829−
2830− step _ (InterleaveSecondOnly _) = undefined
2831−
2832−data InterleaveInfixState s1 s2 a
2833− = InterleaveInfixFirst s1 s2
2834− | InterleaveInfixSecondBuf s1 s2
2835− | InterleaveInfixSecondYield s1 s2 a
2836− | InterleaveInfixFirstYield s1 s2 a
2837− | InterleaveInfixFirstOnly s1
2838−
2839−{-# INLINE_NORMAL interleaveInfix #-}
2840−interleaveInfix :: Monad m => Stream m a -> Stream m a -> Stream m a
2841−interleaveInfix (Stream step1 state1) (Stream step2 state2) =
2842− Stream step (InterleaveInfixFirst state1 state2)
2843−
2844− where
2845−
2846− {-# INLINE_LATE step #-}
2847− step gst (InterleaveInfixFirst st1 st2) = do
2848− r <- step1 gst st1
2849− return $ case r of
2850− Yield a s -> Yield a (InterleaveInfixSecondBuf s st2)
2851− Skip s -> Skip (InterleaveInfixFirst s st2)
2852− Stop -> Stop
2853−
2854− step gst (InterleaveInfixSecondBuf st1 st2) = do
2855− r <- step2 gst st2
2856− return $ case r of
2857− Yield a s -> Skip (InterleaveInfixSecondYield st1 s a)
2858− Skip s -> Skip (InterleaveInfixSecondBuf st1 s)
2859− Stop -> Skip (InterleaveInfixFirstOnly st1)
2860−
2861− step gst (InterleaveInfixSecondYield st1 st2 x) = do
2862− r <- step1 gst st1
2863− return $ case r of
2864− Yield a s -> Yield x (InterleaveInfixFirstYield s st2 a)
2865− Skip s -> Skip (InterleaveInfixSecondYield s st2 x)
2866− Stop -> Stop
2867−
2868− step _ (InterleaveInfixFirstYield st1 st2 x) = do
2869− return $ Yield x (InterleaveInfixSecondBuf st1 st2)
2870−
2871− step gst (InterleaveInfixFirstOnly st1) = do
2872− r <- step1 gst st1
2873− return $ case r of
2874− Yield a s -> Yield a (InterleaveInfixFirstOnly s)
2875− Skip s -> Skip (InterleaveInfixFirstOnly s)
2876− Stop -> Stop
2877−
2878−{-# INLINE_NORMAL roundRobin #-}
2879−roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
2880−roundRobin (Stream step1 state1) (Stream step2 state2) =
2881− Stream step (InterleaveFirst state1 state2)
2882−
2883− where
2884−
2885− {-# INLINE_LATE step #-}
2886− step gst (InterleaveFirst st1 st2) = do
2887− r <- step1 gst st1
2888− return $ case r of
2889− Yield a s -> Yield a (InterleaveSecond s st2)
2890− Skip s -> Skip (InterleaveSecond s st2)
2891− Stop -> Skip (InterleaveSecondOnly st2)
2892−
2893− step gst (InterleaveSecond st1 st2) = do
2894− r <- step2 gst st2
2895− return $ case r of
2896− Yield a s -> Yield a (InterleaveFirst st1 s)
2897− Skip s -> Skip (InterleaveFirst st1 s)
2898− Stop -> Skip (InterleaveFirstOnly st1)
2899−
2900− step gst (InterleaveSecondOnly st2) = do
2901− r <- step2 gst st2
2902− return $ case r of
2903− Yield a s -> Yield a (InterleaveSecondOnly s)
2904− Skip s -> Skip (InterleaveSecondOnly s)
2905− Stop -> Stop
2906−
2907− step gst (InterleaveFirstOnly st1) = do
2908− r <- step1 gst st1
2909− return $ case r of
2910− Yield a s -> Yield a (InterleaveFirstOnly s)
2911− Skip s -> Skip (InterleaveFirstOnly s)
2912− Stop -> Stop
2913−
2914−data ICUState s1 s2 i1 i2 =
2915− ICUFirst s1 s2
2916− | ICUSecond s1 s2
2917− | ICUSecondOnly s2
2918− | ICUFirstOnly s1
2919− | ICUFirstInner s1 s2 i1
2920− | ICUSecondInner s1 s2 i2
2921− | ICUFirstOnlyInner s1 i1
2922− | ICUSecondOnlyInner s2 i2
2923−
2924−-- | Interleave streams (full streams, not the elements) unfolded from two
2925−-- input streams and concat. Stop when the first stream stops. If the second
2926−-- stream ends before the first one then first stream still keeps running alone
2927−-- without any interleaving with the second stream.
2928−--
2929−-- [a1, a2, ... an] [b1, b2 ...]
2930−-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
2931−-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
2932−-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
2933−--
2934−{-# INLINE_NORMAL gintercalateSuffix #-}
2935−gintercalateSuffix
2936− :: Monad m
2937− => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
2938−gintercalateSuffix
2939− (Unfold istep1 inject1) (Stream step1 state1)
2940− (Unfold istep2 inject2) (Stream step2 state2) =
2941− Stream step (ICUFirst state1 state2)
2942−
2943− where
2944−
2945− {-# INLINE_LATE step #-}
2946− step gst (ICUFirst s1 s2) = do
2947− r <- step1 (adaptState gst) s1
2948− case r of
2949− Yield a s -> do
2950− i <- inject1 a
2951− i `seq` return (Skip (ICUFirstInner s s2 i))
2952− Skip s -> return $ Skip (ICUFirst s s2)
2953− Stop -> return Stop
2954−
2955− step gst (ICUFirstOnly s1) = do
2956− r <- step1 (adaptState gst) s1
2957− case r of
2958− Yield a s -> do
2959− i <- inject1 a
2960− i `seq` return (Skip (ICUFirstOnlyInner s i))
2961− Skip s -> return $ Skip (ICUFirstOnly s)
2962− Stop -> return Stop
2963−
2964− step _ (ICUFirstInner s1 s2 i1) = do
2965− r <- istep1 i1
2966− return $ case r of
2967− Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
2968− Skip i' -> Skip (ICUFirstInner s1 s2 i')
2969− Stop -> Skip (ICUSecond s1 s2)
2970−
2971− step _ (ICUFirstOnlyInner s1 i1) = do
2972− r <- istep1 i1
2973− return $ case r of
2974− Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
2975− Skip i' -> Skip (ICUFirstOnlyInner s1 i')
2976− Stop -> Skip (ICUFirstOnly s1)
2977−
2978− step gst (ICUSecond s1 s2) = do
2979− r <- step2 (adaptState gst) s2
2980− case r of
2981− Yield a s -> do
2982− i <- inject2 a
2983− i `seq` return (Skip (ICUSecondInner s1 s i))
2984− Skip s -> return $ Skip (ICUSecond s1 s)
2985− Stop -> return $ Skip (ICUFirstOnly s1)
2986−
2987− step _ (ICUSecondInner s1 s2 i2) = do
2988− r <- istep2 i2
2989− return $ case r of
2990− Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
2991− Skip i' -> Skip (ICUSecondInner s1 s2 i')
2992− Stop -> Skip (ICUFirst s1 s2)
2993−
2994− step _ (ICUSecondOnly _s2) = undefined
2995− step _ (ICUSecondOnlyInner _s2 _i2) = undefined
2996−
2997−{-# ANN type InterposeSuffixState Fuse #-}
2998−data InterposeSuffixState s1 i1 =
2999− InterposeSuffixFirst s1
3000− -- | InterposeSuffixFirstYield s1 i1
3001− | InterposeSuffixFirstInner s1 i1
3002− | InterposeSuffixSecond s1
3003−
3004−-- Note that if an unfolded layer turns out to be nil we still emit the
3005−-- separator effect. An alternate behavior could be to emit the separator
3006−-- effect only if at least one element has been yielded by the unfolding.
3007−-- However, that becomes a bit complicated, so we have chosen the former
3008−-- behvaior for now.
3009−{-# INLINE_NORMAL interposeSuffix #-}
3010−interposeSuffix
3011− :: Monad m
3012− => m c -> Unfold m b c -> Stream m b -> Stream m c
3013−interposeSuffix
3014− action
3015− (Unfold istep1 inject1) (Stream step1 state1) =
3016− Stream step (InterposeSuffixFirst state1)
3017−
3018− where
3019−
3020− {-# INLINE_LATE step #-}
3021− step gst (InterposeSuffixFirst s1) = do
3022− r <- step1 (adaptState gst) s1
3023− case r of
3024− Yield a s -> do
3025− i <- inject1 a
3026− i `seq` return (Skip (InterposeSuffixFirstInner s i))
3027− -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
3028− Skip s -> return $ Skip (InterposeSuffixFirst s)
3029− Stop -> return Stop
3030−
3031− {-
3032− step _ (InterposeSuffixFirstYield s1 i1) = do
3033− r <- istep1 i1
3034− return $ case r of
3035− Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
3036− Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
3037− Stop -> Skip (InterposeSuffixFirst s1)
3038− -}
3039−
3040− step _ (InterposeSuffixFirstInner s1 i1) = do
3041− r <- istep1 i1
3042− return $ case r of
3043− Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
3044− Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
3045− Stop -> Skip (InterposeSuffixSecond s1)
3046−
3047− step _ (InterposeSuffixSecond s1) = do
3048− r <- action
3049− return $ Yield r (InterposeSuffixFirst s1)
3050−
3051−data ICALState s1 s2 i1 i2 a =
3052− ICALFirst s1 s2
3053− -- | ICALFirstYield s1 s2 i1
3054− | ICALFirstInner s1 s2 i1
3055− | ICALFirstOnly s1
3056− | ICALFirstOnlyInner s1 i1
3057− | ICALSecondInject s1 s2
3058− | ICALFirstInject s1 s2 i2
3059− -- | ICALFirstBuf s1 s2 i1 i2
3060− | ICALSecondInner s1 s2 i1 i2
3061− -- -- | ICALSecondInner s1 s2 i1 i2 a
3062− -- -- | ICALFirstResume s1 s2 i1 i2 a
3063−
3064−-- | Interleave streams (full streams, not the elements) unfolded from two
3065−-- input streams and concat. Stop when the first stream stops. If the second
3066−-- stream ends before the first one then first stream still keeps running alone
3067−-- without any interleaving with the second stream.
3068−--
3069−-- [a1, a2, ... an] [b1, b2 ...]
3070−-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
3071−-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
3072−-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
3073−--
3074−{-# INLINE_NORMAL gintercalate #-}
3075−gintercalate
3076− :: Monad m
3077− => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
3078−gintercalate
3079− (Unfold istep1 inject1) (Stream step1 state1)
3080− (Unfold istep2 inject2) (Stream step2 state2) =
3081− Stream step (ICALFirst state1 state2)
3082−
3083− where
3084−
3085− {-# INLINE_LATE step #-}
3086− step gst (ICALFirst s1 s2) = do
3087− r <- step1 (adaptState gst) s1
3088− case r of
3089− Yield a s -> do
3090− i <- inject1 a
3091− i `seq` return (Skip (ICALFirstInner s s2 i))
3092− -- i `seq` return (Skip (ICALFirstYield s s2 i))
3093− Skip s -> return $ Skip (ICALFirst s s2)
3094− Stop -> return Stop
3095−
3096− {-
3097− step _ (ICALFirstYield s1 s2 i1) = do
3098− r <- istep1 i1
3099− return $ case r of
3100− Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
3101− Skip i' -> Skip (ICALFirstYield s1 s2 i')
3102− Stop -> Skip (ICALFirst s1 s2)
3103− -}
3104−
3105− step _ (ICALFirstInner s1 s2 i1) = do
3106− r <- istep1 i1
3107− return $ case r of
3108− Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
3109− Skip i' -> Skip (ICALFirstInner s1 s2 i')
3110− Stop -> Skip (ICALSecondInject s1 s2)
3111−
3112− step gst (ICALFirstOnly s1) = do
3113− r <- step1 (adaptState gst) s1
3114− case r of
3115− Yield a s -> do
3116− i <- inject1 a
3117− i `seq` return (Skip (ICALFirstOnlyInner s i))
3118− Skip s -> return $ Skip (ICALFirstOnly s)
3119− Stop -> return Stop
3120−
3121− step _ (ICALFirstOnlyInner s1 i1) = do
3122− r <- istep1 i1
3123− return $ case r of
3124− Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
3125− Skip i' -> Skip (ICALFirstOnlyInner s1 i')
3126− Stop -> Skip (ICALFirstOnly s1)
3127−
3128− -- We inject the second stream even before checking if the first stream
3129− -- would yield any more elements. There is no clear choice whether we
3130− -- should do this before or after that. Doing it after may make the state
3131− -- machine a bit simpler though.
3132− step gst (ICALSecondInject s1 s2) = do
3133− r <- step2 (adaptState gst) s2
3134− case r of
3135− Yield a s -> do
3136− i <- inject2 a
3137− i `seq` return (Skip (ICALFirstInject s1 s i))
3138− Skip s -> return $ Skip (ICALSecondInject s1 s)
3139− Stop -> return $ Skip (ICALFirstOnly s1)
3140−
3141− step gst (ICALFirstInject s1 s2 i2) = do
3142− r <- step1 (adaptState gst) s1
3143− case r of
3144− Yield a s -> do
3145− i <- inject1 a
3146− i `seq` return (Skip (ICALSecondInner s s2 i i2))
3147− -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
3148− Skip s -> return $ Skip (ICALFirstInject s s2 i2)
3149− Stop -> return Stop
3150−
3151− {-
3152− step _ (ICALFirstBuf s1 s2 i1 i2) = do
3153− r <- istep1 i1
3154− return $ case r of
3155− Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
3156− Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
3157− Stop -> Stop
3158−
3159− step _ (ICALSecondInner s1 s2 i1 i2 v) = do
3160− r <- istep2 i2
3161− return $ case r of
3162− Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
3163− Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
3164− Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
3165− -}
3166−
3167− step _ (ICALSecondInner s1 s2 i1 i2) = do
3168− r <- istep2 i2
3169− return $ case r of
3170− Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
3171− Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
3172− Stop -> Skip (ICALFirstInner s1 s2 i1)
3173− -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
3174−
3175− {-
3176− step _ (ICALFirstResume s1 s2 i1 i2 x) = do
3177− return $ Yield x (ICALFirstInner s1 s2 i1 i2)
3178− -}
3179−
3180−{-# ANN type InterposeState Fuse #-}
3181−data InterposeState s1 i1 a =
3182− InterposeFirst s1
3183− -- | InterposeFirstYield s1 i1
3184− | InterposeFirstInner s1 i1
3185− | InterposeFirstInject s1
3186− -- | InterposeFirstBuf s1 i1
3187− | InterposeSecondYield s1 i1
3188− -- -- | InterposeSecondYield s1 i1 a
3189− -- -- | InterposeFirstResume s1 i1 a
3190−
3191−-- Note that this only interposes the pure values, we may run many effects to
3192−-- generate those values as some effects may not generate anything (Skip).
3193−{-# INLINE_NORMAL interpose #-}
3194−interpose :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
3195−interpose
3196− action
3197− (Unfold istep1 inject1) (Stream step1 state1) =
3198− Stream step (InterposeFirst state1)
3199−
3200− where
3201−
3202− {-# INLINE_LATE step #-}
3203− step gst (InterposeFirst s1) = do
3204− r <- step1 (adaptState gst) s1
3205− case r of
3206− Yield a s -> do
3207− i <- inject1 a
3208− i `seq` return (Skip (InterposeFirstInner s i))
3209− -- i `seq` return (Skip (InterposeFirstYield s i))
3210− Skip s -> return $ Skip (InterposeFirst s)
3211− Stop -> return Stop
3212−
3213− {-
3214− step _ (InterposeFirstYield s1 i1) = do
3215− r <- istep1 i1
3216− return $ case r of
3217− Yield x i' -> Yield x (InterposeFirstInner s1 i')
3218− Skip i' -> Skip (InterposeFirstYield s1 i')
3219− Stop -> Skip (InterposeFirst s1)
3220− -}
3221−
3222− step _ (InterposeFirstInner s1 i1) = do
3223− r <- istep1 i1
3224− return $ case r of
3225− Yield x i' -> Yield x (InterposeFirstInner s1 i')
3226− Skip i' -> Skip (InterposeFirstInner s1 i')
3227− Stop -> Skip (InterposeFirstInject s1)
3228−
3229− step gst (InterposeFirstInject s1) = do
3230− r <- step1 (adaptState gst) s1
3231− case r of
3232− Yield a s -> do
3233− i <- inject1 a
3234− -- i `seq` return (Skip (InterposeFirstBuf s i))
3235− i `seq` return (Skip (InterposeSecondYield s i))
3236− Skip s -> return $ Skip (InterposeFirstInject s)
3237− Stop -> return Stop
3238−
3239− {-
3240− step _ (InterposeFirstBuf s1 i1) = do
3241− r <- istep1 i1
3242− return $ case r of
3243− Yield x i' -> Skip (InterposeSecondYield s1 i' x)
3244− Skip i' -> Skip (InterposeFirstBuf s1 i')
3245− Stop -> Stop
3246− -}
3247−
3248− {-
3249− step _ (InterposeSecondYield s1 i1 v) = do
3250− r <- action
3251− return $ Yield r (InterposeFirstResume s1 i1 v)
3252− -}
3253− step _ (InterposeSecondYield s1 i1) = do
3254− r <- action
3255− return $ Yield r (InterposeFirstInner s1 i1)
3256−
3257− {-
3258− step _ (InterposeFirstResume s1 i1 v) = do
3259− return $ Yield v (InterposeFirstInner s1 i1)
3260− -}
3261−
3262−------------------------------------------------------------------------------
3263−-- Exceptions
3264−------------------------------------------------------------------------------
3265−
3266−data GbracketState s1 s2 v
3267− = GBracketInit
3268− | GBracketNormal s1 v
3269− | GBracketException s2
3270−
3271−-- | Like 'gbracket' but with following differences:
3272−--
3273−-- * alloc action @m c@ runs with async exceptions enabled
3274−-- * cleanup action @c -> m d@ won't run if the stream is garbage collected
3275−-- after partial evaluation.
3276−-- * does not require a 'MonadAsync' constraint.
3277−--
3278−-- /Inhibits stream fusion/
3279−--
3280−-- /Internal/
3281−--
3282−{-# INLINE_NORMAL gbracket_ #-}
3283−gbracket_
3284− :: Monad m
3285− => m c -- ^ before
3286− -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
3287− -> (c -> m d) -- ^ after, on normal stop
3288− -> (c -> e -> Stream m b -> Stream m b) -- ^ on exception
3289− -> (c -> Stream m b) -- ^ stream generator
3290− -> Stream m b
3291−gbracket_ bef exc aft fexc fnormal =
3292− Stream step GBracketInit
3293−
3294− where
3295−
3296− {-# INLINE_LATE step #-}
3297− step _ GBracketInit = do
3298− r <- bef
3299− return $ Skip $ GBracketNormal (fnormal r) r
3300−
3301− step gst (GBracketNormal (UnStream step1 st) v) = do
3302− res <- exc $ step1 gst st
3303− case res of
3304− Right r -> case r of
3305− Yield x s ->
3306− return $ Yield x (GBracketNormal (Stream step1 s) v)
3307− Skip s -> return $ Skip (GBracketNormal (Stream step1 s) v)
3308− Stop -> aft v >> return Stop
3309− -- XXX Do not handle async exceptions, just rethrow them.
3310− Left e ->
3311− return $ Skip (GBracketException (fexc v e (UnStream step1 st)))
3312− step gst (GBracketException (UnStream step1 st)) = do
3313− res <- step1 gst st
3314− case res of
3315− Yield x s -> return $ Yield x (GBracketException (Stream step1 s))
3316− Skip s -> return $ Skip (GBracketException (Stream step1 s))
3317− Stop -> return Stop
3318−
3319−------------------------------------------------------------------------------
3320−-- Finalizers
3321−------------------------------------------------------------------------------
3322−
3323−-- | Make a finalizer from a monadic action @m a@ that can run in IO monad.
3324−mkIOFinalizer :: MonadBaseControl IO m => m b -> m (IO ())
3325−mkIOFinalizer f = do
3326− mrun <- captureMonadState
3327− return $
3328− void $ do
3329− _ <- runInIO mrun f
3330− return ()
3331−
3332−-- | Run an IO action stored in a finalized IORef.
3333−runIORefFinalizerGC :: IORef (Maybe (IO ())) -> IO ()
3334−runIORefFinalizerGC ref = do
3335− res <- readIORef ref
3336− case res of
3337− Nothing -> return ()
3338− Just f -> f
3339−
3340−-- | Create an IORef holding a finalizer that is called automatically when
3341−-- the IORef is garbage collected. The IORef can be written to with a 'Nothing'
3342−-- value to deactivate the finalizer.
3343−--
3344−-- Note: The finalizer is always run with the state of the monad captured at
3345−-- the time of calling newFinalizedIORef. To run it on garbage collection we
3346−-- have no option but to take a snapshot of the monadic state at some point of
3347−-- time. For normal case we could run it with the current state of the monad
3348−-- but we want to keep both the cases consistent.
3349−--
3350−newFinalizedIORef :: (MonadIO m, MonadBaseControl IO m)
3351− => m a -> m (IORef (Maybe (IO ())))
3352−newFinalizedIORef finalizer = do
3353− f <- mkIOFinalizer finalizer
3354− ref <- liftIO $ newIORef $ Just f
3355− _ <- liftIO $ mkWeakIORef ref (runIORefFinalizerGC ref)
3356− return ref
3357−
3358−-- | Run the finalizer stored in an IORef and deactivate it so that it is run
3359−-- only once. Note, the action runs with async exceptions masked.
3360−--
3361−runIORefFinalizer :: MonadIO m => IORef (Maybe (IO ())) -> m ()
3362−runIORefFinalizer ref = liftIO $ do
3363− res <- readIORef ref
3364− case res of
3365− Nothing -> return ()
3366− Just action -> do
3367− -- if an async exception comes after writing 'Nothing' then the
3368− -- finalizing action will never be run. We need to do this
3369− -- atomically wrt async exceptions.
3370− mask_ $ do
3371− writeIORef ref Nothing
3372− action
3373−
3374−-- | Run an action clearing the finalizer IORef atomically wrt async
3375−-- exceptions. The action is run with async exceptions masked.
3376−withIORefFinalizer :: MonadBaseControl IO m
3377− => IORef (Maybe (IO ())) -> m a -> m a
3378−withIORefFinalizer ref action = do
3379− control $ \runinio ->
3380− mask_ $ do
3381− writeIORef ref Nothing
3382− runinio action
3383−
3384−------------------------------------------------------------------------------
3385−
3386−data GbracketIOState s1 s2 v wref
3387− = GBracketIOInit
3388− | GBracketIONormal s1 v wref
3389− | GBracketIOException s2
3390−
3391−-- | Run the alloc action @m c@ with async exceptions disabled but keeping
3392−-- blocking operations interruptible (see 'Control.Exception.mask'). Use the
3393−-- output @c@ as input to @c -> Stream m b@ to generate an output stream. When
3394−-- generating the stream use the supplied @try@ operation @forall s. m s -> m
3395−-- (Either e s)@ to catch synchronous exceptions. If an exception occurs run
3396−-- the exception handler @c -> e -> Stream m b -> m (Stream m b)@.
3397−--
3398−-- The cleanup action @c -> m d@, runs whenever the stream ends normally, due
3399−-- to a sync or async exception or if it gets garbage collected after a partial
3400−-- lazy evaluation. See 'bracket' for the semantics of the cleanup action.
3401−--
3402−-- 'gbracket' can express all other exception handling combinators.
3403−--
3404−-- /Inhibits stream fusion/
3405−--
3406−-- /Internal/
3407−{-# INLINE_NORMAL gbracket #-}
3408−gbracket
3409− :: (MonadIO m, MonadBaseControl IO m)
3410− => m c -- ^ before
3411− -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
3412− -> (c -> m d) -- ^ after, on normal stop or GC
3413− -> (c -> e -> Stream m b -> m (Stream m b)) -- ^ on exception
3414− -> (c -> Stream m b) -- ^ stream generator
3415− -> Stream m b
3416−gbracket bef exc aft fexc fnormal =
3417− Stream step GBracketIOInit
3418−
3419− where
3420−
3421− -- If the stream is never evaluated the "aft" action will never be
3422− -- called. For that to occur we will need the user of this API to pass a
3423− -- weak pointer to us.
3424− {-# INLINE_LATE step #-}
3425− step _ GBracketIOInit = do
3426− -- We mask asynchronous exceptions to make the execution
3427− -- of 'bef' and the registration of 'aft' atomic.
3428− -- A similar thing is done in the resourcet package: https://git.io/JvKV3
3429− -- Tutorial: https://markkarpov.com/tutorial/exceptions.html
3430− (r, ref) <- liftBaseOp_ mask_ $ do
3431− r <- bef
3432− ref <- newFinalizedIORef (aft r)
3433− return (r, ref)
3434− return $ Skip $ GBracketIONormal (fnormal r) r ref
3435−
3436− step gst (GBracketIONormal (UnStream step1 st) v ref) = do
3437− res <- exc $ step1 gst st
3438− case res of
3439− Right r -> case r of
3440− Yield x s ->
3441− return $ Yield x (GBracketIONormal (Stream step1 s) v ref)
3442− Skip s ->
3443− return $ Skip (GBracketIONormal (Stream step1 s) v ref)
3444− Stop -> do
3445− runIORefFinalizer ref
3446− return Stop
3447− -- XXX Do not handle async exceptions, just rethrow them.
3448− Left e -> do
3449− -- Clearing of finalizer and running of exception handler must
3450− -- be atomic wrt async exceptions. Otherwise if we have cleared
3451− -- the finalizer and have not run the exception handler then we
3452− -- may leak the resource.
3453− stream <- withIORefFinalizer ref (fexc v e (UnStream step1 st))
3454− return $ Skip (GBracketIOException stream)
3455− step gst (GBracketIOException (UnStream step1 st)) = do
3456− res <- step1 gst st
3457− case res of
3458− Yield x s ->
3459− return $ Yield x (GBracketIOException (Stream step1 s))
3460− Skip s -> return $ Skip (GBracketIOException (Stream step1 s))
3461− Stop -> return Stop
3462−
3463−-- | See 'Streamly.Internal.Data.Stream.IsStream.after_'.
3464−--
3465−{-# INLINE_NORMAL before #-}
3466−before :: Monad m => m b -> Stream m a -> Stream m a
3467−before action (Stream step state) = Stream step' Nothing
3468−
3469− where
3470−
3471− {-# INLINE_LATE step' #-}
3472− step' _ Nothing = action >> return (Skip (Just state))
3473−
3474− step' gst (Just st) = do
3475− res <- step gst st
3476− case res of
3477− Yield x s -> return $ Yield x (Just s)
3478− Skip s -> return $ Skip (Just s)
3479− Stop -> return Stop
3480−
3481−-- | See 'Streamly.Internal.Data.Stream.IsStream.after_'.
3482−--
3483−{-# INLINE_NORMAL after_ #-}
3484−after_ :: Monad m => m b -> Stream m a -> Stream m a
3485−after_ action (Stream step state) = Stream step' state
3486−
3487− where
3488−
3489− {-# INLINE_LATE step' #-}
3490− step' gst st = do
3491− res <- step gst st
3492− case res of
3493− Yield x s -> return $ Yield x s
3494− Skip s -> return $ Skip s
3495− Stop -> action >> return Stop
3496−
3497−-- | See 'Streamly.Internal.Data.Stream.IsStream.after'.
3498−--
3499−{-# INLINE_NORMAL after #-}
3500−after :: (MonadIO m, MonadBaseControl IO m)
3501− => m b -> Stream m a -> Stream m a
3502−after action (Stream step state) = Stream step' Nothing
3503−
3504− where
3505−
3506− {-# INLINE_LATE step' #-}
3507− step' _ Nothing = do
3508− ref <- newFinalizedIORef action
3509− return $ Skip $ Just (state, ref)
3510− step' gst (Just (st, ref)) = do
3511− res <- step gst st
3512− case res of
3513− Yield x s -> return $ Yield x (Just (s, ref))
3514− Skip s -> return $ Skip (Just (s, ref))
3515− Stop -> do
3516− runIORefFinalizer ref
3517− return Stop
3518−
3519−-- XXX For high performance error checks in busy streams we may need another
3520−-- Error constructor in step.
3521−--
3522−-- | See 'Streamly.Internal.Data.Stream.IsStream.onException'.
3523−--
3524−{-# INLINE_NORMAL onException #-}
3525−onException :: MonadCatch m => m b -> Stream m a -> Stream m a
3526−onException action str =
3527− gbracket_ (return ()) MC.try return
3528− (\_ (e :: MC.SomeException) _ -> nilM (action >> MC.throwM e))
3529− (\_ -> str)
3530−
3531−{-# INLINE_NORMAL _onException #-}
3532−_onException :: MonadCatch m => m b -> Stream m a -> Stream m a
3533−_onException action (Stream step state) = Stream step' state
3534−
3535− where
3536−
3537− {-# INLINE_LATE step' #-}
3538− step' gst st = do
3539− res <- step gst st `MC.onException` action
3540− case res of
3541− Yield x s -> return $ Yield x s
3542− Skip s -> return $ Skip s
3543− Stop -> return Stop
3544−
3545−-- | See 'Streamly.Internal.Data.Stream.IsStream.bracket_'.
3546−--
3547−{-# INLINE_NORMAL bracket_ #-}
3548−bracket_ :: MonadCatch m
3549− => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
3550−bracket_ bef aft bet =
3551− gbracket_ bef MC.try aft
3552− (\a (e :: SomeException) _ -> nilM (aft a >> MC.throwM e)) bet
3553−
3554−-- | See 'Streamly.Internal.Data.Stream.IsStream.bracket'.
3555−--
3556−{-# INLINE_NORMAL bracket #-}
3557−bracket :: (MonadAsync m, MonadCatch m)
3558− => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
3559−bracket bef aft bet =
3560− gbracket bef MC.try aft
3561− (\a (e :: SomeException) _ -> aft a >> return (nilM (MC.throwM e))) bet
3562−
3563−data BracketState s v = BracketInit | BracketRun s v
3564−
3565−-- | Alternate (custom) implementation of 'bracket'.
3566−--
3567−{-# INLINE_NORMAL _bracket #-}
3568−_bracket :: MonadCatch m
3569− => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
3570−_bracket bef aft bet = Stream step' BracketInit
3571−
3572− where
3573−
3574− {-# INLINE_LATE step' #-}
3575− step' _ BracketInit = bef >>= \x -> return (Skip (BracketRun (bet x) x))
3576−
3577− -- NOTE: It is important to use UnStream instead of the Stream pattern
3578− -- here, otherwise we get huge perf degradation, see note in concatMap.
3579− step' gst (BracketRun (UnStream step state) v) = do
3580− -- res <- step gst state `MC.onException` aft v
3581− res <- MC.try $ step gst state
3582− case res of
3583− Left (e :: SomeException) -> aft v >> MC.throwM e >> return Stop
3584− Right r -> case r of
3585− Yield x s -> return $ Yield x (BracketRun (Stream step s) v)
3586− Skip s -> return $ Skip (BracketRun (Stream step s) v)
3587− Stop -> aft v >> return Stop
3588−
3589−-- | See 'Streamly.Internal.Data.Stream.IsStream.finally_'.
3590−--
3591−{-# INLINE finally_ #-}
3592−finally_ :: MonadCatch m => m b -> Stream m a -> Stream m a
3593−finally_ action xs = bracket_ (return ()) (\_ -> action) (const xs)
3594−
3595−-- | See 'Streamly.Internal.Data.Stream.IsStream.finally'.
3596−--
3597−-- finally action xs = after action $ onException action xs
3598−--
3599−{-# INLINE finally #-}
3600−finally :: (MonadAsync m, MonadCatch m) => m b -> Stream m a -> Stream m a
3601−finally action xs = bracket (return ()) (\_ -> action) (const xs)
3602−
3603−-- | See 'Streamly.Internal.Data.Stream.IsStream.ghandle'.
3604−--
3605−{-# INLINE_NORMAL ghandle #-}
3606−ghandle :: (MonadCatch m, Exception e)
3607− => (e -> Stream m a -> Stream m a) -> Stream m a -> Stream m a
3608−ghandle f str =
3609− gbracket_ (return ()) MC.try return (\_ -> f) (\_ -> str)
3610−
3611−-- | See 'Streamly.Internal.Data.Stream.IsStream.handle'.
3612−--
3613−{-# INLINE_NORMAL handle #-}
3614−handle :: (MonadCatch m, Exception e)
3615− => (e -> Stream m a) -> Stream m a -> Stream m a
3616−handle f str =
3617− gbracket_ (return ()) MC.try return (\_ e _ -> f e) (\_ -> str)
3618−
3619−-- | Alternate (custom) implementation of 'handle'.
3620−--
3621−{-# INLINE_NORMAL _handle #-}
3622−_handle :: (MonadCatch m, Exception e)
3623− => (e -> Stream m a) -> Stream m a -> Stream m a
3624−_handle f (Stream step state) = Stream step' (Left state)
3625−
3626− where
3627−
3628− {-# INLINE_LATE step' #-}
3629− step' gst (Left st) = do
3630− res <- MC.try $ step gst st
3631− case res of
3632− Left e -> return $ Skip $ Right (f e)
3633− Right r -> case r of
3634− Yield x s -> return $ Yield x (Left s)
3635− Skip s -> return $ Skip (Left s)
3636− Stop -> return Stop
3637−
3638− step' gst (Right (UnStream step1 st)) = do
3639− res <- step1 gst st
3640− case res of
3641− Yield x s -> return $ Yield x (Right (Stream step1 s))
3642− Skip s -> return $ Skip (Right (Stream step1 s))
3643− Stop -> return Stop
3644−
3645−-------------------------------------------------------------------------------
3646−-- General transformation
3647−-------------------------------------------------------------------------------
3648−
3649−{-# INLINE_NORMAL transform #-}
3650−transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
3651−transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
3652− Stream step' (Consume pstate, state)
3653−
3654− where
3655−
3656− {-# INLINE_LATE step' #-}
3657−
3658− step' gst (Consume pst, st) = pst `seq` do
3659− r <- step (adaptState gst) st
3660− case r of
3661− Yield x s -> do
3662− res <- pstep1 pst x
3663− case res of
3664− Pipe.Yield b pst' -> return $ Yield b (pst', s)
3665− Pipe.Continue pst' -> return $ Skip (pst', s)
3666− Skip s -> return $ Skip (Consume pst, s)
3667− Stop -> return Stop
3668−
3669− step' _ (Produce pst, st) = pst `seq` do
3670− res <- pstep2 pst
3671− case res of
3672− Pipe.Yield b pst' -> return $ Yield b (pst', st)
3673− Pipe.Continue pst' -> return $ Skip (pst', st)
3674−
3675−------------------------------------------------------------------------------
3676−-- Transformation by Folding (Scans)
3677−------------------------------------------------------------------------------
3678−
3679−------------------------------------------------------------------------------
3680−-- Prescans
3681−------------------------------------------------------------------------------
3682−
3683−-- XXX Is a prescan useful, discarding the last step does not sound useful? I
3684−-- am not sure about the utility of this function, so this is implemented but
3685−-- not exposed. We can expose it if someone provides good reasons why this is
3686−-- useful.
3687−--
3688−-- XXX We have to execute the stream one step ahead to know that we are at the
3689−-- last step. The vector implementation of prescan executes the last fold step
3690−-- but does not yield the result. This means we have executed the effect but
3691−-- discarded value. This does not sound right. In this implementation we are
3692−-- not executing the last fold step.
3693−{-# INLINE_NORMAL prescanlM' #-}
3694−prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
3695−prescanlM' f mz (Stream step state) = Stream step' (state, mz)
3696− where
3697− {-# INLINE_LATE step' #-}
3698− step' gst (st, prev) = do
3699− r <- step (adaptState gst) st
3700− case r of
3701− Yield x s -> do
3702− acc <- prev
3703− return $ Yield acc (s, f acc x)
3704− Skip s -> return $ Skip (s, prev)
3705− Stop -> return Stop
3706−
3707−{-# INLINE prescanl' #-}
3708−prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3709−prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
3710−
3711−------------------------------------------------------------------------------
3712−-- Monolithic postscans (postscan followed by a map)
3713−------------------------------------------------------------------------------
3714−
3715−-- The performance of a modular postscan followed by a map seems to be
3716−-- equivalent to this monolithic scan followed by map therefore we may not need
3717−-- this implementation. We just have it for performance comparison and in case
3718−-- modular version does not perform well in some situation.
3719−--
3720−{-# INLINE_NORMAL postscanlMx' #-}
3721−postscanlMx' :: Monad m
3722− => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
3723−postscanlMx' fstep begin done (Stream step state) = do
3724− Stream step' (state, begin)
3725− where
3726− {-# INLINE_LATE step' #-}
3727− step' gst (st, acc) = do
3728− r <- step (adaptState gst) st
3729− case r of
3730− Yield x s -> do
3731− old <- acc
3732− y <- fstep old x
3733− v <- done y
3734− v `seq` y `seq` return (Yield v (s, return y))
3735− Skip s -> return $ Skip (s, acc)
3736− Stop -> return Stop
3737−
3738−{-# INLINE_NORMAL postscanlx' #-}
3739−postscanlx' :: Monad m
3740− => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
3741−postscanlx' fstep begin done s =
3742− postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
3743−
3744−-- XXX do we need consM strict to evaluate the begin value?
3745−{-# INLINE scanlMx' #-}
3746−scanlMx' :: Monad m
3747− => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
3748−scanlMx' fstep begin done s =
3749− (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
3750−
3751−
3752−data PostScanState s f = PostScan s !f
3753−
3754−{-# INLINE_NORMAL postscanOnce #-}
3755−postscanOnce :: Monad m => FL.Fold m a b -> Stream m a -> Stream m b
3756−postscanOnce (FL.Fold fstep begin done) (Stream step state) =
3757− Stream step' (PostScan state begin)
3758−
3759− where
3760−
3761− {-# INLINE_LATE step' #-}
3762− step' gst (PostScan st acc) = do
3763− r <- step (adaptState gst) st
3764− case r of
3765− Yield x s -> do
3766− old <- acc
3767− res <- fstep old x
3768− case res of
3769− FL.Partial fs -> do
3770− !v <- done fs
3771− return $ Yield v $ PostScan s (return fs)
3772− FL.Done _ -> return Stop
3773− Skip s -> return $ Skip $ PostScan s acc
3774− Stop -> return Stop
3775−
3776−{-# INLINE scanOnce #-}
3777−scanOnce :: Monad m
3778− => FL.Fold m a b -> Stream m a -> Stream m b
3779−scanOnce fld@(FL.Fold _ begin done) s =
3780− (begin >>= \x -> x `seq` done x) `consM` postscanOnce fld s
3781−
3782−{-# INLINE scanlx' #-}
3783−scanlx' :: Monad m
3784− => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
3785−scanlx' fstep begin done s =
3786− scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
3787−
3788−------------------------------------------------------------------------------
3789−-- postscans
3790−------------------------------------------------------------------------------
3791−
3792−{-# INLINE_NORMAL postscanlM' #-}
3793−postscanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
3794−postscanlM' fstep begin (Stream step state) =
3795− Stream step' Nothing
3796− where
3797− {-# INLINE_LATE step' #-}
3798− step' _ Nothing = do
3799− !x <- begin
3800− return $ Skip (Just (state, x))
3801−
3802− step' gst (Just (st, acc)) = do
3803− r <- step (adaptState gst) st
3804− case r of
3805− Yield x s -> do
3806− !y <- fstep acc x
3807− return $ Yield y (Just (s, y))
3808− Skip s -> return $ Skip (Just (s, acc))
3809− Stop -> return Stop
3810−
3811−{-# INLINE_NORMAL postscanl' #-}
3812−postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
3813−postscanl' f seed = postscanlM' (\a b -> return (f a b)) (return seed)
3814−
3815−-- We can possibly have the "done" function as a Maybe to provide an option to
3816−-- emit or not emit the accumulator when the stream stops.
3817−--
3818−-- TBD: use a single Yield point
3819−--
3820−{-# INLINE_NORMAL postscanlMAfter' #-}
3821−postscanlMAfter' :: Monad m
3822− => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
3823−postscanlMAfter' fstep initial done (Stream step1 state1) = do
3824− Stream step (Just (state1, initial))
3825−
3826− where
3827−
3828− {-# INLINE_LATE step #-}
3829− step gst (Just (st, acc)) = do
3830− r <- step1 (adaptState gst) st
3831− case r of
3832− Yield x s -> do
3833− old <- acc
3834− y <- fstep old x
3835− y `seq` return (Yield y (Just (s, return y)))
3836− Skip s -> return $ Skip $ Just (s, acc)
3837− Stop -> acc >>= done >>= \res -> return (Yield res Nothing)
3838− step _ Nothing = return Stop
3839−
3840−{-# INLINE_NORMAL postscanlM #-}
3841−postscanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
3842−postscanlM fstep begin (Stream step state) = Stream step' Nothing
3843− where
3844− {-# INLINE_LATE step' #-}
3845− step' _ Nothing = do
3846− r <- begin
3847− return $ Skip (Just (state, r))
3848−
3849− step' gst (Just (st, acc)) = do
3850− r <- step (adaptState gst) st
3851− case r of
3852− Yield x s -> do
3853− y <- fstep acc x
3854− return (Yield y (Just (s, y)))
3855− Skip s -> return $ Skip (Just (s, acc))
3856− Stop -> return Stop
3857−
3858−{-# INLINE_NORMAL postscanl #-}
3859−postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
3860−postscanl f seed = postscanlM (\a b -> return (f a b)) (return seed)
3861−
3862−{-# INLINE_NORMAL scanlM' #-}
3863−scanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
3864−scanlM' fstep begin (Stream step state) = Stream step' Nothing
3865− where
3866− {-# INLINE_LATE step' #-}
3867− step' _ Nothing = do
3868− !x <- begin
3869− return $ Yield x (Just (state, x))
3870− step' gst (Just (st, acc)) = do
3871− r <- step (adaptState gst) st
3872− case r of
3873− Yield x s -> do
3874− !y <- fstep acc x
3875− return $ Yield y (Just (s, y))
3876− Skip s -> return $ Skip (Just (s, acc))
3877− Stop -> return Stop
3878−
3879−{-# INLINE scanlMAfter' #-}
3880−scanlMAfter' :: Monad m
3881− => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
3882−scanlMAfter' fstep initial done s =
3883− (initial >>= \x -> x `seq` return x) `consM`
3884− postscanlMAfter' fstep initial done s
3885−
3886−{-# INLINE scanl' #-}
3887−scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3888−scanl' f seed = scanlM' (\a b -> return (f a b)) (return seed)
3889−
3890−{-# INLINE_NORMAL scanlM #-}
3891−scanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
3892−scanlM fstep begin (Stream step state) = Stream step' Nothing
3893− where
3894− {-# INLINE_LATE step' #-}
3895− step' _ Nothing = do
3896− x <- begin
3897− return $ Yield x (Just (state, x))
3898− step' gst (Just (st, acc)) = do
3899− r <- step (adaptState gst) st
3900− case r of
3901− Yield x s -> do
3902− y <- fstep acc x
3903− return $ Yield y (Just (s, y))
3904− Skip s -> return $ Skip (Just (s, acc))
3905− Stop -> return $ Stop
3906−
3907−{-# INLINE scanl #-}
3908−scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3909−scanl f seed = scanlM (\a b -> return (f a b)) (return seed)
3910−
3911−{-# INLINE_NORMAL scanl1M #-}
3912−scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
3913−scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
3914− where
3915− {-# INLINE_LATE step' #-}
3916− step' gst (st, Nothing) = do
3917− r <- step gst st
3918− case r of
3919− Yield x s -> return $ Yield x (s, Just x)
3920− Skip s -> return $ Skip (s, Nothing)
3921− Stop -> return Stop
3922−
3923− step' gst (st, Just acc) = do
3924− r <- step gst st
3925− case r of
3926− Yield y s -> do
3927− z <- fstep acc y
3928− return $ Yield z (s, Just z)
3929− Skip s -> return $ Skip (s, Just acc)
3930− Stop -> return Stop
3931−
3932−{-# INLINE scanl1 #-}
3933−scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
3934−scanl1 f = scanl1M (\x y -> return (f x y))
3935−
3936−{-# INLINE_NORMAL scanl1M' #-}
3937−scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
3938−scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
3939− where
3940− {-# INLINE_LATE step' #-}
3941− step' gst (st, Nothing) = do
3942− r <- step gst st
3943− case r of
3944− Yield x s -> x `seq` return $ Yield x (s, Just x)
3945− Skip s -> return $ Skip (s, Nothing)
3946− Stop -> return Stop
3947−
3948− step' gst (st, Just acc) = acc `seq` do
3949− r <- step gst st
3950− case r of
3951− Yield y s -> do
3952− z <- fstep acc y
3953− z `seq` return $ Yield z (s, Just z)
3954− Skip s -> return $ Skip (s, Just acc)
3955− Stop -> return Stop
3956−
3957−{-# INLINE scanl1' #-}
3958−scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
3959−scanl1' f = scanl1M' (\x y -> return (f x y))
3960−
3961−------------------------------------------------------------------------------
3962−-- Stateful map/scan
3963−------------------------------------------------------------------------------
3964−
3965−data RollingMapState s a = RollingMapInit s | RollingMapGo s a
3966−
3967−{-# INLINE rollingMapM #-}
3968−rollingMapM :: Monad m => (a -> a -> m b) -> Stream m a -> Stream m b
3969−rollingMapM f (Stream step1 state1) = Stream step (RollingMapInit state1)
3970− where
3971− step gst (RollingMapInit st) = do
3972− r <- step1 (adaptState gst) st
3973− return $ case r of
3974− Yield x s -> Skip $ RollingMapGo s x
3975− Skip s -> Skip $ RollingMapInit s
3976− Stop -> Stop
3977−
3978− step gst (RollingMapGo s1 x1) = do
3979− r <- step1 (adaptState gst) s1
3980− case r of
3981− Yield x s -> do
3982− !res <- f x x1
3983− return $ Yield res $ RollingMapGo s x
3984− Skip s -> return $ Skip $ RollingMapGo s x1
3985− Stop -> return $ Stop
3986−
3987−{-# INLINE rollingMap #-}
3988−rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
3989−rollingMap f = rollingMapM (\x y -> return $ f x y)
3990−
3991−------------------------------------------------------------------------------
3992−-- Tapping/Distributing
3993−------------------------------------------------------------------------------
3994−
3995−data TapState fs st a
3996− = TapInit | Tapping !fs st | TapDone st
3997−
3998−-- XXX Multiple yield points
3999−{-# INLINE tap #-}
4000−tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
4001−tap (Fold fstep initial extract) (Stream step state) = Stream step' TapInit
4002−
4003− where
4004−
4005− step' _ TapInit = do
4006− r <- initial
4007− return $ Skip (Tapping r state)
4008− step' gst (Tapping acc st) = do
4009− r <- step gst st
4010− case r of
4011− Yield x s -> do
4012− res <- fstep acc x
4013− return
4014− $ Yield x
4015− $ case res of
4016− FL.Partial fs -> Tapping fs s
4017− FL.Done _ -> TapDone s
4018− Skip s -> return $ Skip (Tapping acc s)
4019− Stop -> do
4020− void $ extract acc
4021− return Stop
4022− step' gst (TapDone st) = do
4023− r <- step gst st
4024− return
4025− $ case r of
4026− Yield x s -> Yield x (TapDone s)
4027− Skip s -> Skip (TapDone s)
4028− Stop -> Stop
4029−
4030−data TapOffState fs s a
4031− = TapOffInit
4032− | TapOffTapping !fs s Int
4033− | TapOffDone s
4034−
4035−-- XXX Multiple yield points
4036−{-# INLINE_NORMAL tapOffsetEvery #-}
4037−tapOffsetEvery :: Monad m
4038− => Int -> Int -> Fold m a b -> Stream m a -> Stream m a
4039−tapOffsetEvery offset n (Fold fstep initial extract) (Stream step state) =
4040− Stream step' TapOffInit
4041−
4042− where
4043−
4044− {-# INLINE_LATE step' #-}
4045− step' _ TapOffInit = do
4046− r <- initial
4047− return $ Skip $ TapOffTapping r state (offset `mod` n)
4048− step' gst (TapOffTapping acc st count) = do
4049− r <- step gst st
4050− case r of
4051− Yield x s -> do
4052− next <-
4053− if count <= 0
4054− then do
4055− res <- fstep acc x
4056− return
4057− $ case res of
4058− FL.Partial sres ->
4059− TapOffTapping sres s (n - 1)
4060− FL.Done _ -> TapOffDone s
4061− else return $ TapOffTapping acc s (count - 1)
4062− return $ Yield x next
4063− Skip s -> return $ Skip (TapOffTapping acc s count)
4064− Stop -> do
4065− void $ extract acc
4066− return Stop
4067− step' gst (TapOffDone st) = do
4068− r <- step gst st
4069− return
4070− $ case r of
4071− Yield x s -> Yield x (TapOffDone s)
4072− Skip s -> Skip (TapOffDone s)
4073− Stop -> Stop
4074−
4075−{-# INLINE_NORMAL pollCounts #-}
4076−pollCounts
4077− :: MonadAsync m
4078− => (a -> Bool)
4079− -> (Stream m Int -> Stream m Int)
4080− -> Fold m Int b
4081− -> Stream m a
4082− -> Stream m a
4083−pollCounts predicate transf fld (Stream step state) = Stream step' Nothing
4084− where
4085−
4086− {-# INLINE_LATE step' #-}
4087− step' _ Nothing = do
4088− -- As long as we are using an "Int" for counts lockfree reads from
4089− -- Var should work correctly on both 32-bit and 64-bit machines.
4090− -- However, an Int on a 32-bit machine may overflow quickly.
4091− countVar <- liftIO $ Prim.newIORef (0 :: Int)
4092− tid <- forkManaged
4093− $ void $ foldOnce fld
4094− $ transf $ fromPrimIORef countVar
4095− return $ Skip (Just (countVar, tid, state))
4096−
4097− step' gst (Just (countVar, tid, st)) = do
4098− r <- step gst st
4099− case r of
4100− Yield x s -> do
4101− when (predicate x) $ liftIO $ Prim.modifyIORef' countVar (+ 1)
4102− return $ Yield x (Just (countVar, tid, s))
4103− Skip s -> return $ Skip (Just (countVar, tid, s))
4104− Stop -> do
4105− liftIO $ killThread tid
4106− return Stop
4107−
4108−{-# INLINE_NORMAL tapRate #-}
4109−tapRate ::
4110− (MonadAsync m, MonadCatch m)
4111− => Double
4112− -> (Int -> m b)
4113− -> Stream m a
4114− -> Stream m a
4115−tapRate samplingRate action (Stream step state) = Stream step' Nothing
4116− where
4117− {-# NOINLINE loop #-}
4118− loop countVar prev = do
4119− i <-
4120− MC.catch
4121− (do liftIO $ threadDelay (round $ samplingRate * 1000000)
4122− i <- liftIO $ Prim.readIORef countVar
4123− let !diff = i - prev
4124− void $ action diff
4125− return i)
4126− (\(e :: AsyncException) -> do
4127− i <- liftIO $ Prim.readIORef countVar
4128− let !diff = i - prev
4129− void $ action diff
4130− throwM (MC.toException e))
4131− loop countVar i
4132−
4133− {-# INLINE_LATE step' #-}
4134− step' _ Nothing = do
4135− countVar <- liftIO $ Prim.newIORef 0
4136− tid <- fork $ loop countVar 0
4137− ref <- liftIO $ newIORef ()
4138− _ <- liftIO $ mkWeakIORef ref (killThread tid)
4139− return $ Skip (Just (countVar, tid, state, ref))
4140−
4141− step' gst (Just (countVar, tid, st, ref)) = do
4142− r <- step gst st
4143− case r of
4144− Yield x s -> do
4145− liftIO $ Prim.modifyIORef' countVar (+ 1)
4146− return $ Yield x (Just (countVar, tid, s, ref))
4147− Skip s -> return $ Skip (Just (countVar, tid, s, ref))
4148− Stop -> do
4149− liftIO $ killThread tid
4150− return Stop
4151−
4152−
4153−-------------------------------------------------------------------------------
4154−-- Filtering
4155−-------------------------------------------------------------------------------
4156−
4157−{-# INLINE_NORMAL takeWhileM #-}
4158−takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
4159−takeWhileM f (Stream step state) = Stream step' state
4160− where
4161− {-# INLINE_LATE step' #-}
4162− step' gst st = do
4163− r <- step gst st
4164− case r of
4165− Yield x s -> do
4166− b <- f x
4167− return $ if b then Yield x s else Stop
4168− Skip s -> return $ Skip s
4169− Stop -> return Stop
4170−
4171−{-# INLINE takeWhile #-}
4172−takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
4173−takeWhile f = takeWhileM (return . f)
4174−
4175−{-# INLINE_NORMAL drop #-}
4176−drop :: Monad m => Int -> Stream m a -> Stream m a
4177−drop n (Stream step state) = Stream step' (state, Just n)
4178− where
4179− {-# INLINE_LATE step' #-}
4180− step' gst (st, Just i)
4181− | i > 0 = do
4182− r <- step gst st
4183− return $
4184− case r of
4185− Yield _ s -> Skip (s, Just (i - 1))
4186− Skip s -> Skip (s, Just i)
4187− Stop -> Stop
4188− | otherwise = return $ Skip (st, Nothing)
4189−
4190− step' gst (st, Nothing) = do
4191− r <- step gst st
4192− return $
4193− case r of
4194− Yield x s -> Yield x (s, Nothing)
4195− Skip s -> Skip (s, Nothing)
4196− Stop -> Stop
4197−
4198−data DropWhileState s a
4199− = DropWhileDrop s
4200− | DropWhileYield a s
4201− | DropWhileNext s
4202−
4203−{-# INLINE_NORMAL dropWhileM #-}
4204−dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
4205−dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
4206− where
4207− {-# INLINE_LATE step' #-}
4208− step' gst (DropWhileDrop st) = do
4209− r <- step gst st
4210− case r of
4211− Yield x s -> do
4212− b <- f x
4213− if b
4214− then return $ Skip (DropWhileDrop s)
4215− else return $ Skip (DropWhileYield x s)
4216− Skip s -> return $ Skip (DropWhileDrop s)
4217− Stop -> return Stop
4218−
4219− step' gst (DropWhileNext st) = do
4220− r <- step gst st
4221− case r of
4222− Yield x s -> return $ Skip (DropWhileYield x s)
4223− Skip s -> return $ Skip (DropWhileNext s)
4224− Stop -> return Stop
4225−
4226− step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
4227−
4228−{-# INLINE dropWhile #-}
4229−dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
4230−dropWhile f = dropWhileM (return . f)
4231−
4232−{-# INLINE_NORMAL filterM #-}
4233−filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
4234−filterM f (Stream step state) = Stream step' state
4235− where
4236− {-# INLINE_LATE step' #-}
4237− step' gst st = do
4238− r <- step gst st
4239− case r of
4240− Yield x s -> do
4241− b <- f x
4242− return $ if b
4243− then Yield x s
4244− else Skip s
4245− Skip s -> return $ Skip s
4246− Stop -> return Stop
4247−
4248−{-# INLINE filter #-}
4249−filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
4250−filter f = filterM (return . f)
4251−
4252−{-# INLINE_NORMAL uniq #-}
4253−uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
4254−uniq (Stream step state) = Stream step' (Nothing, state)
4255− where
4256− {-# INLINE_LATE step' #-}
4257− step' gst (Nothing, st) = do
4258− r <- step gst st
4259− case r of
4260− Yield x s -> return $ Yield x (Just x, s)
4261− Skip s -> return $ Skip (Nothing, s)
4262− Stop -> return Stop
4263− step' gst (Just x, st) = do
4264− r <- step gst st
4265− case r of
4266− Yield y s | x == y -> return $ Skip (Just x, s)
4267− | otherwise -> return $ Yield y (Just y, s)
4268− Skip s -> return $ Skip (Just x, s)
4269− Stop -> return Stop
4270−
4271−------------------------------------------------------------------------------
4272−-- Transformation by Mapping
4273−------------------------------------------------------------------------------
4274−
4275−{-# INLINE_NORMAL sequence #-}
4276−sequence :: Monad m => Stream m (m a) -> Stream m a
4277−sequence (Stream step state) = Stream step' state
4278− where
4279− {-# INLINE_LATE step' #-}
4280− step' gst st = do
4281− r <- step (adaptState gst) st
4282− case r of
4283− Yield x s -> x >>= \a -> return (Yield a s)
4284− Skip s -> return $ Skip s
4285− Stop -> return Stop
4286−
4287−------------------------------------------------------------------------------
4288−-- Inserting
4289−------------------------------------------------------------------------------
4290−
4291−data LoopState x s = FirstYield s
4292− | InterspersingYield s
4293− | YieldAndCarry x s
4294−
4295−{-# INLINE_NORMAL intersperseM #-}
4296−intersperseM :: Monad m => m a -> Stream m a -> Stream m a
4297−intersperseM m (Stream step state) = Stream step' (FirstYield state)
4298− where
4299− {-# INLINE_LATE step' #-}
4300− step' gst (FirstYield st) = do
4301− r <- step gst st
4302− return $
4303− case r of
4304− Yield x s -> Skip (YieldAndCarry x s)
4305− Skip s -> Skip (FirstYield s)
4306− Stop -> Stop
4307−
4308− step' gst (InterspersingYield st) = do
4309− r <- step gst st
4310− case r of
4311− Yield x s -> do
4312− a <- m
4313− return $ Yield a (YieldAndCarry x s)
4314− Skip s -> return $ Skip $ InterspersingYield s
4315− Stop -> return Stop
4316−
4317− step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
4318−
4319−{-# INLINE_NORMAL intersperseM_ #-}
4320−intersperseM_ :: Monad m => m b -> Stream m a -> Stream m a
4321−intersperseM_ m (Stream step1 state1) = Stream step (Left (pure (), state1))
4322− where
4323− {-# INLINE_LATE step #-}
4324− step gst (Left (eff, st)) = do
4325− r <- step1 gst st
4326− case r of
4327− Yield x s -> eff >> return (Yield x (Right s))
4328− Skip s -> return $ Skip (Left (eff, s))
4329− Stop -> return Stop
4330−
4331− step _ (Right st) = return $ Skip $ Left (void m, st)
4332−
4333−data SuffixState s a
4334− = SuffixElem s
4335− | SuffixSuffix s
4336− | SuffixYield a (SuffixState s a)
4337−
4338−{-# INLINE_NORMAL intersperseSuffix #-}
4339−intersperseSuffix :: forall m a. Monad m => m a -> Stream m a -> Stream m a
4340−intersperseSuffix action (Stream step state) = Stream step' (SuffixElem state)
4341− where
4342− {-# INLINE_LATE step' #-}
4343− step' gst (SuffixElem st) = do
4344− r <- step gst st
4345− return $ case r of
4346− Yield x s -> Skip (SuffixYield x (SuffixSuffix s))
4347− Skip s -> Skip (SuffixElem s)
4348− Stop -> Stop
4349−
4350− step' _ (SuffixSuffix st) = do
4351− action >>= \r -> return $ Skip (SuffixYield r (SuffixElem st))
4352−
4353− step' _ (SuffixYield x next) = return $ Yield x next
4354−
4355−{-# INLINE_NORMAL intersperseSuffix_ #-}
4356−intersperseSuffix_ :: Monad m => m b -> Stream m a -> Stream m a
4357−intersperseSuffix_ m (Stream step1 state1) = Stream step (Left state1)
4358− where
4359− {-# INLINE_LATE step #-}
4360− step gst (Left st) = do
4361− r <- step1 gst st
4362− case r of
4363− Yield x s -> return $ Yield x (Right s)
4364− Skip s -> return $ Skip $ Left s
4365− Stop -> return Stop
4366−
4367− step _ (Right st) = m >> return (Skip (Left st))
4368−
4369−data SuffixSpanState s a
4370− = SuffixSpanElem s Int
4371− | SuffixSpanSuffix s
4372− | SuffixSpanYield a (SuffixSpanState s a)
4373− | SuffixSpanLast
4374− | SuffixSpanStop
4375−
4376−-- | intersperse after every n items
4377−{-# INLINE_NORMAL intersperseSuffixBySpan #-}
4378−intersperseSuffixBySpan :: forall m a. Monad m
4379− => Int -> m a -> Stream m a -> Stream m a
4380−intersperseSuffixBySpan n action (Stream step state) =
4381− Stream step' (SuffixSpanElem state n)
4382− where
4383− {-# INLINE_LATE step' #-}
4384− step' gst (SuffixSpanElem st i) | i > 0 = do
4385− r <- step gst st
4386− return $ case r of
4387− Yield x s -> Skip (SuffixSpanYield x (SuffixSpanElem s (i - 1)))
4388− Skip s -> Skip (SuffixSpanElem s i)
4389− Stop -> if i == n then Stop else Skip SuffixSpanLast
4390− step' _ (SuffixSpanElem st _) = return $ Skip (SuffixSpanSuffix st)
4391−
4392− step' _ (SuffixSpanSuffix st) = do
4393− action >>= \r -> return $ Skip (SuffixSpanYield r (SuffixSpanElem st n))
4394−
4395− step' _ (SuffixSpanLast) = do
4396− action >>= \r -> return $ Skip (SuffixSpanYield r SuffixSpanStop)
4397−
4398− step' _ (SuffixSpanYield x next) = return $ Yield x next
4399−
4400− step' _ (SuffixSpanStop) = return Stop
4401−
4402−{-# INLINE intersperse #-}
4403−intersperse :: Monad m => a -> Stream m a -> Stream m a
4404−intersperse a = intersperseM (return a)
4405−
4406−{-# INLINE_NORMAL insertBy #-}
4407−insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
4408−insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
4409− where
4410− {-# INLINE_LATE step' #-}
4411− step' gst (st, False, _) = do
4412− r <- step gst st
4413− case r of
4414− Yield x s -> case cmp a x of
4415− GT -> return $ Yield x (s, False, Nothing)
4416− _ -> return $ Yield a (s, True, Just x)
4417− Skip s -> return $ Skip (s, False, Nothing)
4418− Stop -> return $ Yield a (st, True, Nothing)
4419−
4420− step' _ (_, True, Nothing) = return Stop
4421−
4422− step' gst (st, True, Just prev) = do
4423− r <- step gst st
4424− case r of
4425− Yield x s -> return $ Yield prev (s, True, Just x)
4426− Skip s -> return $ Skip (s, True, Just prev)
4427− Stop -> return $ Yield prev (st, True, Nothing)
4428−
4429−------------------------------------------------------------------------------
4430−-- Deleting
4431−------------------------------------------------------------------------------
4432−
4433−{-# INLINE_NORMAL deleteBy #-}
4434−deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
4435−deleteBy eq x (Stream step state) = Stream step' (state, False)
4436− where
4437− {-# INLINE_LATE step' #-}
4438− step' gst (st, False) = do
4439− r <- step gst st
4440− case r of
4441− Yield y s -> return $
4442− if eq x y then Skip (s, True) else Yield y (s, False)
4443− Skip s -> return $ Skip (s, False)
4444− Stop -> return Stop
4445−
4446− step' gst (st, True) = do
4447− r <- step gst st
4448− case r of
4449− Yield y s -> return $ Yield y (s, True)
4450− Skip s -> return $ Skip (s, True)
4451− Stop -> return Stop
4452−
4453−------------------------------------------------------------------------------
4454−-- Transformation by Map and Filter
4455−------------------------------------------------------------------------------
4456−
4457−-- XXX Will this always fuse properly?
4458−{-# INLINE_NORMAL mapMaybe #-}
4459−mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
4460−mapMaybe f = fmap fromJust . filter isJust . map f
4461−
4462−{-# INLINE_NORMAL mapMaybeM #-}
4463−mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
4464−mapMaybeM f = fmap fromJust . filter isJust . mapM f
4465−
4466−------------------------------------------------------------------------------
4467−-- Zipping
4468−------------------------------------------------------------------------------
4469−
4470−{-# INLINE_NORMAL indexed #-}
4471−indexed :: Monad m => Stream m a -> Stream m (Int, a)
4472−indexed (Stream step state) = Stream step' (state, 0)
4473− where
4474− {-# INLINE_LATE step' #-}
4475− step' gst (st, i) = i `seq` do
4476− r <- step (adaptState gst) st
4477− case r of
4478− Yield x s -> return $ Yield (i, x) (s, i+1)
4479− Skip s -> return $ Skip (s, i)
4480− Stop -> return Stop
4481−
4482−{-# INLINE_NORMAL indexedR #-}
4483−indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
4484−indexedR m (Stream step state) = Stream step' (state, m)
4485− where
4486− {-# INLINE_LATE step' #-}
4487− step' gst (st, i) = i `seq` do
4488− r <- step (adaptState gst) st
4489− case r of
4490− Yield x s -> let i' = i - 1
4491− in return $ Yield (i, x) (s, i')
4492− Skip s -> return $ Skip (s, i)
4493− Stop -> return Stop
4494−
4495−{-# INLINE_NORMAL zipWithM #-}
4496−zipWithM :: Monad m
4497− => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
4498−zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
4499− where
4500− {-# INLINE_LATE step #-}
4501− step gst (sa, sb, Nothing) = do
4502− r <- stepa (adaptState gst) sa
4503− return $
4504− case r of
4505− Yield x sa' -> Skip (sa', sb, Just x)
4506− Skip sa' -> Skip (sa', sb, Nothing)
4507− Stop -> Stop
4508−
4509− step gst (sa, sb, Just x) = do
4510− r <- stepb (adaptState gst) sb
4511− case r of
4512− Yield y sb' -> do
4513− z <- f x y
4514− return $ Yield z (sa, sb', Nothing)
4515− Skip sb' -> return $ Skip (sa, sb', Just x)
4516− Stop -> return Stop
4517−
4518−#if __GLASGOW_HASKELL__ >= 801
4519−{-# RULES "zipWithM xs xs"
4520− forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
4521−#endif
4522−
4523−{-# INLINE zipWith #-}
4524−zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
4525−zipWith f = zipWithM (\a b -> return (f a b))
4526−
4527−------------------------------------------------------------------------------
4528−-- Merging
4529−------------------------------------------------------------------------------
4530−
4531−{-# INLINE_NORMAL mergeByM #-}
4532−mergeByM
4533− :: (Monad m)
4534− => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
4535−mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
4536− Stream step (Just ta, Just tb, Nothing, Nothing)
4537− where
4538− {-# INLINE_LATE step #-}
4539−
4540− -- one of the values is missing, and the corresponding stream is running
4541− step gst (Just sa, sb, Nothing, b) = do
4542− r <- stepa gst sa
4543− return $ case r of
4544− Yield a sa' -> Skip (Just sa', sb, Just a, b)
4545− Skip sa' -> Skip (Just sa', sb, Nothing, b)
4546− Stop -> Skip (Nothing, sb, Nothing, b)
4547−
4548− step gst (sa, Just sb, a, Nothing) = do
4549− r <- stepb gst sb
4550− return $ case r of
4551− Yield b sb' -> Skip (sa, Just sb', a, Just b)
4552− Skip sb' -> Skip (sa, Just sb', a, Nothing)
4553− Stop -> Skip (sa, Nothing, a, Nothing)
4554−
4555− -- both the values are available
4556− step _ (sa, sb, Just a, Just b) = do
4557− res <- cmp a b
4558− return $ case res of
4559− GT -> Yield b (sa, sb, Just a, Nothing)
4560− _ -> Yield a (sa, sb, Nothing, Just b)
4561−
4562− -- one of the values is missing, corresponding stream is done
4563− step _ (Nothing, sb, Nothing, Just b) =
4564− return $ Yield b (Nothing, sb, Nothing, Nothing)
4565−
4566− step _ (sa, Nothing, Just a, Nothing) =
4567− return $ Yield a (sa, Nothing, Nothing, Nothing)
4568−
4569− step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
4570−
4571−{-# INLINE mergeBy #-}
4572−mergeBy
4573− :: (Monad m)
4574− => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
4575−mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
4576−
4577−------------------------------------------------------------------------------
4578−-- Transformation comprehensions
4579−------------------------------------------------------------------------------
4580−
4581−{-# INLINE_NORMAL the #-}
4582−the :: (Eq a, Monad m) => Stream m a -> m (Maybe a)
4583−the (Stream step state) = go state
4584− where
4585− go st = do
4586− r <- step defState st
4587− case r of
4588− Yield x s -> go' x s
4589− Skip s -> go s
4590− Stop -> return Nothing
4591− go' n st = do
4592− r <- step defState st
4593− case r of
4594− Yield x s | x == n -> go' n s
4595− | otherwise -> return Nothing
4596− Skip s -> go' n s
4597− Stop -> return (Just n)
4598−
4599−{-# INLINE_NORMAL foldOnce #-}
4600−foldOnce :: (Monad m) => Fold m a b -> Stream m a -> m b
4601−foldOnce (Fold fstep begin done) (Stream step state) =
4602− begin >>= \x -> go SPEC x state
4603−
4604− where
4605−
4606− {-# INLINE go #-}
4607− go !_ !fs st = do
4608− r <- step defState st
4609− case r of
4610− Yield x s -> do
4611− res <- fstep fs x
4612− case res of
4613− FL.Done b -> return b
4614− FL.Partial fs1 -> go SPEC fs1 s
4615− Skip s -> go SPEC fs s
4616− Stop -> done fs
4617−
4618−-------------------------------------------------------------------------------
4619−-- Concurrent application and fold
4620−-------------------------------------------------------------------------------
4621−
4622−-- XXX These functions should be moved to Stream/Parallel.hs
4623−--
4624−-- Using StreamD the worker stream producing code can fuse with the code to
4625−-- queue output to the SVar giving some perf boost.
4626−--
4627−-- Note that StreamD can only be used in limited situations, specifically, we
4628−-- cannot implement joinStreamVarPar using this.
4629−--
4630−-- XXX make sure that the SVar passed is a Parallel style SVar.
4631−
4632−-- | Fold the supplied stream to the SVar asynchronously using Parallel
4633−-- concurrency style.
4634−-- {-# INLINE_NORMAL toSVarParallel #-}
4635−{-# INLINE toSVarParallel #-}
4636−toSVarParallel :: MonadAsync m
4637− => State t m a -> SVar t m a -> Stream m a -> m ()
4638−toSVarParallel st sv xs =
4639− if svarInspectMode sv
4640− then forkWithDiag
4641− else do
4642− tid <-
4643− case getYieldLimit st of
4644− Nothing -> doFork (work Nothing)
4645− (svarMrun sv)
4646− (handleChildException sv)
4647− Just _ -> doFork (workLim Nothing)
4648− (svarMrun sv)
4649− (handleChildException sv)
4650− modifyThread sv tid
4651−
4652− where
4653−
4654− {-# NOINLINE work #-}
4655− work info = (foldOnce (FL.toParallelSVar sv info) xs)
4656−
4657− {-# NOINLINE workLim #-}
4658− workLim info = foldOnce (FL.toParallelSVarLimited sv info) xs
4659−
4660− {-# NOINLINE forkWithDiag #-}
4661− forkWithDiag = do
4662− -- We do not use workerCount in case of ParallelVar but still there is
4663− -- no harm in maintaining it correctly.
4664− liftIO $ atomicModifyIORefCAS_ (workerCount sv) $ \n -> n + 1
4665− recordMaxWorkers sv
4666− -- This allocation matters when significant number of workers are being
4667− -- sent. We allocate it only when needed. The overhead increases by 4x.
4668− winfo <-
4669− case yieldRateInfo sv of
4670− Nothing -> return Nothing
4671− Just _ -> liftIO $ do
4672− cntRef <- newIORef 0
4673− t <- getTime Monotonic
4674− lat <- newIORef (0, t)
4675− return $ Just WorkerInfo
4676− { workerYieldMax = 0
4677− , workerYieldCount = cntRef
4678− , workerLatencyStart = lat
4679− }
4680− tid <-
4681− case getYieldLimit st of
4682− Nothing -> doFork (work winfo)
4683− (svarMrun sv)
4684− (handleChildException sv)
4685− Just _ -> doFork (workLim winfo)
4686− (svarMrun sv)
4687− (handleChildException sv)
4688− modifyThread sv tid
4689−
4690−{-# INLINE_NORMAL mkParallelD #-}
4691−mkParallelD :: MonadAsync m => Stream m a -> Stream m a
4692−mkParallelD m = Stream step Nothing
4693− where
4694−
4695− step gst Nothing = do
4696− sv <- newParallelVar StopNone gst
4697− toSVarParallel gst sv m
4698− -- XXX use unfold instead?
4699− return $ Skip $ Just $ fromSVar sv
4700−
4701− step gst (Just (UnStream step1 st)) = do
4702− r <- step1 gst st
4703− return $ case r of
4704− Yield a s -> Yield a (Just $ Stream step1 s)
4705− Skip s -> Skip (Just $ Stream step1 s)
4706− Stop -> Stop
4707−
4708−-- Compare with mkAsync. mkAsync uses an Async style SVar whereas this uses a
4709−-- parallel style SVar for evaluation. Currently, parallel style cannot use
4710−-- rate control whereas Async style can use rate control. In async style SVar
4711−-- the worker thread terminates when the buffer is full whereas in Parallel
4712−-- style it blocks.
4713−--
4714−-- | Make the stream producer and consumer run concurrently by introducing a
4715−-- buffer between them. The producer thread evaluates the input stream until
4716−-- the buffer fills, it blocks if the buffer is full until there is space in
4717−-- the buffer. The consumer consumes the stream lazily from the buffer.
4718−--
4719−-- /Internal/
4720−--
4721−{-# INLINE_NORMAL mkParallel #-}
4722−mkParallel :: (K.IsStream t, MonadAsync m) => t m a -> t m a
4723−mkParallel = fromStreamD . mkParallelD . toStreamD
4724−
4725−-- Note: we can use another API with two callbacks stop and yield if we want
4726−-- the callback to be able to indicate end of stream.
4727−--
4728−-- | Generates a callback and a stream pair. The callback returned is used to
4729−-- queue values to the stream. The stream is infinite, there is no way for the
4730−-- callback to indicate that it is done now.
4731−--
4732−-- /Internal/
4733−--
4734−{-# INLINE_NORMAL newCallbackStream #-}
4735−newCallbackStream :: (K.IsStream t, MonadAsync m) => m ((a -> m ()), t m a)
4736−newCallbackStream = do
4737− sv <- newParallelVar StopNone defState
4738−
4739− -- XXX Add our own thread-id to the SVar as we can not know the callback's
4740− -- thread-id and the callback is not run in a managed worker. We need to
4741− -- handle this better.
4742− liftIO myThreadId >>= modifyThread sv
4743−
4744− let callback a = liftIO $ void $ send sv (ChildYield a)
4745− -- XXX we can return an SVar and then the consumer can unfold from the
4746− -- SVar?
4747− return (callback, fromStreamD (fromSVar sv))
4748−
4749−-------------------------------------------------------------------------------
4750−-- Concurrent tap
4751−-------------------------------------------------------------------------------
4752−
4753−-- | Create an SVar with a fold consumer that will fold any elements sent to it
4754−-- using the supplied fold function.
4755−{-# INLINE newFoldSVar #-}
4756−newFoldSVar :: MonadAsync m => State t m a -> Fold m a b -> m (SVar t m a)
4757−newFoldSVar stt f = do
4758− -- Buffer size for the SVar is derived from the current state
4759− sv <- newParallelVar StopAny (adaptState stt)
4760− -- Add the producer thread-id to the SVar.
4761− liftIO myThreadId >>= modifyThread sv
4762− void $ doFork (work sv) (svarMrun sv) (handleFoldException sv)
4763− return sv
4764−
4765− where
4766−
4767− {-# NOINLINE work #-}
4768− work sv = void $ foldOnce f $ fromProducer sv
4769−
4770−{-# INLINE_NORMAL tapAsync #-}
4771−tapAsync :: MonadAsync m => Fold m a b -> Stream m a -> Stream m a
4772−tapAsync f (Stream step1 state1) = Stream step TapInit
4773− where
4774−
4775− drainFold svr = do
4776− -- In general, a Stop event would come equipped with the result
4777− -- of the fold. It is not used here but it would be useful in
4778− -- applicative and distribute.
4779− done <- fromConsumer svr
4780− when (not done) $ do
4781− liftIO $ withDiagMVar svr "teeToSVar: waiting to drain"
4782− $ takeMVar (outputDoorBellFromConsumer svr)
4783− drainFold svr
4784−
4785− stopFold svr = do
4786− liftIO $ sendStop svr Nothing
4787− -- drain/wait until a stop event arrives from the fold.
4788− drainFold svr
4789−
4790− {-# INLINE_LATE step #-}
4791− step gst TapInit = do
4792− sv <- newFoldSVar gst f
4793− return $ Skip (Tapping sv state1)
4794−
4795− step gst (Tapping sv st) = do
4796− r <- step1 gst st
4797− case r of
4798− Yield a s -> do
4799− done <- pushToFold sv a
4800− if done
4801− then do
4802− -- XXX we do not need to wait synchronously here
4803− stopFold sv
4804− return $ Yield a (TapDone s)
4805− else return $ Yield a (Tapping sv s)
4806− Skip s -> return $ Skip (Tapping sv s)
4807− Stop -> do
4808− stopFold sv
4809− return $ Stop
4810−
4811− step gst (TapDone st) = do
4812− r <- step1 gst st
4813− return $ case r of
4814− Yield a s -> Yield a (TapDone s)
4815− Skip s -> Skip (TapDone s)
4816− Stop -> Stop
4817−
4818−------------------------------------------------------------------------------
4819−-- Time related
4820−------------------------------------------------------------------------------
4821−
4822−-- XXX using getTime in the loop can be pretty expensive especially for
4823−-- computations where iterations are lightweight. We have the following
4824−-- options:
4825−--
4826−-- 1) Run a timeout thread updating a flag asynchronously and check that
4827−-- flag here, that way we can have a cheap termination check.
4828−--
4829−-- 2) Use COARSE clock to get time with lower resolution but more efficiently.
4830−--
4831−-- 3) Use rdtscp/rdtsc to get time directly from the processor, compute the
4832−-- termination value of rdtsc in the beginning and then in each iteration just
4833−-- get rdtsc and check if we should terminate.
4834−--
4835−data TakeByTime st s
4836− = TakeByTimeInit st
4837− | TakeByTimeCheck st s
4838− | TakeByTimeYield st s
4839−
4840−{-# INLINE_NORMAL takeByTime #-}
4841−takeByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
4842−takeByTime duration (Stream step1 state1) = Stream step (TakeByTimeInit state1)
4843− where
4844−
4845− lim = toRelTime64 duration
4846−
4847− {-# INLINE_LATE step #-}
4848− step _ (TakeByTimeInit _) | lim == 0 = return Stop
4849− step _ (TakeByTimeInit st) = do
4850− t0 <- liftIO $ getTime Monotonic
4851− return $ Skip (TakeByTimeYield st t0)
4852− step _ (TakeByTimeCheck st t0) = do
4853− t <- liftIO $ getTime Monotonic
4854− return $
4855− if diffAbsTime64 t t0 > lim
4856− then Stop
4857− else Skip (TakeByTimeYield st t0)
4858− step gst (TakeByTimeYield st t0) = do
4859− r <- step1 gst st
4860− return $ case r of
4861− Yield x s -> Yield x (TakeByTimeCheck s t0)
4862− Skip s -> Skip (TakeByTimeCheck s t0)
4863− Stop -> Stop
4864−
4865−data DropByTime st s x
4866− = DropByTimeInit st
4867− | DropByTimeGen st s
4868− | DropByTimeCheck st s x
4869− | DropByTimeYield st
4870−
4871−{-# INLINE_NORMAL dropByTime #-}
4872−dropByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
4873−dropByTime duration (Stream step1 state1) = Stream step (DropByTimeInit state1)
4874− where
4875−
4876− lim = toRelTime64 duration
4877−
4878− {-# INLINE_LATE step #-}
4879− step _ (DropByTimeInit st) = do
4880− t0 <- liftIO $ getTime Monotonic
4881− return $ Skip (DropByTimeGen st t0)
4882− step gst (DropByTimeGen st t0) = do
4883− r <- step1 gst st
4884− return $ case r of
4885− Yield x s -> Skip (DropByTimeCheck s t0 x)
4886− Skip s -> Skip (DropByTimeGen s t0)
4887− Stop -> Stop
4888− step _ (DropByTimeCheck st t0 x) = do
4889− t <- liftIO $ getTime Monotonic
4890− if diffAbsTime64 t t0 <= lim
4891− then return $ Skip $ DropByTimeGen st t0
4892− else return $ Yield x $ DropByTimeYield st
4893− step gst (DropByTimeYield st) = do
4894− r <- step1 gst st
4895− return $ case r of
4896− Yield x s -> Yield x (DropByTimeYield s)
4897− Skip s -> Skip (DropByTimeYield s)
4898− Stop -> Stop
4899−
4900−{-# INLINE updateTimeVar #-}
4901−updateTimeVar :: Prim.IORef Int64 -> IO ()
4902−updateTimeVar timeVar = do
4903− MicroSecond64 t <- fromAbsTime <$> getTime Monotonic
4904− Prim.modifyIORef' timeVar (const t)
4905−
4906−{-# INLINE updateWithDelay #-}
4907−updateWithDelay :: RealFrac a => a -> Prim.IORef Int64 -> IO ()
4908−updateWithDelay precision timeVar = do
4909− threadDelay (delayTime precision)
4910− updateTimeVar timeVar
4911−
4912− where
4913−
4914− -- Keep the minimum at least a millisecond to avoid high CPU usage
4915− {-# INLINE delayTime #-}
4916− delayTime g
4917− | g' >= fromIntegral (maxBound :: Int) = maxBound
4918− | g' < 1000 = 1000
4919− | otherwise = round g'
4920−
4921− where
4922−
4923− g' = g * 10 ^ (6 :: Int)
4924−
4925−-- XXX we should move this to stream generation section of this file. Also, the
4926−-- take/drop combinators above should be moved to filtering section.
4927−
4928−{-# INLINE_NORMAL times #-}
4929−times :: MonadAsync m => Double -> Stream m (AbsTime, RelTime64)
4930−times g = Stream step Nothing
4931−
4932− where
4933−
4934− {-# INLINE_LATE step #-}
4935− step _ Nothing = do
4936− -- XXX note that this is safe only on a 64-bit machine. On a 32-bit
4937− -- machine a 64-bit 'Var' cannot be read consistently without a lock
4938− -- while another thread is writing to it.
4939− timeVar <- liftIO $ Prim.newIORef (0 :: Int64)
4940− liftIO $ updateTimeVar timeVar
4941− tid <- forkManaged $ liftIO $ forever (updateWithDelay g timeVar)
4942− a <- liftIO $ Prim.readIORef timeVar
4943− return $ Skip $ Just (timeVar, tid, a)
4944−
4945− step _ s@(Just (timeVar, _, t0)) = do
4946− a <- liftIO $ Prim.readIORef timeVar
4947− -- XXX we can perhaps use an AbsTime64 using a 64 bit Int for
4948− -- efficiency. or maybe we can use a representation using Double for
4949− -- floating precision time
4950− return $ Yield (toAbsTime (MicroSecond64 t0),
4951− (toRelTime64 (MicroSecond64 (a - t0)))) s
309+-- XXX We could just export these modules directly
310+import Streamly.Internal.Data.Stream.StreamD.Type
311+import Streamly.Internal.Data.Stream.StreamD.Generate
312+import Streamly.Internal.Data.Stream.StreamD.Eliminate
313+import Streamly.Internal.Data.Stream.StreamD.Exception
314+import Streamly.Internal.Data.Stream.StreamD.Lift
315+import Streamly.Internal.Data.Stream.StreamD.Nesting
316+import Streamly.Internal.Data.Stream.StreamD.Transform
src/Streamly/Internal/Data/Stream/StreamD/Eliminate.hsnew file+494
@@ -0,0 +1,494 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.StreamD.Eliminate
3+-- Copyright : (c) 2018 Composewell Technologies
4+-- (c) Roman Leshchinskiy 2008-2010
5+-- License : BSD-3-Clause
6+-- Maintainer : streamly@composewell.com
7+-- Stability : experimental
8+-- Portability : GHC
9+
10+-- A few functions in this module have been adapted from the vector package
11+-- (c) Roman Leshchinskiy.
12+--
13+module Streamly.Internal.Data.Stream.StreamD.Eliminate
14+ (
15+ -- * Running a 'Fold'
16+ foldOnce -- XXX rename to "fold"
17+
18+ -- -- * Running a 'Parser'
19+ -- , parse
20+
21+ -- * Stream Deconstruction
22+ , uncons
23+
24+ -- * Right Folds
25+ , foldrM
26+ , foldr
27+ , foldrMx
28+ , foldr1
29+
30+ -- * Left Folds
31+ , foldlM'
32+ , foldl'
33+ , foldlMx'
34+ , foldlx'
35+ , parselMx'
36+
37+ -- * Specific Fold Functions
38+ , drain
39+ , mapM_ -- Map and Fold
40+ , null
41+ , head
42+ , headElse
43+ , tail
44+ , last
45+ , elem
46+ , notElem
47+ , all
48+ , any
49+ , maximum
50+ , maximumBy
51+ , minimum
52+ , minimumBy
53+ , lookup
54+ , findM
55+ , find
56+ , (!!)
57+ , the
58+
59+ -- * To containers
60+ , toList
61+ , toListRev
62+ , toSVarParallel
63+
64+ -- * Multi-Stream Folds
65+ -- ** Comparisons
66+ -- | These should probably be expressed using zipping operations.
67+ , eqBy
68+ , cmpBy
69+
70+ -- ** Substreams
71+ -- | These should probably be expressed using parsers.
72+ , isPrefixOf
73+ , isSubsequenceOf
74+ , stripPrefix
75+ )
76+where
77+
78+#include "inline.hs"
79+
80+import Control.Exception (assert)
81+import Control.Monad.Catch (MonadThrow, throwM)
82+import GHC.Exts (SpecConstrAnnotation(..))
83+import GHC.Types (SPEC(..))
84+import Streamly.Internal.Data.Parser (ParseError(..))
85+
86+import qualified Streamly.Internal.Data.Parser as PR
87+
88+import Prelude hiding
89+ ( all, any, elem, foldr, foldr1, head, last, lookup, mapM, mapM_
90+ , maximum, minimum, notElem, null, splitAt, tail, (!!))
91+import Streamly.Internal.Data.Stream.StreamD.Type
92+import Streamly.Internal.Data.SVar
93+
94+------------------------------------------------------------------------------
95+-- Elimination by Folds
96+------------------------------------------------------------------------------
97+
98+------------------------------------------------------------------------------
99+-- Right Folds
100+------------------------------------------------------------------------------
101+
102+{-# INLINE_NORMAL foldr1 #-}
103+foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
104+foldr1 f m = do
105+ r <- uncons m
106+ case r of
107+ Nothing -> return Nothing
108+ Just (h, t) -> fmap Just (foldr f h t)
109+
110+------------------------------------------------------------------------------
111+-- Parsers
112+------------------------------------------------------------------------------
113+
114+-- Inlined definition. Without the inline "serially/parser/take" benchmark
115+-- degrades and parseMany does not fuse. Even using "inline" at the callsite
116+-- does not help.
117+{-# INLINE splitAt #-}
118+splitAt :: Int -> [a] -> ([a],[a])
119+splitAt n ls
120+ | n <= 0 = ([], ls)
121+ | otherwise = splitAt' n ls
122+ where
123+ splitAt' :: Int -> [a] -> ([a], [a])
124+ splitAt' _ [] = ([], [])
125+ splitAt' 1 (x:xs) = ([x], xs)
126+ splitAt' m (x:xs) = (x:xs', xs'')
127+ where
128+ (xs', xs'') = splitAt' (m - 1) xs
129+
130+-- GHC parser does not accept {-# ANN type [] NoSpecConstr #-}, so we need
131+-- to make a newtype.
132+{-# ANN type List NoSpecConstr #-}
133+newtype List a = List {getList :: [a]}
134+
135+-- | Run a 'Parse' over a stream.
136+{-# INLINE_NORMAL parselMx' #-}
137+parselMx'
138+ :: MonadThrow m
139+ => (s -> a -> m (PR.Step s b))
140+ -> m s
141+ -> (s -> m b)
142+ -> Stream m a
143+ -> m b
144+parselMx' pstep initial extract (Stream step state) = do
145+ initial >>= go SPEC state (List [])
146+
147+ where
148+
149+ -- XXX currently we are using a dumb list based approach for backtracking
150+ -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
151+ -- That will allow us more efficient random back and forth movement.
152+ {-# INLINE go #-}
153+ go !_ st buf !pst = do
154+ r <- step defState st
155+ case r of
156+ Yield x s -> do
157+ pRes <- pstep pst x
158+ case pRes of
159+ PR.Partial 0 pst1 -> go SPEC s (List []) pst1
160+ PR.Partial n pst1 -> do
161+ assert (n <= length (x:getList buf)) (return ())
162+ let src0 = Prelude.take n (x:getList buf)
163+ src = Prelude.reverse src0
164+ gobuf SPEC s (List []) (List src) pst1
165+ PR.Continue 0 pst1 -> go SPEC s (List (x:getList buf)) pst1
166+ PR.Continue n pst1 -> do
167+ assert (n <= length (x:getList buf)) (return ())
168+ let (src0, buf1) = splitAt n (x:getList buf)
169+ src = Prelude.reverse src0
170+ gobuf SPEC s (List buf1) (List src) pst1
171+ PR.Done _ b -> return b
172+ PR.Error err -> throwM $ ParseError err
173+ Skip s -> go SPEC s buf pst
174+ Stop -> extract pst
175+
176+ gobuf !_ s buf (List []) !pst = go SPEC s buf pst
177+ gobuf !_ s buf (List (x:xs)) !pst = do
178+ pRes <- pstep pst x
179+ case pRes of
180+ PR.Partial 0 pst1 ->
181+ gobuf SPEC s (List []) (List xs) pst1
182+ PR.Partial n pst1 -> do
183+ assert (n <= length (x:getList buf)) (return ())
184+ let src0 = Prelude.take n (x:getList buf)
185+ src = Prelude.reverse src0 ++ xs
186+ gobuf SPEC s (List []) (List src) pst1
187+ PR.Continue 0 pst1 ->
188+ gobuf SPEC s (List (x:getList buf)) (List xs) pst1
189+ PR.Continue n pst1 -> do
190+ assert (n <= length (x:getList buf)) (return ())
191+ let (src0, buf1) = splitAt n (x:getList buf)
192+ src = Prelude.reverse src0 ++ xs
193+ gobuf SPEC s (List buf1) (List src) pst1
194+ PR.Done _ b -> return b
195+ PR.Error err -> throwM $ ParseError err
196+
197+------------------------------------------------------------------------------
198+-- Specialized Folds
199+------------------------------------------------------------------------------
200+
201+-- | Run a streaming composition, discard the results.
202+{-# INLINE_LATE drain #-}
203+drain :: Monad m => Stream m a -> m ()
204+-- drain = foldrM (\_ xs -> xs) (return ())
205+drain (Stream step state) = go SPEC state
206+ where
207+ go !_ st = do
208+ r <- step defState st
209+ case r of
210+ Yield _ s -> go SPEC s
211+ Skip s -> go SPEC s
212+ Stop -> return ()
213+
214+{-# INLINE_NORMAL null #-}
215+null :: Monad m => Stream m a -> m Bool
216+null m = foldrM (\_ _ -> return False) (return True) m
217+
218+{-# INLINE_NORMAL head #-}
219+head :: Monad m => Stream m a -> m (Maybe a)
220+head m = foldrM (\x _ -> return (Just x)) (return Nothing) m
221+
222+{-# INLINE_NORMAL headElse #-}
223+headElse :: Monad m => a -> Stream m a -> m a
224+headElse a m = foldrM (\x _ -> return x) (return a) m
225+
226+-- Does not fuse, has the same performance as the StreamK version.
227+{-# INLINE_NORMAL tail #-}
228+tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
229+tail (UnStream step state) = go state
230+ where
231+ go st = do
232+ r <- step defState st
233+ case r of
234+ Yield _ s -> return (Just $ Stream step s)
235+ Skip s -> go s
236+ Stop -> return Nothing
237+
238+-- XXX will it fuse? need custom impl?
239+{-# INLINE_NORMAL last #-}
240+last :: Monad m => Stream m a -> m (Maybe a)
241+last = foldl' (\_ y -> Just y) Nothing
242+
243+{-# INLINE_NORMAL elem #-}
244+elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
245+-- elem e m = foldrM (\x xs -> if x == e then return True else xs) (return False) m
246+elem e (Stream step state) = go state
247+ where
248+ go st = do
249+ r <- step defState st
250+ case r of
251+ Yield x s
252+ | x == e -> return True
253+ | otherwise -> go s
254+ Skip s -> go s
255+ Stop -> return False
256+
257+{-# INLINE_NORMAL notElem #-}
258+notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
259+notElem e s = fmap not (elem e s)
260+
261+{-# INLINE_NORMAL all #-}
262+all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
263+-- all p m = foldrM (\x xs -> if p x then xs else return False) (return True) m
264+all p (Stream step state) = go state
265+ where
266+ go st = do
267+ r <- step defState st
268+ case r of
269+ Yield x s
270+ | p x -> go s
271+ | otherwise -> return False
272+ Skip s -> go s
273+ Stop -> return True
274+
275+{-# INLINE_NORMAL any #-}
276+any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
277+-- any p m = foldrM (\x xs -> if p x then return True else xs) (return False) m
278+any p (Stream step state) = go state
279+ where
280+ go st = do
281+ r <- step defState st
282+ case r of
283+ Yield x s
284+ | p x -> return True
285+ | otherwise -> go s
286+ Skip s -> go s
287+ Stop -> return False
288+
289+{-# INLINE_NORMAL maximum #-}
290+maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
291+maximum (Stream step state) = go Nothing state
292+ where
293+ go Nothing st = do
294+ r <- step defState st
295+ case r of
296+ Yield x s -> go (Just x) s
297+ Skip s -> go Nothing s
298+ Stop -> return Nothing
299+ go (Just acc) st = do
300+ r <- step defState st
301+ case r of
302+ Yield x s
303+ | acc <= x -> go (Just x) s
304+ | otherwise -> go (Just acc) s
305+ Skip s -> go (Just acc) s
306+ Stop -> return (Just acc)
307+
308+{-# INLINE_NORMAL maximumBy #-}
309+maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
310+maximumBy cmp (Stream step state) = go Nothing state
311+ where
312+ go Nothing st = do
313+ r <- step defState st
314+ case r of
315+ Yield x s -> go (Just x) s
316+ Skip s -> go Nothing s
317+ Stop -> return Nothing
318+ go (Just acc) st = do
319+ r <- step defState st
320+ case r of
321+ Yield x s -> case cmp acc x of
322+ GT -> go (Just acc) s
323+ _ -> go (Just x) s
324+ Skip s -> go (Just acc) s
325+ Stop -> return (Just acc)
326+
327+{-# INLINE_NORMAL minimum #-}
328+minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
329+minimum (Stream step state) = go Nothing state
330+ where
331+ go Nothing st = do
332+ r <- step defState st
333+ case r of
334+ Yield x s -> go (Just x) s
335+ Skip s -> go Nothing s
336+ Stop -> return Nothing
337+ go (Just acc) st = do
338+ r <- step defState st
339+ case r of
340+ Yield x s
341+ | acc <= x -> go (Just acc) s
342+ | otherwise -> go (Just x) s
343+ Skip s -> go (Just acc) s
344+ Stop -> return (Just acc)
345+
346+{-# INLINE_NORMAL minimumBy #-}
347+minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
348+minimumBy cmp (Stream step state) = go Nothing state
349+ where
350+ go Nothing st = do
351+ r <- step defState st
352+ case r of
353+ Yield x s -> go (Just x) s
354+ Skip s -> go Nothing s
355+ Stop -> return Nothing
356+ go (Just acc) st = do
357+ r <- step defState st
358+ case r of
359+ Yield x s -> case cmp acc x of
360+ GT -> go (Just x) s
361+ _ -> go (Just acc) s
362+ Skip s -> go (Just acc) s
363+ Stop -> return (Just acc)
364+
365+{-# INLINE_NORMAL (!!) #-}
366+(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
367+(Stream step state) !! i = go i state
368+ where
369+ go n st = do
370+ r <- step defState st
371+ case r of
372+ Yield x s | n < 0 -> return Nothing
373+ | n == 0 -> return $ Just x
374+ | otherwise -> go (n - 1) s
375+ Skip s -> go n s
376+ Stop -> return Nothing
377+
378+{-# INLINE_NORMAL lookup #-}
379+lookup :: (Monad m, Eq a) => a -> Stream m (a, b) -> m (Maybe b)
380+lookup e m = foldrM (\(a, b) xs -> if e == a then return (Just b) else xs)
381+ (return Nothing) m
382+
383+{-# INLINE_NORMAL findM #-}
384+findM :: Monad m => (a -> m Bool) -> Stream m a -> m (Maybe a)
385+findM p m = foldrM (\x xs -> p x >>= \r -> if r then return (Just x) else xs)
386+ (return Nothing) m
387+
388+{-# INLINE find #-}
389+find :: Monad m => (a -> Bool) -> Stream m a -> m (Maybe a)
390+find p = findM (return . p)
391+
392+{-# INLINE toListRev #-}
393+toListRev :: Monad m => Stream m a -> m [a]
394+toListRev = foldl' (flip (:)) []
395+
396+------------------------------------------------------------------------------
397+-- Transformation comprehensions
398+------------------------------------------------------------------------------
399+
400+{-# INLINE_NORMAL the #-}
401+the :: (Eq a, Monad m) => Stream m a -> m (Maybe a)
402+the (Stream step state) = go state
403+ where
404+ go st = do
405+ r <- step defState st
406+ case r of
407+ Yield x s -> go' x s
408+ Skip s -> go s
409+ Stop -> return Nothing
410+ go' n st = do
411+ r <- step defState st
412+ case r of
413+ Yield x s | x == n -> go' n s
414+ | otherwise -> return Nothing
415+ Skip s -> go' n s
416+ Stop -> return (Just n)
417+
418+------------------------------------------------------------------------------
419+-- Map and Fold
420+------------------------------------------------------------------------------
421+
422+-- | Execute a monadic action for each element of the 'Stream'
423+{-# INLINE_NORMAL mapM_ #-}
424+mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
425+mapM_ m = drain . mapM m
426+
427+------------------------------------------------------------------------------
428+-- Multi-stream folds
429+------------------------------------------------------------------------------
430+
431+{-# INLINE_NORMAL isPrefixOf #-}
432+isPrefixOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
433+isPrefixOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
434+ where
435+ go (sa, sb, Nothing) = do
436+ r <- stepa defState sa
437+ case r of
438+ Yield x sa' -> go (sa', sb, Just x)
439+ Skip sa' -> go (sa', sb, Nothing)
440+ Stop -> return True
441+
442+ go (sa, sb, Just x) = do
443+ r <- stepb defState sb
444+ case r of
445+ Yield y sb' ->
446+ if x == y
447+ then go (sa, sb', Nothing)
448+ else return False
449+ Skip sb' -> go (sa, sb', Just x)
450+ Stop -> return False
451+
452+{-# INLINE_NORMAL isSubsequenceOf #-}
453+isSubsequenceOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
454+isSubsequenceOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
455+ where
456+ go (sa, sb, Nothing) = do
457+ r <- stepa defState sa
458+ case r of
459+ Yield x sa' -> go (sa', sb, Just x)
460+ Skip sa' -> go (sa', sb, Nothing)
461+ Stop -> return True
462+
463+ go (sa, sb, Just x) = do
464+ r <- stepb defState sb
465+ case r of
466+ Yield y sb' ->
467+ if x == y
468+ then go (sa, sb', Nothing)
469+ else go (sa, sb', Just x)
470+ Skip sb' -> go (sa, sb', Just x)
471+ Stop -> return False
472+
473+{-# INLINE_NORMAL stripPrefix #-}
474+stripPrefix
475+ :: (Eq a, Monad m)
476+ => Stream m a -> Stream m a -> m (Maybe (Stream m a))
477+stripPrefix (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
478+ where
479+ go (sa, sb, Nothing) = do
480+ r <- stepa defState sa
481+ case r of
482+ Yield x sa' -> go (sa', sb, Just x)
483+ Skip sa' -> go (sa', sb, Nothing)
484+ Stop -> return $ Just (Stream stepb sb)
485+
486+ go (sa, sb, Just x) = do
487+ r <- stepb defState sb
488+ case r of
489+ Yield y sb' ->
490+ if x == y
491+ then go (sa, sb', Nothing)
492+ else return Nothing
493+ Skip sb' -> go (sa, sb', Just x)
494+ Stop -> return Nothing
src/Streamly/Internal/Data/Stream/StreamD/Exception.hsnew file+425
@@ -0,0 +1,425 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.StreamD.Exception
3+-- Copyright : (c) 2020 Composewell Technologies and Contributors
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+
9+module Streamly.Internal.Data.Stream.StreamD.Exception
10+ (
11+ -- * Finalizers
12+ newFinalizedIORef
13+ , runIORefFinalizer
14+ , withIORefFinalizer
15+
16+ -- * Combinators
17+ , gbracket_
18+ , gbracket
19+ , before
20+ , after_
21+ , after
22+ , bracket_
23+ , bracket
24+ , onException
25+ , finally_
26+ , finally
27+ , ghandle
28+ , handle
29+ )
30+where
31+
32+#include "inline.hs"
33+
34+import Control.Exception (Exception, SomeException, mask_)
35+import Control.Monad (void)
36+import Control.Monad.Catch (MonadCatch)
37+import Control.Monad.IO.Class (MonadIO(..))
38+import Control.Monad.Trans.Control (MonadBaseControl, liftBaseOp_, control)
39+import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef, IORef)
40+
41+import qualified Control.Monad.Catch as MC
42+
43+import Streamly.Internal.Data.Stream.StreamD.Type
44+import Streamly.Internal.Data.SVar
45+
46+------------------------------------------------------------------------------
47+-- Finalizers
48+------------------------------------------------------------------------------
49+
50+-- | Make a finalizer from a monadic action @m a@ that can run in IO monad.
51+mkIOFinalizer :: MonadBaseControl IO m => m b -> m (IO ())
52+mkIOFinalizer f = do
53+ mrun <- captureMonadState
54+ return $
55+ void $ do
56+ _ <- runInIO mrun f
57+ return ()
58+
59+-- | Run an IO action stored in a finalized IORef.
60+runIORefFinalizerGC :: IORef (Maybe (IO ())) -> IO ()
61+runIORefFinalizerGC ref = do
62+ res <- readIORef ref
63+ case res of
64+ Nothing -> return ()
65+ Just f -> f
66+
67+-- | Create an IORef holding a finalizer that is called automatically when
68+-- the IORef is garbage collected. The IORef can be written to with a 'Nothing'
69+-- value to deactivate the finalizer.
70+--
71+-- Note: The finalizer is always run with the state of the monad captured at
72+-- the time of calling newFinalizedIORef. To run it on garbage collection we
73+-- have no option but to take a snapshot of the monadic state at some point of
74+-- time. For normal case we could run it with the current state of the monad
75+-- but we want to keep both the cases consistent.
76+--
77+newFinalizedIORef :: (MonadIO m, MonadBaseControl IO m)
78+ => m a -> m (IORef (Maybe (IO ())))
79+newFinalizedIORef finalizer = do
80+ f <- mkIOFinalizer finalizer
81+ ref <- liftIO $ newIORef $ Just f
82+ _ <- liftIO $ mkWeakIORef ref (runIORefFinalizerGC ref)
83+ return ref
84+
85+-- | Run the finalizer stored in an IORef and deactivate it so that it is run
86+-- only once. Note, the action runs with async exceptions masked.
87+--
88+runIORefFinalizer :: MonadIO m => IORef (Maybe (IO ())) -> m ()
89+runIORefFinalizer ref = liftIO $ do
90+ res <- readIORef ref
91+ case res of
92+ Nothing -> return ()
93+ Just action -> do
94+ -- if an async exception comes after writing 'Nothing' then the
95+ -- finalizing action will never be run. We need to do this
96+ -- atomically wrt async exceptions.
97+ mask_ $ do
98+ writeIORef ref Nothing
99+ action
100+
101+-- | Run an action clearing the finalizer IORef atomically wrt async
102+-- exceptions. The action is run with async exceptions masked.
103+withIORefFinalizer :: MonadBaseControl IO m
104+ => IORef (Maybe (IO ())) -> m a -> m a
105+withIORefFinalizer ref action = do
106+ control $ \runinio ->
107+ mask_ $ do
108+ writeIORef ref Nothing
109+ runinio action
110+
111+------------------------------------------------------------------------------
112+-- Exception handling combinators.
113+------------------------------------------------------------------------------
114+
115+data GbracketState s1 s2 v
116+ = GBracketInit
117+ | GBracketNormal s1 v
118+ | GBracketException s2
119+
120+-- | Like 'gbracket' but with following differences:
121+--
122+-- * alloc action @m c@ runs with async exceptions enabled
123+-- * cleanup action @c -> m d@ won't run if the stream is garbage collected
124+-- after partial evaluation.
125+-- * does not require a 'MonadAsync' constraint.
126+--
127+-- /Inhibits stream fusion/
128+--
129+-- /Internal/
130+--
131+{-# INLINE_NORMAL gbracket_ #-}
132+gbracket_
133+ :: Monad m
134+ => m c -- ^ before
135+ -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
136+ -> (c -> m d) -- ^ after, on normal stop
137+ -> (c -> e -> Stream m b -> Stream m b) -- ^ on exception
138+ -> (c -> Stream m b) -- ^ stream generator
139+ -> Stream m b
140+gbracket_ bef exc aft fexc fnormal =
141+ Stream step GBracketInit
142+
143+ where
144+
145+ {-# INLINE_LATE step #-}
146+ step _ GBracketInit = do
147+ r <- bef
148+ return $ Skip $ GBracketNormal (fnormal r) r
149+
150+ step gst (GBracketNormal (UnStream step1 st) v) = do
151+ res <- exc $ step1 gst st
152+ case res of
153+ Right r -> case r of
154+ Yield x s ->
155+ return $ Yield x (GBracketNormal (Stream step1 s) v)
156+ Skip s -> return $ Skip (GBracketNormal (Stream step1 s) v)
157+ Stop -> aft v >> return Stop
158+ -- XXX Do not handle async exceptions, just rethrow them.
159+ Left e ->
160+ return $ Skip (GBracketException (fexc v e (UnStream step1 st)))
161+ step gst (GBracketException (UnStream step1 st)) = do
162+ res <- step1 gst st
163+ case res of
164+ Yield x s -> return $ Yield x (GBracketException (Stream step1 s))
165+ Skip s -> return $ Skip (GBracketException (Stream step1 s))
166+ Stop -> return Stop
167+
168+data GbracketIOState s1 s2 v wref
169+ = GBracketIOInit
170+ | GBracketIONormal s1 v wref
171+ | GBracketIOException s2
172+
173+-- | Run the alloc action @m c@ with async exceptions disabled but keeping
174+-- blocking operations interruptible (see 'Control.Exception.mask'). Use the
175+-- output @c@ as input to @c -> Stream m b@ to generate an output stream. When
176+-- generating the stream use the supplied @try@ operation @forall s. m s -> m
177+-- (Either e s)@ to catch synchronous exceptions. If an exception occurs run
178+-- the exception handler @c -> e -> Stream m b -> m (Stream m b)@.
179+--
180+-- The cleanup action @c -> m d@, runs whenever the stream ends normally, due
181+-- to a sync or async exception or if it gets garbage collected after a partial
182+-- lazy evaluation. See 'bracket' for the semantics of the cleanup action.
183+--
184+-- 'gbracket' can express all other exception handling combinators.
185+--
186+-- /Inhibits stream fusion/
187+--
188+-- /Internal/
189+{-# INLINE_NORMAL gbracket #-}
190+gbracket
191+ :: (MonadIO m, MonadBaseControl IO m)
192+ => m c -- ^ before
193+ -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
194+ -> (c -> m d) -- ^ after, on normal stop or GC
195+ -> (c -> e -> Stream m b -> m (Stream m b)) -- ^ on exception
196+ -> (c -> Stream m b) -- ^ stream generator
197+ -> Stream m b
198+gbracket bef exc aft fexc fnormal =
199+ Stream step GBracketIOInit
200+
201+ where
202+
203+ -- If the stream is never evaluated the "aft" action will never be
204+ -- called. For that to occur we will need the user of this API to pass a
205+ -- weak pointer to us.
206+ {-# INLINE_LATE step #-}
207+ step _ GBracketIOInit = do
208+ -- We mask asynchronous exceptions to make the execution
209+ -- of 'bef' and the registration of 'aft' atomic.
210+ -- A similar thing is done in the resourcet package: https://git.io/JvKV3
211+ -- Tutorial: https://markkarpov.com/tutorial/exceptions.html
212+ (r, ref) <- liftBaseOp_ mask_ $ do
213+ r <- bef
214+ ref <- newFinalizedIORef (aft r)
215+ return (r, ref)
216+ return $ Skip $ GBracketIONormal (fnormal r) r ref
217+
218+ step gst (GBracketIONormal (UnStream step1 st) v ref) = do
219+ res <- exc $ step1 gst st
220+ case res of
221+ Right r -> case r of
222+ Yield x s ->
223+ return $ Yield x (GBracketIONormal (Stream step1 s) v ref)
224+ Skip s ->
225+ return $ Skip (GBracketIONormal (Stream step1 s) v ref)
226+ Stop -> do
227+ runIORefFinalizer ref
228+ return Stop
229+ -- XXX Do not handle async exceptions, just rethrow them.
230+ Left e -> do
231+ -- Clearing of finalizer and running of exception handler must
232+ -- be atomic wrt async exceptions. Otherwise if we have cleared
233+ -- the finalizer and have not run the exception handler then we
234+ -- may leak the resource.
235+ stream <- withIORefFinalizer ref (fexc v e (UnStream step1 st))
236+ return $ Skip (GBracketIOException stream)
237+ step gst (GBracketIOException (UnStream step1 st)) = do
238+ res <- step1 gst st
239+ case res of
240+ Yield x s ->
241+ return $ Yield x (GBracketIOException (Stream step1 s))
242+ Skip s -> return $ Skip (GBracketIOException (Stream step1 s))
243+ Stop -> return Stop
244+
245+-- | See 'Streamly.Internal.Data.Stream.IsStream.before'.
246+--
247+{-# INLINE_NORMAL before #-}
248+before :: Monad m => m b -> Stream m a -> Stream m a
249+before action (Stream step state) = Stream step' Nothing
250+
251+ where
252+
253+ {-# INLINE_LATE step' #-}
254+ step' _ Nothing = action >> return (Skip (Just state))
255+
256+ step' gst (Just st) = do
257+ res <- step gst st
258+ case res of
259+ Yield x s -> return $ Yield x (Just s)
260+ Skip s -> return $ Skip (Just s)
261+ Stop -> return Stop
262+
263+-- | See 'Streamly.Internal.Data.Stream.IsStream.after_'.
264+--
265+{-# INLINE_NORMAL after_ #-}
266+after_ :: Monad m => m b -> Stream m a -> Stream m a
267+after_ action (Stream step state) = Stream step' state
268+
269+ where
270+
271+ {-# INLINE_LATE step' #-}
272+ step' gst st = do
273+ res <- step gst st
274+ case res of
275+ Yield x s -> return $ Yield x s
276+ Skip s -> return $ Skip s
277+ Stop -> action >> return Stop
278+
279+-- | See 'Streamly.Internal.Data.Stream.IsStream.after'.
280+--
281+{-# INLINE_NORMAL after #-}
282+after :: (MonadIO m, MonadBaseControl IO m)
283+ => m b -> Stream m a -> Stream m a
284+after action (Stream step state) = Stream step' Nothing
285+
286+ where
287+
288+ {-# INLINE_LATE step' #-}
289+ step' _ Nothing = do
290+ ref <- newFinalizedIORef action
291+ return $ Skip $ Just (state, ref)
292+ step' gst (Just (st, ref)) = do
293+ res <- step gst st
294+ case res of
295+ Yield x s -> return $ Yield x (Just (s, ref))
296+ Skip s -> return $ Skip (Just (s, ref))
297+ Stop -> do
298+ runIORefFinalizer ref
299+ return Stop
300+
301+-- XXX For high performance error checks in busy streams we may need another
302+-- Error constructor in step.
303+--
304+-- | See 'Streamly.Internal.Data.Stream.IsStream.onException'.
305+--
306+{-# INLINE_NORMAL onException #-}
307+onException :: MonadCatch m => m b -> Stream m a -> Stream m a
308+onException action str =
309+ gbracket_ (return ()) MC.try return
310+ (\_ (e :: MC.SomeException) _ -> nilM (action >> MC.throwM e))
311+ (\_ -> str)
312+
313+{-# INLINE_NORMAL _onException #-}
314+_onException :: MonadCatch m => m b -> Stream m a -> Stream m a
315+_onException action (Stream step state) = Stream step' state
316+
317+ where
318+
319+ {-# INLINE_LATE step' #-}
320+ step' gst st = do
321+ res <- step gst st `MC.onException` action
322+ case res of
323+ Yield x s -> return $ Yield x s
324+ Skip s -> return $ Skip s
325+ Stop -> return Stop
326+
327+-- | See 'Streamly.Internal.Data.Stream.IsStream.bracket_'.
328+--
329+{-# INLINE_NORMAL bracket_ #-}
330+bracket_ :: MonadCatch m
331+ => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
332+bracket_ bef aft bet =
333+ gbracket_ bef MC.try aft
334+ (\a (e :: SomeException) _ -> nilM (aft a >> MC.throwM e)) bet
335+
336+-- | See 'Streamly.Internal.Data.Stream.IsStream.bracket'.
337+--
338+{-# INLINE_NORMAL bracket #-}
339+bracket :: (MonadAsync m, MonadCatch m)
340+ => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
341+bracket bef aft bet =
342+ gbracket bef MC.try aft
343+ (\a (e :: SomeException) _ -> aft a >> return (nilM (MC.throwM e))) bet
344+
345+data BracketState s v = BracketInit | BracketRun s v
346+
347+-- | Alternate (custom) implementation of 'bracket'.
348+--
349+{-# INLINE_NORMAL _bracket #-}
350+_bracket :: MonadCatch m
351+ => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
352+_bracket bef aft bet = Stream step' BracketInit
353+
354+ where
355+
356+ {-# INLINE_LATE step' #-}
357+ step' _ BracketInit = bef >>= \x -> return (Skip (BracketRun (bet x) x))
358+
359+ -- NOTE: It is important to use UnStream instead of the Stream pattern
360+ -- here, otherwise we get huge perf degradation, see note in concatMap.
361+ step' gst (BracketRun (UnStream step state) v) = do
362+ -- res <- step gst state `MC.onException` aft v
363+ res <- MC.try $ step gst state
364+ case res of
365+ Left (e :: SomeException) -> aft v >> MC.throwM e >> return Stop
366+ Right r -> case r of
367+ Yield x s -> return $ Yield x (BracketRun (Stream step s) v)
368+ Skip s -> return $ Skip (BracketRun (Stream step s) v)
369+ Stop -> aft v >> return Stop
370+
371+-- | See 'Streamly.Internal.Data.Stream.IsStream.finally_'.
372+--
373+{-# INLINE finally_ #-}
374+finally_ :: MonadCatch m => m b -> Stream m a -> Stream m a
375+finally_ action xs = bracket_ (return ()) (\_ -> action) (const xs)
376+
377+-- | See 'Streamly.Internal.Data.Stream.IsStream.finally'.
378+--
379+-- finally action xs = after action $ onException action xs
380+--
381+{-# INLINE finally #-}
382+finally :: (MonadAsync m, MonadCatch m) => m b -> Stream m a -> Stream m a
383+finally action xs = bracket (return ()) (\_ -> action) (const xs)
384+
385+-- | See 'Streamly.Internal.Data.Stream.IsStream.ghandle'.
386+--
387+{-# INLINE_NORMAL ghandle #-}
388+ghandle :: (MonadCatch m, Exception e)
389+ => (e -> Stream m a -> Stream m a) -> Stream m a -> Stream m a
390+ghandle f str =
391+ gbracket_ (return ()) MC.try return (\_ -> f) (\_ -> str)
392+
393+-- | See 'Streamly.Internal.Data.Stream.IsStream.handle'.
394+--
395+{-# INLINE_NORMAL handle #-}
396+handle :: (MonadCatch m, Exception e)
397+ => (e -> Stream m a) -> Stream m a -> Stream m a
398+handle f str =
399+ gbracket_ (return ()) MC.try return (\_ e _ -> f e) (\_ -> str)
400+
401+-- | Alternate (custom) implementation of 'handle'.
402+--
403+{-# INLINE_NORMAL _handle #-}
404+_handle :: (MonadCatch m, Exception e)
405+ => (e -> Stream m a) -> Stream m a -> Stream m a
406+_handle f (Stream step state) = Stream step' (Left state)
407+
408+ where
409+
410+ {-# INLINE_LATE step' #-}
411+ step' gst (Left st) = do
412+ res <- MC.try $ step gst st
413+ case res of
414+ Left e -> return $ Skip $ Right (f e)
415+ Right r -> case r of
416+ Yield x s -> return $ Yield x (Left s)
417+ Skip s -> return $ Skip (Left s)
418+ Stop -> return Stop
419+
420+ step' gst (Right (UnStream step1 st)) = do
421+ res <- step1 gst st
422+ case res of
423+ Yield x s -> return $ Yield x (Right (Stream step1 s))
424+ Skip s -> return $ Skip (Right (Stream step1 s))
425+ Stop -> return Stop
src/Streamly/Internal/Data/Stream/StreamD/Generate.hsnew file+491
@@ -0,0 +1,491 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.StreamD.Generate
3+-- Copyright : (c) 2020 Composewell Technologies and Contributors
4+-- (c) Roman Leshchinskiy 2008-2010
5+-- License : BSD-3-Clause
6+-- Maintainer : streamly@composewell.com
7+-- Stability : experimental
8+-- Portability : GHC
9+--
10+-- Prefer unfolds ("Streamly.Internal.Data.Unfold") over the combinators in
11+-- this module. They are more powerful and efficient as they can be transformed
12+-- and composed on the input side efficiently and they can fuse in nested
13+-- operations (e.g. concatUnfold). All the combinators in this module can be
14+-- expressed using unfolds with the same efficiency.
15+--
16+-- Operations in this module that are not in "Streamly.Internal.Data.Unfold":
17+-- generate, times, fromPrimIORef.
18+--
19+-- We should plan to replace this module with "Streamly.Internal.Data.Unfold"
20+-- in future.
21+
22+-- A few combinators in this module have been adapted from the vector package
23+-- (c) Roman Leshchinskiy. See the notes in specific combinators.
24+--
25+module Streamly.Internal.Data.Stream.StreamD.Generate
26+ (
27+ -- * Primitives
28+ nil
29+ , nilM
30+ , cons
31+ , consM
32+
33+ -- * From 'Unfold'
34+ , unfold
35+
36+ -- * Unfolding
37+ , unfoldr
38+ , unfoldrM
39+
40+ -- * From Values
41+ , yield
42+ , yieldM
43+ , repeat
44+ , repeatM
45+ , replicate
46+ , replicateM
47+
48+ -- * Enumeration
49+ , enumerateFromStepIntegral
50+ , enumerateFromIntegral
51+ , enumerateFromThenIntegral
52+ , enumerateFromToIntegral
53+ , enumerateFromThenToIntegral
54+
55+ , enumerateFromStepNum
56+ , numFrom
57+ , numFromThen
58+ , enumerateFromToFractional
59+ , enumerateFromThenToFractional
60+
61+ -- * Time Enumeration
62+ , times
63+
64+ -- * From Generators
65+ -- | Generate a monadic stream from a seed.
66+ , fromIndices
67+ , fromIndicesM
68+ , generate
69+ , generateM
70+
71+ -- * Iteration
72+ , iterate
73+ , iterateM
74+
75+ -- * From Containers
76+ -- | Transform an input structure into a stream.
77+
78+ -- Note: Direct style stream does not support @fromFoldable@.
79+ , fromList
80+ , fromListM
81+ , fromPrimIORef
82+ , fromProducer
83+ , fromSVar
84+
85+ -- * Callbacks
86+ , newCallbackStream
87+
88+ -- * Conversions
89+ , fromStreamK
90+ , toStreamK
91+ , fromStreamD
92+ , toStreamD
93+ )
94+where
95+
96+#include "inline.hs"
97+
98+import Control.Concurrent (myThreadId, threadDelay)
99+import Control.Monad (void, forever)
100+import Control.Monad.IO.Class (MonadIO(..))
101+import Data.Int (Int64)
102+import Streamly.Internal.Data.Time.Units (toRelTime64, RelTime64)
103+import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
104+import Streamly.Internal.Data.Time.Units
105+ (MicroSecond64(..), fromAbsTime, toAbsTime, AbsTime)
106+import Streamly.Internal.Data.Unfold.Types (Unfold(..))
107+
108+import qualified Streamly.Internal.Data.IORef.Prim as Prim
109+import qualified Streamly.Internal.Data.Stream.StreamK as K
110+
111+import Prelude hiding (iterate, repeat, replicate, takeWhile)
112+import Streamly.Internal.Data.Stream.StreamD.Type
113+import Streamly.Internal.Data.SVar
114+
115+------------------------------------------------------------------------------
116+-- Primitives
117+------------------------------------------------------------------------------
118+
119+-- | An empty 'Stream'.
120+{-# INLINE_NORMAL nil #-}
121+nil :: Monad m => Stream m a
122+nil = Stream (\_ _ -> return Stop) ()
123+
124+-- XXX implement in terms of consM?
125+-- cons x = consM (return x)
126+--
127+-- | Can fuse but has O(n^2) complexity.
128+{-# INLINE_NORMAL cons #-}
129+cons :: Monad m => a -> Stream m a -> Stream m a
130+cons x (Stream step state) = Stream step1 Nothing
131+ where
132+ {-# INLINE_LATE step1 #-}
133+ step1 _ Nothing = return $ Yield x (Just state)
134+ step1 gst (Just st) = do
135+ r <- step gst st
136+ return $
137+ case r of
138+ Yield a s -> Yield a (Just s)
139+ Skip s -> Skip (Just s)
140+ Stop -> Stop
141+
142+------------------------------------------------------------------------------
143+-- From 'Unfold'
144+------------------------------------------------------------------------------
145+
146+data UnfoldState s = UnfoldNothing | UnfoldJust s
147+
148+-- | Convert an 'Unfold' into a 'Stream' by supplying it a seed.
149+--
150+{-# INLINE_NORMAL unfold #-}
151+unfold :: Monad m => Unfold m a b -> a -> Stream m b
152+unfold (Unfold ustep inject) seed = Stream step UnfoldNothing
153+ where
154+ {-# INLINE_LATE step #-}
155+ step _ UnfoldNothing = inject seed >>= return . Skip . UnfoldJust
156+ step _ (UnfoldJust st) = do
157+ r <- ustep st
158+ return $ case r of
159+ Yield x s -> Yield x (UnfoldJust s)
160+ Skip s -> Skip (UnfoldJust s)
161+ Stop -> Stop
162+
163+------------------------------------------------------------------------------
164+-- Unfolding
165+------------------------------------------------------------------------------
166+
167+-- Adapted from vector package
168+{-# INLINE_NORMAL unfoldrM #-}
169+unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
170+unfoldrM next state = Stream step state
171+ where
172+ {-# INLINE_LATE step #-}
173+ step _ st = do
174+ r <- next st
175+ return $ case r of
176+ Just (x, s) -> Yield x s
177+ Nothing -> Stop
178+
179+{-# INLINE_LATE unfoldr #-}
180+unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
181+unfoldr f = unfoldrM (return . f)
182+
183+------------------------------------------------------------------------------
184+-- From values
185+------------------------------------------------------------------------------
186+
187+{-# INLINE_NORMAL repeatM #-}
188+repeatM :: Monad m => m a -> Stream m a
189+repeatM x = Stream (\_ _ -> x >>= \r -> return $ Yield r ()) ()
190+
191+{-# INLINE_NORMAL repeat #-}
192+repeat :: Monad m => a -> Stream m a
193+repeat x = Stream (\_ _ -> return $ Yield x ()) ()
194+
195+-- Adapted from the vector package
196+{-# INLINE_NORMAL replicateM #-}
197+replicateM :: forall m a. Monad m => Int -> m a -> Stream m a
198+replicateM n p = Stream step n
199+ where
200+ {-# INLINE_LATE step #-}
201+ step _ (i :: Int)
202+ | i <= 0 = return Stop
203+ | otherwise = do
204+ x <- p
205+ return $ Yield x (i - 1)
206+
207+{-# INLINE_NORMAL replicate #-}
208+replicate :: Monad m => Int -> a -> Stream m a
209+replicate n x = replicateM n (return x)
210+
211+------------------------------------------------------------------------------
212+-- Enumeration
213+------------------------------------------------------------------------------
214+
215+-- This would not work properly for floats, therefore we put an Integral
216+-- constraint.
217+-- | Can be used to enumerate unbounded integrals. This does not check for
218+-- overflow or underflow for bounded integrals.
219+{-# INLINE_NORMAL enumerateFromStepIntegral #-}
220+enumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
221+enumerateFromStepIntegral from stride =
222+ from `seq` stride `seq` Stream step from
223+ where
224+ {-# INLINE_LATE step #-}
225+ step _ !x = return $ Yield x $! (x + stride)
226+
227+data EnumState a = EnumInit | EnumYield a a a | EnumStop
228+
229+{-# INLINE_NORMAL enumerateFromThenToIntegralUp #-}
230+enumerateFromThenToIntegralUp
231+ :: (Monad m, Integral a)
232+ => a -> a -> a -> Stream m a
233+enumerateFromThenToIntegralUp from next to = Stream step EnumInit
234+ where
235+ {-# INLINE_LATE step #-}
236+ step _ EnumInit =
237+ return $
238+ if to < next
239+ then if to < from
240+ then Stop
241+ else Yield from EnumStop
242+ else -- from <= next <= to
243+ let stride = next - from
244+ in Skip $ EnumYield from stride (to - stride)
245+
246+ step _ (EnumYield x stride toMinus) =
247+ return $
248+ if x > toMinus
249+ then Yield x EnumStop
250+ else Yield x $ EnumYield (x + stride) stride toMinus
251+
252+ step _ EnumStop = return Stop
253+
254+{-# INLINE_NORMAL enumerateFromThenToIntegralDn #-}
255+enumerateFromThenToIntegralDn
256+ :: (Monad m, Integral a)
257+ => a -> a -> a -> Stream m a
258+enumerateFromThenToIntegralDn from next to = Stream step EnumInit
259+ where
260+ {-# INLINE_LATE step #-}
261+ step _ EnumInit =
262+ return $ if to > next
263+ then if to > from
264+ then Stop
265+ else Yield from EnumStop
266+ else -- from >= next >= to
267+ let stride = next - from
268+ in Skip $ EnumYield from stride (to - stride)
269+
270+ step _ (EnumYield x stride toMinus) =
271+ return $
272+ if x < toMinus
273+ then Yield x EnumStop
274+ else Yield x $ EnumYield (x + stride) stride toMinus
275+
276+ step _ EnumStop = return Stop
277+
278+{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
279+enumerateFromThenToIntegral
280+ :: (Monad m, Integral a)
281+ => a -> a -> a -> Stream m a
282+enumerateFromThenToIntegral from next to
283+ | next >= from = enumerateFromThenToIntegralUp from next to
284+ | otherwise = enumerateFromThenToIntegralDn from next to
285+
286+{-# INLINE_NORMAL enumerateFromThenIntegral #-}
287+enumerateFromThenIntegral
288+ :: (Monad m, Integral a, Bounded a)
289+ => a -> a -> Stream m a
290+enumerateFromThenIntegral from next =
291+ if next > from
292+ then enumerateFromThenToIntegralUp from next maxBound
293+ else enumerateFromThenToIntegralDn from next minBound
294+
295+-- We are assuming that "to" is constrained by the type to be within
296+-- max/min bounds.
297+{-# INLINE enumerateFromToIntegral #-}
298+enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
299+enumerateFromToIntegral from to =
300+ takeWhile (<= to) $ enumerateFromStepIntegral from 1
301+
302+{-# INLINE enumerateFromIntegral #-}
303+enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
304+enumerateFromIntegral from = enumerateFromToIntegral from maxBound
305+
306+-- We cannot write a general function for Num. The only way to write code
307+-- portable between the two is to use a 'Real' constraint and convert between
308+-- Fractional and Integral using fromRational which is horribly slow.
309+{-# INLINE_NORMAL enumerateFromToFractional #-}
310+enumerateFromToFractional
311+ :: (Monad m, Fractional a, Ord a)
312+ => a -> a -> Stream m a
313+enumerateFromToFractional from to =
314+ takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
315+
316+{-# INLINE_NORMAL enumerateFromThenToFractional #-}
317+enumerateFromThenToFractional
318+ :: (Monad m, Fractional a, Ord a)
319+ => a -> a -> a -> Stream m a
320+enumerateFromThenToFractional from next to =
321+ takeWhile predicate $ numFromThen from next
322+ where
323+ mid = (next - from) / 2
324+ predicate | next >= from = (<= to + mid)
325+ | otherwise = (>= to + mid)
326+
327+-- For floating point numbers if the increment is less than the precision then
328+-- it just gets lost. Therefore we cannot always increment it correctly by just
329+-- repeated addition.
330+-- 9007199254740992 + 1 + 1 :: Double => 9.007199254740992e15
331+-- 9007199254740992 + 2 :: Double => 9.007199254740994e15
332+
333+-- Instead we accumulate the increment counter and compute the increment
334+-- every time before adding it to the starting number.
335+--
336+-- This works for Integrals as well as floating point numbers, but
337+-- enumerateFromStepIntegral is faster for integrals.
338+{-# INLINE_NORMAL enumerateFromStepNum #-}
339+enumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
340+enumerateFromStepNum from stride = Stream step 0
341+ where
342+ {-# INLINE_LATE step #-}
343+ step _ !i = return $ (Yield $! (from + i * stride)) $! (i + 1)
344+
345+{-# INLINE_NORMAL numFrom #-}
346+numFrom :: (Monad m, Num a) => a -> Stream m a
347+numFrom from = enumerateFromStepNum from 1
348+
349+{-# INLINE_NORMAL numFromThen #-}
350+numFromThen :: (Monad m, Num a) => a -> a -> Stream m a
351+numFromThen from next = enumerateFromStepNum from (next - from)
352+
353+------------------------------------------------------------------------------
354+-- Time Enumeration
355+------------------------------------------------------------------------------
356+
357+{-# INLINE updateTimeVar #-}
358+updateTimeVar :: Prim.IORef Int64 -> IO ()
359+updateTimeVar timeVar = do
360+ MicroSecond64 t <- fromAbsTime <$> getTime Monotonic
361+ Prim.modifyIORef' timeVar (const t)
362+
363+{-# INLINE updateWithDelay #-}
364+updateWithDelay :: RealFrac a => a -> Prim.IORef Int64 -> IO ()
365+updateWithDelay precision timeVar = do
366+ threadDelay (delayTime precision)
367+ updateTimeVar timeVar
368+
369+ where
370+
371+ -- Keep the minimum at least a millisecond to avoid high CPU usage
372+ {-# INLINE delayTime #-}
373+ delayTime g
374+ | g' >= fromIntegral (maxBound :: Int) = maxBound
375+ | g' < 1000 = 1000
376+ | otherwise = round g'
377+
378+ where
379+
380+ g' = g * 10 ^ (6 :: Int)
381+
382+{-# INLINE_NORMAL times #-}
383+times :: MonadAsync m => Double -> Stream m (AbsTime, RelTime64)
384+times g = Stream step Nothing
385+
386+ where
387+
388+ {-# INLINE_LATE step #-}
389+ step _ Nothing = do
390+ -- XXX note that this is safe only on a 64-bit machine. On a 32-bit
391+ -- machine a 64-bit 'Var' cannot be read consistently without a lock
392+ -- while another thread is writing to it.
393+ timeVar <- liftIO $ Prim.newIORef (0 :: Int64)
394+ liftIO $ updateTimeVar timeVar
395+ tid <- forkManaged $ liftIO $ forever (updateWithDelay g timeVar)
396+ a <- liftIO $ Prim.readIORef timeVar
397+ return $ Skip $ Just (timeVar, tid, a)
398+
399+ step _ s@(Just (timeVar, _, t0)) = do
400+ a <- liftIO $ Prim.readIORef timeVar
401+ -- XXX we can perhaps use an AbsTime64 using a 64 bit Int for
402+ -- efficiency. or maybe we can use a representation using Double for
403+ -- floating precision time
404+ return $ Yield (toAbsTime (MicroSecond64 t0),
405+ (toRelTime64 (MicroSecond64 (a - t0)))) s
406+
407+-------------------------------------------------------------------------------
408+-- From Generators
409+-------------------------------------------------------------------------------
410+
411+{-# INLINE_NORMAL fromIndicesM #-}
412+fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
413+fromIndicesM gen = Stream step 0
414+ where
415+ {-# INLINE_LATE step #-}
416+ step _ i = do
417+ x <- gen i
418+ return $ Yield x (i + 1)
419+
420+{-# INLINE fromIndices #-}
421+fromIndices :: Monad m => (Int -> a) -> Stream m a
422+fromIndices gen = fromIndicesM (return . gen)
423+
424+-- Adapted from the vector package
425+{-# INLINE_NORMAL generateM #-}
426+generateM :: Monad m => Int -> (Int -> m a) -> Stream m a
427+generateM n gen = n `seq` Stream step 0
428+ where
429+ {-# INLINE_LATE step #-}
430+ step _ i | i < n = do
431+ x <- gen i
432+ return $ Yield x (i + 1)
433+ | otherwise = return Stop
434+
435+{-# INLINE generate #-}
436+generate :: Monad m => Int -> (Int -> a) -> Stream m a
437+generate n gen = generateM n (return . gen)
438+
439+-------------------------------------------------------------------------------
440+-- Iteration
441+-------------------------------------------------------------------------------
442+
443+{-# INLINE_NORMAL iterateM #-}
444+iterateM :: Monad m => (a -> m a) -> m a -> Stream m a
445+iterateM step = Stream (\_ st -> st >>= \x -> return $ Yield x (step x))
446+
447+{-# INLINE_NORMAL iterate #-}
448+iterate :: Monad m => (a -> a) -> a -> Stream m a
449+iterate step st = iterateM (return . step) (return st)
450+
451+-------------------------------------------------------------------------------
452+-- From containers
453+-------------------------------------------------------------------------------
454+
455+-- XXX we need the MonadAsync constraint because of a rewrite rule.
456+-- | Convert a list of monadic actions to a 'Stream'
457+{-# INLINE_LATE fromListM #-}
458+fromListM :: MonadAsync m => [m a] -> Stream m a
459+fromListM = Stream step
460+ where
461+ {-# INLINE_LATE step #-}
462+ step _ (m:ms) = m >>= \x -> return $ Yield x ms
463+ step _ [] = return Stop
464+
465+-------------------------------------------------------------------------------
466+-- From callback
467+-------------------------------------------------------------------------------
468+
469+-- Note: we can use another API with two callbacks stop and yield if we want
470+-- the callback to be able to indicate end of stream.
471+--
472+-- | Generates a callback and a stream pair. The callback returned is used to
473+-- queue values to the stream. The stream is infinite, there is no way for the
474+-- callback to indicate that it is done now.
475+--
476+-- /Internal/
477+--
478+{-# INLINE_NORMAL newCallbackStream #-}
479+newCallbackStream :: (K.IsStream t, MonadAsync m) => m ((a -> m ()), t m a)
480+newCallbackStream = do
481+ sv <- newParallelVar StopNone defState
482+
483+ -- XXX Add our own thread-id to the SVar as we can not know the callback's
484+ -- thread-id and the callback is not run in a managed worker. We need to
485+ -- handle this better.
486+ liftIO myThreadId >>= modifyThread sv
487+
488+ let callback a = liftIO $ void $ send sv (ChildYield a)
489+ -- XXX we can return an SVar and then the consumer can unfold from the
490+ -- SVar?
491+ return (callback, fromStreamD (fromSVar sv))
src/Streamly/Internal/Data/Stream/StreamD/Lift.hsnew file+112
@@ -0,0 +1,112 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.StreamD.Lift
3+-- Copyright : (c) 2018 Composewell Technologies
4+-- License : BSD-3-Clause
5+-- Maintainer : streamly@composewell.com
6+-- Stability : experimental
7+-- Portability : GHC
8+--
9+-- Transform the underlying monad of a stream.
10+
11+module Streamly.Internal.Data.Stream.StreamD.Lift
12+ (
13+ -- * Generalize Inner Monad
14+ hoist
15+ , generally -- XXX generalize
16+
17+ -- * Transform Inner Monad
18+ , liftInner
19+ , runReaderT
20+ , evalStateT
21+ , runStateT
22+ )
23+where
24+
25+#include "inline.hs"
26+
27+import Control.Monad.Trans.Class (MonadTrans(lift))
28+import Control.Monad.Trans.Reader (ReaderT)
29+import Control.Monad.Trans.State.Strict (StateT)
30+import Data.Functor.Identity (Identity(..))
31+import Streamly.Internal.Data.SVar (adaptState)
32+
33+import qualified Control.Monad.Trans.Reader as Reader
34+import qualified Control.Monad.Trans.State.Strict as State
35+
36+import Streamly.Internal.Data.Stream.StreamD.Type
37+
38+-------------------------------------------------------------------------------
39+-- Generalize Inner Monad
40+-------------------------------------------------------------------------------
41+
42+{-# INLINE_NORMAL hoist #-}
43+hoist :: Monad n => (forall x. m x -> n x) -> Stream m a -> Stream n a
44+hoist f (Stream step state) = (Stream step' state)
45+ where
46+ {-# INLINE_LATE step' #-}
47+ step' gst st = do
48+ r <- f $ step (adaptState gst) st
49+ return $ case r of
50+ Yield x s -> Yield x s
51+ Skip s -> Skip s
52+ Stop -> Stop
53+
54+{-# INLINE generally #-}
55+generally :: Monad m => Stream Identity a -> Stream m a
56+generally = hoist (return . runIdentity)
57+
58+-------------------------------------------------------------------------------
59+-- Transform Inner Monad
60+-------------------------------------------------------------------------------
61+
62+{-# INLINE_NORMAL liftInner #-}
63+liftInner :: (Monad m, MonadTrans t, Monad (t m))
64+ => Stream m a -> Stream (t m) a
65+liftInner (Stream step state) = Stream step' state
66+ where
67+ {-# INLINE_LATE step' #-}
68+ step' gst st = do
69+ r <- lift $ step (adaptState gst) st
70+ return $ case r of
71+ Yield x s -> Yield x s
72+ Skip s -> Skip s
73+ Stop -> Stop
74+
75+{-# INLINE_NORMAL runReaderT #-}
76+runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
77+runReaderT env (Stream step state) = Stream step' (state, env)
78+ where
79+ {-# INLINE_LATE step' #-}
80+ step' gst (st, action) = do
81+ sv <- action
82+ r <- Reader.runReaderT (step (adaptState gst) st) sv
83+ return $ case r of
84+ Yield x s -> Yield x (s, return sv)
85+ Skip s -> Skip (s, return sv)
86+ Stop -> Stop
87+
88+{-# INLINE_NORMAL evalStateT #-}
89+evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
90+evalStateT initial (Stream step state) = Stream step' (state, initial)
91+ where
92+ {-# INLINE_LATE step' #-}
93+ step' gst (st, action) = do
94+ sv <- action
95+ (r, sv') <- State.runStateT (step (adaptState gst) st) sv
96+ return $ case r of
97+ Yield x s -> Yield x (s, return sv')
98+ Skip s -> Skip (s, return sv')
99+ Stop -> Stop
100+
101+{-# INLINE_NORMAL runStateT #-}
102+runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
103+runStateT initial (Stream step state) = Stream step' (state, initial)
104+ where
105+ {-# INLINE_LATE step' #-}
106+ step' gst (st, action) = do
107+ sv <- action
108+ (r, sv') <- State.runStateT (step (adaptState gst) st) sv
109+ return $ case r of
110+ Yield x s -> Yield (sv', x) (s, return sv')
111+ Skip s -> Skip (s, return sv')
112+ Stop -> Stop
src/Streamly/Internal/Data/Stream/StreamD/Nesting.hsnew file+2183
@@ -0,0 +1,2183 @@
1+-- |
2+-- Module : Streamly.Internal.Data.Stream.StreamD.Nesting
3+-- Copyright : (c) 2018 Composewell Technologies
4+-- (c) Roman Leshchinskiy 2008-2010
5+-- License : BSD-3-Clause
6+-- Maintainer : streamly@composewell.com
7+-- Stability : experimental
8+-- Portability : GHC
9+--
10+-- This module contains transformations involving multiple streams, unfolds or
11+-- folds. There are two types of transformations generational or eliminational.
12+-- Generational transformations are like the "Generate" module but they
13+-- generate a stream by combining streams instead of elements. Eliminational
14+-- transformations are like the "Eliminate" module but they transform a stream
15+-- by eliminating parts of the stream instead of eliminating the whole stream.
16+--
17+-- These combinators involve transformation, generation, elimination so can be
18+-- classified under any of those.
19+--
20+-- Ultimately these operations should be supported by Unfolds, Pipes and Folds,
21+-- and this module may become redundant.
22+
23+-- The zipWithM combinator in this module has been adapted from the vector
24+-- package (c) Roman Leshchinskiy.
25+--
26+module Streamly.Internal.Data.Stream.StreamD.Nesting
27+ (
28+ -- * Generate
29+ -- | Combining streams to generate streams.
30+
31+ -- ** Combine Two Streams
32+ -- | Functions ending in the shape:
33+ --
34+ -- @t m a -> t m a -> t m a@.
35+
36+ -- *** Appending
37+ -- | Append a stream after another. A special case of concatMap or
38+ -- concatUnfold.
39+ AppendState(..)
40+ , append
41+
42+ -- *** Interleaving
43+ -- | Interleave elements from two streams alternately. A special case of
44+ -- concatUnfoldInterleave.
45+ , InterleaveState(..)
46+ , interleave
47+ , interleaveMin
48+ , interleaveSuffix
49+ , interleaveInfix
50+
51+ -- *** Scheduling
52+ -- | Execute streams alternately irrespective of whether they generate
53+ -- elements or not. Note 'interleave' would execute a stream until it
54+ -- yields an element. A special case of concatUnfoldRoundrobin.
55+ , roundRobin -- interleaveFair?/ParallelFair
56+
57+ -- *** Zipping
58+ -- | Zip corresponding elements of two streams.
59+ , zipWith
60+ , zipWithM
61+
62+ -- *** Merging
63+ -- | Interleave elements from two streams based on a condition.
64+ , mergeBy
65+ , mergeByM
66+
67+ -- ** Combine N Streams
68+ -- | Functions generally ending in these shapes:
69+ --
70+ -- @
71+ -- concat: f (t m a) -> t m a
72+ -- concatMap: (a -> t m b) -> t m a -> t m b
73+ -- concatUnfold: Unfold m a b -> t m a -> t m b
74+ -- @
75+
76+ -- *** ConcatMap
77+ -- | Generate streams by mapping a stream generator on each element of an
78+ -- input stream, append the resulting streams and flatten.
79+ , concatMap
80+ , concatMapM
81+
82+ -- *** ConcatUnfold
83+ -- | Generate streams by using an unfold on each element of an input
84+ -- stream, append the resulting streams and flatten. A special case of
85+ -- gintercalate.
86+ , ConcatMapUState (..)
87+ , concatMapU
88+ , ConcatUnfoldInterleaveState (..)
89+ , concatUnfoldInterleave
90+ , concatUnfoldRoundrobin
91+
92+ -- *** Interpose
93+ -- | Like concatUnfold but intersperses an effect between the streams. A
94+ -- special case of gintercalate.
95+ , interpose
96+ , interposeSuffix
97+
98+ -- *** Intercalate
99+ -- | Like concatUnfold but intersperses streams from another source between
100+ -- the streams from the first source.
101+ , gintercalate
102+ , gintercalateSuffix
103+
104+ -- * Eliminate
105+ -- | Folding and Parsing chunks of streams to eliminate nested streams.
106+ -- Functions generally ending in these shapes:
107+ --
108+ -- @
109+ -- f (Fold m a b) -> t m a -> t m b
110+ -- f (Parser m a b) -> t m a -> t m b
111+ -- @
112+
113+ -- ** Folding
114+ -- | Apply folds on a stream.
115+ , foldMany
116+
117+ -- ** Parsing
118+ -- | Parsing is opposite to flattening. 'parseMany' is dual to concatMap or
119+ -- concatUnfold. concatMap generates a stream from single values in a
120+ -- stream and flattens, parseMany does the opposite of flattening by
121+ -- splitting the stream and then folds each such split to single value in
122+ -- the output stream.
123+ , parseMany
124+ , parseIterate
125+
126+ -- ** Grouping
127+ -- | Group segments of a stream and fold. Special case of parsing.
128+ , groupsOf2
129+ , groupsBy
130+ , groupsRollingBy
131+
132+ -- ** Splitting
133+ -- | A special case of parsing.
134+ , wordsBy
135+ , splitOnSeq
136+ , splitOnSuffixSeq
137+
138+ -- * Transform (Nested Containers)
139+ -- | Opposite to compact in ArrayStream
140+ , splitInnerBy
141+ , splitInnerBySuffix
142+ )
143+where
144+
145+#include "inline.hs"
146+
147+import Control.Exception (assert)
148+import Control.Monad.Catch (MonadThrow, throwM)
149+import Control.Monad.IO.Class (MonadIO(..))
150+import Data.Bits (shiftR, shiftL, (.|.), (.&.))
151+#if __GLASGOW_HASKELL__ >= 801
152+import Data.Functor.Identity ( Identity )
153+#endif
154+import Data.Word (Word32)
155+import Foreign.Storable (Storable(..))
156+import Fusion.Plugin.Types (Fuse(..))
157+import GHC.Types (SPEC(..))
158+
159+import Streamly.Internal.Data.Array.Storable.Foreign.Types (Array(..))
160+import Streamly.Internal.Data.Fold.Types (Fold(..))
161+import Streamly.Internal.Data.Parser (ParseError(..))
162+import Streamly.Internal.Data.Unfold.Types (Unfold(..))
163+
164+import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as A
165+import qualified Streamly.Internal.Data.Fold as FL
166+import qualified Streamly.Internal.Data.Parser as PR
167+import qualified Streamly.Internal.Data.Parser.ParserD as PRD
168+import qualified Streamly.Memory.Ring as RB
169+
170+import Streamly.Internal.Data.Stream.StreamD.Type
171+import Streamly.Internal.Data.SVar
172+
173+import Prelude hiding (concatMap, mapM, zipWith)
174+
175+------------------------------------------------------------------------------
176+-- Appending
177+------------------------------------------------------------------------------
178+
179+data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
180+
181+-- Note that this could be much faster compared to the CPS stream. However, as
182+-- the number of streams being composed increases this may become expensive.
183+-- Need to see where the breaking point is between the two.
184+--
185+{-# INLINE_NORMAL append #-}
186+append :: Monad m => Stream m a -> Stream m a -> Stream m a
187+append (Stream step1 state1) (Stream step2 state2) =
188+ Stream step (AppendFirst state1)
189+
190+ where
191+
192+ {-# INLINE_LATE step #-}
193+ step gst (AppendFirst st) = do
194+ r <- step1 gst st
195+ return $ case r of
196+ Yield a s -> Yield a (AppendFirst s)
197+ Skip s -> Skip (AppendFirst s)
198+ Stop -> Skip (AppendSecond state2)
199+
200+ step gst (AppendSecond st) = do
201+ r <- step2 gst st
202+ return $ case r of
203+ Yield a s -> Yield a (AppendSecond s)
204+ Skip s -> Skip (AppendSecond s)
205+ Stop -> Stop
206+
207+------------------------------------------------------------------------------
208+-- Interleaving
209+------------------------------------------------------------------------------
210+
211+data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
212+ | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
213+
214+{-# INLINE_NORMAL interleave #-}
215+interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
216+interleave (Stream step1 state1) (Stream step2 state2) =
217+ Stream step (InterleaveFirst state1 state2)
218+
219+ where
220+
221+ {-# INLINE_LATE step #-}
222+ step gst (InterleaveFirst st1 st2) = do
223+ r <- step1 gst st1
224+ return $ case r of
225+ Yield a s -> Yield a (InterleaveSecond s st2)
226+ Skip s -> Skip (InterleaveFirst s st2)
227+ Stop -> Skip (InterleaveSecondOnly st2)
228+
229+ step gst (InterleaveSecond st1 st2) = do
230+ r <- step2 gst st2
231+ return $ case r of
232+ Yield a s -> Yield a (InterleaveFirst st1 s)
233+ Skip s -> Skip (InterleaveSecond st1 s)
234+ Stop -> Skip (InterleaveFirstOnly st1)
235+
236+ step gst (InterleaveFirstOnly st1) = do
237+ r <- step1 gst st1
238+ return $ case r of
239+ Yield a s -> Yield a (InterleaveFirstOnly s)
240+ Skip s -> Skip (InterleaveFirstOnly s)
241+ Stop -> Stop
242+
243+ step gst (InterleaveSecondOnly st2) = do
244+ r <- step2 gst st2
245+ return $ case r of
246+ Yield a s -> Yield a (InterleaveSecondOnly s)
247+ Skip s -> Skip (InterleaveSecondOnly s)
248+ Stop -> Stop
249+
250+{-# INLINE_NORMAL interleaveMin #-}
251+interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
252+interleaveMin (Stream step1 state1) (Stream step2 state2) =
253+ Stream step (InterleaveFirst state1 state2)
254+
255+ where
256+
257+ {-# INLINE_LATE step #-}
258+ step gst (InterleaveFirst st1 st2) = do
259+ r <- step1 gst st1
260+ return $ case r of
261+ Yield a s -> Yield a (InterleaveSecond s st2)
262+ Skip s -> Skip (InterleaveFirst s st2)
263+ Stop -> Stop
264+
265+ step gst (InterleaveSecond st1 st2) = do
266+ r <- step2 gst st2
267+ return $ case r of
268+ Yield a s -> Yield a (InterleaveFirst st1 s)
269+ Skip s -> Skip (InterleaveSecond st1 s)
270+ Stop -> Stop
271+
272+ step _ (InterleaveFirstOnly _) = undefined
273+ step _ (InterleaveSecondOnly _) = undefined
274+
275+{-# INLINE_NORMAL interleaveSuffix #-}
276+interleaveSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
277+interleaveSuffix (Stream step1 state1) (Stream step2 state2) =
278+ Stream step (InterleaveFirst state1 state2)
279+
280+ where
281+
282+ {-# INLINE_LATE step #-}
283+ step gst (InterleaveFirst st1 st2) = do
284+ r <- step1 gst st1
285+ return $ case r of
286+ Yield a s -> Yield a (InterleaveSecond s st2)
287+ Skip s -> Skip (InterleaveFirst s st2)
288+ Stop -> Stop
289+
290+ step gst (InterleaveSecond st1 st2) = do
291+ r <- step2 gst st2
292+ return $ case r of
293+ Yield a s -> Yield a (InterleaveFirst st1 s)
294+ Skip s -> Skip (InterleaveSecond st1 s)
295+ Stop -> Skip (InterleaveFirstOnly st1)
296+
297+ step gst (InterleaveFirstOnly st1) = do
298+ r <- step1 gst st1
299+ return $ case r of
300+ Yield a s -> Yield a (InterleaveFirstOnly s)
301+ Skip s -> Skip (InterleaveFirstOnly s)
302+ Stop -> Stop
303+
304+ step _ (InterleaveSecondOnly _) = undefined
305+
306+data InterleaveInfixState s1 s2 a
307+ = InterleaveInfixFirst s1 s2
308+ | InterleaveInfixSecondBuf s1 s2
309+ | InterleaveInfixSecondYield s1 s2 a
310+ | InterleaveInfixFirstYield s1 s2 a
311+ | InterleaveInfixFirstOnly s1
312+
313+{-# INLINE_NORMAL interleaveInfix #-}
314+interleaveInfix :: Monad m => Stream m a -> Stream m a -> Stream m a
315+interleaveInfix (Stream step1 state1) (Stream step2 state2) =
316+ Stream step (InterleaveInfixFirst state1 state2)
317+
318+ where
319+
320+ {-# INLINE_LATE step #-}
321+ step gst (InterleaveInfixFirst st1 st2) = do
322+ r <- step1 gst st1
323+ return $ case r of
324+ Yield a s -> Yield a (InterleaveInfixSecondBuf s st2)
325+ Skip s -> Skip (InterleaveInfixFirst s st2)
326+ Stop -> Stop
327+
328+ step gst (InterleaveInfixSecondBuf st1 st2) = do
329+ r <- step2 gst st2
330+ return $ case r of
331+ Yield a s -> Skip (InterleaveInfixSecondYield st1 s a)
332+ Skip s -> Skip (InterleaveInfixSecondBuf st1 s)
333+ Stop -> Skip (InterleaveInfixFirstOnly st1)
334+
335+ step gst (InterleaveInfixSecondYield st1 st2 x) = do
336+ r <- step1 gst st1
337+ return $ case r of
338+ Yield a s -> Yield x (InterleaveInfixFirstYield s st2 a)
339+ Skip s -> Skip (InterleaveInfixSecondYield s st2 x)
340+ Stop -> Stop
341+
342+ step _ (InterleaveInfixFirstYield st1 st2 x) = do
343+ return $ Yield x (InterleaveInfixSecondBuf st1 st2)
344+
345+ step gst (InterleaveInfixFirstOnly st1) = do
346+ r <- step1 gst st1
347+ return $ case r of
348+ Yield a s -> Yield a (InterleaveInfixFirstOnly s)
349+ Skip s -> Skip (InterleaveInfixFirstOnly s)
350+ Stop -> Stop
351+
352+------------------------------------------------------------------------------
353+-- Scheduling
354+------------------------------------------------------------------------------
355+
356+{-# INLINE_NORMAL roundRobin #-}
357+roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
358+roundRobin (Stream step1 state1) (Stream step2 state2) =
359+ Stream step (InterleaveFirst state1 state2)
360+
361+ where
362+
363+ {-# INLINE_LATE step #-}
364+ step gst (InterleaveFirst st1 st2) = do
365+ r <- step1 gst st1
366+ return $ case r of
367+ Yield a s -> Yield a (InterleaveSecond s st2)
368+ Skip s -> Skip (InterleaveSecond s st2)
369+ Stop -> Skip (InterleaveSecondOnly st2)
370+
371+ step gst (InterleaveSecond st1 st2) = do
372+ r <- step2 gst st2
373+ return $ case r of
374+ Yield a s -> Yield a (InterleaveFirst st1 s)
375+ Skip s -> Skip (InterleaveFirst st1 s)
376+ Stop -> Skip (InterleaveFirstOnly st1)
377+
378+ step gst (InterleaveSecondOnly st2) = do
379+ r <- step2 gst st2
380+ return $ case r of
381+ Yield a s -> Yield a (InterleaveSecondOnly s)
382+ Skip s -> Skip (InterleaveSecondOnly s)
383+ Stop -> Stop
384+
385+ step gst (InterleaveFirstOnly st1) = do
386+ r <- step1 gst st1
387+ return $ case r of
388+ Yield a s -> Yield a (InterleaveFirstOnly s)
389+ Skip s -> Skip (InterleaveFirstOnly s)
390+ Stop -> Stop
391+
392+------------------------------------------------------------------------------
393+-- Zipping
394+------------------------------------------------------------------------------
395+
396+{-# INLINE_NORMAL zipWithM #-}
397+zipWithM :: Monad m
398+ => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
399+zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
400+ where
401+ {-# INLINE_LATE step #-}
402+ step gst (sa, sb, Nothing) = do
403+ r <- stepa (adaptState gst) sa
404+ return $
405+ case r of
406+ Yield x sa' -> Skip (sa', sb, Just x)
407+ Skip sa' -> Skip (sa', sb, Nothing)
408+ Stop -> Stop
409+
410+ step gst (sa, sb, Just x) = do
411+ r <- stepb (adaptState gst) sb
412+ case r of
413+ Yield y sb' -> do
414+ z <- f x y
415+ return $ Yield z (sa, sb', Nothing)
416+ Skip sb' -> return $ Skip (sa, sb', Just x)
417+ Stop -> return Stop
418+
419+#if __GLASGOW_HASKELL__ >= 801
420+{-# RULES "zipWithM xs xs"
421+ forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
422+#endif
423+
424+{-# INLINE zipWith #-}
425+zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
426+zipWith f = zipWithM (\a b -> return (f a b))
427+
428+------------------------------------------------------------------------------
429+-- Merging
430+------------------------------------------------------------------------------
431+
432+{-# INLINE_NORMAL mergeByM #-}
433+mergeByM
434+ :: (Monad m)
435+ => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
436+mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
437+ Stream step (Just ta, Just tb, Nothing, Nothing)
438+ where
439+ {-# INLINE_LATE step #-}
440+
441+ -- one of the values is missing, and the corresponding stream is running
442+ step gst (Just sa, sb, Nothing, b) = do
443+ r <- stepa gst sa
444+ return $ case r of
445+ Yield a sa' -> Skip (Just sa', sb, Just a, b)
446+ Skip sa' -> Skip (Just sa', sb, Nothing, b)
447+ Stop -> Skip (Nothing, sb, Nothing, b)
448+
449+ step gst (sa, Just sb, a, Nothing) = do
450+ r <- stepb gst sb
451+ return $ case r of
452+ Yield b sb' -> Skip (sa, Just sb', a, Just b)
453+ Skip sb' -> Skip (sa, Just sb', a, Nothing)
454+ Stop -> Skip (sa, Nothing, a, Nothing)
455+
456+ -- both the values are available
457+ step _ (sa, sb, Just a, Just b) = do
458+ res <- cmp a b
459+ return $ case res of
460+ GT -> Yield b (sa, sb, Just a, Nothing)
461+ _ -> Yield a (sa, sb, Nothing, Just b)
462+
463+ -- one of the values is missing, corresponding stream is done
464+ step _ (Nothing, sb, Nothing, Just b) =
465+ return $ Yield b (Nothing, sb, Nothing, Nothing)
466+
467+ step _ (sa, Nothing, Just a, Nothing) =
468+ return $ Yield a (sa, Nothing, Nothing, Nothing)
469+
470+ step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
471+
472+{-# INLINE mergeBy #-}
473+mergeBy
474+ :: (Monad m)
475+ => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
476+mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
477+
478+------------------------------------------------------------------------------
479+-- Combine N Streams - concatUnfold
480+------------------------------------------------------------------------------
481+
482+-- Define a unique structure to use in inspection testing
483+data ConcatMapUState o i =
484+ ConcatMapUOuter o
485+ | ConcatMapUInner o i
486+
487+-- | @concatMapU unfold stream@ uses @unfold@ to map the input stream elements
488+-- to streams and then flattens the generated streams into a single output
489+-- stream.
490+
491+-- This is like 'concatMap' but uses an unfold with an explicit state to
492+-- generate the stream instead of a 'Stream' type generator. This allows better
493+-- optimization via fusion. This can be many times more efficient than
494+-- 'concatMap'.
495+
496+{-# INLINE_NORMAL concatMapU #-}
497+concatMapU :: Monad m => Unfold m a b -> Stream m a -> Stream m b
498+concatMapU (Unfold istep inject) (Stream ostep ost) =
499+ Stream step (ConcatMapUOuter ost)
500+ where
501+ {-# INLINE_LATE step #-}
502+ step gst (ConcatMapUOuter o) = do
503+ r <- ostep (adaptState gst) o
504+ case r of
505+ Yield a o' -> do
506+ i <- inject a
507+ i `seq` return (Skip (ConcatMapUInner o' i))
508+ Skip o' -> return $ Skip (ConcatMapUOuter o')
509+ Stop -> return $ Stop
510+
511+ step _ (ConcatMapUInner o i) = do
512+ r <- istep i
513+ return $ case r of
514+ Yield x i' -> Yield x (ConcatMapUInner o i')
515+ Skip i' -> Skip (ConcatMapUInner o i')
516+ Stop -> Skip (ConcatMapUOuter o)
517+
518+data ConcatUnfoldInterleaveState o i =
519+ ConcatUnfoldInterleaveOuter o [i]
520+ | ConcatUnfoldInterleaveInner o [i]
521+ | ConcatUnfoldInterleaveInnerL [i] [i]
522+ | ConcatUnfoldInterleaveInnerR [i] [i]
523+
524+-- XXX use arrays to store state instead of lists.
525+-- XXX In general we can use different scheduling strategies e.g. how to
526+-- schedule the outer vs inner loop or assigning weights to different streams
527+-- or outer and inner loops.
528+
529+-- After a yield, switch to the next stream. Do not switch streams on Skip.
530+-- Yield from outer stream switches to the inner stream.
531+--
532+-- There are two choices here, (1) exhaust the outer stream first and then
533+-- start yielding from the inner streams, this is much simpler to implement,
534+-- (2) yield at least one element from an inner stream before going back to
535+-- outer stream and opening the next stream from it.
536+--
537+-- Ideally, we need some scheduling bias to inner streams vs outer stream.
538+-- Maybe we can configure the behavior.
539+--
540+{-# INLINE_NORMAL concatUnfoldInterleave #-}
541+concatUnfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
542+concatUnfoldInterleave (Unfold istep inject) (Stream ostep ost) =
543+ Stream step (ConcatUnfoldInterleaveOuter ost [])
544+ where
545+ {-# INLINE_LATE step #-}
546+ step gst (ConcatUnfoldInterleaveOuter o ls) = do
547+ r <- ostep (adaptState gst) o
548+ case r of
549+ Yield a o' -> do
550+ i <- inject a
551+ i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
552+ Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
553+ Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
554+
555+ step _ (ConcatUnfoldInterleaveInner _ []) = undefined
556+ step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
557+ r <- istep st
558+ return $ case r of
559+ Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
560+ Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
561+ Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
562+
563+ step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
564+ step _ (ConcatUnfoldInterleaveInnerL [] rs) =
565+ return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
566+
567+ step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
568+ r <- istep st
569+ return $ case r of
570+ Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
571+ Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
572+ Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
573+
574+ step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
575+ step _ (ConcatUnfoldInterleaveInnerR ls []) =
576+ return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
577+
578+ step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
579+ r <- istep st
580+ return $ case r of
581+ Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
582+ Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
583+ Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
584+
585+-- XXX In general we can use different scheduling strategies e.g. how to
586+-- schedule the outer vs inner loop or assigning weights to different streams
587+-- or outer and inner loops.
588+--
589+-- This could be inefficient if the tasks are too small.
590+--
591+-- Compared to concatUnfoldInterleave this one switches streams on Skips.
592+--
593+{-# INLINE_NORMAL concatUnfoldRoundrobin #-}
594+concatUnfoldRoundrobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
595+concatUnfoldRoundrobin (Unfold istep inject) (Stream ostep ost) =
596+ Stream step (ConcatUnfoldInterleaveOuter ost [])
597+ where
598+ {-# INLINE_LATE step #-}
599+ step gst (ConcatUnfoldInterleaveOuter o ls) = do
600+ r <- ostep (adaptState gst) o
601+ case r of
602+ Yield a o' -> do
603+ i <- inject a
604+ i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
605+ Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
606+ Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
607+
608+ step _ (ConcatUnfoldInterleaveInner o []) =
609+ return $ Skip (ConcatUnfoldInterleaveOuter o [])
610+
611+ step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
612+ r <- istep st
613+ return $ case r of
614+ Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
615+ Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
616+ Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
617+
618+ step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
619+ step _ (ConcatUnfoldInterleaveInnerL [] rs) =
620+ return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
621+
622+ step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
623+ r <- istep st
624+ return $ case r of
625+ Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
626+ Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
627+ Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
628+
629+ step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
630+ step _ (ConcatUnfoldInterleaveInnerR ls []) =
631+ return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
632+
633+ step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
634+ r <- istep st
635+ return $ case r of
636+ Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
637+ Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
638+ Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
639+
640+------------------------------------------------------------------------------
641+-- Combine N Streams - interpose
642+------------------------------------------------------------------------------
643+
644+{-# ANN type InterposeSuffixState Fuse #-}
645+data InterposeSuffixState s1 i1 =
646+ InterposeSuffixFirst s1
647+ -- | InterposeSuffixFirstYield s1 i1
648+ | InterposeSuffixFirstInner s1 i1
649+ | InterposeSuffixSecond s1
650+
651+-- Note that if an unfolded layer turns out to be nil we still emit the
652+-- separator effect. An alternate behavior could be to emit the separator
653+-- effect only if at least one element has been yielded by the unfolding.
654+-- However, that becomes a bit complicated, so we have chosen the former
655+-- behvaior for now.
656+{-# INLINE_NORMAL interposeSuffix #-}
657+interposeSuffix
658+ :: Monad m
659+ => m c -> Unfold m b c -> Stream m b -> Stream m c
660+interposeSuffix
661+ action
662+ (Unfold istep1 inject1) (Stream step1 state1) =
663+ Stream step (InterposeSuffixFirst state1)
664+
665+ where
666+
667+ {-# INLINE_LATE step #-}
668+ step gst (InterposeSuffixFirst s1) = do
669+ r <- step1 (adaptState gst) s1
670+ case r of
671+ Yield a s -> do
672+ i <- inject1 a
673+ i `seq` return (Skip (InterposeSuffixFirstInner s i))
674+ -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
675+ Skip s -> return $ Skip (InterposeSuffixFirst s)
676+ Stop -> return Stop
677+
678+ {-
679+ step _ (InterposeSuffixFirstYield s1 i1) = do
680+ r <- istep1 i1
681+ return $ case r of
682+ Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
683+ Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
684+ Stop -> Skip (InterposeSuffixFirst s1)
685+ -}
686+
687+ step _ (InterposeSuffixFirstInner s1 i1) = do
688+ r <- istep1 i1
689+ return $ case r of
690+ Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
691+ Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
692+ Stop -> Skip (InterposeSuffixSecond s1)
693+
694+ step _ (InterposeSuffixSecond s1) = do
695+ r <- action
696+ return $ Yield r (InterposeSuffixFirst s1)
697+
698+{-# ANN type InterposeState Fuse #-}
699+data InterposeState s1 i1 a =
700+ InterposeFirst s1
701+ -- | InterposeFirstYield s1 i1
702+ | InterposeFirstInner s1 i1
703+ | InterposeFirstInject s1
704+ -- | InterposeFirstBuf s1 i1
705+ | InterposeSecondYield s1 i1
706+ -- -- | InterposeSecondYield s1 i1 a
707+ -- -- | InterposeFirstResume s1 i1 a
708+
709+-- Note that this only interposes the pure values, we may run many effects to
710+-- generate those values as some effects may not generate anything (Skip).
711+{-# INLINE_NORMAL interpose #-}
712+interpose :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
713+interpose
714+ action
715+ (Unfold istep1 inject1) (Stream step1 state1) =
716+ Stream step (InterposeFirst state1)
717+
718+ where
719+
720+ {-# INLINE_LATE step #-}
721+ step gst (InterposeFirst s1) = do
722+ r <- step1 (adaptState gst) s1
723+ case r of
724+ Yield a s -> do
725+ i <- inject1 a
726+ i `seq` return (Skip (InterposeFirstInner s i))
727+ -- i `seq` return (Skip (InterposeFirstYield s i))
728+ Skip s -> return $ Skip (InterposeFirst s)
729+ Stop -> return Stop
730+
731+ {-
732+ step _ (InterposeFirstYield s1 i1) = do
733+ r <- istep1 i1
734+ return $ case r of
735+ Yield x i' -> Yield x (InterposeFirstInner s1 i')
736+ Skip i' -> Skip (InterposeFirstYield s1 i')
737+ Stop -> Skip (InterposeFirst s1)
738+ -}
739+
740+ step _ (InterposeFirstInner s1 i1) = do
741+ r <- istep1 i1
742+ return $ case r of
743+ Yield x i' -> Yield x (InterposeFirstInner s1 i')
744+ Skip i' -> Skip (InterposeFirstInner s1 i')
745+ Stop -> Skip (InterposeFirstInject s1)
746+
747+ step gst (InterposeFirstInject s1) = do
748+ r <- step1 (adaptState gst) s1
749+ case r of
750+ Yield a s -> do
751+ i <- inject1 a
752+ -- i `seq` return (Skip (InterposeFirstBuf s i))
753+ i `seq` return (Skip (InterposeSecondYield s i))
754+ Skip s -> return $ Skip (InterposeFirstInject s)
755+ Stop -> return Stop
756+
757+ {-
758+ step _ (InterposeFirstBuf s1 i1) = do
759+ r <- istep1 i1
760+ return $ case r of
761+ Yield x i' -> Skip (InterposeSecondYield s1 i' x)
762+ Skip i' -> Skip (InterposeFirstBuf s1 i')
763+ Stop -> Stop
764+ -}
765+
766+ {-
767+ step _ (InterposeSecondYield s1 i1 v) = do
768+ r <- action
769+ return $ Yield r (InterposeFirstResume s1 i1 v)
770+ -}
771+ step _ (InterposeSecondYield s1 i1) = do
772+ r <- action
773+ return $ Yield r (InterposeFirstInner s1 i1)
774+
775+ {-
776+ step _ (InterposeFirstResume s1 i1 v) = do
777+ return $ Yield v (InterposeFirstInner s1 i1)
778+ -}
779+
780+------------------------------------------------------------------------------
781+-- Combine N Streams - intercalate
782+------------------------------------------------------------------------------
783+
784+data ICUState s1 s2 i1 i2 =
785+ ICUFirst s1 s2
786+ | ICUSecond s1 s2
787+ | ICUSecondOnly s2
788+ | ICUFirstOnly s1
789+ | ICUFirstInner s1 s2 i1
790+ | ICUSecondInner s1 s2 i2
791+ | ICUFirstOnlyInner s1 i1
792+ | ICUSecondOnlyInner s2 i2
793+
794+-- | Interleave streams (full streams, not the elements) unfolded from two
795+-- input streams and concat. Stop when the first stream stops. If the second
796+-- stream ends before the first one then first stream still keeps running alone
797+-- without any interleaving with the second stream.
798+--
799+-- [a1, a2, ... an] [b1, b2 ...]
800+-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
801+-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
802+-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
803+--
804+{-# INLINE_NORMAL gintercalateSuffix #-}
805+gintercalateSuffix
806+ :: Monad m
807+ => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
808+gintercalateSuffix
809+ (Unfold istep1 inject1) (Stream step1 state1)
810+ (Unfold istep2 inject2) (Stream step2 state2) =
811+ Stream step (ICUFirst state1 state2)
812+
813+ where
814+
815+ {-# INLINE_LATE step #-}
816+ step gst (ICUFirst s1 s2) = do
817+ r <- step1 (adaptState gst) s1
818+ case r of
819+ Yield a s -> do
820+ i <- inject1 a
821+ i `seq` return (Skip (ICUFirstInner s s2 i))
822+ Skip s -> return $ Skip (ICUFirst s s2)
823+ Stop -> return Stop
824+
825+ step gst (ICUFirstOnly s1) = do
826+ r <- step1 (adaptState gst) s1
827+ case r of
828+ Yield a s -> do
829+ i <- inject1 a
830+ i `seq` return (Skip (ICUFirstOnlyInner s i))
831+ Skip s -> return $ Skip (ICUFirstOnly s)
832+ Stop -> return Stop
833+
834+ step _ (ICUFirstInner s1 s2 i1) = do
835+ r <- istep1 i1
836+ return $ case r of
837+ Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
838+ Skip i' -> Skip (ICUFirstInner s1 s2 i')
839+ Stop -> Skip (ICUSecond s1 s2)
840+
841+ step _ (ICUFirstOnlyInner s1 i1) = do
842+ r <- istep1 i1
843+ return $ case r of
844+ Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
845+ Skip i' -> Skip (ICUFirstOnlyInner s1 i')
846+ Stop -> Skip (ICUFirstOnly s1)
847+
848+ step gst (ICUSecond s1 s2) = do
849+ r <- step2 (adaptState gst) s2
850+ case r of
851+ Yield a s -> do
852+ i <- inject2 a
853+ i `seq` return (Skip (ICUSecondInner s1 s i))
854+ Skip s -> return $ Skip (ICUSecond s1 s)
855+ Stop -> return $ Skip (ICUFirstOnly s1)
856+
857+ step _ (ICUSecondInner s1 s2 i2) = do
858+ r <- istep2 i2
859+ return $ case r of
860+ Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
861+ Skip i' -> Skip (ICUSecondInner s1 s2 i')
862+ Stop -> Skip (ICUFirst s1 s2)
863+
864+ step _ (ICUSecondOnly _s2) = undefined
865+ step _ (ICUSecondOnlyInner _s2 _i2) = undefined
866+
867+data ICALState s1 s2 i1 i2 a =
868+ ICALFirst s1 s2
869+ -- | ICALFirstYield s1 s2 i1
870+ | ICALFirstInner s1 s2 i1
871+ | ICALFirstOnly s1
872+ | ICALFirstOnlyInner s1 i1
873+ | ICALSecondInject s1 s2
874+ | ICALFirstInject s1 s2 i2
875+ -- | ICALFirstBuf s1 s2 i1 i2
876+ | ICALSecondInner s1 s2 i1 i2
877+ -- -- | ICALSecondInner s1 s2 i1 i2 a
878+ -- -- | ICALFirstResume s1 s2 i1 i2 a
879+
880+-- | Interleave streams (full streams, not the elements) unfolded from two
881+-- input streams and concat. Stop when the first stream stops. If the second
882+-- stream ends before the first one then first stream still keeps running alone
883+-- without any interleaving with the second stream.
884+--
885+-- [a1, a2, ... an] [b1, b2 ...]
886+-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
887+-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
888+-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
889+--
890+{-# INLINE_NORMAL gintercalate #-}
891+gintercalate
892+ :: Monad m
893+ => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
894+gintercalate
895+ (Unfold istep1 inject1) (Stream step1 state1)
896+ (Unfold istep2 inject2) (Stream step2 state2) =
897+ Stream step (ICALFirst state1 state2)
898+
899+ where
900+
901+ {-# INLINE_LATE step #-}
902+ step gst (ICALFirst s1 s2) = do
903+ r <- step1 (adaptState gst) s1
904+ case r of
905+ Yield a s -> do
906+ i <- inject1 a
907+ i `seq` return (Skip (ICALFirstInner s s2 i))
908+ -- i `seq` return (Skip (ICALFirstYield s s2 i))
909+ Skip s -> return $ Skip (ICALFirst s s2)
910+ Stop -> return Stop
911+
912+ {-
913+ step _ (ICALFirstYield s1 s2 i1) = do
914+ r <- istep1 i1
915+ return $ case r of
916+ Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
917+ Skip i' -> Skip (ICALFirstYield s1 s2 i')
918+ Stop -> Skip (ICALFirst s1 s2)
919+ -}
920+
921+ step _ (ICALFirstInner s1 s2 i1) = do
922+ r <- istep1 i1
923+ return $ case r of
924+ Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
925+ Skip i' -> Skip (ICALFirstInner s1 s2 i')
926+ Stop -> Skip (ICALSecondInject s1 s2)
927+
928+ step gst (ICALFirstOnly s1) = do
929+ r <- step1 (adaptState gst) s1
930+ case r of
931+ Yield a s -> do
932+ i <- inject1 a
933+ i `seq` return (Skip (ICALFirstOnlyInner s i))
934+ Skip s -> return $ Skip (ICALFirstOnly s)
935+ Stop -> return Stop
936+
937+ step _ (ICALFirstOnlyInner s1 i1) = do
938+ r <- istep1 i1
939+ return $ case r of
940+ Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
941+ Skip i' -> Skip (ICALFirstOnlyInner s1 i')
942+ Stop -> Skip (ICALFirstOnly s1)
943+
944+ -- We inject the second stream even before checking if the first stream
945+ -- would yield any more elements. There is no clear choice whether we
946+ -- should do this before or after that. Doing it after may make the state
947+ -- machine a bit simpler though.
948+ step gst (ICALSecondInject s1 s2) = do
949+ r <- step2 (adaptState gst) s2
950+ case r of
951+ Yield a s -> do
952+ i <- inject2 a
953+ i `seq` return (Skip (ICALFirstInject s1 s i))
954+ Skip s -> return $ Skip (ICALSecondInject s1 s)
955+ Stop -> return $ Skip (ICALFirstOnly s1)
956+
957+ step gst (ICALFirstInject s1 s2 i2) = do
958+ r <- step1 (adaptState gst) s1
959+ case r of
960+ Yield a s -> do
961+ i <- inject1 a
962+ i `seq` return (Skip (ICALSecondInner s s2 i i2))
963+ -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
964+ Skip s -> return $ Skip (ICALFirstInject s s2 i2)
965+ Stop -> return Stop
966+
967+ {-
968+ step _ (ICALFirstBuf s1 s2 i1 i2) = do
969+ r <- istep1 i1
970+ return $ case r of
971+ Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
972+ Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
973+ Stop -> Stop
974+
975+ step _ (ICALSecondInner s1 s2 i1 i2 v) = do
976+ r <- istep2 i2
977+ return $ case r of
978+ Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
979+ Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
980+ Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
981+ -}
982+
983+ step _ (ICALSecondInner s1 s2 i1 i2) = do
984+ r <- istep2 i2
985+ return $ case r of
986+ Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
987+ Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
988+ Stop -> Skip (ICALFirstInner s1 s2 i1)
989+ -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
990+
991+ {-
992+ step _ (ICALFirstResume s1 s2 i1 i2 x) = do
993+ return $ Yield x (ICALFirstInner s1 s2 i1 i2)
994+ -}
995+
996+------------------------------------------------------------------------------
997+-- Parsing
998+------------------------------------------------------------------------------
999+
1000+{-# ANN type ParseChunksState Fuse #-}
1001+data ParseChunksState x inpBuf st pst =
1002+ ParseChunksInit inpBuf st
1003+ | ParseChunksInitLeftOver inpBuf
1004+ | ParseChunksStream st inpBuf !pst
1005+ | ParseChunksBuf inpBuf st inpBuf !pst
1006+ | ParseChunksYield x (ParseChunksState x inpBuf st pst)
1007+
1008+{-# INLINE_NORMAL parseMany #-}
1009+parseMany
1010+ :: MonadThrow m
1011+ => PRD.Parser m a b
1012+ -> Stream m a
1013+ -> Stream m b
1014+parseMany (PRD.Parser pstep initial extract) (Stream step state) =
1015+ Stream stepOuter (ParseChunksInit [] state)
1016+
1017+ where
1018+
1019+ {-# INLINE_LATE stepOuter #-}
1020+ -- Buffer is empty, get the first element from the stream, initialize the
1021+ -- fold and then go to stream processing loop.
1022+ stepOuter gst (ParseChunksInit [] st) = do
1023+ r <- step (adaptState gst) st
1024+ case r of
1025+ Yield x s -> initial >>= return . Skip . ParseChunksBuf [x] s []
1026+ Skip s -> return $ Skip $ ParseChunksInit [] s
1027+ Stop -> return Stop
1028+
1029+ -- Buffer is not empty, go to buffered processing loop
1030+ stepOuter _ (ParseChunksInit src st) = do
1031+ initial >>= return . Skip . ParseChunksBuf src st []
1032+
1033+ -- XXX we just discard any leftover input at the end
1034+ stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1035+
1036+ -- Buffer is empty, process elements from the stream
1037+ stepOuter gst (ParseChunksStream st buf pst) = do
1038+ r <- step (adaptState gst) st
1039+ case r of
1040+ Yield x s -> do
1041+ pRes <- pstep pst x
1042+ case pRes of
1043+ PR.Partial 0 pst1 ->
1044+ return $ Skip $ ParseChunksStream s [] pst1
1045+ PR.Partial n pst1 -> do
1046+ assert (n <= length (x:buf)) (return ())
1047+ let src0 = Prelude.take n (x:buf)
1048+ src = Prelude.reverse src0
1049+ return $ Skip $ ParseChunksBuf src s [] pst1
1050+ PR.Continue 0 pst1 ->
1051+ return $ Skip $ ParseChunksStream s (x:buf) pst1
1052+ PR.Continue n pst1 -> do
1053+ assert (n <= length (x:buf)) (return ())
1054+ let (src0, buf1) = splitAt n (x:buf)
1055+ src = Prelude.reverse src0
1056+ return $ Skip $ ParseChunksBuf src s buf1 pst1
1057+ PR.Done 0 b -> do
1058+ return $ Skip $
1059+ ParseChunksYield b (ParseChunksInit [] s)
1060+ PR.Done n b -> do
1061+ assert (n <= length (x:buf)) (return ())
1062+ let src = Prelude.reverse (Prelude.take n (x:buf))
1063+ return $ Skip $
1064+ ParseChunksYield b (ParseChunksInit src s)
1065+ PR.Error err -> throwM $ ParseError err
1066+ Skip s -> return $ Skip $ ParseChunksStream s buf pst
1067+ Stop -> do
1068+ b <- extract pst
1069+ let src = Prelude.reverse buf
1070+ return $ Skip $
1071+ ParseChunksYield b (ParseChunksInitLeftOver src)
1072+
1073+ -- go back to stream processing mode
1074+ stepOuter _ (ParseChunksBuf [] s buf pst) =
1075+ return $ Skip $ ParseChunksStream s buf pst
1076+
1077+ -- buffered processing loop
1078+ stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1079+ pRes <- pstep pst x
1080+ case pRes of
1081+ PR.Partial 0 pst1 ->
1082+ return $ Skip $ ParseChunksBuf xs s [] pst1
1083+ PR.Partial n pst1 -> do
1084+ assert (n <= length (x:buf)) (return ())
1085+ let src0 = Prelude.take n (x:buf)
1086+ src = Prelude.reverse src0 ++ xs
1087+ return $ Skip $ ParseChunksBuf src s [] pst1
1088+ PR.Continue 0 pst1 ->
1089+ return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1090+ PR.Continue n pst1 -> do
1091+ assert (n <= length (x:buf)) (return ())
1092+ let (src0, buf1) = splitAt n (x:buf)
1093+ src = Prelude.reverse src0 ++ xs
1094+ return $ Skip $ ParseChunksBuf src s buf1 pst1
1095+ PR.Done 0 b ->
1096+ return $ Skip $ ParseChunksYield b (ParseChunksInit xs s)
1097+ PR.Done n b -> do
1098+ assert (n <= length (x:buf)) (return ())
1099+ let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1100+ return $ Skip $ ParseChunksYield b (ParseChunksInit src s)
1101+ PR.Error err -> throwM $ ParseError err
1102+
1103+ stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1104+
1105+{-# ANN type ConcatParseState Fuse #-}
1106+data ConcatParseState x inpBuf st p =
1107+ ConcatParseInit inpBuf st p
1108+ | ConcatParseInitLeftOver inpBuf
1109+ | ConcatParseStream st inpBuf p
1110+ | ConcatParseBuf inpBuf st inpBuf p
1111+ | ConcatParseYield x (ConcatParseState x inpBuf st p)
1112+
1113+{-# INLINE_NORMAL parseIterate #-}
1114+parseIterate
1115+ :: MonadThrow m
1116+ => (b -> PRD.Parser m a b)
1117+ -> b
1118+ -> Stream m a
1119+ -> Stream m b
1120+parseIterate func seed (Stream step state) =
1121+ Stream stepOuter (ConcatParseInit [] state (func seed))
1122+
1123+ where
1124+
1125+ {-# INLINE_LATE stepOuter #-}
1126+ -- Buffer is empty, go to stream processing loop
1127+ stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1128+ initial >>= \r -> return $ Skip $ ConcatParseStream st []
1129+ (PRD.Parser pstep (return r) extract)
1130+
1131+ -- Buffer is not empty, go to buffered processing loop
1132+ stepOuter _ (ConcatParseInit src st
1133+ (PRD.Parser pstep initial extract)) = do
1134+ initial >>= \r -> return $ Skip $ ConcatParseBuf src st []
1135+ (PRD.Parser pstep (return r) extract)
1136+
1137+ -- XXX we just discard any leftover input at the end
1138+ stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1139+
1140+ -- Buffer is empty process elements from the stream
1141+ stepOuter gst (ConcatParseStream st buf
1142+ p@(PRD.Parser pstep initial extract)) = do
1143+ r <- step (adaptState gst) st
1144+ case r of
1145+ Yield x s -> do
1146+ pst <- initial
1147+ pRes <- pstep pst x
1148+ case pRes of
1149+ PR.Partial 0 pst1 ->
1150+ return $ Skip $ ConcatParseStream s []
1151+ (PRD.Parser pstep (return pst1) extract)
1152+ PR.Partial n pst1 -> do
1153+ assert (n <= length (x:buf)) (return ())
1154+ let src0 = Prelude.take n (x:buf)
1155+ src = Prelude.reverse src0
1156+ return $ Skip $ ConcatParseBuf src s []
1157+ (PRD.Parser pstep (return pst1) extract)
1158+ -- PR.Continue 0 pst1 ->
1159+ -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1160+ PR.Continue n pst1 -> do
1161+ assert (n <= length (x:buf)) (return ())
1162+ let (src0, buf1) = splitAt n (x:buf)
1163+ src = Prelude.reverse src0
1164+ return $ Skip $ ConcatParseBuf src s buf1
1165+ (PRD.Parser pstep (return pst1) extract)
1166+ -- XXX Specialize for Stop 0 common case?
1167+ PR.Done n b -> do
1168+ assert (n <= length (x:buf)) (return ())
1169+ let src = Prelude.reverse (Prelude.take n (x:buf))
1170+ return $ Skip $
1171+ ConcatParseYield b (ConcatParseInit src s (func b))
1172+ PR.Error err -> throwM $ ParseError err
1173+ Skip s -> return $ Skip $ ConcatParseStream s buf p
1174+ Stop -> do
1175+ pst <- initial
1176+ b <- extract pst
1177+ let src = Prelude.reverse buf
1178+ return $ Skip $
1179+ ConcatParseYield b (ConcatParseInitLeftOver src)
1180+
1181+ -- go back to stream processing mode
1182+ stepOuter _ (ConcatParseBuf [] s buf p) =
1183+ return $ Skip $ ConcatParseStream s buf p
1184+
1185+ -- buffered processing loop
1186+ stepOuter _ (ConcatParseBuf (x:xs) s buf
1187+ (PRD.Parser pstep initial extract)) = do
1188+ pst <- initial
1189+ pRes <- pstep pst x
1190+ case pRes of
1191+ PR.Partial 0 pst1 ->
1192+ return $ Skip $ ConcatParseBuf xs s []
1193+ (PRD.Parser pstep (return pst1) extract)
1194+ PR.Partial n pst1 -> do
1195+ assert (n <= length (x:buf)) (return ())
1196+ let src0 = Prelude.take n (x:buf)
1197+ src = Prelude.reverse src0 ++ xs
1198+ return $ Skip $ ConcatParseBuf src s []
1199+ (PRD.Parser pstep (return pst1) extract)
1200+ -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1201+ PR.Continue n pst1 -> do
1202+ assert (n <= length (x:buf)) (return ())
1203+ let (src0, buf1) = splitAt n (x:buf)
1204+ src = Prelude.reverse src0 ++ xs
1205+ return $ Skip $ ConcatParseBuf src s buf1
1206+ (PRD.Parser pstep (return pst1) extract)
1207+ -- XXX Specialize for Stop 0 common case?
1208+ PR.Done n b -> do
1209+ assert (n <= length (x:buf)) (return ())
1210+ let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1211+ return $ Skip $ ConcatParseYield b
1212+ (ConcatParseInit src s (func b))
1213+ PR.Error err -> throwM $ ParseError err
1214+
1215+ stepOuter _ (ConcatParseYield a next) = return $ Yield a next
1216+
1217+------------------------------------------------------------------------------
1218+-- Grouping
1219+------------------------------------------------------------------------------
1220+
1221+{-# INLINE_NORMAL groupsBy #-}
1222+groupsBy :: Monad m
1223+ => (a -> a -> Bool)
1224+ -> Fold m a b
1225+ -> Stream m a
1226+ -> Stream m b
1227+groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
1228+
1229+ where
1230+
1231+ {-# INLINE_LATE stepOuter #-}
1232+ stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1233+ res <- step (adaptState gst) st
1234+ case res of
1235+ Yield x s -> do
1236+ fs <- initial
1237+ r <- fstep fs x
1238+ case r of
1239+ FL.Partial fs1 -> go SPEC x s fs1
1240+ FL.Done b -> return $ Yield b (Just s, Just x)
1241+ Skip s -> return $ Skip (Just s, Nothing)
1242+ Stop -> return Stop
1243+
1244+ where
1245+
1246+ go !_ prev stt !acc = do
1247+ res <- step (adaptState gst) stt
1248+ case res of
1249+ Yield x s -> do
1250+ if cmp x prev
1251+ then do
1252+ r <- fstep acc x
1253+ case r of
1254+ FL.Partial fs1 -> go SPEC prev s fs1
1255+ FL.Done b -> return $ Yield b (Just s, Just x)
1256+ else done acc >>= \r -> return $ Yield r (Just s, Just x)
1257+ Skip s -> go SPEC prev s acc
1258+ Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1259+ stepOuter (Fold fstep initial done) gst (Just st, Just prev) = do
1260+ fs <- initial
1261+ r <- fstep fs prev
1262+ case r of
1263+ FL.Partial fs1 -> go SPEC st fs1
1264+ FL.Done b -> return $ Yield b (Just st, Nothing)
1265+
1266+ where
1267+
1268+ -- XXX code duplicated from the previous equation
1269+ go !_ stt !acc = do
1270+ res <- step (adaptState gst) stt
1271+ case res of
1272+ Yield x s -> do
1273+ if cmp x prev
1274+ then do
1275+ r <- fstep acc x
1276+ case r of
1277+ FL.Partial fs1 -> go SPEC s fs1
1278+ FL.Done b -> return $ Yield b (Just s, Just x)
1279+ else done acc >>= \r -> return $ Yield r (Just s, Just x)
1280+ Skip s -> go SPEC s acc
1281+ Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1282+ stepOuter _ _ (Nothing, _) = return Stop
1283+
1284+{-# INLINE_NORMAL groupsRollingBy #-}
1285+groupsRollingBy :: Monad m
1286+ => (a -> a -> Bool)
1287+ -> Fold m a b
1288+ -> Stream m a
1289+ -> Stream m b
1290+groupsRollingBy cmp f (Stream step state) =
1291+ Stream (stepOuter f) (Just state, Nothing)
1292+
1293+ where
1294+
1295+ {-# INLINE_LATE stepOuter #-}
1296+ stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1297+ res <- step (adaptState gst) st
1298+ case res of
1299+ Yield x s -> do
1300+ fs <- initial
1301+ r <- fstep fs x
1302+ case r of
1303+ FL.Partial fs1 -> go SPEC x s fs1
1304+ FL.Done b -> return $ Yield b (Just s, Just x)
1305+ Skip s -> return $ Skip $ (Just s, Nothing)
1306+ Stop -> return Stop
1307+
1308+ where
1309+
1310+ go !_ prev stt !acc = do
1311+ res <- step (adaptState gst) stt
1312+ case res of
1313+ Yield x s -> do
1314+ if cmp prev x
1315+ then do
1316+ r <- fstep acc x
1317+ case r of
1318+ FL.Partial fs1 -> go SPEC x s fs1
1319+ FL.Done b -> return $ Yield b (Just s, Just x)
1320+ else done acc >>= \r -> return $ Yield r (Just s, Just x)
1321+ Skip s -> go SPEC prev s acc
1322+ Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1323+ stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1324+ fs <- initial
1325+ r <- fstep fs prev'
1326+ case r of
1327+ FL.Partial fs1 -> go SPEC prev' st fs1
1328+ FL.Done b -> return $ Yield b (Just st, Nothing)
1329+
1330+ where
1331+
1332+ go !_ prevv stt !acc = do
1333+ res <- step (adaptState gst) stt
1334+ case res of
1335+ Yield x s -> do
1336+ if cmp prevv x
1337+ then do
1338+ r <- fstep acc x
1339+ case r of
1340+ FL.Partial fs1 -> go SPEC x s fs1
1341+ FL.Done b -> return $ Yield b (Just s, Just x)
1342+ else done acc >>= \r -> return $ Yield r (Just s, Just x)
1343+ Skip s -> go SPEC prevv s acc
1344+ Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1345+ stepOuter _ _ (Nothing, _) = return Stop
1346+
1347+------------------------------------------------------------------------------
1348+-- Splitting - by a predicate
1349+------------------------------------------------------------------------------
1350+
1351+data WordsByState s = WordsByJust s | WordsByNothing
1352+
1353+{-# INLINE_NORMAL wordsBy #-}
1354+wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1355+wordsBy predicate f (Stream step state) =
1356+ Stream (stepOuter f) (WordsByJust state)
1357+
1358+ where
1359+
1360+ {-# INLINE_LATE stepOuter #-}
1361+ stepOuter (Fold fstep initial done) gst (WordsByJust st) = do
1362+ res <- step (adaptState gst) st
1363+ case res of
1364+ Yield x s -> do
1365+ if predicate x
1366+ then return $ Skip (WordsByJust s)
1367+ else do
1368+ fs <- initial
1369+ r <- fstep fs x
1370+ case r of
1371+ FL.Partial fs1 -> go SPEC s fs1
1372+ FL.Done b -> return $ Yield b (WordsByJust s)
1373+
1374+ Skip s -> return $ Skip $ WordsByJust s
1375+ Stop -> return Stop
1376+
1377+ where
1378+
1379+ go !_ stt !acc = do
1380+ res <- step (adaptState gst) stt
1381+ case res of
1382+ Yield x s -> do
1383+ if predicate x
1384+ then done acc >>= \r -> return $ Yield r (WordsByJust s)
1385+ else do
1386+ r <- fstep acc x
1387+ case r of
1388+ FL.Partial fs1 -> go SPEC s fs1
1389+ FL.Done b -> return $ Yield b (WordsByJust s)
1390+ Skip s -> go SPEC s acc
1391+ Stop -> done acc >>= \r -> return $ Yield r WordsByNothing
1392+
1393+ stepOuter _ _ WordsByNothing = return Stop
1394+
1395+------------------------------------------------------------------------------
1396+-- Splitting on a sequence
1397+------------------------------------------------------------------------------
1398+
1399+-- String search algorithms:
1400+-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1401+
1402+{-
1403+-- TODO can we unify the splitting operations using a splitting configuration
1404+-- like in the split package.
1405+--
1406+data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1407+data SplitOptions = SplitOptions
1408+ { style :: SplitStyle
1409+ , withSep :: Bool -- ^ keep the separators in output
1410+ -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1411+ -- , trimHead :: Bool -- ^ drop blank at head
1412+ -- , trimTail :: Bool -- ^ drop blank at tail
1413+ }
1414+-}
1415+
1416+{-# ANN type SplitOnSeqState Fuse #-}
1417+data SplitOnSeqState rb rh ck w fs s b x =
1418+ SplitOnSeqInit
1419+ | SplitOnSeqYield b (SplitOnSeqState rb rh ck w fs s b x)
1420+ | SplitOnSeqDone
1421+
1422+ | SplitOnSeqEmpty s
1423+
1424+ | SplitOnSeqSingle !fs s x
1425+
1426+ | SplitOnSeqWordInit s
1427+ | SplitOnSeqWordLoop !w s !fs
1428+ | SplitOnSeqWordDone Int !fs !w
1429+
1430+ | SplitOnSeqKRInit Int s rb !rh
1431+ | SplitOnSeqKRLoop fs s rb !rh !ck
1432+ | SplitOnSeqKRCheck fs s rb !rh
1433+ | SplitOnSeqKRDone Int !fs rb !rh
1434+
1435+{-# INLINE_NORMAL splitOnSeq #-}
1436+splitOnSeq
1437+ :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1438+ => Array a
1439+ -> Fold m a b
1440+ -> Stream m a
1441+ -> Stream m b
1442+splitOnSeq patArr (Fold fstep initial done) (Stream step state) =
1443+ Stream stepOuter SplitOnSeqInit
1444+
1445+ where
1446+
1447+ patLen = A.length patArr
1448+ maxIndex = patLen - 1
1449+ elemBits = sizeOf (undefined :: a) * 8
1450+
1451+ -- For word pattern case
1452+ wordMask :: Word
1453+ wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1454+
1455+ elemMask :: Word
1456+ elemMask = (1 `shiftL` elemBits) - 1
1457+
1458+ wordPat :: Word
1459+ wordPat = wordMask .&. A.foldl' addToWord 0 patArr
1460+
1461+ addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1462+
1463+ -- For Rabin-Karp search
1464+ k = 2891336453 :: Word32
1465+ coeff = k ^ patLen
1466+
1467+ addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1468+
1469+ deltaCksum cksum old new =
1470+ addCksum cksum new - coeff * fromIntegral (fromEnum old)
1471+
1472+ -- XXX shall we use a random starting hash or 1 instead of 0?
1473+ patHash = A.foldl' addCksum 0 patArr
1474+
1475+ skip = return . Skip
1476+
1477+ {-# INLINE_LATE stepOuter #-}
1478+ stepOuter _ SplitOnSeqInit =
1479+ if patLen == 0
1480+ then return $ Skip $ SplitOnSeqEmpty state
1481+ else if patLen == 1
1482+ then do
1483+ acc <- initial
1484+ pat <- liftIO $ A.unsafeIndexIO patArr 0
1485+ return $ Skip $ SplitOnSeqSingle acc state pat
1486+ else if sizeOf (undefined :: a) * patLen
1487+ <= sizeOf (undefined :: Word)
1488+ then return $ Skip $ SplitOnSeqWordInit state
1489+ else do
1490+ (rb, rhead) <- liftIO $ RB.new patLen
1491+ skip $ SplitOnSeqKRInit 0 state rb rhead
1492+
1493+ stepOuter _ (SplitOnSeqYield x next) = return $ Yield x next
1494+
1495+ ---------------------------
1496+ -- Empty pattern
1497+ ---------------------------
1498+
1499+ stepOuter gst (SplitOnSeqEmpty st) = do
1500+ res <- step (adaptState gst) st
1501+ case res of
1502+ Yield x s -> do
1503+ fs <- initial
1504+ r <- fstep fs x
1505+ case r of
1506+ FL.Partial fs1 -> do
1507+ b <- done fs1
1508+ skip $ SplitOnSeqYield b (SplitOnSeqEmpty s)
1509+ FL.Done b -> skip $ SplitOnSeqYield b (SplitOnSeqEmpty s)
1510+
1511+ Skip s -> return $ Skip (SplitOnSeqEmpty s)
1512+ Stop -> return Stop
1513+
1514+ -----------------
1515+ -- Done
1516+ -----------------
1517+
1518+ stepOuter _ SplitOnSeqDone = return Stop
1519+
1520+ -----------------
1521+ -- Single Pattern
1522+ -----------------
1523+
1524+ stepOuter gst (SplitOnSeqSingle fs st pat) = do
1525+ res <- step (adaptState gst) st
1526+ case res of
1527+ Yield x s -> do
1528+ if pat == x
1529+ then do
1530+ r <- done fs
1531+ fs1 <- initial
1532+ return $ Skip $ SplitOnSeqYield r (SplitOnSeqSingle fs1 s pat)
1533+ else do
1534+ r <- fstep fs x
1535+ case r of
1536+ FL.Partial fs1 -> skip $ SplitOnSeqSingle fs1 s pat
1537+ FL.Done b -> do
1538+ fs1 <- initial
1539+ skip $ SplitOnSeqYield b (SplitOnSeqSingle fs1 s pat)
1540+ Skip s -> return $ Skip $ SplitOnSeqSingle fs s pat
1541+ Stop -> do
1542+ r <- done fs
1543+ return $ Skip $ SplitOnSeqYield r SplitOnSeqDone
1544+
1545+ ---------------------------
1546+ -- Short Pattern - Shift Or
1547+ ---------------------------
1548+
1549+ stepOuter _ (SplitOnSeqWordDone 0 fs _) = do
1550+ r <- done fs
1551+ skip $ SplitOnSeqYield r SplitOnSeqDone
1552+ stepOuter _ (SplitOnSeqWordDone n fs wrd) = do
1553+ let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1554+ r <- fstep fs (toEnum $ fromIntegral old)
1555+ case r of
1556+ FL.Partial fs1 -> skip $ SplitOnSeqWordDone (n - 1) fs1 wrd
1557+ FL.Done b -> do
1558+ fs1 <- initial
1559+ let next = SplitOnSeqWordDone (n - 1) fs1 wrd
1560+ skip $ SplitOnSeqYield b next
1561+
1562+ stepOuter gst (SplitOnSeqWordInit st0) =
1563+ go SPEC 0 0 st0
1564+
1565+ where
1566+
1567+ {-# INLINE go #-}
1568+ go !_ !idx !wrd !st = do
1569+ res <- step (adaptState gst) st
1570+ case res of
1571+ Yield x s -> do
1572+ let wrd1 = addToWord wrd x
1573+ if idx == maxIndex
1574+ then do
1575+ fs <- initial
1576+ if wrd1 .&. wordMask == wordPat
1577+ then do
1578+ r <- done fs
1579+ let next = SplitOnSeqWordInit s
1580+ skip $ SplitOnSeqYield r next
1581+ else skip $ SplitOnSeqWordLoop wrd1 s fs
1582+ else go SPEC (idx + 1) wrd1 s
1583+ Skip s -> go SPEC idx wrd s
1584+ Stop -> do
1585+ fs <- initial
1586+ if idx /= 0
1587+ then skip $ SplitOnSeqWordDone idx fs wrd
1588+ else do
1589+ r <- done fs
1590+ skip $ SplitOnSeqYield r SplitOnSeqDone
1591+
1592+ stepOuter gst (SplitOnSeqWordLoop wrd0 st0 fs0) =
1593+ go SPEC wrd0 st0 fs0
1594+
1595+ where
1596+
1597+ {-# INLINE go #-}
1598+ go !_ !wrd !st !fs = do
1599+ res <- step (adaptState gst) st
1600+ case res of
1601+ Yield x s -> do
1602+ let wrd1 = addToWord wrd x
1603+ old = (wordMask .&. wrd)
1604+ `shiftR` (elemBits * (patLen - 1))
1605+ r <- fstep fs (toEnum $ fromIntegral old)
1606+ case r of
1607+ FL.Partial fs1 -> do
1608+ if wrd1 .&. wordMask == wordPat
1609+ then do
1610+ b <- done fs1
1611+ let next = SplitOnSeqWordInit s
1612+ skip $ SplitOnSeqYield b next
1613+ else go SPEC wrd1 s fs1
1614+ FL.Done b ->
1615+ let next = SplitOnSeqWordInit s
1616+ in skip $ SplitOnSeqYield b next
1617+ Skip s -> go SPEC wrd s fs
1618+ Stop -> skip $ SplitOnSeqWordDone patLen fs wrd
1619+
1620+ -------------------------------
1621+ -- General Pattern - Karp Rabin
1622+ -------------------------------
1623+
1624+ stepOuter gst (SplitOnSeqKRInit idx st rb rh) = do
1625+ res <- step (adaptState gst) st
1626+ case res of
1627+ Yield x s -> do
1628+ rh1 <- liftIO $ RB.unsafeInsert rb rh x
1629+ if idx == maxIndex
1630+ then do
1631+ let fold = RB.unsafeFoldRing (RB.ringBound rb)
1632+ let !ringHash = fold addCksum 0 rb
1633+ fs <- initial
1634+ if ringHash == patHash
1635+ then skip $ SplitOnSeqKRCheck fs s rb rh1
1636+ else skip $ SplitOnSeqKRLoop fs s rb rh1 ringHash
1637+ else skip $ SplitOnSeqKRInit (idx + 1) s rb rh1
1638+ Skip s -> skip $ SplitOnSeqKRInit idx s rb rh
1639+ Stop -> do
1640+ fs <- initial
1641+ skip $ SplitOnSeqKRDone idx fs rb (RB.startOf rb)
1642+
1643+ -- XXX The recursive "go" is more efficient than the state based recursion
1644+ -- code commented out below. Perhaps its more efficient because of
1645+ -- factoring out "rb" outside the loop.
1646+ --
1647+ stepOuter gst (SplitOnSeqKRLoop fs0 st0 rb rh0 cksum0) =
1648+ go SPEC fs0 st0 rh0 cksum0
1649+
1650+ where
1651+
1652+ go !_ !fs !st !rh !cksum = do
1653+ res <- step (adaptState gst) st
1654+ case res of
1655+ Yield x s -> do
1656+ old <- liftIO $ peek rh
1657+ let cksum1 = deltaCksum cksum old x
1658+ r <- fstep fs old
1659+ case r of
1660+ FL.Partial fs1 -> do
1661+ rh1 <- liftIO (RB.unsafeInsert rb rh x)
1662+ if cksum1 == patHash
1663+ then skip $ SplitOnSeqKRCheck fs1 s rb rh1
1664+ else go SPEC fs1 s rh1 cksum1
1665+ FL.Done b ->
1666+ let next = SplitOnSeqKRInit 0 s rb (RB.startOf rb)
1667+ in skip $ SplitOnSeqYield b next
1668+ Skip s -> go SPEC fs s rh cksum
1669+ Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1670+
1671+ -- XXX The following code is 5 times slower compared to the recursive loop
1672+ -- based code above. Need to investigate why. One possibility is that the
1673+ -- go loop above does not thread around the ring buffer (rb). This code may
1674+ -- be causing the state to bloat and getting allocated on each iteration.
1675+ -- We can check the cmm/asm code to confirm. If so a good GHC solution to
1676+ -- such problem is needed. One way to avoid this could be to use unboxed
1677+ -- mutable state?
1678+ {-
1679+ stepOuter gst (SplitOnSeqKRLoop fs st rb rh cksum) = do
1680+ res <- step (adaptState gst) st
1681+ case res of
1682+ Yield x s -> do
1683+ old <- liftIO $ peek rh
1684+ let cksum1 = deltaCksum cksum old x
1685+ fs1 <- fstep fs old
1686+ if (cksum1 == patHash)
1687+ then do
1688+ r <- done fs1
1689+ skip $ SplitOnSeqYield r $ SplitOnSeqKRInit 0 s rb rh
1690+ else do
1691+ rh1 <- liftIO (RB.unsafeInsert rb rh x)
1692+ skip $ SplitOnSeqKRLoop fs1 s rb rh1 cksum1
1693+ Skip s -> skip $ SplitOnSeqKRLoop fs s rb rh cksum
1694+ Stop -> skip $ SplitOnSeqKRDone patLen fs rb rh
1695+ -}
1696+
1697+ stepOuter _ (SplitOnSeqKRCheck fs st rb rh) = do
1698+ if RB.unsafeEqArray rb rh patArr
1699+ then do
1700+ r <- done fs
1701+ let next = SplitOnSeqKRInit 0 st rb (RB.startOf rb)
1702+ skip $ SplitOnSeqYield r next
1703+ else skip $ SplitOnSeqKRLoop fs st rb rh patHash
1704+ stepOuter _ (SplitOnSeqKRDone 0 fs _ _) = do
1705+ r <- done fs
1706+ skip $ SplitOnSeqYield r SplitOnSeqDone
1707+ stepOuter _ (SplitOnSeqKRDone n fs rb rh) = do
1708+ old <- liftIO $ peek rh
1709+ let rh1 = RB.advance rb rh
1710+ r <- fstep fs old
1711+ case r of
1712+ FL.Partial fs1 -> skip $ SplitOnSeqKRDone (n - 1) fs1 rb rh1
1713+ FL.Done b -> do
1714+ fs1 <- initial
1715+ let next = SplitOnSeqKRDone (n - 1) fs1 rb rh1
1716+ skip $ SplitOnSeqYield b next
1717+
1718+{-# ANN type SplitOnSuffixSeqState Fuse #-}
1719+data SplitOnSuffixSeqState rb rh ck w fs s b x =
1720+ SplitOnSuffixSeqInit
1721+ | SplitOnSuffixSeqYield b (SplitOnSuffixSeqState rb rh ck w fs s b x)
1722+ | SplitOnSuffixSeqDone
1723+
1724+ | SplitOnSuffixSeqEmpty s
1725+
1726+ | SplitOnSuffixSeqSingleInit s x
1727+ | SplitOnSuffixSeqSingle !fs s x
1728+
1729+ | SplitOnSuffixSeqWordInit s
1730+ | SplitOnSuffixSeqWordLoop !w s !fs
1731+ | SplitOnSuffixSeqWordDone Int !fs !w
1732+
1733+ | SplitOnSuffixSeqKRInit Int s rb !rh
1734+ | SplitOnSuffixSeqKRInit1 !fs s rb !rh
1735+ | SplitOnSuffixSeqKRLoop fs s rb !rh !ck
1736+ | SplitOnSuffixSeqKRCheck fs s rb !rh
1737+ | SplitOnSuffixSeqKRDone Int !fs rb !rh
1738+
1739+{-# INLINE_NORMAL splitOnSuffixSeq #-}
1740+splitOnSuffixSeq
1741+ :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1742+ => Bool
1743+ -> Array a
1744+ -> Fold m a b
1745+ -> Stream m a
1746+ -> Stream m b
1747+splitOnSuffixSeq withSep patArr (Fold fstep initial done) (Stream step state) =
1748+ Stream stepOuter SplitOnSuffixSeqInit
1749+
1750+ where
1751+
1752+ patLen = A.length patArr
1753+ maxIndex = patLen - 1
1754+ elemBits = sizeOf (undefined :: a) * 8
1755+
1756+ -- For word pattern case
1757+ wordMask :: Word
1758+ wordMask = (1 `shiftL` (elemBits * patLen)) - 1
1759+
1760+ elemMask :: Word
1761+ elemMask = (1 `shiftL` elemBits) - 1
1762+
1763+ wordPat :: Word
1764+ wordPat = wordMask .&. A.foldl' addToWord 0 patArr
1765+
1766+ addToWord wd a = (wd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1767+
1768+ -- For single element pattern case
1769+ {-# INLINE processYieldSingle #-}
1770+ processYieldSingle pat x s fs =
1771+ if pat == x
1772+ then do
1773+ r <- if withSep then fstep fs x else return $ FL.Partial fs
1774+ case r of
1775+ FL.Partial fs1 -> do
1776+ b <- done fs1
1777+ let next = SplitOnSuffixSeqSingleInit s pat
1778+ skip $ SplitOnSuffixSeqYield b next
1779+ FL.Done b ->
1780+ let next = SplitOnSuffixSeqSingleInit s pat
1781+ in skip $ SplitOnSuffixSeqYield b next
1782+ else do
1783+ r <- fstep fs x
1784+ case r of
1785+ FL.Partial fs1 -> skip $ SplitOnSuffixSeqSingle fs1 s pat
1786+ FL.Done b ->
1787+ let next = SplitOnSuffixSeqSingleInit s pat
1788+ in skip $ SplitOnSuffixSeqYield b next
1789+
1790+ -- For Rabin-Karp search
1791+ k = 2891336453 :: Word32
1792+ coeff = k ^ patLen
1793+
1794+ addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1795+
1796+ deltaCksum cksum old new =
1797+ addCksum cksum new - coeff * fromIntegral (fromEnum old)
1798+
1799+ -- XXX shall we use a random starting hash or 1 instead of 0?
1800+ patHash = A.foldl' addCksum 0 patArr
1801+
1802+ skip = return . Skip
1803+
1804+ {-# INLINE_LATE stepOuter #-}
1805+ stepOuter _ SplitOnSuffixSeqInit =
1806+ if patLen == 0
1807+ then skip $ SplitOnSuffixSeqEmpty state
1808+ else if patLen == 1
1809+ then do
1810+ pat <- liftIO $ A.unsafeIndexIO patArr 0
1811+ skip $ SplitOnSuffixSeqSingleInit state pat
1812+ else if sizeOf (undefined :: a) * patLen
1813+ <= sizeOf (undefined :: Word)
1814+ then skip $ SplitOnSuffixSeqWordInit state
1815+ else do
1816+ (rb, rhead) <- liftIO $ RB.new patLen
1817+ skip $ SplitOnSuffixSeqKRInit 0 state rb rhead
1818+
1819+ stepOuter _ (SplitOnSuffixSeqYield x next) = return $ Yield x next
1820+
1821+ ---------------------------
1822+ -- Empty pattern
1823+ ---------------------------
1824+
1825+ stepOuter gst (SplitOnSuffixSeqEmpty st) = do
1826+ res <- step (adaptState gst) st
1827+ case res of
1828+ Yield x s -> do
1829+ acc <- initial
1830+ r <- fstep acc x
1831+ case r of
1832+ FL.Partial fs -> do
1833+ b <- done fs
1834+ skip $ SplitOnSuffixSeqYield b (SplitOnSuffixSeqEmpty s)
1835+ FL.Done b ->
1836+ skip $ SplitOnSuffixSeqYield b (SplitOnSuffixSeqEmpty s)
1837+ Skip s -> skip (SplitOnSuffixSeqEmpty s)
1838+ Stop -> return Stop
1839+
1840+ -----------------
1841+ -- Done
1842+ -----------------
1843+
1844+ stepOuter _ SplitOnSuffixSeqDone = return Stop
1845+
1846+ -----------------
1847+ -- Single Pattern
1848+ -----------------
1849+
1850+ stepOuter gst (SplitOnSuffixSeqSingleInit st pat) = do
1851+ res <- step (adaptState gst) st
1852+ case res of
1853+ Yield x s -> initial >>= processYieldSingle pat x s
1854+ Skip s -> skip $ SplitOnSuffixSeqSingleInit s pat
1855+ Stop -> return Stop
1856+
1857+ stepOuter gst (SplitOnSuffixSeqSingle fs st pat) = do
1858+ res <- step (adaptState gst) st
1859+ case res of
1860+ Yield x s -> processYieldSingle pat x s fs
1861+ Skip s -> skip $ SplitOnSuffixSeqSingle fs s pat
1862+ Stop -> do
1863+ r <- done fs
1864+ skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
1865+
1866+ ---------------------------
1867+ -- Short Pattern - Shift Or
1868+ ---------------------------
1869+
1870+ stepOuter _ (SplitOnSuffixSeqWordDone 0 fs _) = do
1871+ r <- done fs
1872+ skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
1873+ stepOuter _ (SplitOnSuffixSeqWordDone n fs wrd) = do
1874+ let old = elemMask .&. (wrd `shiftR` (elemBits * (n - 1)))
1875+ r <- fstep fs (toEnum $ fromIntegral old)
1876+ case r of
1877+ FL.Partial fs1 -> skip $ SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
1878+ FL.Done b -> do
1879+ fs1 <- initial
1880+ let next = SplitOnSuffixSeqWordDone (n - 1) fs1 wrd
1881+ skip $ SplitOnSuffixSeqYield b next
1882+
1883+ stepOuter gst (SplitOnSuffixSeqWordInit st0) = do
1884+ res <- step (adaptState gst) st0
1885+ case res of
1886+ Yield x s -> do
1887+ fs <- initial
1888+ let wrd = addToWord 0 x
1889+ r <- if withSep then fstep fs x else return $ FL.Partial fs
1890+ case r of
1891+ FL.Partial fs1 -> go SPEC 1 wrd s fs1
1892+ FL.Done b -> do
1893+ let next = SplitOnSuffixSeqWordInit s
1894+ in skip $ SplitOnSuffixSeqYield b next
1895+ Skip s -> skip (SplitOnSuffixSeqWordInit s)
1896+ Stop -> return Stop
1897+
1898+ where
1899+
1900+ {-# INLINE go #-}
1901+ go !_ !idx !wrd !st !fs = do
1902+ res <- step (adaptState gst) st
1903+ case res of
1904+ Yield x s -> do
1905+ let wrd1 = addToWord wrd x
1906+ r <- if withSep then fstep fs x else return $ FL.Partial fs
1907+ case r of
1908+ FL.Partial fs1 ->
1909+ if idx /= maxIndex
1910+ then go SPEC (idx + 1) wrd1 s fs1
1911+ else if wrd1 .&. wordMask /= wordPat
1912+ then skip $ SplitOnSuffixSeqWordLoop wrd1 s fs1
1913+ else do
1914+ b <- done fs
1915+ let next = SplitOnSuffixSeqWordInit s
1916+ skip $ SplitOnSuffixSeqYield b next
1917+ FL.Done b ->
1918+ let next = SplitOnSuffixSeqWordInit s
1919+ in skip $ SplitOnSuffixSeqYield b next
1920+ Skip s -> go SPEC idx wrd s fs
1921+ Stop -> skip $ SplitOnSuffixSeqWordDone idx fs wrd
1922+
1923+ stepOuter gst (SplitOnSuffixSeqWordLoop wrd0 st0 fs0) =
1924+ go SPEC wrd0 st0 fs0
1925+
1926+ where
1927+
1928+ {-# INLINE go #-}
1929+ go !_ !wrd !st !fs = do
1930+ res <- step (adaptState gst) st
1931+ case res of
1932+ Yield x s -> do
1933+ let wrd1 = addToWord wrd x
1934+ old = (wordMask .&. wrd)
1935+ `shiftR` (elemBits * (patLen - 1))
1936+ r <-
1937+ if withSep
1938+ then fstep fs x
1939+ else fstep fs (toEnum $ fromIntegral old)
1940+ case r of
1941+ FL.Partial fs1 ->
1942+ if wrd1 .&. wordMask == wordPat
1943+ then do
1944+ b <- done fs1
1945+ let next = SplitOnSuffixSeqWordInit s
1946+ skip $ SplitOnSuffixSeqYield b next
1947+ else go SPEC wrd1 s fs1
1948+ FL.Done b ->
1949+ let next = SplitOnSuffixSeqWordInit s
1950+ in skip $ SplitOnSuffixSeqYield b next
1951+ Skip s -> go SPEC wrd s fs
1952+ Stop ->
1953+ if wrd .&. wordMask == wordPat
1954+ then return Stop
1955+ else if withSep
1956+ then do
1957+ r <- done fs
1958+ skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
1959+ else skip $ SplitOnSuffixSeqWordDone patLen fs wrd
1960+
1961+ -------------------------------
1962+ -- General Pattern - Karp Rabin
1963+ -------------------------------
1964+
1965+ stepOuter gst (SplitOnSuffixSeqKRInit idx0 st0 rb rh0) = do
1966+ res <- step (adaptState gst) st0
1967+ case res of
1968+ Yield x s -> do
1969+ rh1 <- liftIO $ RB.unsafeInsert rb rh0 x
1970+ fs <- initial
1971+ r <- if withSep then fstep fs x else return $ FL.Partial fs
1972+ case r of
1973+ FL.Partial fs1 ->
1974+ skip $ SplitOnSuffixSeqKRInit1 fs1 s rb rh1
1975+ FL.Done b ->
1976+ let next = SplitOnSuffixSeqKRInit 0 s rb (RB.startOf rb)
1977+ in skip $ SplitOnSuffixSeqYield b next
1978+ Skip s -> skip $ SplitOnSuffixSeqKRInit idx0 s rb rh0
1979+ Stop -> return Stop
1980+
1981+ stepOuter gst (SplitOnSuffixSeqKRInit1 fs0 st0 rb rh0) = do
1982+ go SPEC 1 rh0 st0 fs0
1983+
1984+ where
1985+
1986+ go !_ !idx !rh st !fs = do
1987+ res <- step (adaptState gst) st
1988+ case res of
1989+ Yield x s -> do
1990+ rh1 <- liftIO (RB.unsafeInsert rb rh x)
1991+ r <- if withSep then fstep fs x else return $ FL.Partial fs
1992+ case r of
1993+ FL.Partial fs1 ->
1994+ if idx /= maxIndex
1995+ then go SPEC (idx + 1) rh1 s fs1
1996+ else skip $
1997+ let fold = RB.unsafeFoldRing (RB.ringBound rb)
1998+ !ringHash = fold addCksum 0 rb
1999+ in if ringHash == patHash
2000+ then SplitOnSuffixSeqKRCheck fs1 s rb rh1
2001+ else SplitOnSuffixSeqKRLoop
2002+ fs1 s rb rh1 ringHash
2003+ FL.Done b ->
2004+ let next = SplitOnSuffixSeqKRInit
2005+ 0 st rb (RB.startOf rb)
2006+ in skip $ SplitOnSuffixSeqYield b next
2007+ Skip s -> go SPEC idx rh s fs
2008+ Stop -> do
2009+ -- do not issue a blank segment when we end at pattern
2010+ if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
2011+ then return Stop
2012+ else if withSep
2013+ then do
2014+ r <- done fs
2015+ skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2016+ else skip $ SplitOnSuffixSeqKRDone idx fs rb (RB.startOf rb)
2017+
2018+ stepOuter gst (SplitOnSuffixSeqKRLoop fs0 st0 rb rh0 cksum0) =
2019+ go SPEC fs0 st0 rh0 cksum0
2020+
2021+ where
2022+
2023+ go !_ !fs !st !rh !cksum = do
2024+ res <- step (adaptState gst) st
2025+ case res of
2026+ Yield x s -> do
2027+ old <- liftIO $ peek rh
2028+ rh1 <- liftIO (RB.unsafeInsert rb rh x)
2029+ let cksum1 = deltaCksum cksum old x
2030+ r <- if withSep then fstep fs x else fstep fs old
2031+ case r of
2032+ FL.Partial fs1 ->
2033+ if (cksum1 /= patHash)
2034+ then go SPEC fs1 s rh1 cksum1
2035+ else skip $ SplitOnSuffixSeqKRCheck fs1 s rb rh1
2036+ FL.Done b ->
2037+ let next = SplitOnSuffixSeqKRInit
2038+ 0 st rb (RB.startOf rb)
2039+ in skip $ SplitOnSuffixSeqYield b next
2040+ Skip s -> go SPEC fs s rh cksum
2041+ Stop ->
2042+ if RB.unsafeEqArray rb rh patArr
2043+ then return Stop
2044+ else if withSep
2045+ then do
2046+ r <- done fs
2047+ skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2048+ else skip $ SplitOnSuffixSeqKRDone patLen fs rb rh
2049+
2050+ stepOuter _ (SplitOnSuffixSeqKRCheck fs st rb rh) = do
2051+ if RB.unsafeEqArray rb rh patArr
2052+ then do
2053+ r <- done fs
2054+ let next = SplitOnSuffixSeqKRInit 0 st rb (RB.startOf rb)
2055+ skip $ SplitOnSuffixSeqYield r next
2056+ else skip $ SplitOnSuffixSeqKRLoop fs st rb rh patHash
2057+
2058+ stepOuter _ (SplitOnSuffixSeqKRDone 0 fs _ _) = do
2059+ r <- done fs
2060+ skip $ SplitOnSuffixSeqYield r SplitOnSuffixSeqDone
2061+ stepOuter _ (SplitOnSuffixSeqKRDone n fs rb rh) = do
2062+ old <- liftIO $ peek rh
2063+ let rh1 = RB.advance rb rh
2064+ r <- fstep fs old
2065+ case r of
2066+ FL.Partial fs1 -> skip $ SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2067+ FL.Done b -> do
2068+ fs1 <- initial
2069+ let next = SplitOnSuffixSeqKRDone (n - 1) fs1 rb rh1
2070+ skip $ SplitOnSuffixSeqYield b next
2071+
2072+------------------------------------------------------------------------------
2073+-- Nested Container Transformation
2074+------------------------------------------------------------------------------
2075+
2076+{-# ANN type SplitState Fuse #-}
2077+data SplitState s arr
2078+ = SplitInitial s
2079+ | SplitBuffering s arr
2080+ | SplitSplitting s arr
2081+ | SplitYielding arr (SplitState s arr)
2082+ | SplitFinishing
2083+
2084+-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
2085+-- split using a splitBy like combinator. The Fold would consume upto the
2086+-- separator and return any leftover which can then be fed to the next fold.
2087+--
2088+-- We can revisit this once we have partial folds/parsers.
2089+--
2090+-- | Performs infix separator style splitting.
2091+{-# INLINE_NORMAL splitInnerBy #-}
2092+splitInnerBy
2093+ :: Monad m
2094+ => (f a -> m (f a, Maybe (f a))) -- splitter
2095+ -> (f a -> f a -> m (f a)) -- joiner
2096+ -> Stream m (f a)
2097+ -> Stream m (f a)
2098+splitInnerBy splitter joiner (Stream step1 state1) =
2099+ (Stream step (SplitInitial state1))
2100+
2101+ where
2102+
2103+ {-# INLINE_LATE step #-}
2104+ step gst (SplitInitial st) = do
2105+ r <- step1 gst st
2106+ case r of
2107+ Yield x s -> do
2108+ (x1, mx2) <- splitter x
2109+ return $ case mx2 of
2110+ Nothing -> Skip (SplitBuffering s x1)
2111+ Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2112+ Skip s -> return $ Skip (SplitInitial s)
2113+ Stop -> return $ Stop
2114+
2115+ step gst (SplitBuffering st buf) = do
2116+ r <- step1 gst st
2117+ case r of
2118+ Yield x s -> do
2119+ (x1, mx2) <- splitter x
2120+ buf' <- joiner buf x1
2121+ return $ case mx2 of
2122+ Nothing -> Skip (SplitBuffering s buf')
2123+ Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2124+ Skip s -> return $ Skip (SplitBuffering s buf)
2125+ Stop -> return $ Skip (SplitYielding buf SplitFinishing)
2126+
2127+ step _ (SplitSplitting st buf) = do
2128+ (x1, mx2) <- splitter buf
2129+ return $ case mx2 of
2130+ Nothing -> Skip $ SplitBuffering st x1
2131+ Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2132+
2133+ step _ (SplitYielding x next) = return $ Yield x next
2134+ step _ SplitFinishing = return $ Stop
2135+
2136+-- | Performs infix separator style splitting.
2137+{-# INLINE_NORMAL splitInnerBySuffix #-}
2138+splitInnerBySuffix
2139+ :: (Monad m, Eq (f a), Monoid (f a))
2140+ => (f a -> m (f a, Maybe (f a))) -- splitter
2141+ -> (f a -> f a -> m (f a)) -- joiner
2142+ -> Stream m (f a)
2143+ -> Stream m (f a)
2144+splitInnerBySuffix splitter joiner (Stream step1 state1) =
2145+ (Stream step (SplitInitial state1))
2146+
2147+ where
2148+
2149+ {-# INLINE_LATE step #-}
2150+ step gst (SplitInitial st) = do
2151+ r <- step1 gst st
2152+ case r of
2153+ Yield x s -> do
2154+ (x1, mx2) <- splitter x
2155+ return $ case mx2 of
2156+ Nothing -> Skip (SplitBuffering s x1)
2157+ Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2158+ Skip s -> return $ Skip (SplitInitial s)
2159+ Stop -> return $ Stop
2160+
2161+ step gst (SplitBuffering st buf) = do
2162+ r <- step1 gst st
2163+ case r of
2164+ Yield x s -> do
2165+ (x1, mx2) <- splitter x
2166+ buf' <- joiner buf x1
2167+ return $ case mx2 of
2168+ Nothing -> Skip (SplitBuffering s buf')
2169+ Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2170+ Skip s -> return $ Skip (SplitBuffering s buf)
2171+ Stop -> return $
2172+ if buf == mempty
2173+ then Stop
2174+ else Skip (SplitYielding buf SplitFinishing)
2175+
2176+ step _ (SplitSplitting st buf) = do
2177+ (x1, mx2) <- splitter buf
2178+ return $ case mx2 of
2179+ Nothing -> Skip $ SplitBuffering st x1
2180+ Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2181+
2182+ step _ (SplitYielding x next) = return $ Yield x next
2183+ step _ SplitFinishing = return Stop
src/Streamly/Internal/Data/Stream/StreamD/Transform.hsnew file+1304

This diff is too big to show here.

src/Streamly/Internal/Data/Stream/StreamD/Type.hs+598−238

This diff is too big to show here.

streamly.cabal+14−1

This diff is too big to show here.