-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Streaming, dataflow programming and declarative concurrency -- -- For upgrading to streamly-0.9.0+ please read the Streamly-0.9.0 -- upgrade guide. -- -- Streamly is a standard library for Haskell that focuses on C-like -- performance, modular combinators, and streaming data flow model. -- Streamly consists of two packages, the streamly-core package -- provides functionality that depends only on boot libraries, and the -- streamly package provides additional functionality like -- concurrency, time, lifted exceptions, and networking. For unified -- documentation visit the streamly website. -- -- Streamly provides unified, modular building blocks to build -- high-performance, concurrent, scalable applications in Haskell. Stream -- fusion optimizations in streamly enable exceptional modularity with -- high performance comparable to C. Streamly complements the Haskell -- base package, supplying additional functionality to quickly -- build general-purpose applications in Haskell. For high-level -- functionality built over streamly like streaming OS processes, shell -- programming, GNU coreutils, statistics, and compression libraries -- please see the streamly ecosystem packages. -- -- Performance with modularity: -- -- -- -- Unified and powerful abstractions: -- -- @package streamly @version 0.10.1 -- | This module provides immutable arrays in pinned memory (non GC memory) -- suitable for long lived data storage, random access and for -- interfacing with the operating system. -- -- Arrays in this module are chunks of pinned memory that hold a sequence -- of Storable values of a given type, they cannot store -- non-serializable data like functions. Once created an array cannot be -- modified. Pinned memory allows efficient buffering of long lived data -- without adding any impact to GC. One array is just one pointer visible -- to GC and it does not have to be copied across generations. Moreover, -- pinned memory allows communication with foreign consumers and -- producers (e.g. file or network IO) without copying the data. -- --

Programmer Notes

-- -- Array creation APIs require a MonadIO Monad, except -- fromList which is a pure API. To operate on streams in pure -- Monads like Identity you can hoist it to IO monad as follows: -- --
--   >>> import Data.Functor.Identity (Identity, runIdentity)
--   
--   >>> s = Stream.fromList [1..10] :: SerialT Identity Int
--   
--   >>> s1 = Stream.hoist (return . runIdentity) s :: SerialT IO Int
--   
--   >>> Stream.fold Array.write s1 :: IO (Array Int)
--   fromList [1,2,3,4,5,6,7,8,9,10]
--   
-- -- unsafePerformIO can be used to get a pure API from IO, as -- long as you know it is safe to do so: -- --
--   >>> import System.IO.Unsafe (unsafePerformIO)
--   
--   >>> unsafePerformIO $ Stream.fold Array.write s1 :: Array Int
--   fromList [1,2,3,4,5,6,7,8,9,10]
--   
-- -- To apply a transformation to an array use read to unfold the -- array into a stream, apply a transformation on the stream and then use -- write to fold it back to an array. -- -- This module is designed to be imported qualified: -- --
--   import qualified Streamly.Data.Array as Array
--   
-- -- For experimental APIs see Streamly.Internal.Data.Array. -- | Deprecated: Please use Streamly.Data.Array module from the -- streamly-core package. module Streamly.Data.Array.Foreign data Array a fromListN :: Unbox a => Int -> [a] -> Array a fromList :: Unbox a => [a] -> Array a writeN :: forall (m :: Type -> Type) a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a) write :: forall (m :: Type -> Type) a. (MonadIO m, Unbox a) => Fold m a (Array a) writeLastN :: forall a (m :: Type -> Type). (Storable a, Unbox a, MonadIO m) => Int -> Fold m a (Array a) toList :: Unbox a => Array a -> [a] read :: forall (m :: Type -> Type) a. (Monad m, Unbox a) => Array a -> Stream m a readRev :: forall (m :: Type -> Type) a. (Monad m, Unbox a) => Array a -> Stream m a cast :: forall a b. Unbox b => Array a -> Maybe (Array b) asBytes :: Array a -> Array Word8 length :: Unbox a => Array a -> Int getIndex :: Unbox a => Int -> Array a -> Maybe a instance Control.DeepSeq.NFData (Streamly.Internal.Data.Array.Type.Array a) instance Control.DeepSeq.NFData1 Streamly.Internal.Data.Array.Type.Array -- | Deprecated: Please use Streamly.Data.Fold module from the -- streamly-core package. module Streamly.Data.Fold.Tee newtype Tee (m :: Type -> Type) a b Tee :: Fold m a b -> Tee (m :: Type -> Type) a b [unTee] :: Tee (m :: Type -> Type) a b -> Fold m a b toFold :: forall (m :: Type -> Type) a b. Tee m a b -> Fold m a b -- | Please do not add any general routines in this. It should be renamed -- appropriately. module Streamly.Internal.Control.Concurrent -- | A monad that can perform concurrent or parallel IO operations. Streams -- that can be composed concurrently require the underlying monad to be -- MonadAsync. type MonadAsync m = (MonadIO m, MonadBaseControl IO m, MonadThrow m) type MonadRunInIO m = (MonadIO m, MonadBaseControl IO m) newtype RunInIO (m :: Type -> Type) RunInIO :: (forall b. () => m b -> IO (StM m b)) -> RunInIO (m :: Type -> Type) [runInIO] :: RunInIO (m :: Type -> Type) -> forall b. () => m b -> IO (StM m b) -- | When we run computations concurrently, we completely isolate the state -- of the concurrent computations from the parent computation. The -- invariant is that we should never be running two concurrent -- computations in the same thread without using the runInIO function. -- Also, we should never be running a concurrent computation in the -- parent thread, otherwise it may affect the state of the parent which -- is against the defined semantics of concurrent execution. askRunInIO :: MonadRunInIO m => m (RunInIO m) withRunInIO :: MonadRunInIO m => ((forall a. m a -> IO (StM m a)) -> IO (StM m b)) -> m b withRunInIONoRestore :: MonadRunInIO m => ((forall a. m a -> IO (StM m a)) -> IO b) -> m b -- | Construct a m computation from the monadic state of -- m that is returned from a RunInBase function. -- -- Instances should satisfy: -- --
--   liftBaseWith (\runInBase -> runInBase m) >>= restoreM = m
--   
-- -- restoreM is usually not implemented directly, but -- using defaultRestoreM. restoreM :: MonadBaseControl b m => StM m a -> m a module Streamly.Internal.Control.ForkLifted -- | Fork a thread to run the given computation, installing the provided -- exception handler. Lifted to any monad with 'MonadRunInIO m' -- capability. -- -- TODO: the RunInIO argument can be removed, we can directly pass the -- action as "mrun action" instead. doFork :: MonadRunInIO m => m () -> RunInIO m -> (SomeException -> IO ()) -> m ThreadId -- | Similar to doFork, but has a "bound" boolean parameter for -- specifying whether forkOS should be used instead of -- rawForkIO. doForkWith :: MonadRunInIO m => Bool -> m () -> RunInIO m -> (SomeException -> IO ()) -> m ThreadId -- | fork lifted to any monad with 'MonadBaseControl IO m' -- capability. fork :: MonadRunInIO m => m () -> m ThreadId -- | Fork a thread that is automatically killed as soon as the reference to -- the returned threadId is garbage collected. forkManaged :: MonadRunInIO m => m () -> m ThreadId module Streamly.Internal.Data.Atomics atomicModifyIORefCAS :: IORef a -> (a -> (a, b)) -> IO b atomicModifyIORefCAS_ :: IORef t -> (t -> t) -> IO () writeBarrier :: IO () storeLoadBarrier :: IO () module Streamly.Internal.Data.Channel -- | This is a magic number and it is overloaded, and used at several -- places to achieve batching: -- --
    --
  1. If we have to sleep to slowdown this is the minimum period that we -- accumulate before we sleep. Also, workers do not stop until this much -- sleep time is accumulated.
  2. --
  3. Collected latencies are computed and transferred to measured -- latency after a minimum of this period.
  4. --
minThreadDelay :: NanoSecond64 collectLatency :: Bool -> SVarStats -> YieldRateInfo -> Bool -> IO (Count, AbsTime, NanoSecond64) addThread :: MonadIO m => IORef (Set ThreadId) -> ThreadId -> m () delThread :: MonadIO m => IORef (Set ThreadId) -> ThreadId -> m () modifyThread :: MonadIO m => IORef (Set ThreadId) -> MVar () -> ThreadId -> m () -- | This is safe even if we are adding more threads concurrently because -- if a child thread is adding another thread then anyway -- workerThreads will not be empty. allThreadsDone :: MonadIO m => IORef (Set ThreadId) -> m Bool recordMaxWorkers :: MonadIO m => IORef Int -> SVarStats -> m () dumpSVarStats :: Bool -> Maybe YieldRateInfo -> SVarStats -> IO String newtype Count Count :: Int64 -> Count data Limit Unlimited :: Limit Limited :: Word -> Limit -- | Channel driver throws this exception to all active workers to clean up -- the channel. data ThreadAbort ThreadAbort :: ThreadAbort -- | Events that a child thread may send to a parent thread. data ChildEvent a ChildYield :: a -> ChildEvent a ChildStopChannel :: ChildEvent a ChildStop :: ThreadId -> Maybe SomeException -> ChildEvent a data SVarStats SVarStats :: IORef Int -> IORef Int -> IORef Int -> IORef Int -> IORef Int -> IORef (Count, NanoSecond64) -> IORef NanoSecond64 -> IORef NanoSecond64 -> IORef (Maybe AbsTime) -> SVarStats [totalDispatches] :: SVarStats -> IORef Int [maxWorkers] :: SVarStats -> IORef Int [maxOutQSize] :: SVarStats -> IORef Int [maxHeapSize] :: SVarStats -> IORef Int [maxWorkQSize] :: SVarStats -> IORef Int [avgWorkerLatency] :: SVarStats -> IORef (Count, NanoSecond64) [minWorkerLatency] :: SVarStats -> IORef NanoSecond64 [maxWorkerLatency] :: SVarStats -> IORef NanoSecond64 [svarStopTime] :: SVarStats -> IORef (Maybe AbsTime) newSVarStats :: IO SVarStats -- | We measure the individual worker latencies to estimate the number of -- workers needed or the amount of time we have to sleep between -- dispatches to achieve a particular rate when controlled pace mode it -- used. data WorkerInfo WorkerInfo :: Count -> IORef Count -> IORef (Count, AbsTime) -> WorkerInfo -- | 0 means unlimited [workerYieldMax] :: WorkerInfo -> Count -- | total number of yields by the worker till now [workerYieldCount] :: WorkerInfo -> IORef Count -- | yieldCount at start, timestamp [workerLatencyStart] :: WorkerInfo -> IORef (Count, AbsTime) data LatencyRange LatencyRange :: NanoSecond64 -> NanoSecond64 -> LatencyRange [minLatency] :: LatencyRange -> NanoSecond64 [maxLatency] :: LatencyRange -> NanoSecond64 -- | Rate control. data YieldRateInfo YieldRateInfo :: NanoSecond64 -> LatencyRange -> Int -> IORef Count -> IORef (Count, AbsTime) -> Maybe NanoSecond64 -> IORef Count -> IORef (Count, Count, NanoSecond64) -> IORef (Count, Count, NanoSecond64) -> IORef NanoSecond64 -> YieldRateInfo [svarLatencyTarget] :: YieldRateInfo -> NanoSecond64 [svarLatencyRange] :: YieldRateInfo -> LatencyRange [svarRateBuffer] :: YieldRateInfo -> Int -- | [svarGainedLostYields] :: YieldRateInfo -> IORef Count -- | Actual latency/througput as seen from the consumer side, we count the -- yields and the time it took to generates those yields. This is used to -- increase or decrease the number of workers needed to achieve the -- desired rate. The idle time of workers is adjusted in this, so that we -- only account for the rate when the consumer actually demands data. XXX -- interval latency is enough, we can move this under diagnostics build -- [LOCKING] Unlocked access. Modified by the consumer thread and -- unsafely read by the worker threads [svarAllTimeLatency] :: YieldRateInfo -> IORef (Count, AbsTime) [workerBootstrapLatency] :: YieldRateInfo -> Maybe NanoSecond64 -- | After how many yields the worker should update the latency -- information. If the latency is high, this count is kept lower and -- vice-versa. XXX If the latency suddenly becomes too high this count -- may remain too high for long time, in such cases the consumer can -- change it. 0 means no latency computation XXX this is derivable from -- workerMeasuredLatency, can be removed. [LOCKING] Unlocked access. -- Modified by the consumer thread and unsafely read by the worker -- threads [workerPollingInterval] :: YieldRateInfo -> IORef Count -- | This is in progress latency stats maintained by the workers which we -- empty into workerCollectedLatency stats at certain intervals - -- whenever we process the stream elements yielded in this period. The -- first count is all yields, the second count is only those yields for -- which the latency was measured to be non-zero (note that if the timer -- resolution is low the measured latency may be zero e.g. on JS -- platform). [LOCKING] Locked access. Modified by the consumer thread as -- well as worker threads. Workers modify it periodically based on -- workerPollingInterval and not on every yield to reduce the locking -- overhead. (allYieldCount, yieldCount, timeTaken) [workerPendingLatency] :: YieldRateInfo -> IORef (Count, Count, NanoSecond64) -- | This is the second level stat which is an accmulation from -- workerPendingLatency stats. We keep accumulating latencies in this -- bucket until we have stats for a sufficient period and then we reset -- it to start collecting for the next period and retain the computed -- average latency for the last period in workerMeasuredLatency. -- [LOCKING] Unlocked access. Modified by the consumer thread and -- unsafely read by the worker threads (allYieldCount, yieldCount, -- timeTaken) [workerCollectedLatency] :: YieldRateInfo -> IORef (Count, Count, NanoSecond64) -- | Latency as measured by workers, aggregated for the last period. -- [LOCKING] Unlocked access. Modified by the consumer thread and -- unsafely read by the worker threads [workerMeasuredLatency] :: YieldRateInfo -> IORef NanoSecond64 newRateInfo :: Config -> IO (Maybe YieldRateInfo) readOutputQRaw :: IORef ([ChildEvent a], Int) -> Maybe SVarStats -> IO ([ChildEvent a], Int) readOutputQBasic :: IORef ([ChildEvent a], Int) -> IO ([ChildEvent a], Int) ringDoorBell :: IORef Bool -> MVar () -> IO () -- | A worker decrements the yield limit before it executes an action. -- However, the action may not result in an element being yielded, in -- that case we have to increment the yield limit. -- -- Note that we need it to be an Int type so that we have the ability to -- undo a decrement that takes it below zero. decrementYieldLimit :: Maybe (IORef Count) -> IO Bool incrementYieldLimit :: Maybe (IORef Count) -> IO () -- | Specifies the stream yield rate in yields per second (Hertz). -- We keep accumulating yield credits at rateGoal. At any point of -- time we allow only as many yields as we have accumulated as per -- rateGoal since the start of time. If the consumer or the -- producer is slower or faster, the actual rate may fall behind or -- exceed rateGoal. We try to recover the gap between the two by -- increasing or decreasing the pull rate from the producer. However, if -- the gap becomes more than rateBuffer we try to recover only as -- much as rateBuffer. -- -- rateLow puts a bound on how low the instantaneous rate can go -- when recovering the rate gap. In other words, it determines the -- maximum yield latency. Similarly, rateHigh puts a bound on how -- high the instantaneous rate can go when recovering the rate gap. In -- other words, it determines the minimum yield latency. We reduce the -- latency by increasing concurrency, therefore we can say that it puts -- an upper bound on concurrency. -- -- If the rateGoal is 0 or negative the stream never yields a -- value. If the rateBuffer is 0 or negative we do not attempt to -- recover. data Rate Rate :: Double -> Double -> Double -> Int -> Rate -- | The lower rate limit [rateLow] :: Rate -> Double -- | The target rate we want to achieve [rateGoal] :: Rate -> Double -- | The upper rate limit [rateHigh] :: Rate -> Double -- | Maximum slack from the goal [rateBuffer] :: Rate -> Int -- | Specify when the Channel should stop. data StopWhen -- | Stop when the first stream ends. FirstStops :: StopWhen -- | Stop when all the streams end. AllStop :: StopWhen -- | Stop when any one stream ends. AnyStops :: StopWhen -- | An abstract type for specifying the configuration parameters of a -- Channel. Use Config -> Config modifier functions -- to modify the default configuration. See the individual modifier -- documentation for default values. data Config -- | A magical value for the buffer size arrived at by running the smallest -- possible task and measuring the optimal value of the buffer for that. -- This is obviously dependent on hardware, this figure is based on a -- 2.2GHz intel core-i7 processor. magicMaxBuffer :: Word -- | The fields prefixed by an _ are not to be accessed or updated directly -- but via smart accessor APIs. Use get/set routines instead of directly -- accessing the Config fields defaultConfig :: Config -- | Specify the maximum number of threads that can be spawned by the -- channel. A value of 0 resets the thread limit to default, a negative -- value means there is no limit. The default value is 1500. -- -- When the actions in a stream are IO bound, having blocking IO calls, -- this option can be used to control the maximum number of in-flight IO -- requests. When the actions are CPU bound this option can be used to -- control the amount of CPU used by the stream. maxThreads :: Int -> Config -> Config -- | Specify the maximum size of the buffer for storing the results from -- concurrent computations. If the buffer becomes full we stop spawning -- more concurrent tasks until there is space in the buffer. A value of 0 -- resets the buffer size to default, a negative value means there is no -- limit. The default value is 1500. -- -- CAUTION! using an unbounded maxBuffer value (i.e. a negative -- value) coupled with an unbounded maxThreads value is a recipe -- for disaster in presence of infinite streams, or very large streams. -- Especially, it must not be used when pure is used in -- ZipAsyncM streams as pure in applicative zip streams -- generates an infinite stream causing unbounded concurrent generation -- with no limit on the buffer or threads. maxBuffer :: Int -> Config -> Config maxYields :: Maybe Int64 -> Config -> Config -- | Print debug information about the Channel when the stream -- ends. inspect :: Bool -> Config -> Config -- | By default, processing of output from the worker threads is given -- priority over dispatching new workers. More workers are dispatched -- only when there is no output to process. When eager is set to -- True, workers are dispatched aggresively as long as there is -- more work to do irrespective of whether there is output pending to be -- processed by the stream consumer. However, dispatching may stop if -- maxThreads or maxBuffer is reached. -- -- Note: This option has no effect when rate has been specified. -- -- Note: Not supported with interleaved. eager :: Bool -> Config -> Config -- | Specify when the Channel should stop. stopWhen :: StopWhen -> Config -> Config -- | When enabled the streams may be evaluated cocnurrently but the results -- are produced in the same sequence as a serial evaluation would -- produce. -- -- Note: Not supported with interleaved. ordered :: Bool -> Config -> Config -- | Interleave the streams fairly instead of prioritizing the left stream. -- This schedules all streams in a round robin fashion over limited -- number of threads. -- -- Note: Can only be used on finite number of streams. -- -- Note: Not supported with ordered. interleaved :: Bool -> Config -> Config -- | Spawn bound threads (i.e., spawn threads using forkOS instead -- of forkIO). The default value is False. -- -- Currently, this only takes effect only for concurrent folds. boundThreads :: Bool -> Config -> Config -- | Specify the stream evaluation rate of a channel. -- -- A Nothing value means there is no smart rate control, -- concurrent execution blocks only if maxThreads or -- maxBuffer is reached, or there are no more concurrent tasks to -- execute. This is the default. -- -- When rate (throughput) is specified, concurrent production may be -- ramped up or down automatically to achieve the specified stream -- throughput. The specific behavior for different styles of Rate -- specifications is documented under Rate. The effective maximum -- production rate achieved by a channel is governed by: -- -- -- -- Maximum production rate is given by: -- -- <math> -- -- If we know the average latency of the tasks we can set -- maxThreads accordingly. rate :: Maybe Rate -> Config -> Config -- | Same as rate (Just $ Rate (r/2) r (2*r) maxBound) -- -- Specifies the average production rate of a stream in number of yields -- per second (i.e. Hertz). Concurrent production is ramped up -- or down automatically to achieve the specified average yield rate. The -- rate can go down to half of the specified rate on the lower side and -- double of the specified rate on the higher side. avgRate :: Double -> Config -> Config -- | Same as rate (Just $ Rate r r (2*r) maxBound) -- -- Specifies the minimum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go below the -- specified rate, even though it may possibly go above it at times, the -- upper limit is double of the specified rate. minRate :: Double -> Config -> Config -- | Same as rate (Just $ Rate (r/2) r r maxBound) -- -- Specifies the maximum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go above the -- specified rate, even though it may possibly go below it at times, the -- lower limit is half of the specified rate. This can be useful in -- applications where certain resource usage must not be allowed to go -- beyond certain limits. maxRate :: Double -> Config -> Config -- | Same as rate (Just $ Rate r r r 0) -- -- Specifies a constant yield rate. If for some reason the actual rate -- goes above or below the specified rate we do not try to recover it by -- increasing or decreasing the rate in future. This can be useful in -- applications like graphics frame refresh where we need to maintain a -- constant refresh rate. constRate :: Double -> Config -> Config getMaxThreads :: Config -> Limit getMaxBuffer :: Config -> Limit getStreamRate :: Config -> Maybe Rate getStreamLatency :: Config -> Maybe NanoSecond64 setStreamLatency :: Int -> Config -> Config getYieldLimit :: Config -> Maybe Count getInspectMode :: Config -> Bool getEagerDispatch :: Config -> Bool getStopWhen :: Config -> StopWhen getOrdered :: Config -> Bool getInterleaved :: Config -> Bool getBound :: Config -> Bool -- | Never called from a worker thread. cleanupSVar :: IORef (Set ThreadId) -> IO () dumpCreator :: Show a => a -> String dumpOutputQ :: (Foldable t, Show a1) => IORef (t a2, a1) -> IO String dumpDoorBell :: Show a => MVar a -> IO String dumpNeedDoorBell :: Show a => IORef a -> IO String dumpRunningThreads :: Show a => IORef a -> IO String dumpWorkerCount :: Show a => IORef a -> IO String -- | MVar diagnostics has some overhead - around 5% on AsyncT null -- benchmark, we can keep it on in production to debug problems quickly -- if and when they happen, but it may result in unexpected output when -- threads are left hanging until they are GCed because the consumer went -- away. withDiagMVar :: Bool -> IO String -> String -> IO () -> IO () printSVar :: IO String -> String -> IO () data Work BlockWait :: NanoSecond64 -> Work PartialWorker :: Count -> Work ManyWorkers :: Int -> Count -> Work estimateWorkers :: Limit -> Count -> Count -> NanoSecond64 -> NanoSecond64 -> NanoSecond64 -> LatencyRange -> Work isBeyondMaxRate :: Limit -> IORef Int -> YieldRateInfo -> IO Bool -- | CAUTION! this also updates the yield count and therefore should be -- called only when we are actually yielding an element. workerRateControl :: Limit -> IORef Int -> YieldRateInfo -> WorkerInfo -> IO Bool sendWithDoorBell :: IORef ([ChildEvent a], Int) -> MVar () -> ChildEvent a -> IO Int -- | Returns whether the worker should continue (True) or stop (False). sendYield :: Limit -> Limit -> IORef Int -> Maybe WorkerInfo -> Maybe YieldRateInfo -> IORef ([ChildEvent a], Int) -> MVar () -> ChildEvent a -> IO Bool sendStop :: IORef Int -> Maybe WorkerInfo -> Maybe YieldRateInfo -> IORef ([ChildEvent a], Int) -> MVar () -> IO () handleChildException :: IORef ([ChildEvent a], Int) -> MVar () -> SomeException -> IO () -- | Continuation style utilities. module Streamly.Internal.Data.Cont -- | Given a continuation based transformation from a to -- b and a continuation based transformation from [b] -- to c, make continuation based transformation from -- [a] to c. -- -- Pre-release contListMap :: (a -> (b -> r) -> r) -> ([b] -> (c -> r) -> r) -> [a] -> (c -> r) -> r -- | A value associated with an IO action that is automatically called -- whenever the value is garbage collected. module Streamly.Internal.Data.IOFinalizer.Lifted data IOFinalizer -- | Create a finalizer that calls the supplied function automatically when -- the it is garbage collected. -- -- /The finalizer is always run using the state of the monad that is -- captured at the time of calling newFinalizer./ -- -- Note: To run it on garbage collection we have no option but to use the -- monad state captured at some earlier point of time. For the case when -- the finalizer is run manually before GC we could run it with the -- current state of the monad but we want to keep both the cases -- consistent. -- -- Pre-release newIOFinalizer :: MonadRunInIO m => m a -> m IOFinalizer runIOFinalizer :: MonadIO m => IOFinalizer -> m () -- | Run an action clearing the finalizer atomically wrt async exceptions. -- The action is run with async exceptions masked. -- -- Pre-release clearingIOFinalizer :: MonadRunInIO m => IOFinalizer -> m a -> m a -- | Adds an orphan HashMap instance for the IsMap type class from -- streamly-core package. This is useful for various combinators that use -- a map type. We cannot define this in streamly-core as it adds several -- non-boot library dependencies on streamly-core. module Streamly.Internal.Data.IsMap.HashMap instance (Data.Hashable.Class.Hashable k, GHC.Classes.Eq k) => Streamly.Internal.Data.IsMap.IsMap (Data.HashMap.Internal.HashMap k) -- | All Fold related combinators including the streamly-core -- Streamly.Data.Fold module, concurrency, unordered container -- operations. module Streamly.Data.Fold.Prelude -- | An abstract type for specifying the configuration parameters of a -- Channel. Use Config -> Config modifier functions -- to modify the default configuration. See the individual modifier -- documentation for default values. data Config -- | Specify the maximum size of the buffer for storing the results from -- concurrent computations. If the buffer becomes full we stop spawning -- more concurrent tasks until there is space in the buffer. A value of 0 -- resets the buffer size to default, a negative value means there is no -- limit. The default value is 1500. -- -- CAUTION! using an unbounded maxBuffer value (i.e. a negative -- value) coupled with an unbounded maxThreads value is a recipe -- for disaster in presence of infinite streams, or very large streams. -- Especially, it must not be used when pure is used in -- ZipAsyncM streams as pure in applicative zip streams -- generates an infinite stream causing unbounded concurrent generation -- with no limit on the buffer or threads. maxBuffer :: Int -> Config -> Config -- | Spawn bound threads (i.e., spawn threads using forkOS instead -- of forkIO). The default value is False. -- -- Currently, this only takes effect only for concurrent folds. boundThreads :: Bool -> Config -> Config -- | Print debug information about the Channel when the stream -- ends. inspect :: Bool -> Config -> Config -- | Evaluate a fold asynchronously using a concurrent channel. The driver -- just queues the input stream values to the fold channel buffer and -- returns. The fold evaluates the queued values asynchronously. On -- finalization, parEval waits for the asynchronous fold to -- complete before it returns. parEval :: MonadAsync m => (Config -> Config) -> Fold m a b -> Fold m a b -- | Split the input stream based on a hashable component of the key field -- and fold each split using the given fold. Useful for map/reduce, -- bucketizing the input in different bins or for generating histograms. -- --
--   >>> import Data.HashMap.Strict (HashMap, fromList)
--   
--   >>> import qualified Streamly.Data.Fold.Prelude as Fold
--   
--   >>> import qualified Streamly.Data.Stream as Stream
--   
-- -- Consider a stream of key value pairs: -- --
--   >>> input = Stream.fromList [("k1",1),("k1",1.1),("k2",2), ("k2",2.2)]
--   
-- -- Classify each key to a different hash bin and fold the bins: -- --
--   >>> classify = Fold.toHashMapIO fst (Fold.lmap snd Fold.toList)
--   
--   >>> Stream.fold classify input :: IO (HashMap String [Double])
--   fromList [("k2",[2.0,2.2]),("k1",[1.0,1.1])]
--   
-- -- Pre-release toHashMapIO :: (MonadIO m, Hashable k, Ord k) => (a -> k) -> Fold m a b -> Fold m a (HashMap k b) -- | Deprecated: SVar is replaced by Channel. module Streamly.Internal.Data.SVar decrementYieldLimit :: SVar t m a -> IO Bool incrementYieldLimit :: SVar t m a -> IO () decrementBufferLimit :: SVar t m a -> IO () incrementBufferLimit :: SVar t m a -> IO () resetBufferLimit :: SVar t m a -> IO () data Work BlockWait :: NanoSecond64 -> Work PartialWorker :: Count -> Work ManyWorkers :: Int -> Count -> Work isBeyondMaxRate :: SVar t m a -> YieldRateInfo -> IO Bool estimateWorkers :: Limit -> Count -> Count -> NanoSecond64 -> NanoSecond64 -> NanoSecond64 -> LatencyRange -> Work updateYieldCount :: WorkerInfo -> IO Count -- | This is a magic number and it is overloaded, and used at several -- places to achieve batching: -- --
    --
  1. If we have to sleep to slowdown this is the minimum period that we -- accumulate before we sleep. Also, workers do not stop until this much -- sleep time is accumulated.
  2. --
  3. Collected latencies are computed and transferred to measured -- latency after a minimum of this period.
  4. --
minThreadDelay :: NanoSecond64 workerRateControl :: SVar t m a -> YieldRateInfo -> WorkerInfo -> IO Bool workerUpdateLatency :: YieldRateInfo -> WorkerInfo -> IO () -- | This function is used by the producer threads to queue output for the -- consumer thread to consume. Returns whether the queue has more space. send :: SVar t m a -> ChildEvent a -> IO Int ringDoorBell :: SVar t m a -> IO () sendYield :: SVar t m a -> Maybe WorkerInfo -> ChildEvent a -> IO Bool sendToProducer :: SVar t m a -> ChildEvent a -> IO Int sendStop :: SVar t m a -> Maybe WorkerInfo -> IO () sendStopToProducer :: MonadIO m => SVar t m a -> m () handleChildException :: SVar t m a -> SomeException -> IO () handleFoldException :: SVar t m a -> SomeException -> IO () collectLatency :: SVar t m a -> YieldRateInfo -> Bool -> IO (Count, AbsTime, NanoSecond64) withDiagMVar :: SVar t m a -> String -> IO () -> IO () dumpSVar :: SVar t m a -> IO String printSVar :: SVar t m a -> String -> IO () delThread :: MonadIO m => SVar t m a -> ThreadId -> m () modifyThread :: MonadIO m => SVar t m a -> ThreadId -> m () -- | This is safe even if we are adding more threads concurrently because -- if a child thread is adding another thread then anyway -- workerThreads will not be empty. allThreadsDone :: MonadIO m => SVar t m a -> m Bool recordMaxWorkers :: MonadIO m => SVar t m a -> m () pushWorker :: MonadAsync m => Count -> SVar t m a -> m () -- | In contrast to pushWorker which always happens only from the consumer -- thread, a pushWorkerPar can happen concurrently from multiple threads -- on the producer side. So we need to use a thread safe modification of -- workerThreads. Alternatively, we can use a CreateThread event to avoid -- using a CAS based modification. pushWorkerPar :: MonadAsync m => SVar t m a -> (Maybe WorkerInfo -> m ()) -> m () dispatchWorker :: MonadAsync m => Count -> SVar t m a -> m Bool dispatchWorkerPaced :: MonadAsync m => SVar t m a -> m Bool sendWorkerWait :: MonadAsync m => (SVar t m a -> IO ()) -> (SVar t m a -> m Bool) -> SVar t m a -> m () sendFirstWorker :: MonadAsync m => SVar t m a -> t m a -> m (SVar t m a) sendWorkerDelay :: SVar t m a -> IO () sendWorkerDelayPaced :: SVar t m a -> IO () readOutputQBasic :: IORef ([ChildEvent a], Int) -> IO ([ChildEvent a], Int) readOutputQRaw :: SVar t m a -> IO ([ChildEvent a], Int) readOutputQPaced :: MonadAsync m => SVar t m a -> m [ChildEvent a] readOutputQBounded :: MonadAsync m => SVar t m a -> m [ChildEvent a] postProcessPaced :: MonadAsync m => SVar t m a -> m Bool postProcessBounded :: MonadAsync m => SVar t m a -> m Bool cleanupSVar :: SVar t m a -> IO () cleanupSVarFromWorker :: SVar t m a -> IO () getYieldRateInfo :: State t m a -> IO (Maybe YieldRateInfo) newSVarStats :: IO SVarStats newParallelVar :: MonadAsync m => SVarStopStyle -> State t m a -> m (SVar t m a) enqueueAhead :: SVar t m a -> IORef ([t m a], Int) -> (RunInIO m, t m a) -> IO () reEnqueueAhead :: SVar t m a -> IORef ([t m a], Int) -> t m a -> IO () queueEmptyAhead :: MonadIO m => IORef ([t m a], Int) -> m Bool dequeueAhead :: MonadIO m => IORef ([t m a], Int) -> m (Maybe (t m a, Int)) data HeapDequeueResult t m a Clearing :: HeapDequeueResult t m a Waiting :: Int -> HeapDequeueResult t m a Ready :: Entry Int (AheadHeapEntry t m a) -> HeapDequeueResult t m a dequeueFromHeap :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int) -> IO (HeapDequeueResult t m a) dequeueFromHeapSeq :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int) -> Int -> IO (HeapDequeueResult t m a) requeueOnHeapTop :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int) -> Entry Int (AheadHeapEntry t m a) -> Int -> IO () updateHeapSeq :: IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int) -> Int -> IO () withIORef :: IORef a -> (a -> IO b) -> IO b heapIsSane :: Maybe Int -> Int -> Bool newAheadVar :: MonadAsync m => State t m a -> t m a -> (IORef ([t m a], Int) -> IORef (Heap (Entry Int (AheadHeapEntry t m a)), Maybe Int) -> State t m a -> SVar t m a -> Maybe WorkerInfo -> m ()) -> m (SVar t m a) module Streamly.Internal.Data.Fold.Prelude -- | takeInterval n fold uses fold to fold the input -- items arriving within a window of first n seconds. -- --
--   >>> input = Stream.delay 0.2 $ Stream.fromList [1..10]
--   
--   >>> Stream.fold (Fold.takeInterval 1.0 Fold.toList) input
--   [1,2,3,4,5,6]
--   
-- --
--   >>> f = Fold.takeInterval 0.5 Fold.toList
--   
--   >>> Stream.fold Fold.toList $ Stream.foldMany f input
--   [[1,2,3,4],[5,6,7],[8,9,10]]
--   
-- -- Stops when fold stops or when the timeout occurs. Note that -- the fold needs an input after the timeout to stop. For example, if no -- input is pushed to the fold until one hour after the timeout had -- occurred, then the fold will be done only after consuming that input. -- -- Pre-release takeInterval :: MonadAsync m => Double -> Fold m a b -> Fold m a b -- | Group the input stream into windows of n second each using the first -- fold and then fold the resulting groups using the second fold. -- --
--   >>> intervals = Fold.intervalsOf 0.5 Fold.toList Fold.toList
--   
--   >>> Stream.fold intervals $ Stream.delay 0.2 $ Stream.fromList [1..10]
--   [[1,2,3,4],[5,6,7],[8,9,10]]
--   
-- --
--   intervalsOf n split = many (takeInterval n split)
--   
-- -- Pre-release intervalsOf :: MonadAsync m => Double -> Fold m a b -> Fold m b c -> Fold m a c data Channel m a b Channel :: IORef ([ChildEvent a], Int) -> Limit -> MVar () -> m [ChildEvent a] -> IORef ([ChildEvent b], Int) -> MVar () -> MVar () -> Maybe (IORef ()) -> SVarStats -> Bool -> ThreadId -> Channel m a b [outputQueue] :: Channel m a b -> IORef ([ChildEvent a], Int) [maxBufferLimit] :: Channel m a b -> Limit [outputDoorBell] :: Channel m a b -> MVar () [readOutputQ] :: Channel m a b -> m [ChildEvent a] [outputQueueFromConsumer] :: Channel m a b -> IORef ([ChildEvent b], Int) [outputDoorBellFromConsumer] :: Channel m a b -> MVar () [bufferSpaceDoorBell] :: Channel m a b -> MVar () [svarRef] :: Channel m a b -> Maybe (IORef ()) [svarStats] :: Channel m a b -> SVarStats [svarInspectMode] :: Channel m a b -> Bool [svarCreator] :: Channel m a b -> ThreadId newChannel :: MonadRunInIO m => (Config -> Config) -> Fold m a b -> m (Channel m a b) -- | An abstract type for specifying the configuration parameters of a -- Channel. Use Config -> Config modifier functions -- to modify the default configuration. See the individual modifier -- documentation for default values. data Config -- | Push values from a driver to a fold worker via a Channel. Before -- pushing a value to the Channel it polls for events received from the -- fold worker. If a stop event is received then it returns True -- otherwise false. Propagates exceptions received from the fold wroker. sendToWorker :: MonadAsync m => Channel m a b -> a -> m (Maybe b) -- | Poll for events sent by the fold worker to the fold driver. The fold -- consumer can send a Stop event or an exception. When a -- Stop is received this function returns True. If an -- exception is recieved then it throws the exception. checkFoldStatus :: MonadAsync m => Channel m a b -> m (Maybe b) dumpSVar :: Channel m a b -> IO String -- | Specify the maximum size of the buffer for storing the results from -- concurrent computations. If the buffer becomes full we stop spawning -- more concurrent tasks until there is space in the buffer. A value of 0 -- resets the buffer size to default, a negative value means there is no -- limit. The default value is 1500. -- -- CAUTION! using an unbounded maxBuffer value (i.e. a negative -- value) coupled with an unbounded maxThreads value is a recipe -- for disaster in presence of infinite streams, or very large streams. -- Especially, it must not be used when pure is used in -- ZipAsyncM streams as pure in applicative zip streams -- generates an infinite stream causing unbounded concurrent generation -- with no limit on the buffer or threads. maxBuffer :: Int -> Config -> Config -- | Spawn bound threads (i.e., spawn threads using forkOS instead -- of forkIO). The default value is False. -- -- Currently, this only takes effect only for concurrent folds. boundThreads :: Bool -> Config -> Config -- | Print debug information about the Channel when the stream -- ends. inspect :: Bool -> Config -> Config -- | Evaluate a fold asynchronously using a concurrent channel. The driver -- just queues the input stream values to the fold channel buffer and -- returns. The fold evaluates the queued values asynchronously. On -- finalization, parEval waits for the asynchronous fold to -- complete before it returns. parEval :: MonadAsync m => (Config -> Config) -> Fold m a b -> Fold m a b -- | A fold to write a stream to an SVar. Unlike toSVar this does -- not allow for concurrent evaluation of the stream, as the fold -- receives the input one element at a time, it just forwards the -- elements to the SVar. However, we can safely execute the fold in an -- independent thread, the SVar can act as a buffer decoupling the sender -- from the receiver. Also, we can have multiple folds running -- concurrently pusing the streams to the SVar. write :: MonadIO m => SVar t m a -> Maybe WorkerInfo -> Fold m a () -- | Like write, but applies a yield limit. writeLimited :: MonadIO m => SVar t m a -> Maybe WorkerInfo -> Fold m a () module Streamly.Internal.Data.Stream.MkType -- | Create a type with a zip-like applicative. -- --
--   >>> expr <- runQ (mkZipType "ZipStream" "zipApply" False)
--   
--   >>> putStrLn $ pprint expr
--   newtype ZipStream m a
--       = ZipStream (Stream.Stream m a)
--       deriving Foldable
--   mkZipStream :: Stream.Stream m a -> ZipStream m a
--   mkZipStream = ZipStream
--   unZipStream :: ZipStream m a -> Stream.Stream m a
--   unZipStream (ZipStream strm) = strm
--   deriving instance IsList (ZipStream Identity a)
--   deriving instance a ~
--                     GHC.Types.Char => IsString (ZipStream Identity a)
--   deriving instance GHC.Classes.Eq a => Eq (ZipStream Identity a)
--   deriving instance GHC.Classes.Ord a => Ord (ZipStream Identity a)
--   instance Show a => Show (ZipStream Identity a)
--       where {{-# INLINE show #-}; show (ZipStream strm) = show strm}
--   instance Read a => Read (ZipStream Identity a)
--       where {{-# INLINE readPrec #-}; readPrec = fmap ZipStream readPrec}
--   instance Monad m => Functor (ZipStream m)
--       where {{-# INLINE fmap #-};
--              fmap f (ZipStream strm) = ZipStream (fmap f strm)}
--   instance Monad m => Applicative (ZipStream m)
--       where {{-# INLINE pure #-};
--              pure = ZipStream . Stream.repeat;
--              {-# INLINE (<*>) #-};
--              (<*>) (ZipStream strm1) (ZipStream strm2) = ZipStream (zipApply strm1 strm2)}
--   
mkZipType :: String -> String -> Bool -> Q [Dec] -- | Create a type with specific stream combination properties. -- --
--   >>> expr <- runQ (mkCrossType "Parallel" "parBind" True)
--   
--   >>> putStrLn $ pprint expr
--   newtype Parallel m a = Parallel (Stream.Stream m a)
--   mkParallel :: Stream.Stream m a -> Parallel m a
--   mkParallel = Parallel
--   unParallel :: Parallel m a -> Stream.Stream m a
--   unParallel (Parallel strm) = strm
--   instance Monad m => Functor (Parallel m)
--       where {{-# INLINE fmap #-};
--              fmap f (Parallel strm) = Parallel (fmap f strm)}
--   instance Stream.MonadAsync m => Monad (Parallel m)
--       where {{-# INLINE (>>=) #-};
--              (>>=) (Parallel strm1) f = let f1 a = unParallel (f a)
--                                          in Parallel (parBind strm1 f1)}
--   instance Stream.MonadAsync m => Applicative (Parallel m)
--       where {{-# INLINE pure #-};
--              pure = Parallel . Stream.fromPure;
--              {-# INLINE (<*>) #-};
--              (<*>) = ap}
--   instance (Monad (Parallel m), MonadIO m) => MonadIO (Parallel m)
--       where {{-# INLINE liftIO #-};
--              liftIO = Parallel . (Stream.fromEffect . liftIO)}
--   instance (Monad (Parallel m),
--             MonadThrow m) => MonadThrow (Parallel m)
--       where {{-# INLINE throwM #-};
--              throwM = Parallel . (Stream.fromEffect . throwM)}
--   
mkCrossType :: String -> String -> Bool -> Q [Dec] -- | Monads in which IO computations may be embedded. Any monad -- built by applying a sequence of monad transformers to the IO -- monad will be an instance of this class. -- -- Instances should satisfy the following laws, which state that -- liftIO is a transformer of monads: -- -- class Monad m => MonadIO (m :: Type -> Type) -- | Lift a computation from the IO monad. This allows us to run IO -- computations in any monadic stack, so long as it supports these kinds -- of operations (i.e. IO is the base monad for the stack). -- --

Example

-- --
--   import Control.Monad.Trans.State -- from the "transformers" library
--   
--   printState :: Show s => StateT s IO ()
--   printState = do
--     state <- get
--     liftIO $ print state
--   
-- -- Had we omitted liftIO, we would have ended up with -- this error: -- --
--   • Couldn't match type ‘IO’ with ‘StateT s IO’
--    Expected type: StateT s IO ()
--      Actual type: IO ()
--   
-- -- The important part here is the mismatch between StateT s IO -- () and IO (). -- -- Luckily, we know of a function that takes an IO a and -- returns an (m a): liftIO, enabling us to run -- the program and see the expected results: -- --
--   > evalStateT printState "hello"
--   "hello"
--   
--   > evalStateT printState 3
--   3
--   
liftIO :: MonadIO m => IO a -> m a -- | A class for monads in which exceptions may be thrown. -- -- Instances should obey the following law: -- --
--   throwM e >> x = throwM e
--   
-- -- In other words, throwing an exception short-circuits the rest of the -- monadic computation. class Monad m => MonadThrow (m :: Type -> Type) -- | Throw an exception. Note that this throws when this action is run in -- the monad m, not when it is applied. It is a generalization -- of Control.Exception's throwIO. -- -- Should satisfy the law: -- --
--   throwM e >> f = throwM e
--   
throwM :: (MonadThrow m, Exception e) => e -> m a -- | See examples in Control.Monad.Reader. Note, the partially -- applied function type (->) r is a simple reader monad. See -- the instance declaration below. class Monad m => MonadReader r (m :: Type -> Type) | m -> r -- | Retrieves the monad environment. ask :: MonadReader r m => m r -- | Executes a computation in a modified environment. local :: MonadReader r m => (r -> r) -> m a -> m a -- | Retrieves a function of the current environment. reader :: MonadReader r m => (r -> a) -> m a -- | The class of monad transformers. Instances should satisfy the -- following laws, which state that lift is a monad -- transformation: -- -- class MonadTrans (t :: Type -> Type -> Type -> Type) -- | Lift a computation from the argument monad to the constructed monad. lift :: (MonadTrans t, Monad m) => m a -> t m a -- | In many situations, the liftM operations can be replaced by -- uses of ap, which promotes function application. -- --
--   return f `ap` x1 `ap` ... `ap` xn
--   
-- -- is equivalent to -- --
--   liftMn f x1 x2 ... xn
--   
ap :: Monad m => m (a -> b) -> m a -> m b -- | Template Haskell macros to create custom newtype wrappers for the -- Stream type. See the examples below to create the standard -- stream types that were available in streamly versions before 0.9.0. -- -- To use this module, the following extensions must be enabled: -- --
--   >>> :set -XStandaloneDeriving
--   
--   >>> :set -XTemplateHaskell
--   
--   >>> :set -XTypeFamilies
--   
--   >>> :set -XUndecidableInstances
--   
-- -- Import this module unqualified to bring everything needed in scope -- without having to import several other modules. Also, -- Streamly.Data.Stream or Streamly.Data.Stream.Prelude -- must be imported as Stream. -- --
--   >>> import Streamly.Data.Stream.MkType
--   
--   >>> import qualified Streamly.Data.Stream.Prelude as Stream
--   
-- -- For AsyncT monad type with a concurrent cross product bind: -- --
--   >>> :{
--    bind = flip (Stream.parConcatMap id)
--    $(mkCrossType "AsyncT" "bind" True)
--   :}
--   
-- -- For WAsyncT monad type with a concurrent interleaved bind: -- --
--   >>> :{
--    bind = flip (Stream.parConcatMap (Stream.interleaved True))
--    $(mkCrossType "WAsyncT" "bind" True)
--   :}
--   
-- -- For AheadT monad type with a concurrent ordered cross product -- bind: -- --
--   >>> :{
--    bind = flip (Stream.parConcatMap (Stream.ordered True))
--    $(mkCrossType "AheadT" "bind" True)
--   :}
--   
-- -- For ParallelT monad type with an eager concurrent cross product -- bind: -- --
--   >>> :{
--    parBind = flip (Stream.parConcatMap (Stream.eager True))
--    $(mkCrossType "ParallelT" "parBind" True)
--   :}
--   
-- -- For ZipSerialM serial zipping applicative type: -- --
--   >>> :{
--    zipApply = Stream.zipWith ($)
--    $(mkZipType "ZipSerialM" "zipApply" False)
--   :}
--   
-- -- For ZipAsync concurrent zipping applicative type: -- --
--   >>> :{
--    parApply = Stream.parApply id
--    $(mkZipType "ZipAsync" "parApply" True)
--   :}
--   
-- -- Instead of using these macros directly you could use the generated -- code as well. Use these macros in ghci to generate the required code -- and paste it in your package, you can customize the code as desired. -- See the docs of the macros below for examples about how to view the -- generated code. For example: -- --
--   >>> bind = flip (Stream.parConcatMap id)
--   
--   >>> expr <- runQ (mkCrossType "AsyncT" "bind" True)
--   
-- --
--   > putStrLn $ pprint expr
--   
module Streamly.Data.Stream.MkType -- | Create a type with a zip-like applicative. -- --
--   >>> expr <- runQ (mkZipType "ZipStream" "zipApply" False)
--   
--   >>> putStrLn $ pprint expr
--   newtype ZipStream m a
--       = ZipStream (Stream.Stream m a)
--       deriving Foldable
--   mkZipStream :: Stream.Stream m a -> ZipStream m a
--   mkZipStream = ZipStream
--   unZipStream :: ZipStream m a -> Stream.Stream m a
--   unZipStream (ZipStream strm) = strm
--   deriving instance IsList (ZipStream Identity a)
--   deriving instance a ~
--                     GHC.Types.Char => IsString (ZipStream Identity a)
--   deriving instance GHC.Classes.Eq a => Eq (ZipStream Identity a)
--   deriving instance GHC.Classes.Ord a => Ord (ZipStream Identity a)
--   instance Show a => Show (ZipStream Identity a)
--       where {{-# INLINE show #-}; show (ZipStream strm) = show strm}
--   instance Read a => Read (ZipStream Identity a)
--       where {{-# INLINE readPrec #-}; readPrec = fmap ZipStream readPrec}
--   instance Monad m => Functor (ZipStream m)
--       where {{-# INLINE fmap #-};
--              fmap f (ZipStream strm) = ZipStream (fmap f strm)}
--   instance Monad m => Applicative (ZipStream m)
--       where {{-# INLINE pure #-};
--              pure = ZipStream . Stream.repeat;
--              {-# INLINE (<*>) #-};
--              (<*>) (ZipStream strm1) (ZipStream strm2) = ZipStream (zipApply strm1 strm2)}
--   
mkZipType :: String -> String -> Bool -> Q [Dec] -- | Create a type with specific stream combination properties. -- --
--   >>> expr <- runQ (mkCrossType "Parallel" "parBind" True)
--   
--   >>> putStrLn $ pprint expr
--   newtype Parallel m a = Parallel (Stream.Stream m a)
--   mkParallel :: Stream.Stream m a -> Parallel m a
--   mkParallel = Parallel
--   unParallel :: Parallel m a -> Stream.Stream m a
--   unParallel (Parallel strm) = strm
--   instance Monad m => Functor (Parallel m)
--       where {{-# INLINE fmap #-};
--              fmap f (Parallel strm) = Parallel (fmap f strm)}
--   instance Stream.MonadAsync m => Monad (Parallel m)
--       where {{-# INLINE (>>=) #-};
--              (>>=) (Parallel strm1) f = let f1 a = unParallel (f a)
--                                          in Parallel (parBind strm1 f1)}
--   instance Stream.MonadAsync m => Applicative (Parallel m)
--       where {{-# INLINE pure #-};
--              pure = Parallel . Stream.fromPure;
--              {-# INLINE (<*>) #-};
--              (<*>) = ap}
--   instance (Monad (Parallel m), MonadIO m) => MonadIO (Parallel m)
--       where {{-# INLINE liftIO #-};
--              liftIO = Parallel . (Stream.fromEffect . liftIO)}
--   instance (Monad (Parallel m),
--             MonadThrow m) => MonadThrow (Parallel m)
--       where {{-# INLINE throwM #-};
--              throwM = Parallel . (Stream.fromEffect . throwM)}
--   
mkCrossType :: String -> String -> Bool -> Q [Dec] -- | Parsing of Strings, producing values. -- -- Derived instances of Read make the following assumptions, which -- derived instances of Show obey: -- -- -- -- For example, given the declarations -- --
--   infixr 5 :^:
--   data Tree a =  Leaf a  |  Tree a :^: Tree a
--   
-- -- the derived instance of Read in Haskell 2010 is equivalent to -- --
--   instance (Read a) => Read (Tree a) where
--   
--           readsPrec d r =  readParen (d > app_prec)
--                            (\r -> [(Leaf m,t) |
--                                    ("Leaf",s) <- lex r,
--                                    (m,t) <- readsPrec (app_prec+1) s]) r
--   
--                         ++ readParen (d > up_prec)
--                            (\r -> [(u:^:v,w) |
--                                    (u,s) <- readsPrec (up_prec+1) r,
--                                    (":^:",t) <- lex s,
--                                    (v,w) <- readsPrec (up_prec+1) t]) r
--   
--             where app_prec = 10
--                   up_prec = 5
--   
-- -- Note that right-associativity of :^: is unused. -- -- The derived instance in GHC is equivalent to -- --
--   instance (Read a) => Read (Tree a) where
--   
--           readPrec = parens $ (prec app_prec $ do
--                                    Ident "Leaf" <- lexP
--                                    m <- step readPrec
--                                    return (Leaf m))
--   
--                        +++ (prec up_prec $ do
--                                    u <- step readPrec
--                                    Symbol ":^:" <- lexP
--                                    v <- step readPrec
--                                    return (u :^: v))
--   
--             where app_prec = 10
--                   up_prec = 5
--   
--           readListPrec = readListPrecDefault
--   
-- -- Why do both readsPrec and readPrec exist, and why does -- GHC opt to implement readPrec in derived Read instances -- instead of readsPrec? The reason is that readsPrec is -- based on the ReadS type, and although ReadS is mentioned -- in the Haskell 2010 Report, it is not a very efficient parser data -- structure. -- -- readPrec, on the other hand, is based on a much more efficient -- ReadPrec datatype (a.k.a "new-style parsers"), but its -- definition relies on the use of the RankNTypes language -- extension. Therefore, readPrec (and its cousin, -- readListPrec) are marked as GHC-only. Nevertheless, it is -- recommended to use readPrec instead of readsPrec -- whenever possible for the efficiency improvements it brings. -- -- As mentioned above, derived Read instances in GHC will -- implement readPrec instead of readsPrec. The default -- implementations of readsPrec (and its cousin, readList) -- will simply use readPrec under the hood. If you are writing a -- Read instance by hand, it is recommended to write it like so: -- --
--   instance Read T where
--     readPrec     = ...
--     readListPrec = readListPrecDefault
--   
class Read a -- | attempts to parse a value from the front of the string, returning a -- list of (parsed value, remaining string) pairs. If there is no -- successful parse, the returned list is empty. -- -- Derived instances of Read and Show satisfy the -- following: -- -- -- -- That is, readsPrec parses the string produced by -- showsPrec, and delivers the value that showsPrec started -- with. readsPrec :: Read a => Int -> ReadS a -- | The method readList is provided to allow the programmer to give -- a specialised way of parsing lists of values. For example, this is -- used by the predefined Read instance of the Char type, -- where values of type String should be are expected to use -- double quotes, rather than square brackets. readList :: Read a => ReadS [a] -- | Proposed replacement for readsPrec using new-style parsers (GHC -- only). readPrec :: Read a => ReadPrec a -- | Proposed replacement for readList using new-style parsers (GHC -- only). The default definition uses readList. Instances that -- define readPrec should also define readListPrec as -- readListPrecDefault. readListPrec :: Read a => ReadPrec [a] -- | Monads in which IO computations may be embedded. Any monad -- built by applying a sequence of monad transformers to the IO -- monad will be an instance of this class. -- -- Instances should satisfy the following laws, which state that -- liftIO is a transformer of monads: -- -- class Monad m => MonadIO (m :: Type -> Type) -- | Lift a computation from the IO monad. This allows us to run IO -- computations in any monadic stack, so long as it supports these kinds -- of operations (i.e. IO is the base monad for the stack). -- --

Example

-- --
--   import Control.Monad.Trans.State -- from the "transformers" library
--   
--   printState :: Show s => StateT s IO ()
--   printState = do
--     state <- get
--     liftIO $ print state
--   
-- -- Had we omitted liftIO, we would have ended up with -- this error: -- --
--   • Couldn't match type ‘IO’ with ‘StateT s IO’
--    Expected type: StateT s IO ()
--      Actual type: IO ()
--   
-- -- The important part here is the mismatch between StateT s IO -- () and IO (). -- -- Luckily, we know of a function that takes an IO a and -- returns an (m a): liftIO, enabling us to run -- the program and see the expected results: -- --
--   > evalStateT printState "hello"
--   "hello"
--   
--   > evalStateT printState 3
--   3
--   
liftIO :: MonadIO m => IO a -> m a -- | A class for monads in which exceptions may be thrown. -- -- Instances should obey the following law: -- --
--   throwM e >> x = throwM e
--   
-- -- In other words, throwing an exception short-circuits the rest of the -- monadic computation. class Monad m => MonadThrow (m :: Type -> Type) -- | Throw an exception. Note that this throws when this action is run in -- the monad m, not when it is applied. It is a generalization -- of Control.Exception's throwIO. -- -- Should satisfy the law: -- --
--   throwM e >> f = throwM e
--   
throwM :: (MonadThrow m, Exception e) => e -> m a -- | See examples in Control.Monad.Reader. Note, the partially -- applied function type (->) r is a simple reader monad. See -- the instance declaration below. class Monad m => MonadReader r (m :: Type -> Type) | m -> r -- | Retrieves the monad environment. ask :: MonadReader r m => m r -- | Executes a computation in a modified environment. local :: MonadReader r m => (r -> r) -> m a -> m a -- | Retrieves a function of the current environment. reader :: MonadReader r m => (r -> a) -> m a -- | The class of monad transformers. Instances should satisfy the -- following laws, which state that lift is a monad -- transformation: -- -- class MonadTrans (t :: Type -> Type -> Type -> Type) -- | Lift a computation from the argument monad to the constructed monad. lift :: (MonadTrans t, Monad m) => m a -> t m a -- | Identity functor and monad. (a non-strict monad) data Identity a -- | The IsList class and its methods are intended to be used in -- conjunction with the OverloadedLists extension. class IsList l -- | Class for string-like datastructures; used by the overloaded string -- extension (-XOverloadedStrings in GHC). class IsString a -- | In many situations, the liftM operations can be replaced by -- uses of ap, which promotes function application. -- --
--   return f `ap` x1 `ap` ... `ap` xn
--   
-- -- is equivalent to -- --
--   liftMn f x1 x2 ... xn
--   
ap :: Monad m => m (a -> b) -> m a -> m b -- | To run examples in this module: -- --
--   >>> import qualified Streamly.Prelude as Stream
--   
-- | Deprecated: Please use Streamly.Internal.Data.Stream from -- streamly-core package instead. module Streamly.Internal.Data.Stream.Serial -- | For SerialT streams: -- --
--   (<>) = serial                       -- Semigroup
--   (>>=) = flip . concatMapWith serial -- Monad
--   
-- -- A single Monad bind behaves like a for loop: -- --
--   >>> :{
--   IsStream.toList $ do
--        x <- IsStream.fromList [1,2] -- foreach x in stream
--        return x
--   :}
--   [1,2]
--   
-- -- Nested monad binds behave like nested for loops: -- --
--   >>> :{
--   IsStream.toList $ do
--       x <- IsStream.fromList [1,2] -- foreach x in stream
--       y <- IsStream.fromList [3,4] -- foreach y in stream
--       return (x, y)
--   :}
--   [(1,3),(1,4),(2,3),(2,4)]
--   
-- -- Since: 0.2.0 (Streamly) newtype SerialT m a SerialT :: Stream m a -> SerialT m a [getSerialT] :: SerialT m a -> Stream m a toStreamK :: SerialT m a -> Stream m a fromStreamK :: Stream m a -> SerialT m a -- | A serial IO stream of elements of type a. See SerialT -- documentation for more details. -- -- Since: 0.2.0 (Streamly) type Serial = SerialT IO serial :: SerialT m a -> SerialT m a -> SerialT m a -- | For WSerialT streams: -- --
--   (<>) = wSerial                       -- Semigroup
--   (>>=) = flip . concatMapWith wSerial -- Monad
--   
-- -- Note that <> is associative only if we disregard the -- ordering of elements in the resulting stream. -- -- A single Monad bind behaves like a for loop: -- --
--   >>> :{
--   IsStream.toList $ IsStream.fromWSerial $ do
--        x <- IsStream.fromList [1,2] -- foreach x in stream
--        return x
--   :}
--   [1,2]
--   
-- -- Nested monad binds behave like interleaved nested for loops: -- --
--   >>> :{
--   IsStream.toList $ IsStream.fromWSerial $ do
--       x <- IsStream.fromList [1,2] -- foreach x in stream
--       y <- IsStream.fromList [3,4] -- foreach y in stream
--       return (x, y)
--   :}
--   [(1,3),(2,3),(1,4),(2,4)]
--   
-- -- It is a result of interleaving all the nested iterations corresponding -- to element 1 in the first stream with all the nested -- iterations of element 2: -- --
--   >>> import Streamly.Prelude (wSerial)
--   
--   >>> IsStream.toList $ IsStream.fromList [(1,3),(1,4)] `IsStream.wSerial` IsStream.fromList [(2,3),(2,4)]
--   [(1,3),(2,3),(1,4),(2,4)]
--   
-- -- The W in the name stands for wide or breadth wise -- scheduling in contrast to the depth wise scheduling behavior of -- SerialT. -- -- Since: 0.2.0 (Streamly) newtype WSerialT m a WSerialT :: Stream m a -> WSerialT m a [getWSerialT] :: WSerialT m a -> Stream m a -- | An interleaving serial IO stream of elements of type a. See -- WSerialT documentation for more details. -- -- Since: 0.2.0 (Streamly) type WSerial = WSerialT IO -- | Interleaves two streams, yielding one element from each stream -- alternately. When one stream stops the rest of the other stream is -- used in the output stream. -- -- This gives exponential priority to earlier streams than the ones -- joining later. Because of exponential weighting it can be used with -- concatMapWith. -- -- Not fused wSerial :: WSerialT m a -> WSerialT m a -> WSerialT m a infixr 6 `wSerial` wSerialFst :: WSerialT m a -> WSerialT m a -> WSerialT m a wSerialMin :: WSerialT m a -> WSerialT m a -> WSerialT m a consMWSerial :: Monad m => m a -> WSerialT m a -> WSerialT m a cons :: a -> SerialT m a -> SerialT m a infixr 5 `cons` consM :: Monad m => m a -> SerialT m a -> SerialT m a infixr 5 `consM` -- | Generate an infinite stream by repeating a pure value. repeat :: Monad m => a -> SerialT m a -- | Build a stream by unfolding a monadic step function starting -- from a seed. The step function returns the next element in the stream -- and the next seed value. When it is done it returns Nothing and -- the stream ends. For example, -- --
--   let f b =
--           if b > 3
--           then return Nothing
--           else print b >> return (Just (b, b + 1))
--   in drain $ unfoldrM f 0
--   
-- --
--   0
--   1
--   2
--   3
--   
-- -- Pre-release unfoldrM :: Monad m => (b -> m (Maybe (a, b))) -> b -> SerialT m a -- | The fromList function constructs the structure l from -- the given list of Item l fromList :: IsList l => [Item l] -> l -- | The toList function extracts a list of Item l from the -- structure l. It should satisfy fromList . toList = id. toList :: IsList l => l -> [Item l] -- |
--   map = fmap
--   
-- -- Same as fmap. -- --
--   > S.toList $ S.map (+1) $ S.fromList [1,2,3]
--   [2,3,4]
--   
map :: Monad m => (a -> b) -> SerialT m a -> SerialT m b mapM :: Monad m => (a -> m b) -> SerialT m a -> SerialT m b instance GHC.Base.Monoid (Streamly.Internal.Data.Stream.Serial.SerialT m a) instance GHC.Base.Semigroup (Streamly.Internal.Data.Stream.Serial.SerialT m a) instance Control.Monad.Trans.Class.MonadTrans Streamly.Internal.Data.Stream.Serial.WSerialT instance GHC.Base.Semigroup (Streamly.Internal.Data.Stream.Serial.WSerialT m a) instance GHC.Base.Monoid (Streamly.Internal.Data.Stream.Serial.WSerialT m a) instance GHC.Base.Monad m => GHC.Base.Applicative (Streamly.Internal.Data.Stream.Serial.WSerialT m) instance GHC.Base.Monad m => GHC.Base.Monad (Streamly.Internal.Data.Stream.Serial.WSerialT m) instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.Serial.WSerialT m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Streamly.Internal.Data.Stream.Serial.WSerialT m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Streamly.Internal.Data.Stream.Serial.WSerialT m) instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Streamly.Internal.Data.Stream.Serial.WSerialT m) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Streamly.Internal.Data.Stream.Serial.WSerialT m) instance GHC.Exts.IsList (Streamly.Internal.Data.Stream.Serial.WSerialT Data.Functor.Identity.Identity a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Streamly.Internal.Data.Stream.Serial.WSerialT Data.Functor.Identity.Identity a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Streamly.Internal.Data.Stream.Serial.WSerialT Data.Functor.Identity.Identity a) instance GHC.Show.Show a => GHC.Show.Show (Streamly.Internal.Data.Stream.Serial.WSerialT Data.Functor.Identity.Identity a) instance GHC.Read.Read a => GHC.Read.Read (Streamly.Internal.Data.Stream.Serial.WSerialT Data.Functor.Identity.Identity a) instance (a GHC.Types.~ GHC.Types.Char) => Data.String.IsString (Streamly.Internal.Data.Stream.Serial.WSerialT Data.Functor.Identity.Identity a) instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Streamly.Internal.Data.Stream.Serial.WSerialT Data.Functor.Identity.Identity a) instance Control.DeepSeq.NFData1 (Streamly.Internal.Data.Stream.Serial.WSerialT Data.Functor.Identity.Identity) instance (Data.Foldable.Foldable m, GHC.Base.Monad m) => Data.Foldable.Foldable (Streamly.Internal.Data.Stream.Serial.WSerialT m) instance Data.Traversable.Traversable (Streamly.Internal.Data.Stream.Serial.WSerialT Data.Functor.Identity.Identity) instance GHC.Base.Monad m => GHC.Base.Monad (Streamly.Internal.Data.Stream.Serial.SerialT m) instance Control.Monad.Trans.Class.MonadTrans Streamly.Internal.Data.Stream.Serial.SerialT instance GHC.Base.Monad m => GHC.Base.Applicative (Streamly.Internal.Data.Stream.Serial.SerialT m) instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.Serial.SerialT m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Streamly.Internal.Data.Stream.Serial.SerialT m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Streamly.Internal.Data.Stream.Serial.SerialT m) instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Streamly.Internal.Data.Stream.Serial.SerialT m) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Streamly.Internal.Data.Stream.Serial.SerialT m) instance GHC.Exts.IsList (Streamly.Internal.Data.Stream.Serial.SerialT Data.Functor.Identity.Identity a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Streamly.Internal.Data.Stream.Serial.SerialT Data.Functor.Identity.Identity a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Streamly.Internal.Data.Stream.Serial.SerialT Data.Functor.Identity.Identity a) instance GHC.Show.Show a => GHC.Show.Show (Streamly.Internal.Data.Stream.Serial.SerialT Data.Functor.Identity.Identity a) instance GHC.Read.Read a => GHC.Read.Read (Streamly.Internal.Data.Stream.Serial.SerialT Data.Functor.Identity.Identity a) instance (a GHC.Types.~ GHC.Types.Char) => Data.String.IsString (Streamly.Internal.Data.Stream.Serial.SerialT Data.Functor.Identity.Identity a) instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Streamly.Internal.Data.Stream.Serial.SerialT Data.Functor.Identity.Identity a) instance Control.DeepSeq.NFData1 (Streamly.Internal.Data.Stream.Serial.SerialT Data.Functor.Identity.Identity) instance (Data.Foldable.Foldable m, GHC.Base.Monad m) => Data.Foldable.Foldable (Streamly.Internal.Data.Stream.Serial.SerialT m) instance Data.Traversable.Traversable (Streamly.Internal.Data.Stream.Serial.SerialT Data.Functor.Identity.Identity) instance (Control.Monad.Base.MonadBase b m, GHC.Base.Monad m) => Control.Monad.Base.MonadBase b (Streamly.Internal.Data.Stream.Serial.SerialT m) -- | Deprecated: This module will be removed in future. module Streamly.Internal.Data.Stream.SVar -- | Fold the supplied stream to the SVar asynchronously using Parallel -- concurrency style. {-# INLINE [1] toSVarParallel #-} toSVarParallel :: MonadAsync m => State t m a -> SVar t m a -> Stream m a -> m () -- | Create a Fold style SVar that runs a supplied fold function as the -- consumer. Any elements sent to the SVar are consumed by the supplied -- fold function. newFoldSVar :: MonadAsync m => State Stream m a -> (SerialT m a -> m b) -> m (SVar Stream m a) -- | Like newFoldSVar except that it uses a Fold instead of a -- fold function. newFoldSVarF :: MonadAsync m => State t m a -> Fold m a b -> m (SVar t m a) -- | Poll for events sent by the fold consumer to the stream pusher. The -- fold consumer can send a Stop event or an exception. When a -- Stop is received this function returns True. If an -- exception is recieved then it throws the exception. fromConsumer :: MonadAsync m => SVar Stream m a -> m Bool -- | Push values from a stream to a fold worker via an SVar. Before pushing -- a value to the SVar it polls for events received from the fold -- consumer. If a stop event is received then it returns True -- otherwise false. Propagates exceptions received from the fold -- consumer. pushToFold :: MonadAsync m => SVar Stream m a -> a -> m Bool -- | Tap a stream and send the elements to the specified SVar in addition -- to yielding them again. The SVar runs a fold consumer. Elements are -- tapped and sent to the SVar until the fold finishes. Any exceptions -- from the fold evaluation are propagated in the current thread. -- --
--   ------input stream---------output stream----->
--                      /|\   |
--           exceptions  |    |  input
--                       |   \|/
--                       ----SVar
--                            |
--                           Fold
--   
teeToSVar :: MonadAsync m => SVar Stream m a -> SerialT m a -> SerialT m a -- | Write a stream to an SVar in a non-blocking manner. The stream -- can then be read back from the SVar using fromSVar. toSVar :: MonadAsync m => SVar SerialT m a -> SerialT m a -> m () -- | Generate a stream from an SVar. An unevaluated stream can be pushed to -- an SVar using toSVar. As we pull a stream from the SVar the -- input stream gets evaluated concurrently. The evaluation depends on -- the SVar style and the configuration parameters e.g. using the -- maxBuffer/maxThreads combinators. fromSVar :: MonadAsync m => SVar Stream m a -> SerialT m a -- | Like fromSVar but generates a StreamD style stream instead of -- CPS. fromSVarD :: MonadAsync m => SVar t m a -> Stream m a -- | To run examples in this module: -- --
--   >>> import qualified Streamly.Prelude as Stream
--   
--   >>> import Control.Concurrent (threadDelay)
--   
--   >>> :{
--    delay n = do
--        threadDelay (n * 1000000)   -- sleep for n seconds
--        putStrLn (show n ++ " sec") -- print "n sec"
--        return n                    -- IO Int
--   :}
--   
-- | Deprecated: Please use -- Streamly.Internal.Data.Stream.Concurrent instead. module Streamly.Internal.Data.Stream.Parallel -- | For ParallelT streams: -- --
--   (<>) = parallel
--   (>>=) = flip . concatMapWith parallel
--   
-- -- See AsyncT, ParallelT is similar except that all -- iterations are strictly concurrent while in AsyncT it depends -- on the consumer demand and available threads. See parallel -- for more details. -- -- Since: 0.1.0 (Streamly) -- -- Since: 0.7.0 (maxBuffer applies to ParallelT streams) newtype ParallelT m a ParallelT :: StreamK m a -> ParallelT m a [getParallelT] :: ParallelT m a -> StreamK m a -- | A parallely composing IO stream of elements of type a. See -- ParallelT documentation for more details. -- -- Since: 0.2.0 (Streamly) type Parallel = ParallelT IO -- | XXX we can implement it more efficienty by directly implementing -- instead of combining streams using parallel. consM :: MonadAsync m => m a -> ParallelT m a -> ParallelT m a parallelK :: MonadAsync m => StreamK m a -> StreamK m a -> StreamK m a -- | Like parallel but stops the output as soon as the first -- stream stops. -- -- Pre-release parallelFstK :: MonadAsync m => StreamK m a -> StreamK m a -> StreamK m a -- | Like parallel but stops the output as soon as any of the two -- streams stops. -- -- Pre-release parallelMinK :: MonadAsync m => StreamK m a -> StreamK m a -> StreamK m a -- | Same as mkParallel but for StreamD stream. mkParallelD :: MonadAsync m => Stream m a -> Stream m a -- | Like mkParallel but uses StreamK internally. -- -- Pre-release mkParallelK :: MonadAsync m => StreamK m a -> StreamK m a -- | Redirect a copy of the stream to a supplied fold and run it -- concurrently in an independent thread. The fold may buffer some -- elements. The buffer size is determined by the prevailing -- maxBuffer setting. -- --
--                 StreamK m a -> m b
--                         |
--   -----stream m a ---------------stream m a-----
--   
-- --
--   > S.drain $ S.tapAsync (S.mapM_ print) (S.enumerateFromTo 1 2)
--   1
--   2
--   
-- -- Exceptions from the concurrently running fold are propagated to the -- current computation. Note that, because of buffering in the fold, -- exceptions may be delayed and may not correspond to the current -- element being processed in the parent stream, but we guarantee that -- before the parent stream stops the tap finishes and all exceptions -- from it are drained. -- -- Compare with tap. -- -- Pre-release tapAsyncK :: MonadAsync m => (StreamK m a -> m b) -> StreamK m a -> StreamK m a -- | Like tapAsync but uses a Fold instead of a fold -- function. tapAsyncF :: MonadAsync m => Fold m a b -> Stream m a -> Stream m a -- | Generates a callback and a stream pair. The callback returned is used -- to queue values to the stream. The stream is infinite, there is no way -- for the callback to indicate that it is done now. -- -- Pre-release newCallbackStream :: MonadAsync m => m (a -> m (), StreamK m a) instance Control.Monad.Trans.Class.MonadTrans Streamly.Internal.Data.Stream.Parallel.ParallelT instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Semigroup (Streamly.Internal.Data.Stream.Parallel.ParallelT m a) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Monoid (Streamly.Internal.Data.Stream.Parallel.ParallelT m a) instance (GHC.Base.Monad m, Streamly.Internal.Control.Concurrent.MonadAsync m) => GHC.Base.Applicative (Streamly.Internal.Data.Stream.Parallel.ParallelT m) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Monad (Streamly.Internal.Data.Stream.Parallel.ParallelT m) instance (Control.Monad.Base.MonadBase b m, GHC.Base.Monad m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Base.MonadBase b (Streamly.Internal.Data.Stream.Parallel.ParallelT m) instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.Parallel.ParallelT m) instance (Control.Monad.IO.Class.MonadIO m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.IO.Class.MonadIO (Streamly.Internal.Data.Stream.Parallel.ParallelT m) instance (Control.Monad.Catch.MonadThrow m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Catch.MonadThrow (Streamly.Internal.Data.Stream.Parallel.ParallelT m) instance (Control.Monad.Reader.Class.MonadReader r m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Reader.Class.MonadReader r (Streamly.Internal.Data.Stream.Parallel.ParallelT m) instance (Control.Monad.State.Class.MonadState s m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.State.Class.MonadState s (Streamly.Internal.Data.Stream.Parallel.ParallelT m) -- | To run examples in this module: -- --
--   >>> import qualified Streamly.Prelude as Stream
--   
--   >>> import Control.Concurrent (threadDelay)
--   
--   >>> :{
--    delay n = do
--        threadDelay (n * 1000000)   -- sleep for n seconds
--        putStrLn (show n ++ " sec") -- print "n sec"
--        return n                    -- IO Int
--   :}
--   
-- | Deprecated: Please use -- Streamly.Internal.Data.Stream.Concurrent from streamly package -- instead. module Streamly.Internal.Data.Stream.Async -- | For AsyncT streams: -- --
--   (<>) = async
--   (>>=) = flip . concatMapWith async
--   
-- -- A single Monad bind behaves like a for loop with -- iterations of the loop executed concurrently a la the async -- combinator, producing results and side effects of iterations out of -- order: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAsync $ do
--        x <- Stream.fromList [2,1] -- foreach x in stream
--        Stream.fromEffect $ delay x
--   :}
--   1 sec
--   2 sec
--   [1,2]
--   
-- -- Nested monad binds behave like nested for loops with nested -- iterations executed concurrently, a la the async combinator: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAsync $ do
--       x <- Stream.fromList [1,2] -- foreach x in stream
--       y <- Stream.fromList [2,4] -- foreach y in stream
--       Stream.fromEffect $ delay (x + y)
--   :}
--   3 sec
--   4 sec
--   5 sec
--   6 sec
--   [3,4,5,6]
--   
-- -- The behavior can be explained as follows. All the iterations -- corresponding to the element 1 in the first stream constitute -- one output stream and all the iterations corresponding to 2 -- constitute another output stream and these two output streams are -- merged using async. -- -- Since: 0.1.0 (Streamly) newtype AsyncT m a AsyncT :: Stream m a -> AsyncT m a [getAsyncT] :: AsyncT m a -> Stream m a -- | A demand driven left biased parallely composing IO stream of elements -- of type a. See AsyncT documentation for more details. -- -- Since: 0.2.0 (Streamly) type Async = AsyncT IO -- | XXX we can implement it more efficienty by directly implementing -- instead of combining streams using async. consMAsync :: MonadAsync m => m a -> AsyncT m a -> AsyncT m a asyncK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a -- | Generate a stream asynchronously to keep it buffered, lazily consume -- from the buffer. -- -- Pre-release mkAsyncK :: MonadAsync m => Stream m a -> Stream m a mkAsyncD :: MonadAsync m => Stream m a -> Stream m a -- | For WAsyncT streams: -- --
--   (<>) = wAsync
--   (>>=) = flip . concatMapWith wAsync
--   
-- -- A single Monad bind behaves like a for loop with -- iterations of the loop executed concurrently a la the wAsync -- combinator, producing results and side effects of iterations out of -- order: -- --
--   >>> :{
--   Stream.toList $ Stream.fromWAsync $ do
--        x <- Stream.fromList [2,1] -- foreach x in stream
--        Stream.fromEffect $ delay x
--   :}
--   1 sec
--   2 sec
--   [1,2]
--   
-- -- Nested monad binds behave like nested for loops with nested -- iterations executed concurrently, a la the wAsync combinator: -- --
--   >>> :{
--   Stream.toList $ Stream.fromWAsync $ do
--       x <- Stream.fromList [1,2] -- foreach x in stream
--       y <- Stream.fromList [2,4] -- foreach y in stream
--       Stream.fromEffect $ delay (x + y)
--   :}
--   3 sec
--   4 sec
--   5 sec
--   6 sec
--   [3,4,5,6]
--   
-- -- The behavior can be explained as follows. All the iterations -- corresponding to the element 1 in the first stream constitute -- one WAsyncT output stream and all the iterations corresponding -- to 2 constitute another WAsyncT output stream and -- these two output streams are merged using wAsync. -- -- The W in the name stands for wide or breadth wise -- scheduling in contrast to the depth wise scheduling behavior of -- AsyncT. -- -- Since: 0.2.0 (Streamly) newtype WAsyncT m a WAsyncT :: Stream m a -> WAsyncT m a [getWAsyncT] :: WAsyncT m a -> Stream m a -- | A round robin parallely composing IO stream of elements of type -- a. See WAsyncT documentation for more details. -- -- Since: 0.2.0 (Streamly) type WAsync = WAsyncT IO -- | XXX we can implement it more efficienty by directly implementing -- instead of combining streams using wAsync. consMWAsync :: MonadAsync m => m a -> WAsyncT m a -> WAsyncT m a wAsyncK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a instance Control.Monad.Trans.Class.MonadTrans Streamly.Internal.Data.Stream.Async.WAsyncT instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Semigroup (Streamly.Internal.Data.Stream.Async.WAsyncT m a) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Monoid (Streamly.Internal.Data.Stream.Async.WAsyncT m a) instance (GHC.Base.Monad m, Streamly.Internal.Control.Concurrent.MonadAsync m) => GHC.Base.Applicative (Streamly.Internal.Data.Stream.Async.WAsyncT m) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Monad (Streamly.Internal.Data.Stream.Async.WAsyncT m) instance (Control.Monad.Base.MonadBase b m, GHC.Base.Monad m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Base.MonadBase b (Streamly.Internal.Data.Stream.Async.WAsyncT m) instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.Async.WAsyncT m) instance (Control.Monad.IO.Class.MonadIO m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.IO.Class.MonadIO (Streamly.Internal.Data.Stream.Async.WAsyncT m) instance (Control.Monad.Catch.MonadThrow m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Catch.MonadThrow (Streamly.Internal.Data.Stream.Async.WAsyncT m) instance (Control.Monad.Reader.Class.MonadReader r m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Reader.Class.MonadReader r (Streamly.Internal.Data.Stream.Async.WAsyncT m) instance (Control.Monad.State.Class.MonadState s m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.State.Class.MonadState s (Streamly.Internal.Data.Stream.Async.WAsyncT m) instance Control.Monad.Trans.Class.MonadTrans Streamly.Internal.Data.Stream.Async.AsyncT instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Semigroup (Streamly.Internal.Data.Stream.Async.AsyncT m a) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Monoid (Streamly.Internal.Data.Stream.Async.AsyncT m a) instance (GHC.Base.Monad m, Streamly.Internal.Control.Concurrent.MonadAsync m) => GHC.Base.Applicative (Streamly.Internal.Data.Stream.Async.AsyncT m) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Monad (Streamly.Internal.Data.Stream.Async.AsyncT m) instance (Control.Monad.Base.MonadBase b m, GHC.Base.Monad m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Base.MonadBase b (Streamly.Internal.Data.Stream.Async.AsyncT m) instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.Async.AsyncT m) instance (Control.Monad.IO.Class.MonadIO m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.IO.Class.MonadIO (Streamly.Internal.Data.Stream.Async.AsyncT m) instance (Control.Monad.Catch.MonadThrow m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Catch.MonadThrow (Streamly.Internal.Data.Stream.Async.AsyncT m) instance (Control.Monad.Reader.Class.MonadReader r m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Reader.Class.MonadReader r (Streamly.Internal.Data.Stream.Async.AsyncT m) instance (Control.Monad.State.Class.MonadState s m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.State.Class.MonadState s (Streamly.Internal.Data.Stream.Async.AsyncT m) -- | To run examples in this module: -- --
--   >>> import qualified Streamly.Prelude as Stream
--   
--   >>> import Control.Concurrent (threadDelay)
--   
--   >>> :{
--    delay n = do
--        threadDelay (n * 1000000)   -- sleep for n seconds
--        putStrLn (show n ++ " sec") -- print "n sec"
--        return n                    -- IO Int
--   :}
--   
-- | Deprecated: Please use -- Streamly.Internal.Data.Stream.Concurrent from streamly package -- instead. module Streamly.Internal.Data.Stream.Ahead -- | For AheadT streams: -- --
--   (<>) = ahead
--   (>>=) = flip . concatMapWith ahead
--   
-- -- A single Monad bind behaves like a for loop with -- iterations executed concurrently, ahead of time, producing side -- effects of iterations out of order, but results in order: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAhead $ do
--        x <- Stream.fromList [2,1] -- foreach x in stream
--        Stream.fromEffect $ delay x
--   :}
--   1 sec
--   2 sec
--   [2,1]
--   
-- -- Nested monad binds behave like nested for loops with nested -- iterations executed concurrently, ahead of time: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAhead $ do
--       x <- Stream.fromList [1,2] -- foreach x in stream
--       y <- Stream.fromList [2,4] -- foreach y in stream
--       Stream.fromEffect $ delay (x + y)
--   :}
--   3 sec
--   4 sec
--   5 sec
--   6 sec
--   [3,5,4,6]
--   
-- -- The behavior can be explained as follows. All the iterations -- corresponding to the element 1 in the first stream constitute -- one output stream and all the iterations corresponding to 2 -- constitute another output stream and these two output streams are -- merged using ahead. -- -- Since: 0.3.0 (Streamly) newtype AheadT m a AheadT :: Stream m a -> AheadT m a [getAheadT] :: AheadT m a -> Stream m a -- | A serial IO stream of elements of type a with concurrent -- lookahead. See AheadT documentation for more details. -- -- Since: 0.3.0 (Streamly) type Ahead = AheadT IO aheadK :: MonadAsync m => Stream m a -> Stream m a -> Stream m a -- | XXX we can implement it more efficienty by directly implementing -- instead of combining streams using ahead. consM :: MonadAsync m => m a -> AheadT m a -> AheadT m a instance Control.Monad.Trans.Class.MonadTrans Streamly.Internal.Data.Stream.Ahead.AheadT instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Semigroup (Streamly.Internal.Data.Stream.Ahead.AheadT m a) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Monoid (Streamly.Internal.Data.Stream.Ahead.AheadT m a) instance (GHC.Base.Monad m, Streamly.Internal.Control.Concurrent.MonadAsync m) => GHC.Base.Applicative (Streamly.Internal.Data.Stream.Ahead.AheadT m) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Monad (Streamly.Internal.Data.Stream.Ahead.AheadT m) instance (Control.Monad.Base.MonadBase b m, GHC.Base.Monad m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Base.MonadBase b (Streamly.Internal.Data.Stream.Ahead.AheadT m) instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.Ahead.AheadT m) instance (Control.Monad.IO.Class.MonadIO m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.IO.Class.MonadIO (Streamly.Internal.Data.Stream.Ahead.AheadT m) instance (Control.Monad.Catch.MonadThrow m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Catch.MonadThrow (Streamly.Internal.Data.Stream.Ahead.AheadT m) instance (Control.Monad.Reader.Class.MonadReader r m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.Reader.Class.MonadReader r (Streamly.Internal.Data.Stream.Ahead.AheadT m) instance (Control.Monad.State.Class.MonadState s m, Streamly.Internal.Control.Concurrent.MonadAsync m) => Control.Monad.State.Class.MonadState s (Streamly.Internal.Data.Stream.Ahead.AheadT m) module Streamly.Internal.Data.Stream.Prelude -- | A mutable channel to evaluate multiple streams concurrently and -- provide the combined results as output stream. data Channel m a Channel :: RunInIO m -> IORef ([ChildEvent a], Int) -> MVar () -> m [ChildEvent a] -> m Bool -> Limit -> Limit -> Maybe (IORef Count) -> Maybe YieldRateInfo -> (Bool -> (RunInIO m, StreamK m a) -> IO ()) -> m () -> IO Bool -> IO Bool -> IORef Bool -> (Maybe WorkerInfo -> m ()) -> IORef (Set ThreadId) -> IORef Int -> (ThreadId -> m ()) -> MVar () -> Maybe (IORef ()) -> SVarStats -> Bool -> ThreadId -> Channel m a [svarMrun] :: Channel m a -> RunInIO m [outputQueue] :: Channel m a -> IORef ([ChildEvent a], Int) [outputDoorBell] :: Channel m a -> MVar () [readOutputQ] :: Channel m a -> m [ChildEvent a] [postProcess] :: Channel m a -> m Bool [maxWorkerLimit] :: Channel m a -> Limit [maxBufferLimit] :: Channel m a -> Limit [remainingWork] :: Channel m a -> Maybe (IORef Count) [yieldRateInfo] :: Channel m a -> Maybe YieldRateInfo [enqueue] :: Channel m a -> Bool -> (RunInIO m, StreamK m a) -> IO () [eagerDispatch] :: Channel m a -> m () [isWorkDone] :: Channel m a -> IO Bool [isQueueDone] :: Channel m a -> IO Bool [doorBellOnWorkQ] :: Channel m a -> IORef Bool [workLoop] :: Channel m a -> Maybe WorkerInfo -> m () [workerThreads] :: Channel m a -> IORef (Set ThreadId) [workerCount] :: Channel m a -> IORef Int [accountThread] :: Channel m a -> ThreadId -> m () [workerStopMVar] :: Channel m a -> MVar () [svarRef] :: Channel m a -> Maybe (IORef ()) [svarStats] :: Channel m a -> SVarStats [svarInspectMode] :: Channel m a -> Bool [svarCreator] :: Channel m a -> ThreadId yield :: Channel m a -> Maybe WorkerInfo -> a -> IO Bool stop :: Channel m a -> Maybe WorkerInfo -> IO () -- | Stop the channel. Kill all running worker threads. stopChannel :: MonadIO m => Channel m a -> m () dumpSVar :: Channel m a -> IO String -- | Send a stream to a given channel for concurrent evaluation. toChannel :: MonadRunInIO m => Channel m a -> Stream m a -> m () -- | Write a stream to an SVar in a non-blocking manner. The -- stream can then be read back from the SVar using fromSVar. toChannelK :: MonadRunInIO m => Channel m a -> StreamK m a -> m () -- | Generate a stream of results from concurrent evaluations from a -- channel. Evaluation of the channel does not start until this API is -- called. This API must not be called more than once on a channel. It -- kicks off evaluation of the channel by dispatching concurrent workers -- and ensures that as long there is work queued on the channel workers -- are dispatched proportional to the demand by the consumer. fromChannel :: MonadAsync m => Channel m a -> Stream m a fromChannelK :: MonadAsync m => Channel m a -> StreamK m a -- | Create a new async style concurrent stream evaluation channel. The -- monad state used to run the stream actions is taken from the call site -- of newAppendChannel. newAppendChannel :: MonadRunInIO m => (Config -> Config) -> m (Channel m a) -- | Create a new async style concurrent stream evaluation channel. The -- monad state used to run the stream actions is taken from the call site -- of newInterleaveChannel. newInterleaveChannel :: MonadAsync m => (Config -> Config) -> m (Channel m a) pushWorker :: MonadRunInIO m => Count -> Channel m a -> m () dispatchWorker :: MonadRunInIO m => Count -> Channel m a -> m Bool dispatchWorkerPaced :: MonadRunInIO m => Channel m a -> m Bool sendWorkerWait :: MonadIO m => Bool -> (Channel m a -> IO ()) -> (Channel m a -> m Bool) -> Channel m a -> m () -- | Start the evaluation of the channel's work queue by kicking off a -- worker. Note: Work queue must not be empty otherwise the worker will -- exit without doing anything. startChannel :: MonadRunInIO m => Channel m a -> m () sendWorkerDelay :: Channel m a -> IO () sendWorkerDelayPaced :: Channel m a -> IO () readOutputQPaced :: MonadRunInIO m => Channel m a -> m [ChildEvent a] readOutputQBounded :: MonadRunInIO m => Bool -> Channel m a -> m [ChildEvent a] postProcessPaced :: MonadRunInIO m => Channel m a -> m Bool postProcessBounded :: MonadRunInIO m => Channel m a -> m Bool -- | A mutable channel to evaluate multiple streams concurrently and -- provide the combined results as output stream. data Channel m a Channel :: RunInIO m -> IORef ([ChildEvent a], Int) -> MVar () -> m [ChildEvent a] -> m Bool -> Limit -> Limit -> Maybe (IORef Count) -> Maybe YieldRateInfo -> (Bool -> (RunInIO m, StreamK m a) -> IO ()) -> m () -> IO Bool -> IO Bool -> IORef Bool -> (Maybe WorkerInfo -> m ()) -> IORef (Set ThreadId) -> IORef Int -> (ThreadId -> m ()) -> MVar () -> Maybe (IORef ()) -> SVarStats -> Bool -> ThreadId -> Channel m a [svarMrun] :: Channel m a -> RunInIO m [outputQueue] :: Channel m a -> IORef ([ChildEvent a], Int) [outputDoorBell] :: Channel m a -> MVar () [readOutputQ] :: Channel m a -> m [ChildEvent a] [postProcess] :: Channel m a -> m Bool [maxWorkerLimit] :: Channel m a -> Limit [maxBufferLimit] :: Channel m a -> Limit [remainingWork] :: Channel m a -> Maybe (IORef Count) [yieldRateInfo] :: Channel m a -> Maybe YieldRateInfo [enqueue] :: Channel m a -> Bool -> (RunInIO m, StreamK m a) -> IO () [eagerDispatch] :: Channel m a -> m () [isWorkDone] :: Channel m a -> IO Bool [isQueueDone] :: Channel m a -> IO Bool [doorBellOnWorkQ] :: Channel m a -> IORef Bool [workLoop] :: Channel m a -> Maybe WorkerInfo -> m () [workerThreads] :: Channel m a -> IORef (Set ThreadId) [workerCount] :: Channel m a -> IORef Int [accountThread] :: Channel m a -> ThreadId -> m () [workerStopMVar] :: Channel m a -> MVar () [svarRef] :: Channel m a -> Maybe (IORef ()) [svarStats] :: Channel m a -> SVarStats [svarInspectMode] :: Channel m a -> Bool [svarCreator] :: Channel m a -> ThreadId -- | Create a new concurrent stream evaluation channel. The monad state -- used to run the stream actions is captured from the call site of -- newChannel. newChannel :: MonadAsync m => (Config -> Config) -> m (Channel m a) -- | Allocate a channel and evaluate the stream using the channel and the -- supplied evaluator function. The evaluator is run in a worker thread. withChannel :: MonadAsync m => (Config -> Config) -> Stream m a -> (Channel m b -> Stream m a -> Stream m b) -> Stream m b -- | Allocate a channel and evaluate the stream using the channel and the -- supplied evaluator function. The evaluator is run in a worker thread. withChannelK :: MonadAsync m => (Config -> Config) -> StreamK m a -> (Channel m b -> StreamK m a -> StreamK m b) -> StreamK m b -- | An abstract type for specifying the configuration parameters of a -- Channel. Use Config -> Config modifier functions -- to modify the default configuration. See the individual modifier -- documentation for default values. data Config -- | The fields prefixed by an _ are not to be accessed or updated directly -- but via smart accessor APIs. Use get/set routines instead of directly -- accessing the Config fields defaultConfig :: Config -- | Specify the maximum number of threads that can be spawned by the -- channel. A value of 0 resets the thread limit to default, a negative -- value means there is no limit. The default value is 1500. -- -- When the actions in a stream are IO bound, having blocking IO calls, -- this option can be used to control the maximum number of in-flight IO -- requests. When the actions are CPU bound this option can be used to -- control the amount of CPU used by the stream. maxThreads :: Int -> Config -> Config -- | Specify the maximum size of the buffer for storing the results from -- concurrent computations. If the buffer becomes full we stop spawning -- more concurrent tasks until there is space in the buffer. A value of 0 -- resets the buffer size to default, a negative value means there is no -- limit. The default value is 1500. -- -- CAUTION! using an unbounded maxBuffer value (i.e. a negative -- value) coupled with an unbounded maxThreads value is a recipe -- for disaster in presence of infinite streams, or very large streams. -- Especially, it must not be used when pure is used in -- ZipAsyncM streams as pure in applicative zip streams -- generates an infinite stream causing unbounded concurrent generation -- with no limit on the buffer or threads. maxBuffer :: Int -> Config -> Config -- | Specifies the stream yield rate in yields per second (Hertz). -- We keep accumulating yield credits at rateGoal. At any point of -- time we allow only as many yields as we have accumulated as per -- rateGoal since the start of time. If the consumer or the -- producer is slower or faster, the actual rate may fall behind or -- exceed rateGoal. We try to recover the gap between the two by -- increasing or decreasing the pull rate from the producer. However, if -- the gap becomes more than rateBuffer we try to recover only as -- much as rateBuffer. -- -- rateLow puts a bound on how low the instantaneous rate can go -- when recovering the rate gap. In other words, it determines the -- maximum yield latency. Similarly, rateHigh puts a bound on how -- high the instantaneous rate can go when recovering the rate gap. In -- other words, it determines the minimum yield latency. We reduce the -- latency by increasing concurrency, therefore we can say that it puts -- an upper bound on concurrency. -- -- If the rateGoal is 0 or negative the stream never yields a -- value. If the rateBuffer is 0 or negative we do not attempt to -- recover. data Rate Rate :: Double -> Double -> Double -> Int -> Rate -- | The lower rate limit [rateLow] :: Rate -> Double -- | The target rate we want to achieve [rateGoal] :: Rate -> Double -- | The upper rate limit [rateHigh] :: Rate -> Double -- | Maximum slack from the goal [rateBuffer] :: Rate -> Int -- | Specify the stream evaluation rate of a channel. -- -- A Nothing value means there is no smart rate control, -- concurrent execution blocks only if maxThreads or -- maxBuffer is reached, or there are no more concurrent tasks to -- execute. This is the default. -- -- When rate (throughput) is specified, concurrent production may be -- ramped up or down automatically to achieve the specified stream -- throughput. The specific behavior for different styles of Rate -- specifications is documented under Rate. The effective maximum -- production rate achieved by a channel is governed by: -- -- -- -- Maximum production rate is given by: -- -- <math> -- -- If we know the average latency of the tasks we can set -- maxThreads accordingly. rate :: Maybe Rate -> Config -> Config -- | Same as rate (Just $ Rate (r/2) r (2*r) maxBound) -- -- Specifies the average production rate of a stream in number of yields -- per second (i.e. Hertz). Concurrent production is ramped up -- or down automatically to achieve the specified average yield rate. The -- rate can go down to half of the specified rate on the lower side and -- double of the specified rate on the higher side. avgRate :: Double -> Config -> Config -- | Same as rate (Just $ Rate r r (2*r) maxBound) -- -- Specifies the minimum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go below the -- specified rate, even though it may possibly go above it at times, the -- upper limit is double of the specified rate. minRate :: Double -> Config -> Config -- | Same as rate (Just $ Rate (r/2) r r maxBound) -- -- Specifies the maximum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go above the -- specified rate, even though it may possibly go below it at times, the -- lower limit is half of the specified rate. This can be useful in -- applications where certain resource usage must not be allowed to go -- beyond certain limits. maxRate :: Double -> Config -> Config -- | Same as rate (Just $ Rate r r r 0) -- -- Specifies a constant yield rate. If for some reason the actual rate -- goes above or below the specified rate we do not try to recover it by -- increasing or decreasing the rate in future. This can be useful in -- applications like graphics frame refresh where we need to maintain a -- constant refresh rate. constRate :: Double -> Config -> Config -- | Specify when the Channel should stop. data StopWhen -- | Stop when the first stream ends. FirstStops :: StopWhen -- | Stop when all the streams end. AllStop :: StopWhen -- | Stop when any one stream ends. AnyStops :: StopWhen -- | Specify when the Channel should stop. stopWhen :: StopWhen -> Config -> Config getStopWhen :: Config -> StopWhen -- | By default, processing of output from the worker threads is given -- priority over dispatching new workers. More workers are dispatched -- only when there is no output to process. When eager is set to -- True, workers are dispatched aggresively as long as there is -- more work to do irrespective of whether there is output pending to be -- processed by the stream consumer. However, dispatching may stop if -- maxThreads or maxBuffer is reached. -- -- Note: This option has no effect when rate has been specified. -- -- Note: Not supported with interleaved. eager :: Bool -> Config -> Config -- | When enabled the streams may be evaluated cocnurrently but the results -- are produced in the same sequence as a serial evaluation would -- produce. -- -- Note: Not supported with interleaved. ordered :: Bool -> Config -> Config -- | Interleave the streams fairly instead of prioritizing the left stream. -- This schedules all streams in a round robin fashion over limited -- number of threads. -- -- Note: Can only be used on finite number of streams. -- -- Note: Not supported with ordered. interleaved :: Bool -> Config -> Config -- | Print debug information about the Channel when the stream -- ends. inspect :: Bool -> Config -> Config -- | A monad that can perform concurrent or parallel IO operations. Streams -- that can be composed concurrently require the underlying monad to be -- MonadAsync. type MonadAsync m = (MonadIO m, MonadBaseControl IO m, MonadThrow m) -- | parEval evaluates a stream as a whole asynchronously with -- respect to the consumer of the stream. A worker thread evaluates -- multiple elements of the stream ahead of time and buffers the results; -- the consumer of the stream runs in another thread consuming the -- elements from the buffer, thus decoupling the production and -- consumption of the stream. parEval can be used to run different -- stages of a pipeline concurrently. -- -- It is important to note that parEval does not evaluate -- individual actions in the stream concurrently with respect to each -- other, it merely evaluates the stream serially but in a different -- thread than the consumer thread, thus the consumer and producer can -- run concurrently. See parMapM and parSequence to -- evaluate actions in the stream concurrently. -- -- The evaluation requires only one thread as only one stream needs to be -- evaluated. Therefore, the concurrency options that are relevant to -- multiple streams do not apply here e.g. maxThreads, eager, -- interleaved, ordered, stopWhen options do not have any effect on -- parEval. -- -- Useful idioms: -- --
--   >>> parUnfoldrM step = Stream.parEval id . Stream.unfoldrM step
--   
--   >>> parIterateM step = Stream.parEval id . Stream.iterateM step
--   
parEval :: MonadAsync m => (Config -> Config) -> Stream m a -> Stream m a -- | Definition: -- --
--   >>> parRepeatM cfg = Stream.parSequence cfg . Stream.repeat
--   
-- -- Generate a stream by repeatedly executing a monadic action forever. parRepeatM :: MonadAsync m => (Config -> Config) -> m a -> Stream m a -- | Generate a stream by concurrently performing a monadic action -- n times. -- -- Definition: -- --
--   >>> parReplicateM cfg n = Stream.parSequence cfg . Stream.replicate n
--   
-- -- Example, parReplicateM in the following example executes all -- the replicated actions concurrently, thus taking only 1 second: -- --
--   >>> Stream.fold Fold.drain $ Stream.parReplicateM id 10 $ delay 1
--   ...
--   
parReplicateM :: MonadAsync m => (Config -> Config) -> Int -> m a -> Stream m a -- | Definition: -- --
--   >>> parMapM modifier f = Stream.parConcatMap modifier (Stream.fromEffect . f)
--   
-- -- For example, the following finishes in 3 seconds (as opposed to 6 -- seconds) because all actions run in parallel. Even though results are -- available out of order they are ordered due to the config option: -- --
--   >>> f x = delay x >> return x
--   
--   >>> Stream.fold Fold.toList $ Stream.parMapM (Stream.ordered True) f $ Stream.fromList [3,2,1]
--   1 sec
--   2 sec
--   3 sec
--   [3,2,1]
--   
parMapM :: MonadAsync m => (Config -> Config) -> (a -> m b) -> Stream m a -> Stream m b -- | Definition: -- --
--   >>> parSequence modifier = Stream.parMapM modifier id
--   
-- -- Useful idioms: -- --
--   >>> parFromListM = Stream.parSequence id . Stream.fromList
--   
--   >>> parFromFoldableM = Stream.parSequence id . StreamK.toStream . StreamK.fromFoldable
--   
parSequence :: MonadAsync m => (Config -> Config) -> Stream m (m a) -> Stream m a -- | Binary operation to evaluate two streams concurrently using a channel. -- -- If you want to combine more than two streams you almost always want -- the parList or parConcat operation instead. The -- performance of this operation degrades rapidly when more streams are -- combined as each operation adds one more concurrent channel. On the -- other hand, parConcat uses a single channel for all streams. -- However, with this operation you can precisely control the scheduling -- by creating arbitrary shape expression trees. -- -- Definition: -- --
--   >>> parTwo cfg x y = Stream.parList cfg [x, y]
--   
-- -- Example, the following code finishes in 4 seconds: -- --
--   >>> async = Stream.parTwo id
--   
--   >>> stream1 = Stream.fromEffect (delay 4)
--   
--   >>> stream2 = Stream.fromEffect (delay 2)
--   
--   >>> Stream.fold Fold.toList $ stream1 `async` stream2
--   2 sec
--   4 sec
--   [2,4]
--   
parTwo :: MonadAsync m => (Config -> Config) -> Stream m a -> Stream m a -> Stream m a -- | Evaluates the streams being zipped in separate threads than the -- consumer. The zip function is evaluated in the consumer thread. -- --
--   >>> parZipWithM cfg f m1 m2 = Stream.zipWithM f (Stream.parEval cfg m1) (Stream.parEval cfg m2)
--   
-- -- Multi-stream concurrency options won't apply here, see the notes in -- parEval. -- -- If you want to evaluate the zip function as well in a separate thread, -- you can use a parEval on parZipWithM. parZipWithM :: MonadAsync m => (Config -> Config) -> (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c -- |
--   >>> parZipWith cfg f = Stream.parZipWithM cfg (\a b -> return $ f a b)
--   
-- --
--   >>> m1 = Stream.fromList [1,2,3]
--   
--   >>> m2 = Stream.fromList [4,5,6]
--   
--   >>> Stream.fold Fold.toList $ Stream.parZipWith id (,) m1 m2
--   [(1,4),(2,5),(3,6)]
--   
parZipWith :: MonadAsync m => (Config -> Config) -> (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c -- | Like mergeByM but evaluates both the streams concurrently. -- -- Definition: -- --
--   >>> parMergeByM cfg f m1 m2 = Stream.mergeByM f (Stream.parEval cfg m1) (Stream.parEval cfg m2)
--   
parMergeByM :: MonadAsync m => (Config -> Config) -> (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a -- | Like mergeBy but evaluates both the streams concurrently. -- -- Definition: -- --
--   >>> parMergeBy cfg f = Stream.parMergeByM cfg (\a b -> return $ f a b)
--   
parMergeBy :: MonadAsync m => (Config -> Config) -> (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a -- | Like concat but works on a list of streams. -- --
--   >>> parListLazy = Stream.parList id
--   
parListLazy :: MonadAsync m => [Stream m a] -> Stream m a -- | Like parListLazy but with ordered on. -- --
--   >>> parListOrdered = Stream.parList (Stream.ordered True)
--   
parListOrdered :: MonadAsync m => [Stream m a] -> Stream m a -- | Like parListLazy but interleaves the streams fairly instead of -- prioritizing the left stream. This schedules all streams in a round -- robin fashion over limited number of threads. -- --
--   >>> parListInterleaved = Stream.parList (Stream.interleaved True)
--   
parListInterleaved :: MonadAsync m => [Stream m a] -> Stream m a -- | Like parListLazy but with eager on. -- --
--   >>> parListEager = Stream.parList (Stream.eager True)
--   
parListEager :: MonadAsync m => [Stream m a] -> Stream m a -- | Like parListEager but stops the output as soon as the first -- stream stops. -- --
--   >>> parListEagerFst = Stream.parList (Stream.eager True . Stream.stopWhen Stream.FirstStops)
--   
parListEagerFst :: MonadAsync m => [Stream m a] -> Stream m a -- | Like parListEager but stops the output as soon as any of the -- two streams stops. -- -- Definition: -- --
--   >>> parListEagerMin = Stream.parList (Stream.eager True . Stream.stopWhen Stream.AnyStops)
--   
parListEagerMin :: MonadAsync m => [Stream m a] -> Stream m a -- | Like parConcat but works on a list of streams. -- --
--   >>> parList modifier = Stream.parConcat modifier . Stream.fromList
--   
parList :: MonadAsync m => (Config -> Config) -> [Stream m a] -> Stream m a -- | Apply an argument stream to a function stream concurrently. Uses a -- shared channel for all individual applications within a stream -- application. parApply :: MonadAsync m => (Config -> Config) -> Stream m (a -> b) -> Stream m a -> Stream m b -- | Evaluate the streams in the input stream concurrently and combine -- them. -- --
--   >>> parConcat modifier = Stream.parConcatMap modifier id
--   
parConcat :: MonadAsync m => (Config -> Config) -> Stream m (Stream m a) -> Stream m a -- | Map each element of the input to a stream and then concurrently -- evaluate and concatenate the resulting streams. Multiple streams may -- be evaluated concurrently but earlier streams are perferred. Output -- from the streams are used as they arrive. -- -- Definition: -- --
--   >>> parConcatMap modifier f stream = Stream.parConcat modifier $ fmap f stream
--   
-- -- Examples: -- --
--   >>> f cfg xs = Stream.fold Fold.toList $ Stream.parConcatMap cfg id $ Stream.fromList xs
--   
-- -- The following streams finish in 4 seconds: -- --
--   >>> stream1 = Stream.fromEffect (delay 4)
--   
--   >>> stream2 = Stream.fromEffect (delay 2)
--   
--   >>> stream3 = Stream.fromEffect (delay 1)
--   
--   >>> f id [stream1, stream2, stream3]
--   1 sec
--   2 sec
--   4 sec
--   [1,2,4]
--   
-- -- Limiting threads to 2 schedules the third stream only after one of the -- first two has finished, releasing a thread: -- --
--   >>> f (Stream.maxThreads 2) [stream1, stream2, stream3]
--   ...
--   [2,1,4]
--   
-- -- When used with a Single thread it behaves like serial concatMap: -- --
--   >>> f (Stream.maxThreads 1) [stream1, stream2, stream3]
--   ...
--   [4,2,1]
--   
-- --
--   >>> stream1 = Stream.fromList [1,2,3]
--   
--   >>> stream2 = Stream.fromList [4,5,6]
--   
--   >>> f (Stream.maxThreads 1) [stream1, stream2]
--   [1,2,3,4,5,6]
--   
-- -- Schedule all streams in a round robin fashion over the available -- threads: -- --
--   >>> f cfg xs = Stream.fold Fold.toList $ Stream.parConcatMap (Stream.interleaved True . cfg) id $ Stream.fromList xs
--   
-- --
--   >>> stream1 = Stream.fromList [1,2,3]
--   
--   >>> stream2 = Stream.fromList [4,5,6]
--   
--   >>> f (Stream.maxThreads 1) [stream1, stream2]
--   [1,4,2,5,3,6]
--   
parConcatMap :: MonadAsync m => (Config -> Config) -> (a -> Stream m b) -> Stream m a -> Stream m b -- | Same as concatIterate but concurrent. -- -- Pre-release parConcatIterate :: MonadAsync m => (Config -> Config) -> (a -> Stream m a) -> Stream m a -> Stream m a -- | fromCallback f creates an entangled pair of a callback and a -- stream i.e. whenever the callback is called a value appears in the -- stream. The function f is invoked with the callback as -- argument, and the stream is returned. f would store the -- callback for calling it later for generating values in the stream. -- -- The callback queues a value to a concurrent channel associated with -- the stream. The stream can be evaluated safely in any thread. -- -- Pre-release fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> Stream m a -- | parTapCount predicate fold stream taps the count of those -- elements in the stream that pass the predicate. The resulting -- count stream is sent to a fold running concurrently in -- another thread. -- -- For example, to print the count of elements processed every second: -- --
--   >>> rate = Stream.rollingMap2 (flip (-)) . Stream.delayPost 1
--   
--   >>> report = Stream.fold (Fold.drainMapM print) . rate
--   
--   >>> tap = Stream.parTapCount (const True) report
--   
--   >>> go = Stream.fold Fold.drain $ tap $ Stream.enumerateFrom 0
--   
-- -- Note: This may not work correctly on 32-bit machines because of Int -- overflow. -- -- Pre-release parTapCount :: MonadAsync m => (a -> Bool) -> (Stream m Int -> m b) -> Stream m a -> Stream m a -- | Same as parTapCount. Deprecated. -- | Deprecated: Please use parTapCount instead. tapCount :: MonadAsync m => (a -> Bool) -> (Stream m Int -> m b) -> Stream m a -> Stream m a -- | Generate a stream by running an action periodically at the specified -- time interval. periodic :: MonadIO m => m a -> Double -> Stream m a -- | Generate a tick stream consisting of () elements, each tick -- is generated after the specified time delay given in seconds. -- --
--   >>> ticks = Stream.periodic (return ())
--   
ticks :: MonadIO m => Double -> Stream m () -- | Generate a tick stream, ticks are generated at the specified -- Rate. The rate is adaptive, the tick generation speed can be -- increased or decreased at different times to achieve the specified -- rate. The specific behavior for different styles of Rate -- specifications is documented under Rate. The effective maximum -- rate achieved by a stream is governed by the processor speed. -- --
--   >>> tickStream = Stream.repeatM (return ())
--   
--   >>> ticksRate r = Stream.parEval (Stream.rate (Just r)) tickStream
--   
ticksRate :: MonadAsync m => Rate -> Stream m () -- | Intersperse a monadic action into the input stream after every -- n seconds. -- -- Definition: -- --
--   >>> interject n f xs = Stream.parListEagerFst [xs, Stream.periodic f n]
--   
-- -- Example: -- --
--   >>> s = Stream.fromList "hello"
--   
--   >>> input = Stream.mapM (\x -> threadDelay 1000000 >> putChar x) s
--   
--   >>> Stream.fold Fold.drain $ Stream.interject (putChar ',') 1.05 input
--   h,e,l,l,o
--   
interject :: MonadAsync m => m a -> Double -> Stream m a -> Stream m a -- | takeInterval interval runs the stream only upto the specified -- time interval in seconds. -- -- The interval starts when the stream is evaluated for the first time. takeInterval :: MonadAsync m => Double -> Stream m a -> Stream m a -- | Take time interval i seconds at the end of the stream. -- -- O(n) space, where n is the number elements taken. -- -- Unimplemented takeLastInterval :: Double -> Stream m a -> Stream m a -- | dropInterval interval drops all the stream elements that are -- generated before the specified interval in seconds has -- passed. -- -- The interval begins when the stream is evaluated for the first time. dropInterval :: MonadAsync m => Double -> Stream m a -> Stream m a -- | Drop time interval i seconds at the end of the stream. -- -- O(n) space, where n is the number elements dropped. -- -- Unimplemented dropLastInterval :: Int -> Stream m a -> Stream m a -- | Group the input stream into windows of n second each and then -- fold each group using the provided fold function. -- --
--   >>> twoPerSec = Stream.parEval (Stream.constRate 2) $ Stream.enumerateFrom 1
--   
--   >>> intervals = Stream.intervalsOf 1 Fold.toList twoPerSec
--   
--   >>> Stream.fold Fold.toList $ Stream.take 2 intervals
--   [...,...]
--   
intervalsOf :: MonadAsync m => Double -> Fold m a b -> Stream m a -> Stream m b -- | Like chunksOf but if the chunk is not completed within the -- specified time interval then emit whatever we have collected till now. -- The chunk timeout is reset whenever a chunk is emitted. The -- granularity of the clock is 100 ms. -- --
--   >>> s = Stream.delayPost 0.3 $ Stream.fromList [1..1000]
--   
--   >>> f = Stream.fold (Fold.drainMapM print) $ Stream.groupsOfTimeout 5 1 Fold.toList s
--   
-- -- Pre-release groupsOfTimeout :: MonadAsync m => Int -> Double -> Fold m a b -> Stream m a -> Stream m b -- | Continuously evaluate the input stream and sample the last event in -- each time window of n seconds. -- -- This is also known as throttle in some libraries. -- --
--   >>> sampleIntervalEnd n = Stream.catMaybes . Stream.intervalsOf n Fold.latest
--   
sampleIntervalEnd :: MonadAsync m => Double -> Stream m a -> Stream m a -- | Like sampleInterval but samples at the beginning of the time -- window. -- --
--   >>> sampleIntervalStart n = Stream.catMaybes . Stream.intervalsOf n Fold.one
--   
sampleIntervalStart :: MonadAsync m => Double -> Stream m a -> Stream m a sampleBurst :: MonadAsync m => Bool -> Double -> Stream m a -> Stream m a -- | Sample one event at the end of each burst of events. A burst is a -- group of events close together in time, it ends when an event is -- spaced by more than the specified time interval (in seconds) from the -- previous event. -- -- This is known as debounce in some libraries. -- -- The clock granularity is 10 ms. sampleBurstEnd :: MonadAsync m => Double -> Stream m a -> Stream m a -- | Like sampleBurstEnd but samples the event at the beginning of -- the burst instead of at the end of it. sampleBurstStart :: MonadAsync m => Double -> Stream m a -> Stream m a classifySessionsByGeneric :: forall m f a b. (MonadAsync m, IsMap f) => Proxy (f :: Type -> Type) -> Double -> Bool -> (Int -> m Bool) -> Double -> Fold m a b -> Stream m (AbsTime, (Key f, a)) -> Stream m (Key f, b) -- | classifySessionsBy tick keepalive predicate timeout fold -- stream classifies an input event stream consisting of -- (timestamp, (key, value)) into sessions based on the -- key, folding all the values corresponding to the same key -- into a session using the supplied fold. -- -- When the fold terminates or a timeout occurs, a tuple -- consisting of the session key and the folded value is emitted in the -- output stream. The timeout is measured from the first event in the -- session. If the keepalive option is set to True the -- timeout is reset to 0 whenever an event is received. -- -- The timestamp in the input stream is an absolute time from -- some epoch, characterizing the time when the input event was -- generated. The notion of current time is maintained by a monotonic -- event time clock using the timestamps seen in the input stream. The -- latest timestamp seen till now is used as the base for the current -- time. When no new events are seen, a timer is started with a clock -- resolution of tick seconds. This timer is used to detect -- session timeouts in the absence of new events. -- -- To ensure an upper bound on the memory used the number of sessions can -- be limited to an upper bound. If the ejection predicate -- returns True, the oldest session is ejected before inserting a -- new session. -- -- When the stream ends any buffered sessions are ejected immediately. -- -- If a session key is received even after a session has finished, -- another session is created for that key. -- --
--   >>> :{
--   Stream.fold (Fold.drainMapM print)
--       $ Stream.classifySessionsBy 1 False (const (return False)) 3 (Fold.take 3 Fold.toList)
--       $ Stream.timestamped
--       $ Stream.delay 0.1
--       $ Stream.fromList ((,) <$> [1,2,3] <*> ['a','b','c'])
--   :}
--   (1,"abc")
--   (2,"abc")
--   (3,"abc")
--   
-- -- Pre-release classifySessionsBy :: (MonadAsync m, Ord k) => Double -> Bool -> (Int -> m Bool) -> Double -> Fold m a b -> Stream m (AbsTime, (k, a)) -> Stream m (k, b) -- | Same as classifySessionsBy with a timer tick of 1 second and -- keepalive option set to False. -- --
--   >>> classifySessionsOf = Stream.classifySessionsBy 1 False
--   
-- -- Pre-release classifySessionsOf :: (MonadAsync m, Ord k) => (Int -> m Bool) -> Double -> Fold m a b -> Stream m (AbsTime, (k, a)) -> Stream m (k, b) -- | Same as classifySessionsBy with a timer tick of 1 second and -- keepalive option set to True. -- --
--   classifyKeepAliveSessions = classifySessionsBy 1 True
--   
-- -- Pre-release classifyKeepAliveSessions :: (MonadAsync m, Ord k) => (Int -> m Bool) -> Double -> Fold m a b -> Stream m (AbsTime, (k, a)) -> Stream m (k, b) -- | Always produce the latest available element from the stream without -- any delay. The stream is continuously evaluated at the highest -- possible rate and only the latest element is retained for sampling. -- -- Unimplemented bufferLatest :: Stream m a -> Stream m (Maybe a) -- | Evaluate the input stream continuously and keep only the latest -- n elements in a ring buffer, keep discarding the older ones -- to make space for the new ones. When the output stream is evaluated -- the buffer collected till now is streamed and it starts filling again. -- -- Unimplemented bufferLatestN :: Int -> Stream m a -> Stream m a -- | Evaluate the input stream continuously and keep only the oldest -- n elements in the buffer, discard the new ones when the -- buffer is full. When the output stream is evaluated the collected -- buffer is streamed and the buffer starts filling again. -- -- Unimplemented bufferOldestN :: Int -> Stream m a -> Stream m a -- | Run the action m b whenever the stream Stream m a -- stops normally, or if it is garbage collected after a partial lazy -- evaluation. -- -- The semantics of the action m b are similar to the semantics -- of cleanup action in bracket. -- -- See also after_ after :: (MonadIO m, MonadBaseControl IO m) => m b -> Stream m a -> Stream m a -- | Run the alloc action IO b with async exceptions disabled but -- keeping blocking operations interruptible (see mask). Use the -- output b of the IO action as input to the function b -- -> Stream m a to generate an output stream. -- -- b is usually a resource under the IO monad, e.g. a file -- handle, that requires a cleanup after use. The cleanup action b -- -> m c, runs whenever (1) the stream ends normally, (2) due to -- a sync or async exception or, (3) if it gets garbage collected after a -- partial lazy evaluation. The exception is not caught, it is rethrown. -- -- bracket only guarantees that the cleanup action runs, and it -- runs with async exceptions enabled. The action must ensure that it can -- successfully cleanup the resource in the face of sync or async -- exceptions. -- -- When the stream ends normally or on a sync exception, cleanup action -- runs immediately in the current thread context, whereas in other cases -- it runs in the GC context, therefore, cleanup may be delayed until the -- GC gets to run. -- -- See also: bracket_ -- -- Inhibits stream fusion bracket :: (MonadAsync m, MonadCatch m) => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a -- | Like bracket but can use 3 separate cleanup actions depending -- on the mode of termination: -- --
    --
  1. When the stream stops normally
  2. --
  3. When the stream is garbage collected
  4. --
  5. When the stream encounters an exception
  6. --
-- -- bracket3 before onStop onGC onException action runs -- action using the result of before. If the stream -- stops, onStop action is executed, if the stream is abandoned -- onGC is executed, if the stream encounters an exception -- onException is executed. -- -- The exception is not caught, it is rethrown. -- -- Pre-release bracket3 :: (MonadAsync m, MonadCatch m) => m b -> (b -> m c) -> (b -> m d) -> (b -> m e) -> (b -> Stream m a) -> Stream m a -- | Run the action m b whenever the stream Stream m a -- stops normally, aborts due to an exception or if it is garbage -- collected after a partial lazy evaluation. -- -- The semantics of running the action m b are similar to the -- cleanup action semantics described in bracket. -- --
--   >>> finally action xs = Stream.bracket (return ()) (const action) (const xs)
--   
-- -- See also finally_ -- -- Inhibits stream fusion finally :: (MonadAsync m, MonadCatch m) => m b -> Stream m a -> Stream m a -- | retry takes 3 arguments -- --
    --
  1. A map m whose keys are exceptions and values are the -- number of times to retry the action given that the exception -- occurs.
  2. --
  3. A handler han that decides how to handle an exception -- when the exception cannot be retried.
  4. --
  5. The stream itself that we want to run this mechanism on.
  6. --
-- -- When evaluating a stream if an exception occurs, -- --
    --
  1. The stream evaluation aborts
  2. --
  3. The exception is looked up in m
  4. --
-- -- a. If the exception exists and the mapped value is > 0 then, -- -- i. The value is decreased by 1. -- -- ii. The stream is resumed from where the exception was called, -- retrying the action. -- -- b. If the exception exists and the mapped value is == 0 then the -- stream evaluation stops. -- -- c. If the exception does not exist then we handle the exception using -- han. -- -- Internal retry :: (MonadCatch m, Exception e, Ord e) => Map e Int -> (e -> Stream m a) -> Stream m a -> Stream m a afterD :: MonadRunInIO m => m b -> Stream m a -> Stream m a bracket3D :: (MonadAsync m, MonadCatch m) => m b -> (b -> m c) -> (b -> m d) -> (b -> m e) -> (b -> Stream m a) -> Stream m a -- | See retry retryD :: forall e m a. (Exception e, Ord e, MonadCatch m) => Map e Int -> (e -> Stream m a) -> Stream m a -> Stream m a -- | For upgrading to streamly-0.9.0+ please read the Streamly-0.9.0 -- upgrade guide. Also, see the Streamly.Data.Stream.MkType -- module for direct replacement of stream types that have been removed -- in 0.9.0. -- -- All Stream related combinators including the streamly-core -- Streamly.Data.Stream module, concurrency, time and lifted -- exception operations. For more pre-release operations also see -- Streamly.Internal.Data.Stream.Prelude module. module Streamly.Data.Stream.Prelude -- | A monad that can perform concurrent or parallel IO operations. Streams -- that can be composed concurrently require the underlying monad to be -- MonadAsync. type MonadAsync m = (MonadIO m, MonadBaseControl IO m, MonadThrow m) -- | An abstract type for specifying the configuration parameters of a -- Channel. Use Config -> Config modifier functions -- to modify the default configuration. See the individual modifier -- documentation for default values. data Config -- | Specify the maximum number of threads that can be spawned by the -- channel. A value of 0 resets the thread limit to default, a negative -- value means there is no limit. The default value is 1500. -- -- When the actions in a stream are IO bound, having blocking IO calls, -- this option can be used to control the maximum number of in-flight IO -- requests. When the actions are CPU bound this option can be used to -- control the amount of CPU used by the stream. maxThreads :: Int -> Config -> Config -- | Specify the maximum size of the buffer for storing the results from -- concurrent computations. If the buffer becomes full we stop spawning -- more concurrent tasks until there is space in the buffer. A value of 0 -- resets the buffer size to default, a negative value means there is no -- limit. The default value is 1500. -- -- CAUTION! using an unbounded maxBuffer value (i.e. a negative -- value) coupled with an unbounded maxThreads value is a recipe -- for disaster in presence of infinite streams, or very large streams. -- Especially, it must not be used when pure is used in -- ZipAsyncM streams as pure in applicative zip streams -- generates an infinite stream causing unbounded concurrent generation -- with no limit on the buffer or threads. maxBuffer :: Int -> Config -> Config -- | Specifies the stream yield rate in yields per second (Hertz). -- We keep accumulating yield credits at rateGoal. At any point of -- time we allow only as many yields as we have accumulated as per -- rateGoal since the start of time. If the consumer or the -- producer is slower or faster, the actual rate may fall behind or -- exceed rateGoal. We try to recover the gap between the two by -- increasing or decreasing the pull rate from the producer. However, if -- the gap becomes more than rateBuffer we try to recover only as -- much as rateBuffer. -- -- rateLow puts a bound on how low the instantaneous rate can go -- when recovering the rate gap. In other words, it determines the -- maximum yield latency. Similarly, rateHigh puts a bound on how -- high the instantaneous rate can go when recovering the rate gap. In -- other words, it determines the minimum yield latency. We reduce the -- latency by increasing concurrency, therefore we can say that it puts -- an upper bound on concurrency. -- -- If the rateGoal is 0 or negative the stream never yields a -- value. If the rateBuffer is 0 or negative we do not attempt to -- recover. data Rate Rate :: Double -> Double -> Double -> Int -> Rate -- | The lower rate limit [rateLow] :: Rate -> Double -- | The target rate we want to achieve [rateGoal] :: Rate -> Double -- | The upper rate limit [rateHigh] :: Rate -> Double -- | Maximum slack from the goal [rateBuffer] :: Rate -> Int -- | Specify the stream evaluation rate of a channel. -- -- A Nothing value means there is no smart rate control, -- concurrent execution blocks only if maxThreads or -- maxBuffer is reached, or there are no more concurrent tasks to -- execute. This is the default. -- -- When rate (throughput) is specified, concurrent production may be -- ramped up or down automatically to achieve the specified stream -- throughput. The specific behavior for different styles of Rate -- specifications is documented under Rate. The effective maximum -- production rate achieved by a channel is governed by: -- -- -- -- Maximum production rate is given by: -- -- <math> -- -- If we know the average latency of the tasks we can set -- maxThreads accordingly. rate :: Maybe Rate -> Config -> Config -- | Same as rate (Just $ Rate (r/2) r (2*r) maxBound) -- -- Specifies the average production rate of a stream in number of yields -- per second (i.e. Hertz). Concurrent production is ramped up -- or down automatically to achieve the specified average yield rate. The -- rate can go down to half of the specified rate on the lower side and -- double of the specified rate on the higher side. avgRate :: Double -> Config -> Config -- | Same as rate (Just $ Rate r r (2*r) maxBound) -- -- Specifies the minimum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go below the -- specified rate, even though it may possibly go above it at times, the -- upper limit is double of the specified rate. minRate :: Double -> Config -> Config -- | Same as rate (Just $ Rate (r/2) r r maxBound) -- -- Specifies the maximum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go above the -- specified rate, even though it may possibly go below it at times, the -- lower limit is half of the specified rate. This can be useful in -- applications where certain resource usage must not be allowed to go -- beyond certain limits. maxRate :: Double -> Config -> Config -- | Same as rate (Just $ Rate r r r 0) -- -- Specifies a constant yield rate. If for some reason the actual rate -- goes above or below the specified rate we do not try to recover it by -- increasing or decreasing the rate in future. This can be useful in -- applications like graphics frame refresh where we need to maintain a -- constant refresh rate. constRate :: Double -> Config -> Config -- | Specify when the Channel should stop. data StopWhen -- | Stop when the first stream ends. FirstStops :: StopWhen -- | Stop when all the streams end. AllStop :: StopWhen -- | Stop when any one stream ends. AnyStops :: StopWhen -- | Specify when the Channel should stop. stopWhen :: StopWhen -> Config -> Config -- | By default, processing of output from the worker threads is given -- priority over dispatching new workers. More workers are dispatched -- only when there is no output to process. When eager is set to -- True, workers are dispatched aggresively as long as there is -- more work to do irrespective of whether there is output pending to be -- processed by the stream consumer. However, dispatching may stop if -- maxThreads or maxBuffer is reached. -- -- Note: This option has no effect when rate has been specified. -- -- Note: Not supported with interleaved. eager :: Bool -> Config -> Config -- | When enabled the streams may be evaluated cocnurrently but the results -- are produced in the same sequence as a serial evaluation would -- produce. -- -- Note: Not supported with interleaved. ordered :: Bool -> Config -> Config -- | Interleave the streams fairly instead of prioritizing the left stream. -- This schedules all streams in a round robin fashion over limited -- number of threads. -- -- Note: Can only be used on finite number of streams. -- -- Note: Not supported with ordered. interleaved :: Bool -> Config -> Config -- | Print debug information about the Channel when the stream -- ends. inspect :: Bool -> Config -> Config -- | parEval evaluates a stream as a whole asynchronously with -- respect to the consumer of the stream. A worker thread evaluates -- multiple elements of the stream ahead of time and buffers the results; -- the consumer of the stream runs in another thread consuming the -- elements from the buffer, thus decoupling the production and -- consumption of the stream. parEval can be used to run different -- stages of a pipeline concurrently. -- -- It is important to note that parEval does not evaluate -- individual actions in the stream concurrently with respect to each -- other, it merely evaluates the stream serially but in a different -- thread than the consumer thread, thus the consumer and producer can -- run concurrently. See parMapM and parSequence to -- evaluate actions in the stream concurrently. -- -- The evaluation requires only one thread as only one stream needs to be -- evaluated. Therefore, the concurrency options that are relevant to -- multiple streams do not apply here e.g. maxThreads, eager, -- interleaved, ordered, stopWhen options do not have any effect on -- parEval. -- -- Useful idioms: -- --
--   >>> parUnfoldrM step = Stream.parEval id . Stream.unfoldrM step
--   
--   >>> parIterateM step = Stream.parEval id . Stream.iterateM step
--   
parEval :: MonadAsync m => (Config -> Config) -> Stream m a -> Stream m a -- | Definition: -- --
--   >>> parRepeatM cfg = Stream.parSequence cfg . Stream.repeat
--   
-- -- Generate a stream by repeatedly executing a monadic action forever. parRepeatM :: MonadAsync m => (Config -> Config) -> m a -> Stream m a -- | Generate a stream by concurrently performing a monadic action -- n times. -- -- Definition: -- --
--   >>> parReplicateM cfg n = Stream.parSequence cfg . Stream.replicate n
--   
-- -- Example, parReplicateM in the following example executes all -- the replicated actions concurrently, thus taking only 1 second: -- --
--   >>> Stream.fold Fold.drain $ Stream.parReplicateM id 10 $ delay 1
--   ...
--   
parReplicateM :: MonadAsync m => (Config -> Config) -> Int -> m a -> Stream m a -- | fromCallback f creates an entangled pair of a callback and a -- stream i.e. whenever the callback is called a value appears in the -- stream. The function f is invoked with the callback as -- argument, and the stream is returned. f would store the -- callback for calling it later for generating values in the stream. -- -- The callback queues a value to a concurrent channel associated with -- the stream. The stream can be evaluated safely in any thread. -- -- Pre-release fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> Stream m a -- | Definition: -- --
--   >>> parMapM modifier f = Stream.parConcatMap modifier (Stream.fromEffect . f)
--   
-- -- For example, the following finishes in 3 seconds (as opposed to 6 -- seconds) because all actions run in parallel. Even though results are -- available out of order they are ordered due to the config option: -- --
--   >>> f x = delay x >> return x
--   
--   >>> Stream.fold Fold.toList $ Stream.parMapM (Stream.ordered True) f $ Stream.fromList [3,2,1]
--   1 sec
--   2 sec
--   3 sec
--   [3,2,1]
--   
parMapM :: MonadAsync m => (Config -> Config) -> (a -> m b) -> Stream m a -> Stream m b -- | Definition: -- --
--   >>> parSequence modifier = Stream.parMapM modifier id
--   
-- -- Useful idioms: -- --
--   >>> parFromListM = Stream.parSequence id . Stream.fromList
--   
--   >>> parFromFoldableM = Stream.parSequence id . StreamK.toStream . StreamK.fromFoldable
--   
parSequence :: MonadAsync m => (Config -> Config) -> Stream m (m a) -> Stream m a -- | Evaluates the streams being zipped in separate threads than the -- consumer. The zip function is evaluated in the consumer thread. -- --
--   >>> parZipWithM cfg f m1 m2 = Stream.zipWithM f (Stream.parEval cfg m1) (Stream.parEval cfg m2)
--   
-- -- Multi-stream concurrency options won't apply here, see the notes in -- parEval. -- -- If you want to evaluate the zip function as well in a separate thread, -- you can use a parEval on parZipWithM. parZipWithM :: MonadAsync m => (Config -> Config) -> (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c -- |
--   >>> parZipWith cfg f = Stream.parZipWithM cfg (\a b -> return $ f a b)
--   
-- --
--   >>> m1 = Stream.fromList [1,2,3]
--   
--   >>> m2 = Stream.fromList [4,5,6]
--   
--   >>> Stream.fold Fold.toList $ Stream.parZipWith id (,) m1 m2
--   [(1,4),(2,5),(3,6)]
--   
parZipWith :: MonadAsync m => (Config -> Config) -> (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c -- | Like mergeByM but evaluates both the streams concurrently. -- -- Definition: -- --
--   >>> parMergeByM cfg f m1 m2 = Stream.mergeByM f (Stream.parEval cfg m1) (Stream.parEval cfg m2)
--   
parMergeByM :: MonadAsync m => (Config -> Config) -> (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a -- | Like mergeBy but evaluates both the streams concurrently. -- -- Definition: -- --
--   >>> parMergeBy cfg f = Stream.parMergeByM cfg (\a b -> return $ f a b)
--   
parMergeBy :: MonadAsync m => (Config -> Config) -> (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a -- | Like parConcat but works on a list of streams. -- --
--   >>> parList modifier = Stream.parConcat modifier . Stream.fromList
--   
parList :: MonadAsync m => (Config -> Config) -> [Stream m a] -> Stream m a -- | Apply an argument stream to a function stream concurrently. Uses a -- shared channel for all individual applications within a stream -- application. parApply :: MonadAsync m => (Config -> Config) -> Stream m (a -> b) -> Stream m a -> Stream m b -- | Evaluate the streams in the input stream concurrently and combine -- them. -- --
--   >>> parConcat modifier = Stream.parConcatMap modifier id
--   
parConcat :: MonadAsync m => (Config -> Config) -> Stream m (Stream m a) -> Stream m a -- | Map each element of the input to a stream and then concurrently -- evaluate and concatenate the resulting streams. Multiple streams may -- be evaluated concurrently but earlier streams are perferred. Output -- from the streams are used as they arrive. -- -- Definition: -- --
--   >>> parConcatMap modifier f stream = Stream.parConcat modifier $ fmap f stream
--   
-- -- Examples: -- --
--   >>> f cfg xs = Stream.fold Fold.toList $ Stream.parConcatMap cfg id $ Stream.fromList xs
--   
-- -- The following streams finish in 4 seconds: -- --
--   >>> stream1 = Stream.fromEffect (delay 4)
--   
--   >>> stream2 = Stream.fromEffect (delay 2)
--   
--   >>> stream3 = Stream.fromEffect (delay 1)
--   
--   >>> f id [stream1, stream2, stream3]
--   1 sec
--   2 sec
--   4 sec
--   [1,2,4]
--   
-- -- Limiting threads to 2 schedules the third stream only after one of the -- first two has finished, releasing a thread: -- --
--   >>> f (Stream.maxThreads 2) [stream1, stream2, stream3]
--   ...
--   [2,1,4]
--   
-- -- When used with a Single thread it behaves like serial concatMap: -- --
--   >>> f (Stream.maxThreads 1) [stream1, stream2, stream3]
--   ...
--   [4,2,1]
--   
-- --
--   >>> stream1 = Stream.fromList [1,2,3]
--   
--   >>> stream2 = Stream.fromList [4,5,6]
--   
--   >>> f (Stream.maxThreads 1) [stream1, stream2]
--   [1,2,3,4,5,6]
--   
-- -- Schedule all streams in a round robin fashion over the available -- threads: -- --
--   >>> f cfg xs = Stream.fold Fold.toList $ Stream.parConcatMap (Stream.interleaved True . cfg) id $ Stream.fromList xs
--   
-- --
--   >>> stream1 = Stream.fromList [1,2,3]
--   
--   >>> stream2 = Stream.fromList [4,5,6]
--   
--   >>> f (Stream.maxThreads 1) [stream1, stream2]
--   [1,4,2,5,3,6]
--   
parConcatMap :: MonadAsync m => (Config -> Config) -> (a -> Stream m b) -> Stream m a -> Stream m b -- | Same as concatIterate but concurrent. -- -- Pre-release parConcatIterate :: MonadAsync m => (Config -> Config) -> (a -> Stream m a) -> Stream m a -> Stream m a -- | parTapCount predicate fold stream taps the count of those -- elements in the stream that pass the predicate. The resulting -- count stream is sent to a fold running concurrently in -- another thread. -- -- For example, to print the count of elements processed every second: -- --
--   >>> rate = Stream.rollingMap2 (flip (-)) . Stream.delayPost 1
--   
--   >>> report = Stream.fold (Fold.drainMapM print) . rate
--   
--   >>> tap = Stream.parTapCount (const True) report
--   
--   >>> go = Stream.fold Fold.drain $ tap $ Stream.enumerateFrom 0
--   
-- -- Note: This may not work correctly on 32-bit machines because of Int -- overflow. -- -- Pre-release parTapCount :: MonadAsync m => (a -> Bool) -> (Stream m Int -> m b) -> Stream m a -> Stream m a -- | Intersperse a monadic action into the input stream after every -- n seconds. -- -- Definition: -- --
--   >>> interject n f xs = Stream.parListEagerFst [xs, Stream.periodic f n]
--   
-- -- Example: -- --
--   >>> s = Stream.fromList "hello"
--   
--   >>> input = Stream.mapM (\x -> threadDelay 1000000 >> putChar x) s
--   
--   >>> Stream.fold Fold.drain $ Stream.interject (putChar ',') 1.05 input
--   h,e,l,l,o
--   
interject :: MonadAsync m => m a -> Double -> Stream m a -> Stream m a -- | takeInterval interval runs the stream only upto the specified -- time interval in seconds. -- -- The interval starts when the stream is evaluated for the first time. takeInterval :: MonadAsync m => Double -> Stream m a -> Stream m a -- | dropInterval interval drops all the stream elements that are -- generated before the specified interval in seconds has -- passed. -- -- The interval begins when the stream is evaluated for the first time. dropInterval :: MonadAsync m => Double -> Stream m a -> Stream m a -- | Group the input stream into windows of n second each and then -- fold each group using the provided fold function. -- --
--   >>> twoPerSec = Stream.parEval (Stream.constRate 2) $ Stream.enumerateFrom 1
--   
--   >>> intervals = Stream.intervalsOf 1 Fold.toList twoPerSec
--   
--   >>> Stream.fold Fold.toList $ Stream.take 2 intervals
--   [...,...]
--   
intervalsOf :: MonadAsync m => Double -> Fold m a b -> Stream m a -> Stream m b -- | Continuously evaluate the input stream and sample the last event in -- each time window of n seconds. -- -- This is also known as throttle in some libraries. -- --
--   >>> sampleIntervalEnd n = Stream.catMaybes . Stream.intervalsOf n Fold.latest
--   
sampleIntervalEnd :: MonadAsync m => Double -> Stream m a -> Stream m a -- | Like sampleInterval but samples at the beginning of the time -- window. -- --
--   >>> sampleIntervalStart n = Stream.catMaybes . Stream.intervalsOf n Fold.one
--   
sampleIntervalStart :: MonadAsync m => Double -> Stream m a -> Stream m a -- | Sample one event at the end of each burst of events. A burst is a -- group of events close together in time, it ends when an event is -- spaced by more than the specified time interval (in seconds) from the -- previous event. -- -- This is known as debounce in some libraries. -- -- The clock granularity is 10 ms. sampleBurstEnd :: MonadAsync m => Double -> Stream m a -> Stream m a -- | Like sampleBurstEnd but samples the event at the beginning of -- the burst instead of at the end of it. sampleBurstStart :: MonadAsync m => Double -> Stream m a -> Stream m a -- | Run the action m b whenever the stream Stream m a -- stops normally, or if it is garbage collected after a partial lazy -- evaluation. -- -- The semantics of the action m b are similar to the semantics -- of cleanup action in bracket. -- -- See also after_ after :: (MonadIO m, MonadBaseControl IO m) => m b -> Stream m a -> Stream m a -- | Run the alloc action IO b with async exceptions disabled but -- keeping blocking operations interruptible (see mask). Use the -- output b of the IO action as input to the function b -- -> Stream m a to generate an output stream. -- -- b is usually a resource under the IO monad, e.g. a file -- handle, that requires a cleanup after use. The cleanup action b -- -> m c, runs whenever (1) the stream ends normally, (2) due to -- a sync or async exception or, (3) if it gets garbage collected after a -- partial lazy evaluation. The exception is not caught, it is rethrown. -- -- bracket only guarantees that the cleanup action runs, and it -- runs with async exceptions enabled. The action must ensure that it can -- successfully cleanup the resource in the face of sync or async -- exceptions. -- -- When the stream ends normally or on a sync exception, cleanup action -- runs immediately in the current thread context, whereas in other cases -- it runs in the GC context, therefore, cleanup may be delayed until the -- GC gets to run. -- -- See also: bracket_ -- -- Inhibits stream fusion bracket :: (MonadAsync m, MonadCatch m) => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a -- | Run the action m b whenever the stream Stream m a -- stops normally, aborts due to an exception or if it is garbage -- collected after a partial lazy evaluation. -- -- The semantics of running the action m b are similar to the -- cleanup action semantics described in bracket. -- --
--   >>> finally action xs = Stream.bracket (return ()) (const action) (const xs)
--   
-- -- See also finally_ -- -- Inhibits stream fusion finally :: (MonadAsync m, MonadCatch m) => m b -> Stream m a -> Stream m a -- | Same as parTapCount. Deprecated. -- | Deprecated: Please use parTapCount instead. tapCount :: MonadAsync m => (a -> Bool) -> (Stream m Int -> m b) -> Stream m a -> Stream m a -- | To run examples in this module: -- --
--   >>> import qualified Streamly.Prelude as Stream
--   
--   >>> import qualified Streamly.Internal.Data.Stream as D
--   
--   >>> import qualified Streamly.Data.Fold as Fold
--   
-- | Deprecated: Use Streamly.Data.Stream.MkType instead. module Streamly.Internal.Data.Stream.Zip -- | For ZipSerialM streams: -- --
--   (<>) = serial
--   (*) = 'Streamly.Prelude.serial.zipWith' id
--   
-- -- Applicative evaluates the streams being zipped serially: -- --
--   >>> s1 = Stream.fromFoldable [1, 2]
--   
--   >>> s2 = Stream.fromFoldable [3, 4]
--   
--   >>> s3 = Stream.fromFoldable [5, 6]
--   
--   >>> Stream.toList $ Stream.fromZipSerial $ (,,) <$> s1 <*> s2 <*> s3
--   [(1,3,5),(2,4,6)]
--   
-- -- Since: 0.2.0 (Streamly) newtype ZipSerialM m a ZipSerialM :: Stream m a -> ZipSerialM m a [getZipSerialM] :: ZipSerialM m a -> Stream m a -- | An IO stream whose applicative instance zips streams serially. -- -- Since: 0.2.0 (Streamly) type ZipSerial = ZipSerialM IO consMZip :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a zipWithK :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c zipWithMK :: Monad m => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c newtype ZipConcurrent m a ZipConcurrent :: Stream m a -> ZipConcurrent m a [getZipConcurrent] :: ZipConcurrent m a -> Stream m a type ZipStream = ZipSerialM instance GHC.Base.Monoid (Streamly.Internal.Data.Stream.Zip.ZipSerialM m a) instance GHC.Base.Semigroup (Streamly.Internal.Data.Stream.Zip.ZipSerialM m a) instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.Zip.ZipConcurrent m) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Applicative (Streamly.Internal.Data.Stream.Zip.ZipConcurrent m) instance GHC.Exts.IsList (Streamly.Internal.Data.Stream.Zip.ZipSerialM Data.Functor.Identity.Identity a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Streamly.Internal.Data.Stream.Zip.ZipSerialM Data.Functor.Identity.Identity a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Streamly.Internal.Data.Stream.Zip.ZipSerialM Data.Functor.Identity.Identity a) instance GHC.Show.Show a => GHC.Show.Show (Streamly.Internal.Data.Stream.Zip.ZipSerialM Data.Functor.Identity.Identity a) instance GHC.Read.Read a => GHC.Read.Read (Streamly.Internal.Data.Stream.Zip.ZipSerialM Data.Functor.Identity.Identity a) instance (a GHC.Types.~ GHC.Types.Char) => Data.String.IsString (Streamly.Internal.Data.Stream.Zip.ZipSerialM Data.Functor.Identity.Identity a) instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Streamly.Internal.Data.Stream.Zip.ZipSerialM Data.Functor.Identity.Identity a) instance Control.DeepSeq.NFData1 (Streamly.Internal.Data.Stream.Zip.ZipSerialM Data.Functor.Identity.Identity) instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.Zip.ZipSerialM m) instance GHC.Base.Monad m => GHC.Base.Applicative (Streamly.Internal.Data.Stream.Zip.ZipSerialM m) instance (Data.Foldable.Foldable m, GHC.Base.Monad m) => Data.Foldable.Foldable (Streamly.Internal.Data.Stream.Zip.ZipSerialM m) instance Data.Traversable.Traversable (Streamly.Internal.Data.Stream.Zip.ZipSerialM Data.Functor.Identity.Identity) -- | To run examples in this module: -- --
--   >>> import qualified Streamly.Prelude as Stream
--   
-- | Deprecated: Use Streamly.Data.Stream.MkType instead. module Streamly.Internal.Data.Stream.ZipAsync -- | For ZipAsyncM streams: -- --
--   (<>) = serial
--   (*) = 'Streamly.Prelude.serial.zipAsyncWith' id
--   
-- -- Applicative evaluates the streams being zipped concurrently, the -- following would take half the time that it would take in serial -- zipping: -- --
--   >>> s = Stream.fromFoldableM $ Prelude.map delay [1, 1, 1]
--   
--   >>> Stream.toList $ Stream.fromZipAsync $ (,) <$> s <*> s
--   ...
--   [(1,1),(1,1),(1,1)]
--   
-- -- Since: 0.2.0 (Streamly) newtype ZipAsyncM m a ZipAsyncM :: Stream m a -> ZipAsyncM m a [getZipAsyncM] :: ZipAsyncM m a -> Stream m a -- | An IO stream whose applicative instance zips streams wAsyncly. -- -- Since: 0.2.0 (Streamly) type ZipAsync = ZipAsyncM IO consMZipAsync :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a -- | Like zipWith but zips concurrently i.e. both the streams -- being zipped are evaluated concurrently using the ParallelT -- concurrent evaluation style. The maximum number of elements of each -- stream evaluated in advance can be controlled by maxBuffer. -- -- The stream ends if stream a or stream b ends. -- However, if stream b ends while we are still evaluating -- stream a and waiting for a result then stream will not end -- until after the evaluation of stream a finishes. This -- behavior can potentially be changed in future to end the stream -- immediately as soon as any of the stream end is detected. zipAsyncWithK :: MonadAsync m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c -- | Like zipAsyncWith but with a monadic zipping function. zipAsyncWithMK :: MonadAsync m => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c instance GHC.Base.Monoid (Streamly.Internal.Data.Stream.ZipAsync.ZipAsyncM m a) instance GHC.Base.Semigroup (Streamly.Internal.Data.Stream.ZipAsync.ZipAsyncM m a) instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.ZipAsync.ZipAsyncM m) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Applicative (Streamly.Internal.Data.Stream.ZipAsync.ZipAsyncM m) -- | This is an internal module which is a superset of the corresponding -- released module Streamly.Prelude. It contains some additional -- unreleased or experimental APIs. -- | Deprecated: Please use "Streamly.Internal.Data.Stream from -- streamly-core package", -- Streamly.Internal.Data.Stream.Concurrent, -- Streamly.Internal.Data.Stream.Exception.Lifted, & -- Streamly.Internal.Data.Stream.Time from streamly package -- instead. module Streamly.Internal.Data.Stream.IsStream newtype StreamK (m :: Type -> Type) a MkStream :: (forall r. () => State StreamK m a -> (a -> StreamK m a -> m r) -> (a -> m r) -> m r -> m r) -> StreamK (m :: Type -> Type) a -- | An interleaving serial IO stream of elements of type a. See -- WSerialT documentation for more details. -- -- Since: 0.2.0 (Streamly) type WSerial = WSerialT IO -- | For WSerialT streams: -- --
--   (<>) = wSerial                       -- Semigroup
--   (>>=) = flip . concatMapWith wSerial -- Monad
--   
-- -- Note that <> is associative only if we disregard the -- ordering of elements in the resulting stream. -- -- A single Monad bind behaves like a for loop: -- --
--   >>> :{
--   IsStream.toList $ IsStream.fromWSerial $ do
--        x <- IsStream.fromList [1,2] -- foreach x in stream
--        return x
--   :}
--   [1,2]
--   
-- -- Nested monad binds behave like interleaved nested for loops: -- --
--   >>> :{
--   IsStream.toList $ IsStream.fromWSerial $ do
--       x <- IsStream.fromList [1,2] -- foreach x in stream
--       y <- IsStream.fromList [3,4] -- foreach y in stream
--       return (x, y)
--   :}
--   [(1,3),(2,3),(1,4),(2,4)]
--   
-- -- It is a result of interleaving all the nested iterations corresponding -- to element 1 in the first stream with all the nested -- iterations of element 2: -- --
--   >>> import Streamly.Prelude (wSerial)
--   
--   >>> IsStream.toList $ IsStream.fromList [(1,3),(1,4)] `IsStream.wSerial` IsStream.fromList [(2,3),(2,4)]
--   [(1,3),(2,3),(1,4),(2,4)]
--   
-- -- The W in the name stands for wide or breadth wise -- scheduling in contrast to the depth wise scheduling behavior of -- SerialT. -- -- Since: 0.2.0 (Streamly) data WSerialT m a -- | A serial IO stream of elements of type a. See SerialT -- documentation for more details. -- -- Since: 0.2.0 (Streamly) type Serial = SerialT IO -- | For SerialT streams: -- --
--   (<>) = serial                       -- Semigroup
--   (>>=) = flip . concatMapWith serial -- Monad
--   
-- -- A single Monad bind behaves like a for loop: -- --
--   >>> :{
--   IsStream.toList $ do
--        x <- IsStream.fromList [1,2] -- foreach x in stream
--        return x
--   :}
--   [1,2]
--   
-- -- Nested monad binds behave like nested for loops: -- --
--   >>> :{
--   IsStream.toList $ do
--       x <- IsStream.fromList [1,2] -- foreach x in stream
--       y <- IsStream.fromList [3,4] -- foreach y in stream
--       return (x, y)
--   :}
--   [(1,3),(1,4),(2,3),(2,4)]
--   
-- -- Since: 0.2.0 (Streamly) data SerialT m a -- | A parallely composing IO stream of elements of type a. See -- ParallelT documentation for more details. -- -- Since: 0.2.0 (Streamly) type Parallel = ParallelT IO -- | For ParallelT streams: -- --
--   (<>) = parallel
--   (>>=) = flip . concatMapWith parallel
--   
-- -- See AsyncT, ParallelT is similar except that all -- iterations are strictly concurrent while in AsyncT it depends -- on the consumer demand and available threads. See parallel -- for more details. -- -- Since: 0.1.0 (Streamly) -- -- Since: 0.7.0 (maxBuffer applies to ParallelT streams) data ParallelT m a -- | A round robin parallely composing IO stream of elements of type -- a. See WAsyncT documentation for more details. -- -- Since: 0.2.0 (Streamly) type WAsync = WAsyncT IO -- | For WAsyncT streams: -- --
--   (<>) = wAsync
--   (>>=) = flip . concatMapWith wAsync
--   
-- -- A single Monad bind behaves like a for loop with -- iterations of the loop executed concurrently a la the wAsync -- combinator, producing results and side effects of iterations out of -- order: -- --
--   >>> :{
--   Stream.toList $ Stream.fromWAsync $ do
--        x <- Stream.fromList [2,1] -- foreach x in stream
--        Stream.fromEffect $ delay x
--   :}
--   1 sec
--   2 sec
--   [1,2]
--   
-- -- Nested monad binds behave like nested for loops with nested -- iterations executed concurrently, a la the wAsync combinator: -- --
--   >>> :{
--   Stream.toList $ Stream.fromWAsync $ do
--       x <- Stream.fromList [1,2] -- foreach x in stream
--       y <- Stream.fromList [2,4] -- foreach y in stream
--       Stream.fromEffect $ delay (x + y)
--   :}
--   3 sec
--   4 sec
--   5 sec
--   6 sec
--   [3,4,5,6]
--   
-- -- The behavior can be explained as follows. All the iterations -- corresponding to the element 1 in the first stream constitute -- one WAsyncT output stream and all the iterations corresponding -- to 2 constitute another WAsyncT output stream and -- these two output streams are merged using wAsync. -- -- The W in the name stands for wide or breadth wise -- scheduling in contrast to the depth wise scheduling behavior of -- AsyncT. -- -- Since: 0.2.0 (Streamly) data WAsyncT m a -- | A demand driven left biased parallely composing IO stream of elements -- of type a. See AsyncT documentation for more details. -- -- Since: 0.2.0 (Streamly) type Async = AsyncT IO -- | For AsyncT streams: -- --
--   (<>) = async
--   (>>=) = flip . concatMapWith async
--   
-- -- A single Monad bind behaves like a for loop with -- iterations of the loop executed concurrently a la the async -- combinator, producing results and side effects of iterations out of -- order: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAsync $ do
--        x <- Stream.fromList [2,1] -- foreach x in stream
--        Stream.fromEffect $ delay x
--   :}
--   1 sec
--   2 sec
--   [1,2]
--   
-- -- Nested monad binds behave like nested for loops with nested -- iterations executed concurrently, a la the async combinator: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAsync $ do
--       x <- Stream.fromList [1,2] -- foreach x in stream
--       y <- Stream.fromList [2,4] -- foreach y in stream
--       Stream.fromEffect $ delay (x + y)
--   :}
--   3 sec
--   4 sec
--   5 sec
--   6 sec
--   [3,4,5,6]
--   
-- -- The behavior can be explained as follows. All the iterations -- corresponding to the element 1 in the first stream constitute -- one output stream and all the iterations corresponding to 2 -- constitute another output stream and these two output streams are -- merged using async. -- -- Since: 0.1.0 (Streamly) data AsyncT m a -- | A serial IO stream of elements of type a with concurrent -- lookahead. See AheadT documentation for more details. -- -- Since: 0.3.0 (Streamly) type Ahead = AheadT IO -- | For AheadT streams: -- --
--   (<>) = ahead
--   (>>=) = flip . concatMapWith ahead
--   
-- -- A single Monad bind behaves like a for loop with -- iterations executed concurrently, ahead of time, producing side -- effects of iterations out of order, but results in order: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAhead $ do
--        x <- Stream.fromList [2,1] -- foreach x in stream
--        Stream.fromEffect $ delay x
--   :}
--   1 sec
--   2 sec
--   [2,1]
--   
-- -- Nested monad binds behave like nested for loops with nested -- iterations executed concurrently, ahead of time: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAhead $ do
--       x <- Stream.fromList [1,2] -- foreach x in stream
--       y <- Stream.fromList [2,4] -- foreach y in stream
--       Stream.fromEffect $ delay (x + y)
--   :}
--   3 sec
--   4 sec
--   5 sec
--   6 sec
--   [3,5,4,6]
--   
-- -- The behavior can be explained as follows. All the iterations -- corresponding to the element 1 in the first stream constitute -- one output stream and all the iterations corresponding to 2 -- constitute another output stream and these two output streams are -- merged using ahead. -- -- Since: 0.3.0 (Streamly) data AheadT m a -- | An IO stream whose applicative instance zips streams serially. -- -- Since: 0.2.0 (Streamly) type ZipSerial = ZipSerialM IO -- | For ZipSerialM streams: -- --
--   (<>) = serial
--   (*) = 'Streamly.Prelude.serial.zipWith' id
--   
-- -- Applicative evaluates the streams being zipped serially: -- --
--   >>> s1 = Stream.fromFoldable [1, 2]
--   
--   >>> s2 = Stream.fromFoldable [3, 4]
--   
--   >>> s3 = Stream.fromFoldable [5, 6]
--   
--   >>> Stream.toList $ Stream.fromZipSerial $ (,,) <$> s1 <*> s2 <*> s3
--   [(1,3,5),(2,4,6)]
--   
-- -- Since: 0.2.0 (Streamly) data ZipSerialM m a -- | An IO stream whose applicative instance zips streams wAsyncly. -- -- Since: 0.2.0 (Streamly) type ZipAsync = ZipAsyncM IO -- | For ZipAsyncM streams: -- --
--   (<>) = serial
--   (*) = 'Streamly.Prelude.serial.zipAsyncWith' id
--   
-- -- Applicative evaluates the streams being zipped concurrently, the -- following would take half the time that it would take in serial -- zipping: -- --
--   >>> s = Stream.fromFoldableM $ Prelude.map delay [1, 1, 1]
--   
--   >>> Stream.toList $ Stream.fromZipAsync $ (,) <$> s <*> s
--   ...
--   [(1,1),(1,1),(1,1)]
--   
-- -- Since: 0.2.0 (Streamly) data ZipAsyncM m a -- | Class of types that can represent a stream of elements of some type -- a in some monad m. -- -- Since: 0.2.0 (Streamly) class (forall m a. MonadAsync m => Semigroup (t m a), forall m a. MonadAsync m => Monoid (t m a), forall m. Monad m => Functor (t m), forall m. MonadAsync m => Applicative (t m)) => IsStream t -- | Constructs a stream by adding a monadic action at the head of an -- existing stream. For example: -- --
--   > toList $ getLine `consM` getLine `consM` nil
--   hello
--   world
--   ["hello","world"]
--   
-- -- Concurrent (do not use fromParallel to construct infinite -- streams) consM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a -- | Operator equivalent of consM. We can read it as "parallel -- colon" to remember that | comes before :. -- --
--   > toList $ getLine |: getLine |: nil
--   hello
--   world
--   ["hello","world"]
--   
-- --
--   let delay = threadDelay 1000000 >> print 1
--   drain $ fromSerial  $ delay |: delay |: delay |: nil
--   drain $ fromParallel $ delay |: delay |: delay |: nil
--   
-- -- Concurrent (do not use fromParallel to construct infinite -- streams) (|:) :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a infixr 5 `consM` infixr 5 |: toStreamK :: IsStream t => t m a -> StreamK m a fromStreamK :: IsStream t => StreamK m a -> t m a -- | Adapt any specific stream type to any other specific stream type. -- -- Since: 0.1.0 (Streamly) adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a fromStreamD :: (IsStream t, Monad m) => Stream m a -> t m a -- | Adapt a polymorphic consM operation to a StreamK cons operation toConsK :: IsStream t => (m a -> t m a -> t m a) -> m a -> StreamK m a -> StreamK m a toStreamD :: (IsStream t, Monad m) => t m a -> Stream m a -- |
--   fromList = foldr cons nil
--   
-- -- Construct a stream from a list of pure values. This is more efficient -- than fromFoldable for serial streams. fromList :: (Monad m, IsStream t) => [a] -> t m a -- | Build a stream from an SVar, a stop continuation, a singleton -- stream continuation and a yield continuation. mkStream :: IsStream t => (forall r. State StreamK m a -> (a -> t m a -> m r) -> (a -> m r) -> m r -> m r) -> t m a foldrMx :: (IsStream t, Monad m) => (a -> m x -> m x) -> m x -> (m x -> m b) -> t m a -> m b -- | Like foldlx', but with a monadic step function. foldlMx' :: (IsStream t, Monad m) => (x -> a -> m x) -> m x -> (x -> m b) -> t m a -> m b -- | Strict left fold with an extraction function. Like the standard strict -- left fold, but applies a user supplied extraction function (the third -- argument) to the folded value at the end. This is designed to work -- with the foldl library. The suffix x is a mnemonic -- for extraction. foldlx' :: (IsStream t, Monad m) => (x -> a -> x) -> x -> (x -> b) -> t m a -> m b -- | Fold a stream by providing an SVar, a stop continuation, a singleton -- continuation and a yield continuation. The stream would share the -- current SVar passed via the State. foldStreamShared :: IsStream t => State StreamK m a -> (a -> t m a -> m r) -> (a -> m r) -> m r -> t m a -> m r -- | Fold a stream by providing a State, stop continuation, a singleton -- continuation and a yield continuation. The stream will not use the -- SVar passed via State. foldStream :: IsStream t => State StreamK m a -> (a -> t m a -> m r) -> (a -> m r) -> m r -> t m a -> m r -- | Fix the type of a polymorphic stream as SerialT. -- -- Since: 0.1.0 (Streamly) fromSerial :: IsStream t => SerialT m a -> t m a -- | Fix the type of a polymorphic stream as WSerialT. -- -- Since: 0.2.0 (Streamly) fromWSerial :: IsStream t => WSerialT m a -> t m a -- | Fix the type of a polymorphic stream as AsyncT. -- -- Since: 0.1.0 (Streamly) fromAsync :: IsStream t => AsyncT m a -> t m a -- | Fix the type of a polymorphic stream as WAsyncT. -- -- Since: 0.2.0 (Streamly) fromWAsync :: IsStream t => WAsyncT m a -> t m a -- | Fix the type of a polymorphic stream as AheadT. -- -- Since: 0.3.0 (Streamly) fromAhead :: IsStream t => AheadT m a -> t m a -- | Fix the type of a polymorphic stream as ParallelT. -- -- Since: 0.1.0 (Streamly) fromParallel :: IsStream t => ParallelT m a -> t m a -- | Fix the type of a polymorphic stream as ZipSerialM. -- -- Since: 0.2.0 (Streamly) fromZipSerial :: IsStream t => ZipSerialM m a -> t m a -- | Fix the type of a polymorphic stream as ZipAsyncM. -- -- Since: 0.2.0 (Streamly) fromZipAsync :: IsStream t => ZipAsyncM m a -> t m a -- | Construct a stream by adding a pure value at the head of an existing -- stream. For serial streams this is the same as (return a) `consM` -- r but more efficient. For concurrent streams this is not -- concurrent whereas consM is concurrent. For example: -- --
--   > toList $ 1 `cons` 2 `cons` 3 `cons` nil
--   [1,2,3]
--   
cons :: IsStream t => a -> t m a -> t m a infixr 5 `cons` -- | Operator equivalent of cons. -- --
--   > toList $ 1 .: 2 .: 3 .: nil
--   [1,2,3]
--   
(.:) :: IsStream t => a -> t m a -> t m a infixr 5 .: nil :: IsStream t => t m a nilM :: (IsStream t, Monad m) => m b -> t m a bindWith :: IsStream t => (t m b -> t m b -> t m b) -> t m a -> (a -> t m b) -> t m b -- | concatMapWith mixer generator stream is a two dimensional -- looping combinator. The generator function is used to -- generate streams from the elements in the input stream and -- the mixer function is used to merge those streams. -- -- Note we can merge streams concurrently by using a concurrent merge -- function. -- -- Since: 0.7.0 -- -- Since: 0.8.0 (signature change) concatMapWith :: IsStream t => (t m b -> t m b -> t m b) -> (a -> t m b) -> t m a -> t m b -- | A variant of foldMap that allows you to map a monadic -- streaming action on a Foldable container and then fold it using -- the specified stream merge operation. -- --
--   concatMapFoldableWith async return [1..3]
--   
-- -- Equivalent to: -- --
--   concatMapFoldableWith f g = Prelude.foldr (f . g) S.nil
--   concatMapFoldableWith f g xs = S.concatMapWith f g (S.fromFoldable xs)
--   
-- -- Since: 0.8.0 (Renamed foldMapWith to concatMapFoldableWith) -- -- Since: 0.1.0 (Streamly) concatMapFoldableWith :: (IsStream t, Foldable f) => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b -- | Like concatMapFoldableWith but with the last two arguments -- reversed i.e. the monadic streaming function is the last argument. -- -- Equivalent to: -- --
--   concatForFoldableWith f xs g = Prelude.foldr (f . g) D.nil xs
--   concatForFoldableWith f = flip (D.concatMapFoldableWith f)
--   
-- -- Since: 0.8.0 (Renamed forEachWith to concatForFoldableWith) -- -- Since: 0.1.0 (Streamly) concatForFoldableWith :: (IsStream t, Foldable f) => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b -- | A variant of fold that allows you to fold a Foldable -- container of streams using the specified stream sum operation. -- --
--   concatFoldableWith async $ map return [1..3]
--   
-- -- Equivalent to: -- --
--   concatFoldableWith f = Prelude.foldr f D.nil
--   concatFoldableWith f = D.concatMapFoldableWith f id
--   
-- -- Since: 0.8.0 (Renamed foldWith to concatFoldableWith) -- -- Since: 0.1.0 (Streamly) concatFoldableWith :: (IsStream t, Foldable f) => (t m a -> t m a -> t m a) -> f (t m a) -> t m a nil :: IsStream t => t m a nilM :: (IsStream t, Monad m) => m b -> t m a -- | Construct a stream by adding a pure value at the head of an existing -- stream. For serial streams this is the same as (return a) `consM` -- r but more efficient. For concurrent streams this is not -- concurrent whereas consM is concurrent. For example: -- --
--   > toList $ 1 `cons` 2 `cons` 3 `cons` nil
--   [1,2,3]
--   
cons :: IsStream t => a -> t m a -> t m a infixr 5 `cons` -- | Operator equivalent of cons. -- --
--   > toList $ 1 .: 2 .: 3 .: nil
--   [1,2,3]
--   
(.:) :: IsStream t => a -> t m a -> t m a infixr 5 .: -- | Constructs a stream by adding a monadic action at the head of an -- existing stream. For example: -- --
--   > toList $ getLine `consM` getLine `consM` nil
--   hello
--   world
--   ["hello","world"]
--   
-- -- Concurrent (do not use fromParallel to construct infinite -- streams) consM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a infixr 5 `consM` -- | Operator equivalent of consM. We can read it as "parallel -- colon" to remember that | comes before :. -- --
--   > toList $ getLine |: getLine |: nil
--   hello
--   world
--   ["hello","world"]
--   
-- --
--   let delay = threadDelay 1000000 >> print 1
--   drain $ fromSerial  $ delay |: delay |: delay |: nil
--   drain $ fromParallel $ delay |: delay |: delay |: nil
--   
-- -- Concurrent (do not use fromParallel to construct infinite -- streams) (|:) :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a infixr 5 |: -- | Convert an Unfold into a stream by supplying it an input seed. -- --
--   >>> Stream.drain $ Stream.unfold Unfold.replicateM (3, putStrLn "hello")
--   hello
--   hello
--   hello
--   
-- -- Since: 0.7.0 unfold :: (IsStream t, Monad m) => Unfold m a b -> a -> t m b -- | Convert an Unfold with a closed input end into a stream. -- -- Pre-release unfold0 :: (IsStream t, Monad m) => Unfold m Void b -> t m b -- |
--   >>> :{
--   unfoldr step s =
--       case step s of
--           Nothing -> Stream.nil
--           Just (a, b) -> a `Stream.cons` unfoldr step b
--   :}
--   
-- -- Build a stream by unfolding a pure step function step -- starting from a seed s. The step function returns the next -- element in the stream and the next seed value. When it is done it -- returns Nothing and the stream ends. For example, -- --
--   >>> :{
--   let f b =
--           if b > 2
--           then Nothing
--           else Just (b, b + 1)
--   in Stream.toList $ Stream.unfoldr f 0
--   :}
--   [0,1,2]
--   
unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a -- | Build a stream by unfolding a monadic step function starting -- from a seed. The step function returns the next element in the stream -- and the next seed value. When it is done it returns Nothing and -- the stream ends. For example, -- --
--   >>> :{
--   let f b =
--           if b > 2
--           then return Nothing
--           else return (Just (b, b + 1))
--   in Stream.toList $ Stream.unfoldrM f 0
--   :}
--   [0,1,2]
--   
-- -- When run concurrently, the next unfold step can run concurrently with -- the processing of the output of the previous step. Note that more than -- one step cannot run concurrently as the next step depends on the -- output of the previous step. -- --
--   >>> :{
--   let f b =
--           if b > 2
--           then return Nothing
--           else threadDelay 1000000 >> return (Just (b, b + 1))
--   in Stream.toList $ Stream.delay 1 $ Stream.fromAsync $ Stream.unfoldrM f 0
--   :}
--   [0,1,2]
--   
-- -- Concurrent -- -- Since: 0.1.0 unfoldrM :: forall t m b a. (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a -- |
--   fromPure a = a `cons` nil
--   
-- -- Create a singleton stream from a pure value. -- -- The following holds in monadic streams, but not in Zip streams: -- --
--   fromPure = pure
--   fromPure = fromEffect . pure
--   
-- -- In Zip applicative streams fromPure is not the same as -- pure because in that case pure is equivalent to -- repeat instead. fromPure and pure are equally -- efficient, in other cases fromPure may be slightly more -- efficient than the other equivalent definitions. -- -- Since: 0.8.0 (Renamed yield to fromPure) fromPure :: IsStream t => a -> t m a -- |
--   fromEffect m = m `consM` nil
--   
-- -- Create a singleton stream from a monadic action. -- --
--   > Stream.toList $ Stream.fromEffect getLine
--   hello
--   ["hello"]
--   
-- -- Since: 0.8.0 (Renamed yieldM to fromEffect) fromEffect :: (Monad m, IsStream t) => m a -> t m a -- | Generate an infinite stream by repeating a pure value. repeat :: (IsStream t, Monad m) => a -> t m a -- |
--   >>> repeatM = fix . consM
--   
--   >>> repeatM = cycle1 . fromEffect
--   
-- -- Generate a stream by repeatedly executing a monadic action forever. -- --
--   >>> :{
--   repeatAsync =
--          Stream.repeatM (threadDelay 1000000 >> print 1)
--        & Stream.take 10
--        & Stream.fromAsync
--        & Stream.drain
--   :}
--   
-- -- Concurrent, infinite (do not use with fromParallel) repeatM :: (IsStream t, MonadAsync m) => m a -> t m a -- |
--   >>> replicate n = Stream.take n . Stream.repeat
--   
-- -- Generate a stream of length n by repeating a value n -- times. replicate :: (IsStream t, Monad m) => Int -> a -> t m a -- |
--   >>> replicateM n = Stream.take n . Stream.repeatM
--   
-- -- Generate a stream by performing a monadic action n times. -- Same as: -- --
--   >>> pr n = threadDelay 1000000 >> print n
--   
-- -- This runs serially and takes 3 seconds: -- --
--   >>> Stream.drain $ Stream.fromSerial $ Stream.replicateM 3 $ pr 1
--   1
--   1
--   1
--   
-- -- This runs concurrently and takes just 1 second: -- --
--   >>> Stream.drain $ Stream.fromAsync  $ Stream.replicateM 3 $ pr 1
--   1
--   1
--   1
--   
-- -- Concurrent replicateM :: forall t m a. (IsStream t, MonadAsync m) => Int -> m a -> t m a -- | Types that can be enumerated as a stream. The operations in this type -- class are equivalent to those in the Enum type class, except -- that these generate a stream instead of a list. Use the functions in -- Streamly.Internal.Data.Stream.Enumeration module to define new -- instances. class Enum a => Enumerable a -- | enumerateFrom from generates a stream starting with the -- element from, enumerating up to maxBound when the type -- is Bounded or generating an infinite stream when the type is -- not Bounded. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFrom (0 :: Int)
--   [0,1,2,3]
--   
-- -- For Fractional types, enumeration is numerically stable. -- However, no overflow or underflow checks are performed. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFrom 1.1
--   [1.1,2.1,3.1,4.1]
--   
enumerateFrom :: (Enumerable a, IsStream t, Monad m) => a -> t m a -- | Generate a finite stream starting with the element from, -- enumerating the type up to the value to. If to is -- smaller than from then an empty stream is returned. -- --
--   >>> Stream.toList $ Stream.enumerateFromTo 0 4
--   [0,1,2,3,4]
--   
-- -- For Fractional types, the last element is equal to the -- specified to value after rounding to the nearest integral -- value. -- --
--   >>> Stream.toList $ Stream.enumerateFromTo 1.1 4
--   [1.1,2.1,3.1,4.1]
--   
--   >>> Stream.toList $ Stream.enumerateFromTo 1.1 4.6
--   [1.1,2.1,3.1,4.1,5.1]
--   
enumerateFromTo :: (Enumerable a, IsStream t, Monad m) => a -> a -> t m a -- | enumerateFromThen from then generates a stream whose first -- element is from, the second element is then and the -- successive elements are in increments of then - from. -- Enumeration can occur downwards or upwards depending on whether -- then comes before or after from. For Bounded -- types the stream ends when maxBound is reached, for unbounded -- types it keeps enumerating infinitely. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 2
--   [0,2,4,6]
--   
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 (-2)
--   [0,-2,-4,-6]
--   
enumerateFromThen :: (Enumerable a, IsStream t, Monad m) => a -> a -> t m a -- | enumerateFromThenTo from then to generates a finite stream -- whose first element is from, the second element is -- then and the successive elements are in increments of -- then - from up to to. Enumeration can occur -- downwards or upwards depending on whether then comes before -- or after from. -- --
--   >>> Stream.toList $ Stream.enumerateFromThenTo 0 2 6
--   [0,2,4,6]
--   
--   >>> Stream.toList $ Stream.enumerateFromThenTo 0 (-2) (-6)
--   [0,-2,-4,-6]
--   
enumerateFromThenTo :: (Enumerable a, IsStream t, Monad m) => a -> a -> a -> t m a -- |
--   enumerate = enumerateFrom minBound
--   
-- -- Enumerate a Bounded type from its minBound to -- maxBound enumerate :: (IsStream t, Monad m, Bounded a, Enumerable a) => t m a -- |
--   enumerateTo = enumerateFromTo minBound
--   
-- -- Enumerate a Bounded type from its minBound to specified -- value. enumerateTo :: (IsStream t, Monad m, Bounded a, Enumerable a) => a -> t m a -- | times returns a stream of time value tuples with clock of 10 -- ms granularity. The first component of the tuple is an absolute time -- reference (epoch) denoting the start of the stream and the second -- component is a time relative to the reference. -- --
--   >>> Stream.mapM_ (\x -> print x >> threadDelay 1000000) $ Stream.take 3 $ Stream.times
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
--   
-- -- Note: This API is not safe on 32-bit machines. -- -- Pre-release times :: (IsStream t, MonadAsync m) => t m (AbsTime, RelTime64) -- | absTimes returns a stream of absolute timestamps using a -- clock of 10 ms granularity. -- --
--   >>> Stream.mapM_ print $ Stream.delayPre 1 $ Stream.take 3 $ Stream.absTimes
--   AbsTime (TimeSpec {sec = ..., nsec = ...})
--   AbsTime (TimeSpec {sec = ..., nsec = ...})
--   AbsTime (TimeSpec {sec = ..., nsec = ...})
--   
-- -- Note: This API is not safe on 32-bit machines. -- -- Pre-release absTimes :: (IsStream t, MonadAsync m, Functor (t m)) => t m AbsTime -- | absTimesWith g returns a stream of absolute timestamps using -- a clock of granularity g specified in seconds. A low -- granularity clock is more expensive in terms of CPU usage. Any -- granularity lower than 1 ms is treated as 1 ms. -- --
--   >>> Stream.mapM_ print $ Stream.delayPre 1 $ Stream.take 3 $ absTimesWith 0.01
--   AbsTime (TimeSpec {sec = ..., nsec = ...})
--   AbsTime (TimeSpec {sec = ..., nsec = ...})
--   AbsTime (TimeSpec {sec = ..., nsec = ...})
--   
-- -- Note: This API is not safe on 32-bit machines. -- -- Pre-release absTimesWith :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m AbsTime -- | relTimes returns a stream of relative time values starting -- from 0, using a clock of granularity 10 ms. -- --
--   >>> Stream.mapM_ print $ Stream.delayPre 1 $ Stream.take 3 $ Stream.relTimes
--   RelTime64 (NanoSecond64 ...)
--   RelTime64 (NanoSecond64 ...)
--   RelTime64 (NanoSecond64 ...)
--   
-- -- Note: This API is not safe on 32-bit machines. -- -- Pre-release relTimes :: (IsStream t, MonadAsync m, Functor (t m)) => t m RelTime64 -- | relTimesWith g returns a stream of relative time values -- starting from 0, using a clock of granularity g specified in -- seconds. A low granularity clock is more expensive in terms of CPU -- usage. Any granularity lower than 1 ms is treated as 1 ms. -- --
--   >>> Stream.mapM_ print $ Stream.delayPre 1 $ Stream.take 3 $ Stream.relTimesWith 0.01
--   RelTime64 (NanoSecond64 ...)
--   RelTime64 (NanoSecond64 ...)
--   RelTime64 (NanoSecond64 ...)
--   
-- -- Note: This API is not safe on 32-bit machines. -- -- Pre-release relTimesWith :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m RelTime64 -- | durations g returns a stream of relative time values -- measuring the time elapsed since the immediate predecessor element of -- the stream was generated. The first element of the stream is always 0. -- durations uses a clock of granularity g specified in -- seconds. A low granularity clock is more expensive in terms of CPU -- usage. The minimum granularity is 1 millisecond. Durations lower than -- 1 ms will be 0. -- -- Note: This API is not safe on 32-bit machines. -- -- Unimplemented durations :: Double -> t m RelTime64 -- | Generate ticks at the specified rate. The rate is adaptive, the tick -- generation speed can be increased or decreased at different times to -- achieve the specified rate. The specific behavior for different styles -- of Rate specifications is documented under Rate. The -- effective maximum rate achieved by a stream is governed by the -- processor speed. -- -- Unimplemented ticks :: Rate -> t m () -- | Generate a singleton event at or after the specified absolute time. -- Note that this is different from a threadDelay, a threadDelay starts -- from the time when the action is evaluated, whereas if we use AbsTime -- based timeout it will immediately expire if the action is evaluated -- too late. -- -- Unimplemented timeout :: AbsTime -> t m () -- |
--   >>> fromIndices f = fmap f $ Stream.enumerateFrom 0
--   
--   >>> fromIndices f = let g i = f i `Stream.cons` g (i + 1) in g 0
--   
-- -- Generate an infinite stream, whose values are the output of a function -- f applied on the corresponding index. Index starts at 0. -- --
--   >>> Stream.toList $ Stream.take 5 $ Stream.fromIndices id
--   [0,1,2,3,4]
--   
fromIndices :: (IsStream t, Monad m) => (Int -> a) -> t m a -- |
--   >>> fromIndicesM f = Stream.mapM f $ Stream.enumerateFrom 0
--   
--   >>> fromIndicesM f = let g i = f i `Stream.consM` g (i + 1) in g 0
--   
-- -- Generate an infinite stream, whose values are the output of a monadic -- function f applied on the corresponding index. Index starts -- at 0. -- -- Concurrent fromIndicesM :: forall t m a. (IsStream t, MonadAsync m) => (Int -> m a) -> t m a -- |
--   >>> iterate f x = x `Stream.cons` iterate f x
--   
-- -- Generate an infinite stream with x as the first element and -- each successive element derived by applying the function f on -- the previous element. -- --
--   >>> Stream.toList $ Stream.take 5 $ Stream.iterate (+1) 1
--   [1,2,3,4,5]
--   
iterate :: (IsStream t, Monad m) => (a -> a) -> a -> t m a -- |
--   >>> iterateM f m = m >>= \a -> return a `Stream.consM` iterateM f (f a)
--   
-- -- Generate an infinite stream with the first element generated by the -- action m and each successive element derived by applying the -- monadic function f on the previous element. -- --
--   >>> pr n = threadDelay 1000000 >> print n
--   
--   >>> :{
--   Stream.iterateM (\x -> pr x >> return (x + 1)) (return 0)
--       & Stream.take 3
--       & Stream.fromSerial
--       & Stream.toList
--   :}
--   0
--   1
--   [0,1,2]
--   
-- -- When run concurrently, the next iteration can run concurrently with -- the processing of the previous iteration. Note that more than one -- iteration cannot run concurrently as the next iteration depends on the -- output of the previous iteration. -- --
--   >>> :{
--   Stream.iterateM (\x -> pr x >> return (x + 1)) (return 0)
--       & Stream.delay 1
--       & Stream.take 3
--       & Stream.fromAsync
--       & Stream.toList
--   :}
--   0
--   1
--   ...
--   
-- -- Concurrent -- -- Since: 0.1.2 -- -- Since: 0.7.0 (signature change) iterateM :: forall t m a. (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a -- | We can define cyclic structures using let: -- --
--   >>> let (a, b) = ([1, b], head a) in (a, b)
--   ([1,1],1)
--   
-- -- The function fix defined as: -- --
--   >>> fix f = let x = f x in x
--   
-- -- ensures that the argument of a function and its output refer to the -- same lazy value x i.e. the same location in memory. Thus -- x can be defined in terms of itself, creating structures with -- cyclic references. -- --
--   >>> f ~(a, b) = ([1, b], head a)
--   
--   >>> fix f
--   ([1,1],1)
--   
-- -- mfix is essentially the same as fix but for monadic -- values. -- -- Using mfix for streams we can construct a stream in which each -- element of the stream is defined in a cyclic fashion. The argument of -- the function being fixed represents the current element of the stream -- which is being returned by the stream monad. Thus, we can use the -- argument to construct itself. -- -- Pre-release mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a -- |
--   fromList = foldr cons nil
--   
-- -- Construct a stream from a list of pure values. This is more efficient -- than fromFoldable for serial streams. fromList :: (Monad m, IsStream t) => [a] -> t m a -- |
--   >>> fromListM = Stream.fromFoldableM
--   
--   >>> fromListM = Stream.sequence . Stream.fromList
--   
--   >>> fromListM = Stream.mapM id . Stream.fromList
--   
--   >>> fromListM = Prelude.foldr Stream.consM Stream.nil
--   
-- -- Construct a stream from a list of monadic actions. This is more -- efficient than fromFoldableM for serial streams. fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a -- |
--   >>> fromFoldable = Prelude.foldr Stream.cons Stream.nil
--   
-- -- Construct a stream from a Foldable containing pure values: fromFoldable :: (IsStream t, Foldable f) => f a -> t m a -- |
--   >>> fromFoldableM = Prelude.foldr Stream.consM Stream.nil
--   
-- -- Construct a stream from a Foldable containing monadic actions. -- --
--   >>> pr n = threadDelay 1000000 >> print n
--   
--   >>> Stream.drain $ Stream.fromSerial $ Stream.fromFoldableM $ map pr [1,2,3]
--   1
--   2
--   3
--   
-- --
--   >>> Stream.drain $ Stream.fromAsync $ Stream.fromFoldableM $ map pr [1,2,3]
--   ...
--   ...
--   ...
--   
-- -- Concurrent (do not use with fromParallel on infinite -- containers) fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a -- | Takes a callback setter function and provides it with a callback. The -- callback when invoked adds a value at the tail of the stream. Returns -- a stream of values generated by the callback. -- -- Pre-release fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> SerialT m a -- | Construct a stream by reading an Unboxed IORef -- repeatedly. -- -- Pre-release fromPrimIORef :: (IsStream t, MonadIO m, Unbox a) => IORef a -> t m a -- | Same as fromPure yield :: IsStream t => a -> t m a -- | Same as fromEffect yieldM :: (Monad m, IsStream t) => m a -> t m a -- | Read lines from an IO Handle into a stream of Strings. fromHandle :: (IsStream t, MonadIO m) => Handle -> t m String currentTime :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m AbsTime -- | Fold a stream using the supplied left Fold and reducing the -- resulting expression strictly at each step. The behavior is similar to -- foldl'. A Fold can terminate early without consuming -- the full stream. See the documentation of individual Folds for -- termination behavior. -- --
--   >>> Stream.fold Fold.sum (Stream.enumerateFromTo 1 100)
--   5050
--   
-- -- Folds never fail, therefore, they produce a default value even when no -- input is provided. It means we can always fold an empty stream and get -- a valid result. For example: -- --
--   >>> Stream.fold Fold.sum Stream.nil
--   0
--   
-- -- However, foldMany on an empty stream results in an empty -- stream. Therefore, Stream.fold f is not the same as -- Stream.head . Stream.foldMany f. -- --
--   fold f = Stream.parse (Parser.fromFold f)
--   
fold :: Monad m => Fold m a b -> SerialT m a -> m b -- | Decompose a stream into its head and tail. If the stream is empty, -- returns Nothing. If the stream is non-empty, returns Just -- (a, ma), where a is the head of the stream and -- ma its tail. -- -- This can be used to do pretty much anything in an imperative manner, -- as it just breaks down the stream into individual elements and we can -- loop over them as we deem fit. For example, this can be used to -- convert a streamly stream into other stream types. -- -- All the folds in this module can be expressed in terms of -- uncons, however, this is generally less efficient than specific -- folds because it takes apart the stream one element at a time, -- therefore, does not take adavantage of stream fusion. uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a)) -- | Right associative/lazy pull fold. foldrM build final stream -- constructs an output structure using the step function build. -- build is invoked with the next input element and the -- remaining (lazy) tail of the output structure. It builds a lazy output -- expression using the two. When the "tail structure" in the output -- expression is evaluated it calls build again thus lazily -- consuming the input stream until either the output expression -- built by build is free of the "tail" or the input is -- exhausted in which case final is used as the terminating case -- for the output structure. For more details see the description in the -- previous section. -- -- Example, determine if any element is odd in a stream: -- --
--   >>> Stream.foldrM (\x xs -> if odd x then return True else xs) (return False) $ Stream.fromList (2:4:5:undefined)
--   True
--   
-- -- Since: 0.7.0 (signature changed) -- -- Since: 0.2.0 (signature changed) -- -- Since: 0.1.0 foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b -- | Right fold, lazy for lazy monads and pure streams, and strict for -- strict monads. -- -- Please avoid using this routine in strict monads like IO unless you -- need a strict right fold. This is provided only for use in lazy monads -- (e.g. Identity) or pure streams. Note that with this signature it is -- not possible to implement a lazy foldr when the monad m is -- strict. In that case it would be strict in its accumulator and -- therefore would necessarily consume all its input. foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b -- | Lazy right fold for non-empty streams, using first element as the -- starting value. Returns Nothing if the stream is empty. foldr1 :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a) -- | Lazy left fold to a stream. foldlS :: IsStream t => (t m b -> a -> t m b) -> t m b -> t m a -> t m b -- | Lazy left fold to a transformer monad. -- -- For example, to reverse a stream: -- --
--   D.toList $ D.foldlT (flip D.cons) D.nil $ (D.fromList [1..5] :: SerialT IO Int)
--   
foldlT :: (Monad m, IsStream t, Monad (s m), MonadTrans s) => (s m b -> a -> s m b) -> s m b -> t m a -> s m b -- | Strict left fold with an extraction function. Like the standard strict -- left fold, but applies a user supplied extraction function (the third -- argument) to the folded value at the end. This is designed to work -- with the foldl library. The suffix x is a mnemonic -- for extraction. foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b -- | Left associative/strict push fold. foldl' reduce initial -- stream invokes reduce with the accumulator and the next -- input in the input stream, using initial as the initial value -- of the current value of the accumulator. When the input is exhausted -- the current value of the accumulator is returned. Make sure to use a -- strict data structure for accumulator to not build unnecessary lazy -- expressions unless that's what you want. See the previous section for -- more details. foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b -- | Strict left fold, for non-empty streams, using first element as the -- starting value. Returns Nothing if the stream is empty. foldl1' :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a) -- | Like foldx, but with a monadic step function. foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b -- | Like foldl' but with a monadic step function. -- -- Since: 0.2.0 -- -- Since: 0.8.0 (signature change) foldlM' :: Monad m => (b -> a -> m b) -> m b -> SerialT m a -> m b -- | Parse a stream using the supplied ParserD Parser. -- -- Internal parseD :: Monad m => Parser a m b -> SerialT m a -> m (Either ParseError b) -- | Parse a stream using the supplied Parser. -- -- Unlike folds, parsers may not always result in a valid output, they -- may result in an error. For example: -- --
--   >>> Stream.parse (Parser.takeEQ 1 Fold.drain) Stream.nil
--   Left (ParseError "takeEQ: Expecting exactly 1 elements, input terminated on 0")
--   
-- -- Note: -- --
--   fold f = Stream.parse (Parser.fromFold f)
--   
-- -- parse p is not the same as head . parseMany p on an -- empty stream. -- -- Pre-release parse :: Monad m => Parser a m b -> SerialT m a -> m (Either ParseError b) -- |
--   mapM_ = Stream.drain . Stream.mapM
--   
-- -- Apply a monadic action to each element of the stream and discard the -- output of the action. This is not really a pure transformation -- operation but a transformation followed by fold. mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m () -- |
--   drain = mapM_ (\_ -> return ())
--   drain = Stream.fold Fold.drain
--   
-- -- Run a stream, discarding the results. By default it interprets the -- stream as SerialT, to run other types of streams use the type -- adapting combinators for example Stream.drain . -- fromAsync. drain :: Monad m => SerialT m a -> m () -- |
--   drainN n = Stream.drain . Stream.take n
--   drainN n = Stream.fold (Fold.take n Fold.drain)
--   
-- -- Run maximum up to n iterations of a stream. drainN :: Monad m => Int -> SerialT m a -> m () -- |
--   runN n = runStream . take n
--   
-- -- Run maximum up to n iterations of a stream. runN :: Monad m => Int -> SerialT m a -> m () -- |
--   drainWhile p = Stream.drain . Stream.takeWhile p
--   
-- -- Run a stream as long as the predicate holds true. drainWhile :: Monad m => (a -> Bool) -> SerialT m a -> m () -- |
--   runWhile p = runStream . takeWhile p
--   
-- -- Run a stream as long as the predicate holds true. runWhile :: Monad m => (a -> Bool) -> SerialT m a -> m () -- | Run a stream, discarding the results. By default it interprets the -- stream as SerialT, to run other types of streams use the type -- adapting combinators for example runStream . -- fromAsync. runStream :: Monad m => SerialT m a -> m () -- | Determine whether the stream is empty. -- --
--   null = Stream.fold Fold.null
--   
null :: Monad m => SerialT m a -> m Bool -- | Extract the first element of the stream, if any. -- --
--   head = (!! 0)
--   head = Stream.fold Fold.one
--   
head :: Monad m => SerialT m a -> m (Maybe a) -- | Extract the first element of the stream, if any, otherwise use the -- supplied default value. It can help avoid one branch in high -- performance code. -- -- Pre-release headElse :: Monad m => a -> SerialT m a -> m a -- |
--   tail = fmap (fmap snd) . Stream.uncons
--   
-- -- Extract all but the first element of the stream, if any. tail :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a)) -- | Extract all but the last element of the stream, if any. init :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a)) -- | Extract the last element of the stream, if any. -- --
--   last xs = xs !! (Stream.length xs - 1)
--   last = Stream.fold Fold.last
--   
last :: Monad m => SerialT m a -> m (Maybe a) -- | Determine whether an element is present in the stream. -- --
--   elem = Stream.fold Fold.elem
--   
elem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool -- | Determine whether an element is not present in the stream. -- --
--   notElem = Stream.fold Fold.length
--   
notElem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool -- | Determine the length of the stream. length :: Monad m => SerialT m a -> m Int -- | Determine whether all elements of a stream satisfy a predicate. -- --
--   all = Stream.fold Fold.all
--   
all :: Monad m => (a -> Bool) -> SerialT m a -> m Bool -- | Determine whether any of the elements of a stream satisfy a predicate. -- --
--   any = Stream.fold Fold.any
--   
any :: Monad m => (a -> Bool) -> SerialT m a -> m Bool -- | Determines if all elements of a boolean stream are True. -- --
--   and = Stream.fold Fold.and
--   
and :: Monad m => SerialT m Bool -> m Bool -- | Determines whether at least one element of a boolean stream is True. -- --
--   or = Stream.fold Fold.or
--   
or :: Monad m => SerialT m Bool -> m Bool -- | Determine the sum of all elements of a stream of numbers. Returns -- 0 when the stream is empty. Note that this is not numerically -- stable for floating point numbers. -- --
--   sum = Stream.fold Fold.sum
--   
sum :: (Monad m, Num a) => SerialT m a -> m a -- | Determine the product of all elements of a stream of numbers. Returns -- 1 when the stream is empty. -- --
--   product = Stream.fold Fold.product
--   
product :: (Monad m, Num a) => SerialT m a -> m a -- | Fold a stream of monoid elements by appending them. -- --
--   mconcat = Stream.fold Fold.mconcat
--   
-- -- Pre-release mconcat :: (Monad m, Monoid a) => SerialT m a -> m a -- |
--   minimum = minimumBy compare
--   minimum = Stream.fold Fold.minimum
--   
-- -- Determine the minimum element in a stream. minimum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a) -- | Determine the minimum element in a stream using the supplied -- comparison function. -- --
--   minimumBy = Stream.fold Fold.minimumBy
--   
minimumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a) -- |
--   maximum = maximumBy compare
--   maximum = Stream.fold Fold.maximum
--   
-- -- Determine the maximum element in a stream. maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a) -- | Determine the maximum element in a stream using the supplied -- comparison function. -- --
--   maximumBy = Stream.fold Fold.maximumBy
--   
maximumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a) -- | Ensures that all the elements of the stream are identical and then -- returns that unique element. the :: (Eq a, Monad m) => SerialT m a -> m (Maybe a) -- | Lookup the element at the given index. (!!) :: Monad m => SerialT m a -> Int -> m (Maybe a) -- | In a stream of (key-value) pairs (a, b), return the value -- b of the first pair where the key equals the given value -- a. -- --
--   lookup = snd <$> Stream.find ((==) . fst)
--   lookup = Stream.fold Fold.lookup
--   
lookup :: (Monad m, Eq a) => a -> SerialT m (a, b) -> m (Maybe b) -- | Like findM but with a non-monadic predicate. -- --
--   find p = findM (return . p)
--   find = Stream.fold Fold.find
--   
find :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe a) -- | Returns the first element that satisfies the given predicate. -- --
--   findM = Stream.fold Fold.findM
--   
findM :: Monad m => (a -> m Bool) -> SerialT m a -> m (Maybe a) -- | Returns the first index that satisfies the given predicate. -- --
--   findIndex = Stream.fold Fold.findIndex
--   
findIndex :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe Int) -- | Returns the first index where a given value is found in the stream. -- --
--   elemIndex a = Stream.findIndex (== a)
--   
elemIndex :: (Monad m, Eq a) => a -> SerialT m a -> m (Maybe Int) -- |
--   toList = Stream.foldr (:) []
--   
-- -- Convert a stream into a list in the underlying monad. The list can be -- consumed lazily in a lazy monad (e.g. Identity). In a strict -- monad (e.g. IO) the whole list is generated and buffered before it can -- be consumed. -- -- Warning! working on large lists accumulated as buffers in -- memory could be very inefficient, consider using Streamly.Array -- instead. toList :: Monad m => SerialT m a -> m [a] -- |
--   toListRev = Stream.foldl' (flip (:)) []
--   
-- -- Convert a stream into a list in reverse order in the underlying monad. -- -- Warning! working on large lists accumulated as buffers in -- memory could be very inefficient, consider using Streamly.Array -- instead. -- -- Pre-release toListRev :: Monad m => SerialT m a -> m [a] -- |
--   toHandle h = D.mapM_ $ hPutStrLn h
--   
-- -- Write a stream of Strings to an IO Handle. toHandle :: MonadIO m => Handle -> SerialT m String -> m () -- | Convert a stream to a pure stream in reverse order. -- --
--   toStreamRev = Stream.foldl' (flip Stream.cons) Stream.nil
--   
-- -- Pre-release toStreamRev :: Monad m => SerialT m a -> m (SerialT n a) -- | Parallel fold application operator; applies a fold function t m a -- -> m b to a stream t m a concurrently; The the input -- stream is evaluated asynchronously in an independent thread yielding -- elements to a buffer and the folding action runs in another thread -- consuming the input from the buffer. -- -- If you read the signature as (t m a -> m b) -> (t m a -> -- m b) you can look at it as a transformation that converts a fold -- function to a buffered concurrent fold function. -- -- The . at the end of the operator is a mnemonic for -- termination of the stream. -- -- In the example below, each stage introduces a delay of 1 sec but -- output is printed every second because both stages are concurrent. -- --
--   >>> import Control.Concurrent (threadDelay)
--   
--   >>> import Streamly.Prelude ((|$.))
--   
--   >>> :{
--    Stream.foldlM' (\_ a -> threadDelay 1000000 >> print a) (return ())
--        |$. Stream.replicateM 3 (threadDelay 1000000 >> return 1)
--   :}
--   1
--   1
--   1
--   
-- -- Concurrent -- -- Since: 0.3.0 (Streamly) (|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> t m a -> m b infixr 0 |$. -- | Same as |$.. -- -- Internal foldAsync :: (IsStream t, MonadAsync m) => (t m a -> m b) -> t m a -> m b -- | Same as |$. but with arguments reversed. -- --
--   (|&.) = flip (|$.)
--   
-- -- Concurrent -- -- Since: 0.3.0 (Streamly) (|&.) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> m b) -> m b infixl 1 |&. -- | Returns True if the first stream is the same as or a prefix of -- the second. A stream is a prefix of itself. -- --
--   >>> Stream.isPrefixOf (Stream.fromList "hello") (Stream.fromList "hello" :: SerialT IO Char)
--   True
--   
isPrefixOf :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m Bool -- | Returns True if the first stream is an infix of the second. A -- stream is considered an infix of itself. -- --
--   Stream.isInfixOf (Stream.fromList "hello") (Stream.fromList "hello" :: SerialT IO Char)
--   
-- -- True -- -- Space: O(n) worst case where n is the length of the -- infix. -- -- Pre-release -- -- Requires Storable constraint isInfixOf :: (MonadIO m, Eq a, Enum a, Storable a, Unbox a) => SerialT m a -> SerialT m a -> m Bool -- | Returns True if the first stream is a suffix of the second. A -- stream is considered a suffix of itself. -- --
--   >>> Stream.isSuffixOf (Stream.fromList "hello") (Stream.fromList "hello" :: SerialT IO Char)
--   True
--   
-- -- Space: O(n), buffers entire input stream and the suffix. -- -- Pre-release -- -- Suboptimal - Help wanted. isSuffixOf :: (Monad m, Eq a) => SerialT m a -> SerialT m a -> m Bool -- | Returns True if all the elements of the first stream occur, in -- order, in the second stream. The elements do not have to occur -- consecutively. A stream is a subsequence of itself. -- --
--   >>> Stream.isSubsequenceOf (Stream.fromList "hlo") (Stream.fromList "hello" :: SerialT IO Char)
--   True
--   
isSubsequenceOf :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m Bool -- | stripPrefix prefix stream strips prefix from -- stream if it is a prefix of stream. Returns Nothing if -- the stream does not start with the given prefix, stripped stream -- otherwise. Returns Just nil when the prefix is the same as -- the stream. -- -- See also "Streamly.Internal.Data.Stream.IsStream.Nesting.dropPrefix". -- -- Space: O(1) stripPrefix :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m (Maybe (t m a)) -- | Drops the given suffix from a stream. Returns Nothing if the -- stream does not end with the given suffix. Returns Just nil -- when the suffix is the same as the stream. -- -- It may be more efficient to convert the stream to an Array and use -- stripSuffix on that especially if the elements have a Storable or Prim -- instance. -- -- See also "Streamly.Internal.Data.Stream.IsStream.Nesting.dropSuffix". -- -- Space: O(n), buffers the entire input stream as well as the -- suffix -- -- Pre-release stripSuffix :: (Monad m, Eq a) => SerialT m a -> SerialT m a -> m (Maybe (SerialT m a)) -- | Compare two streams for equality using an equality function. eqBy :: (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> m Bool -- | Compare two streams lexicographically using a comparison function. cmpBy :: (IsStream t, Monad m) => (a -> b -> Ordering) -> t m a -> t m b -> m Ordering -- | Use a Pipe to transform a stream. -- -- Pre-release transform :: (IsStream t, Monad m) => Pipe m a b -> t m a -> t m b -- | Right fold to a streaming monad. -- --
--   foldrS Stream.cons Stream.nil === id
--   
-- -- foldrS can be used to perform stateless stream to stream -- transformations like map and filter in general. It can be coupled with -- a scan to perform stateful transformations. However, note that the -- custom map and filter routines can be much more efficient than this -- due to better stream fusion. -- --
--   >>> Stream.toList $ Stream.foldrS Stream.cons Stream.nil $ Stream.fromList [1..5]
--   [1,2,3,4,5]
--   
-- -- Find if any element in the stream is True: -- --
--   >>> Stream.toList $ Stream.foldrS (\x xs -> if odd x then (Stream.fromPure True) else xs) (Stream.fromPure False) $ (Stream.fromList (2:4:5:undefined) :: Stream.SerialT IO Int)
--   [True]
--   
-- -- Map (+2) on odd elements and filter out the even elements: -- --
--   >>> Stream.toList $ Stream.foldrS (\x xs -> if odd x then (x + 2) `Stream.cons` xs else xs) Stream.nil $ (Stream.fromList [1..5] :: Stream.SerialT IO Int)
--   [3,5,7]
--   
-- -- foldrM can also be represented in terms of foldrS, -- however, the former is much more efficient: -- --
--   foldrM f z s = runIdentityT $ foldrS (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
--   
-- -- Pre-release foldrS :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b foldrSShared :: IsStream t => (a -> t m b -> t m b) -> t m b -> t m a -> t m b -- | Right fold to a transformer monad. This is the most general right fold -- function. foldrS is a special case of foldrT, however -- foldrS implementation can be more efficient: -- --
--   foldrS = foldrT
--   foldrM f z s = runIdentityT $ foldrT (\x xs -> lift $ f x (runIdentityT xs)) (lift z) s
--   
-- -- foldrT can be used to translate streamly streams to other -- transformer monads e.g. to a different streaming type. -- -- Pre-release foldrT :: (IsStream t, Monad m, Monad (s m), MonadTrans s) => (a -> s m b -> s m b) -> s m b -> t m a -> s m b -- |
--   map = fmap
--   
-- -- Same as fmap. -- --
--   > D.toList $ D.map (+1) $ D.fromList [1,2,3]
--   [2,3,4]
--   
map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b -- |
--   sequence = mapM id
--   
-- -- Replace the elements of a stream of monadic actions with the outputs -- of those actions. -- --
--   >>> drain $ Stream.sequence $ Stream.fromList [putStr "a", putStr "b", putStrLn "c"]
--   abc
--   
--   >>> :{
--   drain $ Stream.replicateM 3 (return $ threadDelay 1000000 >> print 1)
--    & (fromSerial . Stream.sequence)
--   :}
--   1
--   1
--   1
--   
--   >>> :{
--   drain $ Stream.replicateM 3 (return $ threadDelay 1000000 >> print 1)
--    & (fromAsync . Stream.sequence)
--   :}
--   1
--   1
--   1
--   
-- -- Concurrent (do not use with fromParallel on infinite -- streams) sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a -- |
--   mapM f = sequence . map f
--   
-- -- Apply a monadic function to each element of the stream and replace it -- with the output of the resulting action. -- --
--   >>> drain $ Stream.mapM putStr $ Stream.fromList ["a", "b", "c"]
--   abc
--   
--   >>> :{
--      drain $ Stream.replicateM 10 (return 1)
--        & (fromSerial . Stream.mapM (x -> threadDelay 1000000 >> print x))
--   :}
--   1
--   ...
--   1
--   
--   > drain $ Stream.replicateM 10 (return 1)
--    & (fromAsync . Stream.mapM (x -> threadDelay 1000000 >> print x))
--   
-- -- Concurrent (do not use with fromParallel on infinite -- streams) mapM :: forall t m a b. (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b -- | A stateful mapM, equivalent to a left scan, more like -- mapAccumL. Hopefully, this is a better alternative to scan. -- Separation of state from the output makes it easier to think in terms -- of a shared state, and also makes it easier to keep the state fully -- strict and the output lazy. -- -- See also: scanlM' -- -- Pre-release smapM :: (IsStream t, Monad m) => (s -> a -> m (s, b)) -> m s -> t m a -> t m b -- | Apply a monadic function to each element flowing through the stream -- and discard the results. -- --
--   >>> Stream.drain $ Stream.trace print (Stream.enumerateFromTo 1 2)
--   1
--   2
--   
-- -- Compare with tap. trace :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m a -- | Perform a side effect before yielding each element of the stream and -- discard the results. -- --
--   >>> Stream.drain $ Stream.trace_ (print "got here") (Stream.enumerateFromTo 1 2)
--   "got here"
--   "got here"
--   
-- -- Same as intersperseMPrefix_ but always serial. -- -- See also: trace -- -- Pre-release trace_ :: (IsStream t, Monad m) => m b -> t m a -> t m a -- | Tap the data flowing through a stream into a Fold. For example, -- you may add a tap to log the contents flowing through the stream. The -- fold is used only for effects, its result is discarded. -- --
--                     Fold m a b
--                         |
--   -----stream m a ---------------stream m a-----
--   
-- --
--   >>> Stream.drain $ Stream.tap (Fold.drainBy print) (Stream.enumerateFromTo 1 2)
--   1
--   2
--   
-- -- Compare with trace. tap :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m a -- | tapOffsetEvery offset n taps every nth element in -- the stream starting at offset. offset can be between -- 0 and n - 1. Offset 0 means start at the first -- element in the stream. If the offset is outside this range then -- offset mod n is used as offset. -- --
--   >>> Stream.drain $ Stream.tapOffsetEvery 0 2 (Fold.rmapM print Fold.toList) $ Stream.enumerateFromTo 0 10
--   [0,2,4,6,8,10]
--   
tapOffsetEvery :: (IsStream t, Monad m) => Int -> Int -> Fold m a b -> t m a -> t m a -- | Redirect a copy of the stream to a supplied fold and run it -- concurrently in an independent thread. The fold may buffer some -- elements. The buffer size is determined by the prevailing -- maxBuffer setting. -- --
--                 Stream m a -> m b
--                         |
--   -----stream m a ---------------stream m a-----
--   
-- --
--   >>> Stream.drain $ Stream.tapAsync (Fold.drainBy print) (Stream.enumerateFromTo 1 2)
--   1
--   2
--   
-- -- Exceptions from the concurrently running fold are propagated to the -- current computation. Note that, because of buffering in the fold, -- exceptions may be delayed and may not correspond to the current -- element being processed in the parent stream, but we guarantee that -- before the parent stream stops the tap finishes and all exceptions -- from it are drained. -- --
--   >>> tapAsync f = Stream.tapAsyncK (Stream.fold f . Stream.adapt)
--   
-- -- Compare with tap. -- -- Pre-release tapAsync :: (IsStream t, MonadAsync m) => Fold m a b -> t m a -> t m a -- | Like tapAsyncF but uses a stream fold function instead of a -- Fold type. -- -- Pre-release tapAsyncK :: (IsStream t, MonadAsync m) => (t m a -> m b) -> t m a -> t m a -- | Concurrently distribute a stream to a collection of fold functions, -- discarding the outputs of the folds. -- --
--   > Stream.drain $ Stream.distributeAsync_ [Stream.mapM_ print, Stream.mapM_ print] (Stream.enumerateFromTo 1 2)
--   1
--   2
--   1
--   2
--   
-- --
--   distributeAsync_ = flip (foldr tapAsync)
--   
-- -- Pre-release distributeAsync_ :: (Foldable f, IsStream t, MonadAsync m) => f (t m a -> m b) -> t m a -> t m a -- | pollCounts predicate transform fold stream counts those -- elements in the stream that pass the predicate. The resulting -- count stream is sent to another thread which transforms it using -- transform and then folds it using fold. The thread -- is automatically cleaned up if the stream stops or aborts due to -- exception. -- -- For example, to print the count of elements processed every second: -- --
--   > Stream.drain $ Stream.pollCounts (const True) (Stream.rollingMap (-) . Stream.delayPost 1) (FLold.drainBy print)
--             $ Stream.enumerateFrom 0
--   
-- -- Note: This may not work correctly on 32-bit machines. -- -- Pre-release pollCounts :: (IsStream t, MonadAsync m) => (a -> Bool) -> (t m Int -> m b) -> t m a -> t m a -- | Scan a stream using the given monadic fold. -- --
--   >>> Stream.toList $ Stream.takeWhile (< 10) $ Stream.scan Fold.sum (Stream.fromList [1..10])
--   [0,1,3,6]
--   
scan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b -- | Like scan but restarts scanning afresh when the scanning fold -- terminates. -- -- Pre-release scanMany :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b -- | Postscan a stream using the given monadic fold. -- -- The following example extracts the input stream up to a point where -- the running average of elements is no more than 10: -- --
--   >>> import Data.Maybe (fromJust)
--   
--   >>> let avg = Fold.teeWith (/) Fold.sum (fmap fromIntegral Fold.length)
--   
--   >>> :{
--    Stream.toList
--     $ Stream.map (fromJust . fst)
--     $ Stream.takeWhile (\(_,x) -> x <= 10)
--     $ Stream.postscan (Fold.tee Fold.last avg) (Stream.enumerateFromTo 1.0 100.0)
--   :}
--   [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0]
--   
postscan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b -- | Strict left scan. Like map, scanl' too is a one to one -- transformation, however it adds an extra element. -- --
--   >>> Stream.toList $ Stream.scanl' (+) 0 $ fromList [1,2,3,4]
--   [0,1,3,6,10]
--   
-- --
--   >>> Stream.toList $ Stream.scanl' (flip (:)) [] $ Stream.fromList [1,2,3,4]
--   [[],[1],[2,1],[3,2,1],[4,3,2,1]]
--   
-- -- The output of scanl' is the initial value of the accumulator -- followed by all the intermediate steps and the final result of -- foldl'. -- -- By streaming the accumulated state after each fold step, we can share -- the state across multiple stages of stream composition. Each stage can -- modify or extend the state, do some processing with it and emit it for -- the next stage, thus modularizing the stream processing. This can be -- useful in stateful or event-driven programming. -- -- Consider the following monolithic example, computing the sum and the -- product of the elements in a stream in one go using a foldl': -- --
--   >>> Stream.foldl' ((s, p) x -> (s + x, p * x)) (0,1) $ Stream.fromList 1,2,3,4
--   
-- -- Using scanl' we can make it modular by computing the sum in -- the first stage and passing it down to the next stage for computing -- the product: -- --
--   >>> :{
--     Stream.foldl' ((_, p) (s, x) -> (s, p * x)) (0,1)
--     $ Stream.scanl' ((s, _) x -> (s + x, x)) (0,1)
--     $ Stream.fromList [1,2,3,4]
--   :}
--   (10,24)
--   
-- -- IMPORTANT: scanl' evaluates the accumulator to WHNF. To avoid -- building lazy expressions inside the accumulator, it is recommended -- that a strict data structure is used for accumulator. -- --
--   >>> scanl' step z = scan (Fold.foldl' step z)
--   
--   >>> scanl' f z xs = scanlM' (\a b -> return (f a b)) (return z) xs
--   
--   >>> scanl' f z xs = z `Stream.cons` postscanl' f z xs
--   
-- -- See also: usingStateT scanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b -- | Like scanl' but with a monadic step function and a monadic -- seed. -- -- Since: 0.4.0 -- -- Since: 0.8.0 (signature change) scanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b -- | scanlMAfter' accumulate initial done stream is like -- scanlM' except that it provides an additional done -- function to be applied on the accumulator when the stream stops. The -- result of done is also emitted in the stream. -- -- This function can be used to allocate a resource in the beginning of -- the scan and release it when the stream ends or to flush the internal -- state of the scan at the end. -- -- Pre-release scanlMAfter' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> (b -> m b) -> t m a -> t m b postscanlMAfter' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> (b -> m b) -> t m a -> t m b -- | Like scanl' but does not stream the initial value of the -- accumulator. -- --
--   >>> postscanl' step z = postscan (Fold.foldl' step z)
--   
--   >>> postscanl' f z = postscanlM' (\a b -> return (f a b)) (return z)
--   
--   >>> postscanl' f z xs = Stream.drop 1 $ Stream.scanl' f z xs
--   
postscanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b -- | Like postscanl' but with a monadic step function and a -- monadic seed. -- --
--   >>> postscanlM' f z xs = Stream.drop 1 $ Stream.scanlM' f z xs
--   
-- -- Since: 0.7.0 -- -- Since: 0.8.0 (signature change) postscanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b -- | Like scanl' but does not stream the final value of the accumulator. -- -- Pre-release prescanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b -- | Like prescanl' but with a monadic step function and a monadic seed. -- -- Pre-release prescanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b -- | Like scanl' but for a non-empty stream. The first element of -- the stream is used as the initial value of the accumulator. Does -- nothing if the stream is empty. -- --
--   >>> Stream.toList $ Stream.scanl1' (+) $ fromList [1,2,3,4]
--   [1,3,6,10]
--   
scanl1' :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> t m a -- | Like scanl1' but with a monadic step function. scanl1M' :: (IsStream t, Monad m) => (a -> a -> m a) -> t m a -> t m a -- | Modify a t m a -> t m a stream transformation that accepts -- a predicate (a -> b) to accept ((s, a) -> b) -- instead, provided a transformation t m a -> t m (s, a). -- Convenient to filter with index or time. -- --
--   filterWithIndex = with indexed filter
--   filterWithAbsTime = with timestamped filter
--   filterWithRelTime = with timeIndexed filter
--   
-- -- Pre-release with :: forall (t :: (Type -> Type) -> Type -> Type) m a b s. Functor (t m) => (t m a -> t m (s, a)) -> (((s, a) -> b) -> t m (s, a) -> t m (s, a)) -> ((s, a) -> b) -> t m a -> t m a -- | Deletes the first occurrence of the element in the stream that -- satisfies the given equality predicate. -- --
--   >>> Stream.toList $ Stream.deleteBy (==) 3 $ Stream.fromList [1,3,3,5]
--   [1,3,5]
--   
deleteBy :: (IsStream t, Monad m) => (a -> a -> Bool) -> a -> t m a -> t m a -- | Include only those elements that pass a predicate. filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a -- | Same as filter but with a monadic predicate. filterM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a -- | Drop repeated elements that are adjacent to each other. uniq :: (Eq a, IsStream t, Monad m) => t m a -> t m a -- | Drop repeated elements that are adjacent to each other using the -- supplied comparison function. -- -- @uniq = uniqBy (==) -- -- To strip duplicate path separators: -- --
--   f x y = x == / && x == y
--   Stream.toList $ Stream.uniqBy f $ Stream.fromList "/a/b"
--   "ab"
--   
-- -- Space: O(1) -- -- See also: nubBy. -- -- Pre-release uniqBy :: (IsStream t, Monad m, Functor (t m)) => (a -> a -> Bool) -> t m a -> t m a -- | Drop repeated elements anywhere in the stream. -- -- Caution: not scalable for infinite streams -- -- See also: nubWindowBy -- -- Unimplemented nubBy :: (a -> a -> Bool) -> t m a -> t m a -- | Strip all leading and trailing occurrences of an element passing a -- predicate and make all other consecutive occurrences uniq. -- --
--   prune p = dropWhileAround p $ uniqBy (x y -> p x && p y)
--   
-- --
--   > Stream.prune isSpace (Stream.fromList "  hello      world!   ")
--   "hello world!"
--   
-- -- Space: O(1) -- -- Unimplemented prune :: (a -> Bool) -> t m a -> t m a -- | Emit only repeated elements, once. -- -- Unimplemented repeated :: t m a -> t m a -- | Take first n elements from the stream and discard the rest. take :: (IsStream t, Monad m) => Int -> t m a -> t m a -- | Take n elements at the end of the stream. -- -- O(n) space, where n is the number elements taken. -- -- Unimplemented takeLast :: Int -> t m a -> t m a -- | Take time interval i seconds at the end of the stream. -- -- O(n) space, where n is the number elements taken. -- -- Unimplemented takeLastInterval :: Double -> t m a -> t m a -- | End the stream as soon as the predicate fails on an element. takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a -- | Same as takeWhile but with a monadic predicate. takeWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a -- | Take all consecutive elements at the end of the stream for which the -- predicate is true. -- -- O(n) space, where n is the number elements taken. -- -- Unimplemented takeWhileLast :: (a -> Bool) -> t m a -> t m a -- | Like takeWhile and takeWhileLast combined. -- -- O(n) space, where n is the number elements taken from the end. -- -- Unimplemented takeWhileAround :: (a -> Bool) -> t m a -> t m a -- | Discard first n elements from the stream and take the rest. drop :: (IsStream t, Monad m) => Int -> t m a -> t m a -- | Drop n elements at the end of the stream. -- -- O(n) space, where n is the number elements dropped. -- -- Unimplemented dropLast :: Int -> t m a -> t m a -- | Drop time interval i seconds at the end of the stream. -- -- O(n) space, where n is the number elements dropped. -- -- Unimplemented dropLastInterval :: Int -> t m a -> t m a -- | Drop elements in the stream as long as the predicate succeeds and then -- take the rest of the stream. dropWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a -- | Same as dropWhile but with a monadic predicate. dropWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a -- | Drop all consecutive elements at the end of the stream for which the -- predicate is true. -- -- O(n) space, where n is the number elements dropped. -- -- Unimplemented dropWhileLast :: (a -> Bool) -> t m a -> t m a -- | Like dropWhile and dropWhileLast combined. -- -- O(n) space, where n is the number elements dropped from the end. -- -- Unimplemented dropWhileAround :: (a -> Bool) -> t m a -> t m a -- | Insert a pure value between successive elements of a stream. -- --
--   >>> Stream.toList $ Stream.intersperse ',' $ Stream.fromList "hello"
--   "h,e,l,l,o"
--   
intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a -- | Insert an effect and its output before consuming an element of a -- stream except the first one. -- --
--   >>> Stream.toList $ Stream.trace putChar $ Stream.intersperseM (putChar '.' >> return ',') $ Stream.fromList "hello"
--   h.,e.,l.,l.,o"h,e,l,l,o"
--   
-- -- Be careful about the order of effects. In the above example we used -- trace after the intersperse, if we use it before the intersperse the -- output would be he.l.l.o."h,e,l,l,o". -- --
--   >>> Stream.toList $ Stream.intersperseM (putChar '.' >> return ',') $ Stream.trace putChar $ Stream.fromList "hello"
--   he.l.l.o."h,e,l,l,o"
--   
intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a -- | Intersperse a monadic action into the input stream after every -- n elements. -- --
--   > Stream.toList $ Stream.intersperseMWith 2 (return ',') $ Stream.fromList "hello"
--   "he,ll,o"
--   
-- -- Unimplemented intersperseMWith :: Int -> m a -> t m a -> t m a -- | Insert an effect and its output after consuming an element of a -- stream. -- --
--   >>> Stream.toList $ Stream.trace putChar $ intersperseMSuffix (putChar '.' >> return ',') $ Stream.fromList "hello"
--   h.,e.,l.,l.,o.,"h,e,l,l,o,"
--   
-- -- Pre-release intersperseMSuffix :: (IsStream t, Monad m) => m a -> t m a -> t m a -- | Like intersperseMSuffix but intersperses an effectful action -- into the input stream after every n elements and after the -- last element. -- --
--   >>> Stream.toList $ Stream.intersperseMSuffixWith 2 (return ',') $ Stream.fromList "hello"
--   "he,ll,o,"
--   
-- -- Pre-release intersperseMSuffixWith :: (IsStream t, Monad m) => Int -> m a -> t m a -> t m a -- | Intersperse a monadic action into the input stream after every -- n seconds. -- --
--   > import Control.Concurrent (threadDelay)
--   > Stream.drain $ Stream.interjectSuffix 1 (putChar ',') $ Stream.mapM (x -> threadDelay 1000000 >> putChar x) $ Stream.fromList "hello"
--   h,e,l,l,o
--   
-- -- Pre-release interjectSuffix :: (IsStream t, MonadAsync m) => Double -> m a -> t m a -> t m a -- | Insert a side effect before consuming an element of a stream except -- the first one. -- --
--   >>> Stream.drain $ Stream.trace putChar $ Stream.intersperseM_ (putChar '.') $ Stream.fromList "hello"
--   h.e.l.l.o
--   
-- -- Pre-release intersperseM_ :: (IsStream t, Monad m) => m b -> t m a -> t m a -- | Introduce a delay of specified seconds before consuming an element of -- the stream except the first one. -- --
--   >>> Stream.mapM_ print $ Stream.timestamped $ Stream.delay 1 $ Stream.enumerateFromTo 1 3
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),1)
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),2)
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),3)
--   
delay :: (IsStream t, MonadIO m) => Double -> t m a -> t m a -- | Insert a side effect after consuming an element of a stream. -- --
--   >>> Stream.mapM_ putChar $ Stream.intersperseMSuffix_ (threadDelay 1000000) $ Stream.fromList "hello"
--   hello
--   
-- -- Pre-release intersperseMSuffix_ :: (IsStream t, Monad m) => m b -> t m a -> t m a -- | Introduce a delay of specified seconds after consuming an element of a -- stream. -- --
--   >>> Stream.mapM_ print $ Stream.timestamped $ Stream.delayPost 1 $ Stream.enumerateFromTo 1 3
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),1)
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),2)
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),3)
--   
-- -- Pre-release delayPost :: (IsStream t, MonadIO m) => Double -> t m a -> t m a -- | Insert a side effect before consuming an element of a stream. -- --
--   >>> Stream.toList $ Stream.trace putChar $ Stream.intersperseMPrefix_ (putChar '.' >> return ',') $ Stream.fromList "hello"
--   .h.e.l.l.o"hello"
--   
-- -- Same as trace_ but may be concurrent. -- -- Concurrent -- -- Pre-release intersperseMPrefix_ :: (IsStream t, MonadAsync m) => m b -> t m a -> t m a -- | Introduce a delay of specified seconds before consuming an element of -- a stream. -- --
--   >>> Stream.mapM_ print $ Stream.timestamped $ Stream.delayPre 1 $ Stream.enumerateFromTo 1 3
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),1)
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),2)
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),3)
--   
-- -- Pre-release delayPre :: (IsStream t, MonadIO m) => Double -> t m a -> t m a -- | insertBy cmp elem stream inserts elem before the -- first element in stream that is less than elem when -- compared using cmp. -- --
--   insertBy cmp x = mergeBy cmp (fromPure x)
--   
-- --
--   >>> Stream.toList $ Stream.insertBy compare 2 $ Stream.fromList [1,3,5]
--   [1,2,3,5]
--   
insertBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> a -> t m a -> t m a -- | Returns the elements of the stream in reverse order. The stream must -- be finite. Note that this necessarily buffers the entire stream in -- memory. -- --
--   >>> reverse = Stream.foldlT (flip Stream.cons) Stream.nil
--   
-- -- Since 0.7.0 (Monad m constraint) -- -- Since: 0.1.1 reverse :: (IsStream t, Monad m) => t m a -> t m a -- | Like reverse but several times faster, requires a -- Storable instance. -- -- Pre-release reverse' :: (IsStream t, MonadIO m, Unbox a) => t m a -> t m a -- | Buffer until the next element in sequence arrives. The function -- argument determines the difference in sequence numbers. This could be -- useful in implementing sequenced streams, for example, TCP reassembly. -- -- Unimplemented reassembleBy :: Fold m a b -> (a -> a -> Int) -> t m a -> t m b -- |
--   indexed = Stream.postscanl' (\(i, _) x -> (i + 1, x)) (-1,undefined)
--   indexed = Stream.zipWith (,) (Stream.enumerateFrom 0)
--   
-- -- Pair each element in a stream with its index, starting from index 0. -- --
--   >>> Stream.toList $ Stream.indexed $ Stream.fromList "hello"
--   [(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')]
--   
indexed :: (IsStream t, Monad m) => t m a -> t m (Int, a) -- |
--   indexedR n = Stream.postscanl' (\(i, _) x -> (i - 1, x)) (n + 1,undefined)
--   indexedR n = Stream.zipWith (,) (Stream.enumerateFromThen n (n - 1))
--   
-- -- Pair each element in a stream with its index, starting from the given -- index n and counting down. -- --
--   >>> Stream.toList $ Stream.indexedR 10 $ Stream.fromList "hello"
--   [(10,'h'),(9,'e'),(8,'l'),(7,'l'),(6,'o')]
--   
indexedR :: (IsStream t, Monad m) => Int -> t m a -> t m (Int, a) timestamped :: (IsStream t, MonadAsync m, Functor (t m)) => t m a -> t m (AbsTime, a) -- | Pair each element in a stream with an absolute timestamp, using a -- clock of specified granularity. The timestamp is generated just before -- the element is consumed. -- --
--   >>> Stream.mapM_ print $ Stream.timestampWith 0.01 $ Stream.delay 1 $ Stream.enumerateFromTo 1 3
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),1)
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),2)
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),3)
--   
-- -- Pre-release timestampWith :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m a -> t m (AbsTime, a) -- | Pair each element in a stream with relative times starting from 0, -- using a 10 ms granularity clock. The time is measured just before the -- element is consumed. -- --
--   >>> Stream.mapM_ print $ Stream.timeIndexed $ Stream.delay 1 $ Stream.enumerateFromTo 1 3
--   (RelTime64 (NanoSecond64 ...),1)
--   (RelTime64 (NanoSecond64 ...),2)
--   (RelTime64 (NanoSecond64 ...),3)
--   
-- -- Pre-release timeIndexed :: (IsStream t, MonadAsync m, Functor (t m)) => t m a -> t m (RelTime64, a) -- | Pair each element in a stream with relative times starting from 0, -- using a clock with the specified granularity. The time is measured -- just before the element is consumed. -- --
--   >>> Stream.mapM_ print $ Stream.timeIndexWith 0.01 $ Stream.delay 1 $ Stream.enumerateFromTo 1 3
--   (RelTime64 (NanoSecond64 ...),1)
--   (RelTime64 (NanoSecond64 ...),2)
--   (RelTime64 (NanoSecond64 ...),3)
--   
-- -- Pre-release timeIndexWith :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m a -> t m (RelTime64, a) -- | Find all the indices where the element in the stream satisfies the -- given predicate. -- --
--   findIndices = fold Fold.findIndices
--   
findIndices :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m Int -- | Find all the indices where the value of the element in the stream is -- equal to the given value. -- --
--   elemIndices a = findIndices (== a)
--   
elemIndices :: (IsStream t, Eq a, Monad m) => a -> t m a -> t m Int -- | Like rollingMap but with an effectful map function. -- -- Pre-release rollingMapM :: (IsStream t, Monad m) => (Maybe a -> a -> m b) -> t m a -> t m b -- | Apply a function on every two successive elements of a stream. The -- first argument of the map function is the previous element and the -- second argument is the current element. When the current element is -- the first element, the previous element is Nothing. -- -- Pre-release rollingMap :: (IsStream t, Monad m) => (Maybe a -> a -> b) -> t m a -> t m b -- | Like rollingMap but requires at least two elements in the -- stream, returns an empty stream otherwise. -- -- This is the stream equivalent of the list idiom zipWith f xs (tail -- xs). -- -- Pre-release rollingMap2 :: (IsStream t, Monad m) => (a -> a -> b) -> t m a -> t m b -- | In a stream of Maybes, discard Nothings and unwrap -- Justs. -- -- Pre-release catMaybes :: (IsStream t, Monad m, Functor (t m)) => t m (Maybe a) -> t m a -- | Map a Maybe returning function to a stream, filter out the -- Nothing elements, and return a stream of values extracted from -- Just. -- -- Equivalent to: -- --
--   mapMaybe f = Stream.map fromJust . Stream.filter isJust . Stream.map f
--   
mapMaybe :: (IsStream t, Monad m) => (a -> Maybe b) -> t m a -> t m b -- | Like mapMaybe but maps a monadic function. -- -- Equivalent to: -- --
--   mapMaybeM f = Stream.map fromJust . Stream.filter isJust . Stream.mapM f
--   
-- -- Concurrent (do not use with fromParallel on infinite -- streams) mapMaybeM :: (IsStream t, MonadAsync m, Functor (t m)) => (a -> m (Maybe b)) -> t m a -> t m b -- | Discard Rights and unwrap Lefts in an Either -- stream. -- -- Pre-release lefts :: (IsStream t, Monad m, Functor (t m)) => t m (Either a b) -> t m a -- | Discard Lefts and unwrap Rights in an Either -- stream. -- -- Pre-release rights :: (IsStream t, Monad m, Functor (t m)) => t m (Either a b) -> t m b -- | Remove the either wrapper and flatten both lefts and as well as rights -- in the output stream. -- -- Pre-release both :: Functor (t m) => t m (Either a a) -> t m a -- | Make the stream producer and consumer run concurrently by introducing -- a buffer between them. The producer thread evaluates the input stream -- until the buffer fills, it terminates if the buffer is full and a -- worker thread is kicked off again to evaluate the remaining stream -- when there is space in the buffer. The consumer consumes the stream -- lazily from the buffer. -- -- Since: 0.2.0 (Streamly) mkAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -- | Make the stream producer and consumer run concurrently by introducing -- a buffer between them. The producer thread evaluates the input stream -- until the buffer fills, it blocks if the buffer is full until there is -- space in the buffer. The consumer consumes the stream lazily from the -- buffer. -- --
--   mkParallel = IsStream.fromStreamD . mkParallelD . IsStream.toStreamD
--   
-- -- Pre-release mkParallel :: (IsStream t, MonadAsync m) => t m a -> t m a -- | Same as |$. -- -- Internal applyAsync :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> t m a -> t m b -- | Parallel transform application operator; applies a stream -- transformation function t m a -> t m b to a stream t m -- a concurrently; the input stream is evaluated asynchronously in -- an independent thread yielding elements to a buffer and the -- transformation function runs in another thread consuming the input -- from the buffer. |$ is just like regular function application -- operator $ except that it is concurrent. -- -- If you read the signature as (t m a -> t m b) -> (t m a -- -> t m b) you can look at it as a transformation that converts -- a transform function to a buffered concurrent transform function. -- -- The following code prints a value every second even though each stage -- adds a 1 second delay. -- --
--   >>> :{
--   Stream.drain $
--      Stream.mapM (\x -> threadDelay 1000000 >> print x)
--        |$ Stream.replicateM 3 (threadDelay 1000000 >> return 1)
--   :}
--   1
--   1
--   1
--   
-- -- Concurrent -- -- Since: 0.3.0 (Streamly) (|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> t m a -> t m b infixr 0 |$ -- | Same as |$ but with arguments reversed. -- -- (|&) = flip (|$) -- -- Concurrent -- -- Since: 0.3.0 (Streamly) (|&) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> t m b) -> t m b infixl 1 |& -- | Specify the maximum number of threads that can be spawned concurrently -- for any concurrent combinator in a stream. A value of 0 resets the -- thread limit to default, a negative value means there is no limit. The -- default value is 1500. maxThreads does not affect -- ParallelT streams as they can use unbounded number of -- threads. -- -- When the actions in a stream are IO bound, having blocking IO calls, -- this option can be used to control the maximum number of in-flight IO -- requests. When the actions are CPU bound this option can be used to -- control the amount of CPU used by the stream. -- -- Since: 0.4.0 (Streamly) maxThreads :: IsStream t => Int -> t m a -> t m a -- | Specify the maximum size of the buffer for storing the results from -- concurrent computations. If the buffer becomes full we stop spawning -- more concurrent tasks until there is space in the buffer. A value of 0 -- resets the buffer size to default, a negative value means there is no -- limit. The default value is 1500. -- -- CAUTION! using an unbounded maxBuffer value (i.e. a negative -- value) coupled with an unbounded maxThreads value is a recipe -- for disaster in presence of infinite streams, or very large streams. -- Especially, it must not be used when pure is used in -- ZipAsyncM streams as pure in applicative zip streams -- generates an infinite stream causing unbounded concurrent generation -- with no limit on the buffer or threads. -- -- Since: 0.4.0 (Streamly) maxBuffer :: IsStream t => Int -> t m a -> t m a -- | Evaluate the input stream continuously and keep only the oldest -- n elements in the buffer, discard the new ones when the -- buffer is full. When the output stream is evaluated it consumes the -- values from the buffer in a FIFO manner. -- -- Unimplemented sampleOld :: Int -> t m a -> t m a -- | Evaluate the input stream continuously and keep only the latest -- n elements in a ring buffer, keep discarding the older ones -- to make space for the new ones. When the output stream is evaluated it -- consumes the values from the buffer in a FIFO manner. -- -- Unimplemented sampleNew :: Int -> t m a -> t m a -- | Like sampleNew but samples at uniform intervals to match the -- consumer rate. Note that sampleNew leads to non-uniform -- sampling depending on the consumer pattern. -- -- Unimplemented sampleRate :: Double -> t m a -> t m a data Rate Rate :: Double -> Double -> Double -> Int -> Rate [rateLow] :: Rate -> Double [rateGoal] :: Rate -> Double [rateHigh] :: Rate -> Double [rateBuffer] :: Rate -> Int -- | Specify the pull rate of a stream. A Nothing value resets the -- rate to default which is unlimited. When the rate is specified, -- concurrent production may be ramped up or down automatically to -- achieve the specified yield rate. The specific behavior for different -- styles of Rate specifications is documented under Rate. -- The effective maximum production rate achieved by a stream is governed -- by: -- -- -- -- Since: 0.5.0 (Streamly) rate :: IsStream t => Maybe Rate -> t m a -> t m a -- | Same as rate (Just $ Rate (r/2) r (2*r) maxBound) -- -- Specifies the average production rate of a stream in number of yields -- per second (i.e. Hertz). Concurrent production is ramped up -- or down automatically to achieve the specified average yield rate. The -- rate can go down to half of the specified rate on the lower side and -- double of the specified rate on the higher side. -- -- Since: 0.5.0 (Streamly) avgRate :: IsStream t => Double -> t m a -> t m a -- | Same as rate (Just $ Rate r r (2*r) maxBound) -- -- Specifies the minimum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go below the -- specified rate, even though it may possibly go above it at times, the -- upper limit is double of the specified rate. -- -- Since: 0.5.0 (Streamly) minRate :: IsStream t => Double -> t m a -> t m a -- | Same as rate (Just $ Rate (r/2) r r maxBound) -- -- Specifies the maximum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go above the -- specified rate, even though it may possibly go below it at times, the -- lower limit is half of the specified rate. This can be useful in -- applications where certain resource usage must not be allowed to go -- beyond certain limits. -- -- Since: 0.5.0 (Streamly) maxRate :: IsStream t => Double -> t m a -> t m a -- | Same as rate (Just $ Rate r r r 0) -- -- Specifies a constant yield rate. If for some reason the actual rate -- goes above or below the specified rate we do not try to recover it by -- increasing or decreasing the rate in future. This can be useful in -- applications like graphics frame refresh where we need to maintain a -- constant refresh rate. -- -- Since: 0.5.0 (Streamly) constRate :: IsStream t => Double -> t m a -> t m a -- | Print debug information about an SVar when the stream ends -- -- Pre-release inspectMode :: IsStream t => t m a -> t m a -- | Strict left scan with an extraction function. Like scanl', but -- applies a user supplied extraction function (the third argument) at -- each step. This is designed to work with the foldl library. -- The suffix x is a mnemonic for extraction. -- -- Since 0.2.0 -- -- Since: 0.7.0 (Monad m constraint) scanx :: (IsStream t, Monad m) => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b -- | Appends two streams sequentially, yielding all elements from the first -- stream, and then all elements from the second stream. -- --
--   >>> import Streamly.Prelude (serial)
--   
--   >>> stream1 = Stream.fromList [1,2]
--   
--   >>> stream2 = Stream.fromList [3,4]
--   
--   >>> Stream.toList $ stream1 `serial` stream2
--   [1,2,3,4]
--   
-- -- This operation can be used to fold an infinite lazy container of -- streams. -- -- Since: 0.2.0 (Streamly) serial :: IsStream t => t m a -> t m a -> t m a infixr 6 `serial` -- | Appends two streams, both the streams may be evaluated concurrently -- but the outputs are used in the same order as the corresponding -- actions in the original streams, side effects will happen in the order -- in which the streams are evaluated: -- --
--   >>> import Streamly.Prelude (ahead, SerialT)
--   
--   >>> stream1 = Stream.fromEffect (delay 4) :: SerialT IO Int
--   
--   >>> stream2 = Stream.fromEffect (delay 2) :: SerialT IO Int
--   
--   >>> Stream.toList $ stream1 `ahead` stream2 :: IO [Int]
--   2 sec
--   4 sec
--   [4,2]
--   
-- -- Multiple streams can be combined. With enough threads, all of them can -- be scheduled simultaneously: -- --
--   >>> stream3 = Stream.fromEffect (delay 1)
--   
--   >>> Stream.toList $ stream1 `ahead` stream2 `ahead` stream3
--   1 sec
--   2 sec
--   4 sec
--   [4,2,1]
--   
-- -- With 2 threads, only two can be scheduled at a time, when one of those -- finishes, the third one gets scheduled: -- --
--   >>> Stream.toList $ Stream.maxThreads 2 $ stream1 `ahead` stream2 `ahead` stream3
--   2 sec
--   1 sec
--   4 sec
--   [4,2,1]
--   
-- -- Only streams are scheduled for ahead evaluation, how actions within a -- stream are evaluated depends on the stream type. If it is a concurrent -- stream they will be evaluated concurrently. It may not make much sense -- combining serial streams using ahead. -- -- ahead can be safely used to fold an infinite lazy container of -- streams. -- -- Since: 0.3.0 (Streamly) ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a infixr 6 `ahead` -- | Merges two streams, both the streams may be evaluated concurrently, -- outputs from both are used as they arrive: -- --
--   >>> import Streamly.Prelude (async)
--   
--   >>> stream1 = Stream.fromEffect (delay 4)
--   
--   >>> stream2 = Stream.fromEffect (delay 2)
--   
--   >>> Stream.toList $ stream1 `async` stream2
--   2 sec
--   4 sec
--   [2,4]
--   
-- -- Multiple streams can be combined. With enough threads, all of them can -- be scheduled simultaneously: -- --
--   >>> stream3 = Stream.fromEffect (delay 1)
--   
--   >>> Stream.toList $ stream1 `async` stream2 `async` stream3
--   ...
--   [1,2,4]
--   
-- -- With 2 threads, only two can be scheduled at a time, when one of those -- finishes, the third one gets scheduled: -- --
--   >>> Stream.toList $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3
--   ...
--   [2,1,4]
--   
-- -- With a single thread, it becomes serial: -- --
--   >>> Stream.toList $ Stream.maxThreads 1 $ stream1 `async` stream2 `async` stream3
--   ...
--   [4,2,1]
--   
-- -- Only streams are scheduled for async evaluation, how actions within a -- stream are evaluated depends on the stream type. If it is a concurrent -- stream they will be evaluated concurrently. -- -- In the following example, both the streams are scheduled for -- concurrent evaluation but each individual stream is evaluated -- serially: -- --
--   >>> stream1 = Stream.fromListM $ Prelude.map delay [3,3] -- SerialT IO Int
--   
--   >>> stream2 = Stream.fromListM $ Prelude.map delay [1,1] -- SerialT IO Int
--   
--   >>> Stream.toList $ stream1 `async` stream2 -- IO [Int]
--   ...
--   [1,1,3,3]
--   
-- -- If total threads are 2, the third stream is scheduled only after one -- of the first two has finished: -- --
--   stream3 = Stream.fromListM $ Prelude.map delay [2,2] -- SerialT IO Int
--   Stream.toList $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3 -- IO [Int]
--   
-- -- ... [1,1,3,2,3,2] -- -- Thus async goes deep in first few streams rather than going -- wide in all streams. It prefers to evaluate the leftmost streams as -- much as possible. Because of this behavior, async can be safely -- used to fold an infinite lazy container of streams. -- -- Since: 0.2.0 (Streamly) async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a infixr 6 `async` -- | For singleton streams, wAsync is the same as async. See -- async for singleton stream behavior. For multi-element streams, -- while async is left biased i.e. it tries to evaluate the left -- side stream as much as possible, wAsync tries to schedule them -- both fairly. In other words, async goes deep while -- wAsync goes wide. However, outputs are always used as they -- arrive. -- -- With a single thread, async starts behaving like serial -- while wAsync starts behaving like wSerial. -- --
--   >>> import Streamly.Prelude (async, wAsync)
--   
--   >>> stream1 = Stream.fromList [1,2,3]
--   
--   >>> stream2 = Stream.fromList [4,5,6]
--   
--   >>> Stream.toList $ Stream.fromAsync $ Stream.maxThreads 1 $ stream1 `async` stream2
--   [1,2,3,4,5,6]
--   
-- --
--   >>> Stream.toList $ Stream.fromWAsync $ Stream.maxThreads 1 $ stream1 `wAsync` stream2
--   [1,4,2,5,3,6]
--   
-- -- With two threads available, and combining three streams: -- --
--   >>> stream3 = Stream.fromList [7,8,9]
--   
--   >>> Stream.toList $ Stream.fromAsync $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3
--   [1,2,3,4,5,6,7,8,9]
--   
-- --
--   >>> Stream.toList $ Stream.fromWAsync $ Stream.maxThreads 2 $ stream1 `wAsync` stream2 `wAsync` stream3
--   [1,4,2,7,5,3,8,6,9]
--   
-- -- This operation cannot be used to fold an infinite lazy container of -- streams, because it schedules all the streams in a round robin manner. -- -- Note that WSerialT and single threaded WAsyncT both -- interleave streams but the exact scheduling is slightly different in -- both cases. -- -- Since: 0.2.0 (Streamly) wAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a infixr 6 `wAsync` -- | Like async except that the execution is much more strict. There -- is no limit on the number of threads. While async may not -- schedule a stream if there is no demand from the consumer, -- parallel always evaluates both the streams immediately. The -- only limit that applies to parallel is maxBuffer. -- Evaluation may block if the output buffer becomes full. -- --
--   >>> import Streamly.Prelude (parallel)
--   
--   >>> stream = Stream.fromEffect (delay 2) `parallel` Stream.fromEffect (delay 1)
--   
--   >>> Stream.toList stream -- IO [Int]
--   1 sec
--   2 sec
--   [1,2]
--   
-- -- parallel guarantees that all the streams are scheduled for -- execution immediately, therefore, we could use things like starting -- timers inside the streams and relying on the fact that all timers were -- started at the same time. -- -- Unlike async this operation cannot be used to fold an infinite -- lazy container of streams, because it schedules all the streams -- strictly concurrently. -- -- Since: 0.2.0 (Streamly) parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a infixr 6 `parallel` -- | Like parallel but stops the output as soon as the first -- stream stops. -- -- Pre-release parallelFst :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a -- | Like parallel but stops the output as soon as any of the two -- streams stops. -- -- Pre-release parallelMin :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a -- | Append the outputs of two streams, yielding all the elements from the -- first stream and then yielding all the elements from the second -- stream. -- -- IMPORTANT NOTE: This could be 100x faster than -- serial/<> for appending a few (say 100) streams because -- it can fuse via stream fusion. However, it does not scale for a large -- number of streams (say 1000s) and becomes qudartically slow. Therefore -- use this for custom appending of a few streams but use -- concatMap or 'concatMapWith serial' for appending n -- streams or infinite containers of streams. -- -- Pre-release append :: (IsStream t, Monad m) => t m b -> t m b -> t m b -- | Interleaves two streams, yielding one element from each stream -- alternately. When one stream stops the rest of the other stream is -- used in the output stream. -- --
--   >>> import Streamly.Prelude (wSerial)
--   
--   >>> stream1 = Stream.fromList [1,2]
--   
--   >>> stream2 = Stream.fromList [3,4]
--   
--   >>> Stream.toList $ Stream.fromWSerial $ stream1 `wSerial` stream2
--   [1,3,2,4]
--   
-- -- Note, for singleton streams wSerial and serial are -- identical. -- -- Note that this operation cannot be used to fold a container of -- infinite streams but it can be used for very large streams as the -- state that it needs to maintain is proportional to the logarithm of -- the number of streams. -- -- Since: 0.2.0 (Streamly) wSerial :: IsStream t => t m a -> t m a -> t m a infixr 6 `wSerial` wSerialFst :: WSerialT m a -> WSerialT m a -> WSerialT m a wSerialMin :: WSerialT m a -> WSerialT m a -> WSerialT m a -- | Interleaves the outputs of two streams, yielding elements from each -- stream alternately, starting from the first stream. If any of the -- streams finishes early the other stream continues alone until it too -- finishes. -- --
--   >>> :set -XOverloadedStrings
--   
--   >>> import Data.Functor.Identity (Identity)
--   
--   >>> Stream.interleave "ab" ",,,," :: Stream.SerialT Identity Char
--   fromList "a,b,,,"
--   
-- --
--   >>> Stream.interleave "abcd" ",," :: Stream.SerialT Identity Char
--   fromList "a,b,cd"
--   
-- -- interleave is dual to interleaveMin, it can be called -- interleaveMax. -- -- Do not use at scale in concatMapWith. -- -- Pre-release interleave :: (IsStream t, Monad m) => t m b -> t m b -> t m b -- | Interleaves the outputs of two streams, yielding elements from each -- stream alternately, starting from the first stream. The output stops -- as soon as any of the two streams finishes, discarding the remaining -- part of the other stream. The last element of the resulting stream -- would be from the longer stream. -- --
--   >>> :set -XOverloadedStrings
--   
--   >>> import Data.Functor.Identity (Identity)
--   
--   >>> Stream.interleaveMin "ab" ",,,," :: Stream.SerialT Identity Char
--   fromList "a,b,"
--   
--   >>> Stream.interleaveMin "abcd" ",," :: Stream.SerialT Identity Char
--   fromList "a,b,c"
--   
-- -- interleaveMin is dual to interleave. -- -- Do not use at scale in concatMapWith. -- -- Pre-release interleaveMin :: (IsStream t, Monad m) => t m b -> t m b -> t m b -- | Interleaves the outputs of two streams, yielding elements from each -- stream alternately, starting from the first stream. As soon as the -- first stream finishes, the output stops, discarding the remaining part -- of the second stream. In this case, the last element in the resulting -- stream would be from the second stream. If the second stream finishes -- early then the first stream still continues to yield elements until it -- finishes. -- --
--   >>> :set -XOverloadedStrings
--   
--   >>> import Data.Functor.Identity (Identity)
--   
--   >>> Stream.interleaveSuffix "abc" ",,,," :: Stream.SerialT Identity Char
--   fromList "a,b,c,"
--   
--   >>> Stream.interleaveSuffix "abc" "," :: Stream.SerialT Identity Char
--   fromList "a,bc"
--   
-- -- interleaveSuffix is a dual of interleaveInfix. -- -- Do not use at scale in concatMapWith. -- -- Pre-release interleaveSuffix :: (IsStream t, Monad m) => t m b -> t m b -> t m b -- | Interleaves the outputs of two streams, yielding elements from each -- stream alternately, starting from the first stream and ending at the -- first stream. If the second stream is longer than the first, elements -- from the second stream are infixed with elements from the first -- stream. If the first stream is longer then it continues yielding -- elements even after the second stream has finished. -- --
--   >>> :set -XOverloadedStrings
--   
--   >>> import Data.Functor.Identity (Identity)
--   
--   >>> Stream.interleaveInfix "abc" ",,,," :: Stream.SerialT Identity Char
--   fromList "a,b,c"
--   
--   >>> Stream.interleaveInfix "abc" "," :: Stream.SerialT Identity Char
--   fromList "a,bc"
--   
-- -- interleaveInfix is a dual of interleaveSuffix. -- -- Do not use at scale in concatMapWith. -- -- Pre-release interleaveInfix :: (IsStream t, Monad m) => t m b -> t m b -> t m b -- | Schedule the execution of two streams in a fair round-robin manner, -- executing each stream once, alternately. Execution of a stream may not -- necessarily result in an output, a stream may chose to Skip -- producing an element until later giving the other stream a chance to -- run. Therefore, this combinator fairly interleaves the execution of -- two streams rather than fairly interleaving the output of the two -- streams. This can be useful in co-operative multitasking without using -- explicit threads. This can be used as an alternative to async. -- -- Do not use at scale in concatMapWith. -- -- Pre-release roundrobin :: (IsStream t, Monad m) => t m b -> t m b -> t m b -- | Stream a is evaluated first, followed by stream b, -- the resulting elements a and b are then zipped using -- the supplied zip function and the result c is yielded to the -- consumer. -- -- If stream a or stream b ends, the zipped stream -- ends. If stream b ends first, the element a from -- previous evaluation of stream a is discarded. -- --
--   > D.toList $ D.zipWith (+) (D.fromList [1,2,3]) (D.fromList [4,5,6])
--   [5,7,9]
--   
zipWith :: (IsStream t, Monad m) => (a -> b -> c) -> t m a -> t m b -> t m c -- | Like zipWith but using a monadic zipping function. zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c -- | Like zipWith but zips concurrently i.e. both the streams being -- zipped are evaluated concurrently using the ParallelT -- concurrent evaluation style. The maximum number of elements of each -- stream evaluated in advance can be controlled by maxBuffer. -- -- The stream ends if stream a or stream b ends. -- However, if stream b ends while we are still evaluating -- stream a and waiting for a result then stream will not end -- until after the evaluation of stream a finishes. This -- behavior can potentially be changed in future to end the stream -- immediately as soon as any of the stream end is detected. zipAsyncWith :: (IsStream t, MonadAsync m) => (a -> b -> c) -> t m a -> t m b -> t m c -- | Like zipAsyncWith but with a monadic zipping function. zipAsyncWithM :: (IsStream t, MonadAsync m) => (a -> b -> m c) -> t m a -> t m b -> t m c -- | Same as mergeBy compare. -- --
--   >>> Stream.toList $ Stream.merge (Stream.fromList [1,3,5]) (Stream.fromList [2,4,6,8])
--   [1,2,3,4,5,6,8]
--   
-- -- Internal merge :: (IsStream t, Ord a) => t m a -> t m a -> t m a -- | Merge two streams using a comparison function. The head elements of -- both the streams are compared and the smaller of the two elements is -- emitted, if both elements are equal then the element from the first -- stream is used first. -- -- If the streams are sorted in ascending order, the resulting stream -- would also remain sorted in ascending order. -- --
--   >>> Stream.toList $ Stream.mergeBy compare (Stream.fromList [1,3,5]) (Stream.fromList [2,4,6,8])
--   [1,2,3,4,5,6,8]
--   
-- -- See also: mergeByMFused mergeBy :: IsStream t => (a -> a -> Ordering) -> t m a -> t m a -> t m a -- | Like mergeBy but with a monadic comparison function. -- -- Merge two streams randomly: -- --
--   > randomly _ _ = randomIO >>= x -> return $ if x then LT else GT
--   > Stream.toList $ Stream.mergeByM randomly (Stream.fromList [1,1,1,1]) (Stream.fromList [2,2,2,2])
--   [2,1,2,2,2,1,1,1]
--   
-- -- Merge two streams in a proportion of 2:1: -- --
--   >>> :{
--   do
--    let proportionately m n = do
--         ref <- newIORef $ cycle $ Prelude.concat [Prelude.replicate m LT, Prelude.replicate n GT]
--         return $ _ _ -> do
--            r <- readIORef ref
--            writeIORef ref $ Prelude.tail r
--            return $ Prelude.head r
--    f <- proportionately 2 1
--    xs <- Stream.toList $ Stream.mergeByM f (Stream.fromList [1,1,1,1,1,1]) (Stream.fromList [2,2,2])
--    print xs
--   :}
--   [1,1,2,1,1,2,1,1,2]
--   
-- -- See also: mergeByMFused mergeByM :: (IsStream t, Monad m) => (a -> a -> m Ordering) -> t m a -> t m a -> t m a -- | Like mergeByM but much faster, works best when merging -- statically known number of streams. When merging more than two streams -- try to merge pairs and pair pf pairs in a tree like -- structure.mergeByM works better with variable number of streams -- being merged using concatPairsWith. -- -- Internal mergeByMFused :: (IsStream t, Monad m) => (a -> a -> m Ordering) -> t m a -> t m a -> t m a -- | Like mergeBy but merges concurrently (i.e. both the elements -- being merged are generated concurrently). mergeAsyncBy :: (IsStream t, MonadAsync m) => (a -> a -> Ordering) -> t m a -> t m a -> t m a -- | Like mergeByM but merges concurrently (i.e. both the elements -- being merged are generated concurrently). mergeAsyncByM :: (IsStream t, MonadAsync m) => (a -> a -> m Ordering) -> t m a -> t m a -> t m a -- | Like mergeByM but stops merging as soon as any of the two -- streams stops. -- -- Unimplemented mergeMinBy :: (a -> a -> m Ordering) -> t m a -> t m a -> t m a -- | Like mergeByM but stops merging as soon as the first stream -- stops. -- -- Unimplemented mergeFstBy :: (a -> a -> m Ordering) -> t m a -> t m a -> t m a -- | Like concatMap but uses an Unfold for stream generation. -- Unlike concatMap this can fuse the Unfold code with the -- inner loop and therefore provide many times better performance. unfoldMany :: (IsStream t, Monad m) => Unfold m a b -> t m a -> t m b -- | Like unfoldMany but interleaves the streams in the same way as -- interleave behaves instead of appending them. -- -- Pre-release unfoldManyInterleave :: (IsStream t, Monad m) => Unfold m a b -> t m a -> t m b -- | Like unfoldMany but executes the streams in the same way as -- roundrobin. -- -- Pre-release unfoldManyRoundRobin :: (IsStream t, Monad m) => Unfold m a b -> t m a -> t m b -- | Unfold the elements of a stream, intersperse the given element between -- the unfolded streams and then concat them into a single stream. -- --
--   unwords = S.interpose ' '
--   
-- -- Pre-release interpose :: (IsStream t, Monad m) => c -> Unfold m b c -> t m b -> t m c -- | Unfold the elements of a stream, append the given element after each -- unfolded stream and then concat them into a single stream. -- --
--   unlines = S.interposeSuffix '\n'
--   
-- -- Pre-release interposeSuffix :: (IsStream t, Monad m) => c -> Unfold m b c -> t m b -> t m c -- | intersperse followed by unfold and concat. -- --
--   intercalate unf a str = unfoldMany unf $ intersperse a str
--   intersperse = intercalate (Unfold.function id)
--   unwords = intercalate Unfold.fromList " "
--   
-- --
--   >>> Stream.toList $ Stream.intercalate Unfold.fromList " " $ Stream.fromList ["abc", "def", "ghi"]
--   "abc def ghi"
--   
intercalate :: (IsStream t, Monad m) => Unfold m b c -> b -> t m b -> t m c -- | intersperseMSuffix followed by unfold and concat. -- --
--   intercalateSuffix unf a str = unfoldMany unf $ intersperseMSuffix a str
--   intersperseMSuffix = intercalateSuffix (Unfold.function id)
--   unlines = intercalateSuffix Unfold.fromList "\n"
--   
-- --
--   >>> Stream.toList $ Stream.intercalateSuffix Unfold.fromList "\n" $ Stream.fromList ["abc", "def", "ghi"]
--   "abc\ndef\nghi\n"
--   
intercalateSuffix :: (IsStream t, Monad m) => Unfold m b c -> b -> t m b -> t m c -- | interleaveInfix followed by unfold and concat. -- -- Pre-release gintercalate :: (IsStream t, Monad m) => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c -- | interleaveSuffix followed by unfold and concat. -- -- Pre-release gintercalateSuffix :: (IsStream t, Monad m) => Unfold m a c -> t m a -> Unfold m b c -> t m b -> t m c -- | Map a stream producing monadic function on each element of the stream -- and then flatten the results into a single stream. Since the stream -- generation function is monadic, unlike concatMap, it can -- produce an effect at the beginning of each iteration of the inner -- loop. concatMapM :: (IsStream t, Monad m) => (a -> m (t m b)) -> t m a -> t m b -- | Map a stream producing function on each element of the stream and then -- flatten the results into a single stream. -- --
--   >>> concatMap f = Stream.concatMapM (return . f)
--   
--   >>> concatMap f = Stream.concatMapWith Stream.serial f
--   
--   >>> concatMap f = Stream.concat . Stream.map f
--   
concatMap :: (IsStream t, Monad m) => (a -> t m b) -> t m a -> t m b -- | Given a stream value in the underlying monad, lift and join the -- underlying monad with the stream monad. -- --
--   >>> concatM = Stream.concat . Stream.fromEffect
--   
--   >>> concatM = Stream.concat . lift    -- requires (MonadTrans t)
--   
--   >>> concatM = join . lift             -- requires (MonadTrans t, Monad (t m))
--   
-- -- See also: concat, sequence -- -- Internal concatM :: (IsStream t, Monad m) => m (t m a) -> t m a -- | Flatten a stream of streams to a single stream. -- --
--   concat = concatMap id
--   
-- -- Pre-release concat :: (IsStream t, Monad m) => t m (t m a) -> t m a -- | A variant of fold that allows you to fold a Foldable -- container of streams using the specified stream sum operation. -- --
--   concatFoldableWith async $ map return [1..3]
--   
-- -- Equivalent to: -- --
--   concatFoldableWith f = Prelude.foldr f D.nil
--   concatFoldableWith f = D.concatMapFoldableWith f id
--   
-- -- Since: 0.8.0 (Renamed foldWith to concatFoldableWith) -- -- Since: 0.1.0 (Streamly) concatFoldableWith :: (IsStream t, Foldable f) => (t m a -> t m a -> t m a) -> f (t m a) -> t m a -- | A variant of foldMap that allows you to map a monadic -- streaming action on a Foldable container and then fold it using -- the specified stream merge operation. -- --
--   concatMapFoldableWith async return [1..3]
--   
-- -- Equivalent to: -- --
--   concatMapFoldableWith f g = Prelude.foldr (f . g) S.nil
--   concatMapFoldableWith f g xs = S.concatMapWith f g (S.fromFoldable xs)
--   
-- -- Since: 0.8.0 (Renamed foldMapWith to concatMapFoldableWith) -- -- Since: 0.1.0 (Streamly) concatMapFoldableWith :: (IsStream t, Foldable f) => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b -- | Like concatMapFoldableWith but with the last two arguments -- reversed i.e. the monadic streaming function is the last argument. -- -- Equivalent to: -- --
--   concatForFoldableWith f xs g = Prelude.foldr (f . g) D.nil xs
--   concatForFoldableWith f = flip (D.concatMapFoldableWith f)
--   
-- -- Since: 0.8.0 (Renamed forEachWith to concatForFoldableWith) -- -- Since: 0.1.0 (Streamly) concatForFoldableWith :: (IsStream t, Foldable f) => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b -- | concatMapWith mixer generator stream is a two dimensional -- looping combinator. The generator function is used to -- generate streams from the elements in the input stream and -- the mixer function is used to merge those streams. -- -- Note we can merge streams concurrently by using a concurrent merge -- function. -- -- Since: 0.7.0 -- -- Since: 0.8.0 (signature change) concatMapWith :: IsStream t => (t m b -> t m b -> t m b) -> (a -> t m b) -> t m a -> t m b bindWith :: IsStream t => (t m b -> t m b -> t m b) -> t m a -> (a -> t m b) -> t m b -- | Like concatMapWith but carries a state which can be used to -- share information across multiple steps of concat. -- --
--   concatSmapMWith combine f initial = concatMapWith combine id . smapM f initial
--   
-- -- Pre-release concatSmapMWith :: (IsStream t, Monad m) => (t m b -> t m b -> t m b) -> (s -> a -> m (s, t m b)) -> m s -> t m a -> t m b -- | Combine streams in pairs using a binary stream combinator, then -- combine the resulting streams in pairs recursively until we get to a -- single combined stream. -- -- For example, you can sort a stream using merge sort like this: -- --
--   >>> Stream.toList $ Stream.concatPairsWith (Stream.mergeBy compare) Stream.fromPure $ Stream.fromList [5,1,7,9,2]
--   [1,2,5,7,9]
--   
-- -- Caution: the stream of streams must be finite -- -- Pre-release concatPairsWith :: IsStream t => (t m b -> t m b -> t m b) -> (a -> t m b) -> t m a -> t m b -- | Like iterateM but iterates after mapping a stream generator -- on the output. -- -- Yield an input element in the output stream, map a stream generator on -- it and then do the same on the resulting stream. This can be used for -- a depth first traversal of a tree like structure. -- -- Note that iterateM is a special case of -- iterateMapWith: -- --
--   iterateM f = iterateMapWith serial (fromEffect . f) . fromEffect
--   
-- -- It can be used to traverse a tree structure. For example, to list a -- directory tree: -- --
--   Stream.iterateMapWith Stream.serial
--       (either Dir.toEither (const nil))
--       (fromPure (Left "tmp"))
--   
-- -- Pre-release iterateMapWith :: IsStream t => (t m a -> t m a -> t m a) -> (a -> t m a) -> t m a -> t m a -- | Like iterateMap but carries a state in the stream generation -- function. This can be used to traverse graph like structures, we can -- remember the visited nodes in the state to avoid cycles. -- -- Note that a combination of iterateMap and usingState -- can also be used to traverse graphs. However, this function provides a -- more localized state instead of using a global state. -- -- See also: mfix -- -- Pre-release iterateSmapMWith :: (IsStream t, Monad m) => (t m a -> t m a -> t m a) -> (b -> a -> m (b, t m a)) -> m b -> t m a -> t m a -- | In an Either stream iterate on Lefts. This is a special -- case of iterateMapWith: -- --
--   iterateMapLeftsWith combine f = iterateMapWith combine (either f (const nil))
--   
-- -- To traverse a directory tree: -- --
--   iterateMapLeftsWith serial Dir.toEither (fromPure (Left "tmp"))
--   
-- -- Pre-release iterateMapLeftsWith :: (IsStream t, b ~ Either a c) => (t m b -> t m b -> t m b) -> (a -> t m b) -> t m b -> t m b -- | Same as iterateMapWith Stream.serial but more efficient due -- to stream fusion. -- -- Unimplemented iterateUnfold :: Unfold m a a -> t m a -> t m a concatUnfold :: (IsStream t, Monad m) => Unfold m a b -> t m a -> t m b -- | Drop prefix from the input stream if present. -- -- Space: O(1) -- -- Unimplemented dropPrefix :: t m a -> t m a -> t m a -- | Drop all matching infix from the input stream if present. Infix stream -- may be consumed multiple times. -- -- Space: O(n) where n is the length of the infix. -- -- Unimplemented dropInfix :: t m a -> t m a -> t m a -- | Drop suffix from the input stream if present. Suffix stream may be -- consumed multiple times. -- -- Space: O(n) where n is the length of the suffix. -- -- Unimplemented dropSuffix :: t m a -> t m a -> t m a -- | Apply a Fold repeatedly on a stream and emit the fold outputs -- in the output stream. -- -- To sum every two contiguous elements in a stream: -- --
--   >>> f = Fold.take 2 Fold.sum
--   
--   >>> Stream.toList $ Stream.foldMany f $ Stream.fromList [1..10]
--   [3,7,11,15,19]
--   
-- -- On an empty stream the output is empty: -- --
--   >>> Stream.toList $ Stream.foldMany f $ Stream.fromList []
--   []
--   
-- -- Note Stream.foldMany (Fold.take 0) would result in an -- infinite loop in a non-empty stream. foldMany :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b -- | Like foldMany but appends empty fold output if the fold and -- stream termination aligns: -- --
--   >>> f = Fold.take 2 Fold.sum
--   
--   >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList []
--   [0]
--   
--   >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList [1..9]
--   [3,7,11,15,9]
--   
--   >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList [1..10]
--   [3,7,11,15,19,0]
--   
-- -- Pre-release foldManyPost :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b -- | Like foldMany but using the Refold type instead of -- Fold. -- -- Pre-release refoldMany :: (IsStream t, Monad m) => Refold m c a b -> m c -> t m a -> t m b -- | Apply a stream of folds to an input stream and emit the results in the -- output stream. -- -- Unimplemented foldSequence :: t m (Fold m a b) -> t m a -> t m b -- | Iterate a fold generator on a stream. The initial value b is -- used to generate the first fold, the fold is applied on the stream and -- the result of the fold is used to generate the next fold and so on. -- --
--   >>> import Data.Monoid (Sum(..))
--   >>> f x = return (Fold.take 2 (Fold.sconcat x))
--   >>> s = Stream.map Sum $ Stream.fromList [1..10]
--   >>> Stream.toList $ Stream.map getSum $ Stream.foldIterateM f (pure 0) s
--   [3,10,21,36,55,55]
--   
-- -- This is the streaming equivalent of monad like sequenced application -- of folds where next fold is dependent on the previous fold. -- -- Pre-release foldIterateM :: (IsStream t, Monad m) => (b -> m (Fold m a b)) -> m b -> t m a -> t m b -- | Like foldIterateM but using the Refold type instead. -- This could be much more efficient due to stream fusion. -- -- Internal refoldIterateM :: (IsStream t, Monad m) => Refold m b a b -> m b -> t m a -> t m b -- | Group the input stream into groups of n elements each and -- then fold each group using the provided fold function. -- --
--   >>> Stream.toList $ Stream.chunksOf 2 Fold.sum (Stream.enumerateFromTo 1 10)
--   [3,7,11,15,19]
--   
-- -- This can be considered as an n-fold version of take where we -- apply take repeatedly on the leftover stream until the stream -- exhausts. -- --
--   chunksOf n f = foldMany (FL.take n f)
--   
chunksOf :: (IsStream t, Monad m) => Int -> Fold m a b -> t m a -> t m b -- | arraysOf n stream groups the elements in the input stream -- into arrays of n elements each. -- -- Same as the following but may be more efficient: -- --
--   arraysOf n = Stream.foldMany (A.writeN n)
--   
-- -- Pre-release arraysOf :: (IsStream t, MonadIO m, Unbox a) => Int -> t m a -> t m (Array a) -- | Group the input stream into windows of n second each and then -- fold each group using the provided fold function. -- --
--   >>> Stream.toList $ Stream.take 5 $ Stream.intervalsOf 1 Fold.sum $ Stream.constRate 2 $ Stream.enumerateFrom 1
--   [...,...,...,...,...]
--   
intervalsOf :: (IsStream t, MonadAsync m) => Double -> Fold m a b -> t m a -> t m b -- | Like chunksOf but if the chunk is not completed within the -- specified time interval then emit whatever we have collected till now. -- The chunk timeout is reset whenever a chunk is emitted. The -- granularity of the clock is 100 ms. -- --
--   >>> s = Stream.delayPost 0.3 $ Stream.fromList [1..1000]
--   
--   >>> f = Stream.mapM_ print $ Stream.chunksOfTimeout 5 1 Fold.toList s
--   
-- -- Pre-release chunksOfTimeout :: (IsStream t, MonadAsync m, Functor (t m)) => Int -> Double -> Fold m a b -> t m a -> t m b -- | Split on an infixed separator element, dropping the separator. The -- supplied Fold is applied on the split segments. Splits the -- stream on separator elements determined by the supplied predicate, -- separator is considered as infixed between two segments: -- --
--   >>> splitOn' p xs = Stream.toList $ Stream.splitOn p Fold.toList (Stream.fromList xs)
--   
--   >>> splitOn' (== '.') "a.b"
--   ["a","b"]
--   
-- -- An empty stream is folded to the default value of the fold: -- --
--   >>> splitOn' (== '.') ""
--   [""]
--   
-- -- If one or both sides of the separator are missing then the empty -- segment on that side is folded to the default output of the fold: -- --
--   >>> splitOn' (== '.') "."
--   ["",""]
--   
-- --
--   >>> splitOn' (== '.') ".a"
--   ["","a"]
--   
-- --
--   >>> splitOn' (== '.') "a."
--   ["a",""]
--   
-- --
--   >>> splitOn' (== '.') "a..b"
--   ["a","","b"]
--   
-- -- splitOn is an inverse of intercalating single element: -- --
--   Stream.intercalate (Stream.fromPure '.') Unfold.fromList . Stream.splitOn (== '.') Fold.toList === id
--   
-- -- Assuming the input stream does not contain the separator: -- --
--   Stream.splitOn (== '.') Fold.toList . Stream.intercalate (Stream.fromPure '.') Unfold.fromList === id
--   
splitOn :: (IsStream t, Monad m) => (a -> Bool) -> Fold m a b -> t m a -> t m b -- | Split on a suffixed separator element, dropping the separator. The -- supplied Fold is applied on the split segments. -- --
--   >>> splitOnSuffix' p xs = Stream.toList $ Stream.splitOnSuffix p Fold.toList (Stream.fromList xs)
--   
--   >>> splitOnSuffix' (== '.') "a.b."
--   ["a","b"]
--   
-- --
--   >>> splitOnSuffix' (== '.') "a."
--   ["a"]
--   
-- -- An empty stream results in an empty output stream: -- --
--   >>> splitOnSuffix' (== '.') ""
--   []
--   
-- -- An empty segment consisting of only a suffix is folded to the default -- output of the fold: -- --
--   >>> splitOnSuffix' (== '.') "."
--   [""]
--   
-- --
--   >>> splitOnSuffix' (== '.') "a..b.."
--   ["a","","b",""]
--   
-- -- A suffix is optional at the end of the stream: -- --
--   >>> splitOnSuffix' (== '.') "a"
--   ["a"]
--   
-- --
--   >>> splitOnSuffix' (== '.') ".a"
--   ["","a"]
--   
-- --
--   >>> splitOnSuffix' (== '.') "a.b"
--   ["a","b"]
--   
-- --
--   lines = splitOnSuffix (== '\n')
--   
-- -- splitOnSuffix is an inverse of intercalateSuffix with -- a single element: -- --
--   Stream.intercalateSuffix (Stream.fromPure '.') Unfold.fromList . Stream.splitOnSuffix (== '.') Fold.toList === id
--   
-- -- Assuming the input stream does not contain the separator: -- --
--   Stream.splitOnSuffix (== '.') Fold.toList . Stream.intercalateSuffix (Stream.fromPure '.') Unfold.fromList === id
--   
splitOnSuffix :: (IsStream t, Monad m) => (a -> Bool) -> Fold m a b -> t m a -> t m b -- | Split on a prefixed separator element, dropping the separator. The -- supplied Fold is applied on the split segments. -- --
--   > splitOnPrefix' p xs = Stream.toList $ Stream.splitOnPrefix p (Fold.toList) (Stream.fromList xs)
--   > splitOnPrefix' (== .) ".a.b"
--   ["a","b"]
--   
-- -- An empty stream results in an empty output stream: > -- splitOnPrefix' (== .) "" [] -- -- An empty segment consisting of only a prefix is folded to the default -- output of the fold: -- --
--   > splitOnPrefix' (== .) "."
--   [""]
--   
--   > splitOnPrefix' (== .) ".a.b."
--   ["a","b",""]
--   
--   > splitOnPrefix' (== .) ".a..b"
--   ["a","","b"]
--   
-- -- A prefix is optional at the beginning of the stream: -- --
--   > splitOnPrefix' (== .) "a"
--   ["a"]
--   
--   > splitOnPrefix' (== .) "a.b"
--   ["a","b"]
--   
-- -- splitOnPrefix is an inverse of intercalatePrefix with -- a single element: -- --
--   Stream.intercalatePrefix (Stream.fromPure '.') Unfold.fromList . Stream.splitOnPrefix (== '.') Fold.toList === id
--   
-- -- Assuming the input stream does not contain the separator: -- --
--   Stream.splitOnPrefix (== '.') Fold.toList . Stream.intercalatePrefix (Stream.fromPure '.') Unfold.fromList === id
--   
-- -- Unimplemented splitOnPrefix :: (a -> Bool) -> Fold m a b -> t m a -> t m b -- | Split on any one of the given patterns. -- -- Unimplemented splitOnAny :: [Array a] -> Fold m a b -> t m a -> t m b -- | Like splitOnSuffix but keeps the suffix attached to the -- resulting splits. -- --
--   >>> splitWithSuffix' p xs = Stream.toList $ splitWithSuffix p Fold.toList (Stream.fromList xs)
--   
-- --
--   >>> splitWithSuffix' (== '.') ""
--   []
--   
-- --
--   >>> splitWithSuffix' (== '.') "."
--   ["."]
--   
-- --
--   >>> splitWithSuffix' (== '.') "a"
--   ["a"]
--   
-- --
--   >>> splitWithSuffix' (== '.') ".a"
--   [".","a"]
--   
-- --
--   >>> splitWithSuffix' (== '.') "a."
--   ["a."]
--   
-- --
--   >>> splitWithSuffix' (== '.') "a.b"
--   ["a.","b"]
--   
-- --
--   >>> splitWithSuffix' (== '.') "a.b."
--   ["a.","b."]
--   
-- --
--   >>> splitWithSuffix' (== '.') "a..b.."
--   ["a.",".","b.","."]
--   
splitWithSuffix :: (IsStream t, Monad m) => (a -> Bool) -> Fold m a b -> t m a -> t m b -- | Like splitOnSeq but splits the separator as well, as an infix -- token. -- --
--   >>> splitOn'_ pat xs = Stream.toList $ Stream.splitBySeq (Array.fromList pat) Fold.toList (Stream.fromList xs)
--   
-- --
--   >>> splitOn'_ "" "hello"
--   ["h","","e","","l","","l","","o"]
--   
-- --
--   >>> splitOn'_ "hello" ""
--   [""]
--   
-- --
--   >>> splitOn'_ "hello" "hello"
--   ["","hello",""]
--   
-- --
--   >>> splitOn'_ "x" "hello"
--   ["hello"]
--   
-- --
--   >>> splitOn'_ "h" "hello"
--   ["","h","ello"]
--   
-- --
--   >>> splitOn'_ "o" "hello"
--   ["hell","o",""]
--   
-- --
--   >>> splitOn'_ "e" "hello"
--   ["h","e","llo"]
--   
-- --
--   >>> splitOn'_ "l" "hello"
--   ["he","l","","l","o"]
--   
-- --
--   >>> splitOn'_ "ll" "hello"
--   ["he","ll","o"]
--   
-- -- Pre-release splitBySeq :: (IsStream t, MonadAsync m, Storable a, Unbox a, Enum a, Eq a) => Array a -> Fold m a b -> t m a -> t m b -- | Like splitOn but the separator is a sequence of elements -- instead of a single element. -- -- For illustration, let's define a function that operates on pure lists: -- --
--   >>> splitOnSeq' pat xs = Stream.toList $ Stream.splitOnSeq (Array.fromList pat) Fold.toList (Stream.fromList xs)
--   
-- --
--   >>> splitOnSeq' "" "hello"
--   ["h","e","l","l","o"]
--   
-- --
--   >>> splitOnSeq' "hello" ""
--   [""]
--   
-- --
--   >>> splitOnSeq' "hello" "hello"
--   ["",""]
--   
-- --
--   >>> splitOnSeq' "x" "hello"
--   ["hello"]
--   
-- --
--   >>> splitOnSeq' "h" "hello"
--   ["","ello"]
--   
-- --
--   >>> splitOnSeq' "o" "hello"
--   ["hell",""]
--   
-- --
--   >>> splitOnSeq' "e" "hello"
--   ["h","llo"]
--   
-- --
--   >>> splitOnSeq' "l" "hello"
--   ["he","","o"]
--   
-- --
--   >>> splitOnSeq' "ll" "hello"
--   ["he","o"]
--   
-- -- splitOnSeq is an inverse of intercalate. The following -- law always holds: -- --
--   intercalate . splitOnSeq == id
--   
-- -- The following law holds when the separator is non-empty and contains -- none of the elements present in the input lists: -- --
--   splitOnSeq . intercalate == id
--   
-- --
--   >>> splitOnSeq pat f = Stream.foldManyPost (Fold.takeEndBySeq_ pat f)
--   
-- -- Pre-release splitOnSeq :: (IsStream t, MonadIO m, Storable a, Unbox a, Enum a, Eq a) => Array a -> Fold m a b -> t m a -> t m b -- | Like splitSuffixBy but the separator is a sequence of -- elements, instead of a predicate for a single element. -- --
--   >>> splitOnSuffixSeq_ pat xs = Stream.toList $ Stream.splitOnSuffixSeq (Array.fromList pat) Fold.toList (Stream.fromList xs)
--   
-- --
--   >>> splitOnSuffixSeq_ "." ""
--   []
--   
-- --
--   >>> splitOnSuffixSeq_ "." "."
--   [""]
--   
-- --
--   >>> splitOnSuffixSeq_ "." "a"
--   ["a"]
--   
-- --
--   >>> splitOnSuffixSeq_ "." ".a"
--   ["","a"]
--   
-- --
--   >>> splitOnSuffixSeq_ "." "a."
--   ["a"]
--   
-- --
--   >>> splitOnSuffixSeq_ "." "a.b"
--   ["a","b"]
--   
-- --
--   >>> splitOnSuffixSeq_ "." "a.b."
--   ["a","b"]
--   
-- --
--   >>> splitOnSuffixSeq_ "." "a..b.."
--   ["a","","b",""]
--   
-- --
--   lines = splitOnSuffixSeq "\n"
--   
-- -- splitOnSuffixSeq is an inverse of intercalateSuffix. -- The following law always holds: -- --
--   intercalateSuffix . splitOnSuffixSeq == id
--   
-- -- The following law holds when the separator is non-empty and contains -- none of the elements present in the input lists: -- --
--   splitSuffixOn . intercalateSuffix == id
--   
-- --
--   >>> splitOnSuffixSeq pat f = Stream.foldMany (Fold.takeEndBySeq_ pat f)
--   
-- -- Pre-release splitOnSuffixSeq :: (IsStream t, MonadIO m, Storable a, Unbox a, Enum a, Eq a) => Array a -> Fold m a b -> t m a -> t m b -- | Like splitOnSuffixSeq but keeps the suffix intact in the -- splits. -- --
--   >>> splitWithSuffixSeq' pat xs = Stream.toList $ Stream.splitWithSuffixSeq (Array.fromList pat) Fold.toList (Stream.fromList xs)
--   
-- --
--   >>> splitWithSuffixSeq' "." ""
--   []
--   
-- --
--   >>> splitWithSuffixSeq' "." "."
--   ["."]
--   
-- --
--   >>> splitWithSuffixSeq' "." "a"
--   ["a"]
--   
-- --
--   >>> splitWithSuffixSeq' "." ".a"
--   [".","a"]
--   
-- --
--   >>> splitWithSuffixSeq' "." "a."
--   ["a."]
--   
-- --
--   >>> splitWithSuffixSeq' "." "a.b"
--   ["a.","b"]
--   
-- --
--   >>> splitWithSuffixSeq' "." "a.b."
--   ["a.","b."]
--   
-- --
--   >>> splitWithSuffixSeq' "." "a..b.."
--   ["a.",".","b.","."]
--   
-- --
--   >>> splitWithSuffixSeq pat f = Stream.foldMany (Fold.takeEndBySeq pat f)
--   
-- -- Pre-release splitWithSuffixSeq :: (IsStream t, MonadIO m, Storable a, Unbox a, Enum a, Eq a) => Array a -> Fold m a b -> t m a -> t m b -- | Split post any one of the given patterns. -- -- Unimplemented splitOnSuffixSeqAny :: [Array a] -> Fold m a b -> t m a -> t m b classifySessionsByGeneric :: forall t m f a b. (IsStream t, MonadAsync m, IsMap f) => Proxy (f :: Type -> Type) -> Double -> Bool -> (Int -> m Bool) -> Double -> Fold m a b -> t m (AbsTime, (Key f, a)) -> t m (Key f, b) -- | classifySessionsBy tick keepalive predicate timeout fold -- stream classifies an input event stream consisting of -- (timestamp, (key, value)) into sessions based on the -- key, folding all the values corresponding to the same key -- into a session using the supplied fold. -- -- When the fold terminates or a timeout occurs, a tuple -- consisting of the session key and the folded value is emitted in the -- output stream. The timeout is measured from the first event in the -- session. If the keepalive option is set to True the -- timeout is reset to 0 whenever an event is received. -- -- The timestamp in the input stream is an absolute time from -- some epoch, characterizing the time when the input event was -- generated. The notion of current time is maintained by a monotonic -- event time clock using the timestamps seen in the input stream. The -- latest timestamp seen till now is used as the base for the current -- time. When no new events are seen, a timer is started with a clock -- resolution of tick seconds. This timer is used to detect -- session timeouts in the absence of new events. -- -- To ensure an upper bound on the memory used the number of sessions can -- be limited to an upper bound. If the ejection predicate -- returns True, the oldest session is ejected before inserting a -- new session. -- -- When the stream ends any buffered sessions are ejected immediately. -- -- If a session key is received even after a session has finished, -- another session is created for that key. -- --
--   >>> :{
--   Stream.mapM_ print
--       $ Stream.classifySessionsBy 1 False (const (return False)) 3 (Fold.take 3 Fold.toList)
--       $ Stream.timestamped
--       $ Stream.delay 0.1
--       $ Stream.fromList ((,) <$> [1,2,3] <*> ['a','b','c'])
--   :}
--   (1,"abc")
--   (2,"abc")
--   (3,"abc")
--   
-- -- Pre-release classifySessionsBy :: (IsStream t, MonadAsync m, Ord k) => Double -> Bool -> (Int -> m Bool) -> Double -> Fold m a b -> t m (AbsTime, (k, a)) -> t m (k, b) -- | Same as classifySessionsBy with a timer tick of 1 second and -- keepalive option set to False. -- --
--   classifySessionsOf = classifySessionsBy 1 False
--   
-- -- Pre-release classifySessionsOf :: (IsStream t, MonadAsync m, Ord k) => (Int -> m Bool) -> Double -> Fold m a b -> t m (AbsTime, (k, a)) -> t m (k, b) -- | Same as classifySessionsBy with a timer tick of 1 second and -- keepalive option set to True. -- --
--   classifyKeepAliveSessions = classifySessionsBy 1 True
--   
-- -- Pre-release classifyKeepAliveSessions :: (IsStream t, MonadAsync m, Ord k) => (Int -> m Bool) -> Double -> Fold m a b -> t m (AbsTime, (k, a)) -> t m (k, b) -- | Apply a Parser repeatedly on a stream and emit the parsed -- values in the output stream. -- -- This is the streaming equivalent of the many parse combinator. -- --
--   >>> Stream.toList $ Stream.parseMany (Parser.takeBetween 0 2 Fold.sum) $ Stream.fromList [1..10]
--   [Right 3,Right 7,Right 11,Right 15,Right 19]
--   
-- --
--   > Stream.toList $ Stream.parseMany (Parser.line Fold.toList) $ Stream.fromList "hello\nworld"
--   ["hello\n","world"]
--   
-- --
--   foldMany f = parseMany (fromFold f)
--   
-- -- Known Issues: When the parser fails there is no way to get the -- remaining stream. -- -- Pre-release parseMany :: (IsStream t, Monad m) => Parser a m b -> t m a -> t m (Either ParseError b) -- | Same as parseMany but for StreamD streams. -- -- Internal parseManyD :: (IsStream t, Monad m) => Parser a m b -> t m a -> t m (Either ParseError b) -- | parseManyTill collect test stream tries the parser -- test on the input, if test fails it backtracks and -- tries collect, after collect succeeds test -- is tried again and so on. The parser stops when test -- succeeds. The output of test is discarded and the output of -- collect is emitted in the output stream. The parser fails if -- collect fails. -- -- Unimplemented parseManyTill :: Parser a m b -> Parser a m x -> t m a -> t m b -- | Apply a stream of parsers to an input stream and emit the results in -- the output stream. -- -- Unimplemented parseSequence :: t m (Parser a m b) -> t m a -> t m b -- | Iterate a parser generating function on a stream. The initial value -- b is used to generate the first parser, the parser is applied -- on the stream and the result is used to generate the next parser and -- so on. -- --
--   >>> import Data.Monoid (Sum(..))
--   
--   >>> Stream.toList $ fmap getSum $ Stream.rights $ Stream.parseIterate (\b -> Parser.takeBetween 0 2 (Fold.sconcat b)) (Sum 0) $ fmap Sum $ Stream.fromList [1..10]
--   [3,10,21,36,55,55]
--   
-- -- This is the streaming equivalent of monad like sequenced application -- of parsers where next parser is dependent on the previous parser. -- -- Pre-release parseIterate :: (IsStream t, Monad m) => (b -> Parser a m b) -> b -> t m a -> t m (Either ParseError b) -- | Like splitOn after stripping leading, trailing, and repeated -- separators. Therefore, ".a..b." with . as the -- separator would be parsed as ["a","b"]. In other words, its -- like parsing words from whitespace separated text. -- --
--   >>> wordsBy' p xs = Stream.toList $ Stream.wordsBy p Fold.toList (Stream.fromList xs)
--   
-- --
--   >>> wordsBy' (== ',') ""
--   []
--   
-- --
--   >>> wordsBy' (== ',') ","
--   []
--   
-- --
--   >>> wordsBy' (== ',') ",a,,b,"
--   ["a","b"]
--   
-- --
--   words = wordsBy isSpace
--   
wordsBy :: (IsStream t, Monad m) => (a -> Bool) -> Fold m a b -> t m a -> t m b -- | Like splitOn but drops any empty splits. -- -- Unimplemented wordsOn :: Array a -> Fold m a b -> t m a -> t m b -- |
--   groups = groupsBy (==)
--   groups = groupsByRolling (==)
--   
-- -- Groups contiguous spans of equal elements together in individual -- groups. -- --
--   >>> Stream.toList $ Stream.groups Fold.toList $ Stream.fromList [1,1,2,2]
--   [[1,1],[2,2]]
--   
groups :: (IsStream t, Monad m, Eq a) => Fold m a b -> t m a -> t m b -- | groupsBy cmp f $ S.fromList [a,b,c,...] assigns the element -- a to the first group, if b `cmp` a is True -- then b is also assigned to the same group. If c `cmp` -- a is True then c is also assigned to the same -- group and so on. When the comparison fails a new group is started. -- Each group is folded using the fold f and the result of the -- fold is emitted in the output stream. -- --
--   >>> Stream.toList $ Stream.groupsBy (>) Fold.toList $ Stream.fromList [1,3,7,0,2,5]
--   [[1,3,7],[0,2,5]]
--   
groupsBy :: (IsStream t, Monad m) => (a -> a -> Bool) -> Fold m a b -> t m a -> t m b -- | Unlike groupsBy this function performs a rolling comparison -- of two successive elements in the input stream. groupsByRolling -- cmp f $ S.fromList [a,b,c,...] assigns the element a to -- the first group, if a `cmp` b is True then b -- is also assigned to the same group. If b `cmp` c is -- True then c is also assigned to the same group and so -- on. When the comparison fails a new group is started. Each group is -- folded using the fold f. -- --
--   >>> Stream.toList $ Stream.groupsByRolling (\a b -> a + 1 == b) Fold.toList $ Stream.fromList [1,2,3,7,8,9]
--   [[1,2,3],[7,8,9]]
--   
groupsByRolling :: (IsStream t, Monad m) => (a -> a -> Bool) -> Fold m a b -> t m a -> t m b -- | splitInnerBy splitter joiner stream splits the inner -- containers f a of an input stream t m (f a) using -- the splitter function. Container elements f a are -- collected until a split occurs, then all the elements before the split -- are joined using the joiner function. -- -- For example, if we have a stream of Array Word8, we may want -- to split the stream into arrays representing lines separated by 'n' -- byte such that the resulting stream after a split would be one array -- for each line. -- -- CAUTION! This is not a true streaming function as the container size -- after the split and merge may not be bounded. -- -- Pre-release splitInnerBy :: (IsStream t, Monad m) => (f a -> m (f a, Maybe (f a))) -> (f a -> f a -> m (f a)) -> t m (f a) -> t m (f a) -- | Like splitInnerBy but splits assuming the separator joins the -- segment in a suffix style. -- -- Pre-release splitInnerBySuffix :: (IsStream t, Monad m, Eq (f a), Monoid (f a)) => (f a -> m (f a, Maybe (f a))) -> (f a -> f a -> m (f a)) -> t m (f a) -> t m (f a) -- | Run the action m b before the stream yields its first -- element. -- -- Same as the following but more efficient due to fusion: -- --
--   >>> before action xs = Stream.nilM action <> xs
--   
--   >>> before action xs = Stream.concatMap (const xs) (Stream.fromEffect action)
--   
before :: (IsStream t, Monad m) => m b -> t m a -> t m a -- | Like after, with following differences: -- -- -- -- Same as the following, but with stream fusion: -- --
--   after_ action xs = xs <> 'nilM' action
--   
-- -- Pre-release after_ :: (IsStream t, Monad m) => m b -> t m a -> t m a -- | Run the action m b whenever the stream t m a stops -- normally, or if it is garbage collected after a partial lazy -- evaluation. -- -- The semantics of the action m b are similar to the semantics -- of cleanup action in bracket. -- -- See also after_ after :: (IsStream t, MonadRunInIO m) => m b -> t m a -> t m a -- | Like bracket but with following differences: -- -- -- -- Inhibits stream fusion -- -- Pre-release bracket_ :: (IsStream t, MonadCatch m) => m b -> (b -> m c) -> (b -> t m a) -> t m a -- | Run the alloc action m b with async exceptions disabled but -- keeping blocking operations interruptible (see mask). Use the -- output b as input to b -> t m a to generate an -- output stream. -- -- b is usually a resource under the state of monad m, -- e.g. a file handle, that requires a cleanup after use. The cleanup -- action b -> m c, runs whenever the stream ends normally, -- due to a sync or async exception or if it gets garbage collected after -- a partial lazy evaluation. -- -- bracket only guarantees that the cleanup action runs, and it -- runs with async exceptions enabled. The action must ensure that it can -- successfully cleanup the resource in the face of sync or async -- exceptions. -- -- When the stream ends normally or on a sync exception, cleanup action -- runs immediately in the current thread context, whereas in other cases -- it runs in the GC context, therefore, cleanup may be delayed until the -- GC gets to run. -- -- See also: bracket_ -- -- Inhibits stream fusion bracket :: (IsStream t, MonadAsync m, MonadCatch m) => m b -> (b -> m c) -> (b -> t m a) -> t m a -- | Like bracket but can use separate cleanup actions depending on -- the mode of termination. bracket' before onStop onGC onException -- action runs action using the result of before. -- If the stream stops, onStop action is executed, if the stream -- is abandoned onGC is executed, if the stream encounters an -- exception onException is executed. -- -- Pre-release bracket' :: (IsStream t, MonadAsync m, MonadCatch m) => m b -> (b -> m c) -> (b -> m d) -> (b -> m e) -> (b -> t m a) -> t m a -- | Run the action m b if the stream aborts due to an exception. -- The exception is not caught, simply rethrown. -- -- Inhibits stream fusion onException :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a -- | Like finally with following differences: -- -- -- -- Inhibits stream fusion -- -- Pre-release finally_ :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a -- | Run the action m b whenever the stream t m a stops -- normally, aborts due to an exception or if it is garbage collected -- after a partial lazy evaluation. -- -- The semantics of running the action m b are similar to the -- cleanup action semantics described in bracket. -- -- See also finally_ -- -- Inhibits stream fusion finally :: (IsStream t, MonadAsync m, MonadCatch m) => m b -> t m a -> t m a -- | Like handle but the exception handler is also provided with the -- stream that generated the exception as input. The exception handler -- can thus re-evaluate the stream to retry the action that failed. The -- exception handler can again call ghandle on it to retry the -- action multiple times. -- -- This is highly experimental. In a stream of actions we can map the -- stream with a retry combinator to retry each action on failure. -- -- Inhibits stream fusion -- -- Pre-release ghandle :: (IsStream t, MonadCatch m, Exception e) => (e -> t m a -> t m a) -> t m a -> t m a -- | When evaluating a stream if an exception occurs, stream evaluation -- aborts and the specified exception handler is run with the exception -- as argument. -- -- Inhibits stream fusion handle :: (IsStream t, MonadCatch m, Exception e) => (e -> t m a) -> t m a -> t m a -- | retry takes 3 arguments -- --
    --
  1. A map m whose keys are exceptions and values are the -- number of times to retry the action given that the exception -- occurs.
  2. --
  3. A handler han that decides how to handle an exception -- when the exception cannot be retried.
  4. --
  5. The stream itself that we want to run this mechanism on.
  6. --
-- -- When evaluating a stream if an exception occurs, -- --
    --
  1. The stream evaluation aborts
  2. --
  3. The exception is looked up in m
  4. --
-- -- a. If the exception exists and the mapped value is > 0 then, -- -- i. The value is decreased by 1. -- -- ii. The stream is resumed from where the exception was called, -- retrying the action. -- -- b. If the exception exists and the mapped value is == 0 then the -- stream evaluation stops. -- -- c. If the exception does not exist then we handle the exception using -- han. -- -- Internal retry :: (IsStream t, MonadCatch m, Exception e, Ord e) => Map e Int -> (e -> t m a) -> t m a -> t m a -- | Transform the inner monad of a stream using a natural transformation. -- -- Internal hoist :: (Monad m, Monad n) => (forall x. m x -> n x) -> SerialT m a -> SerialT n a -- | Generalize the inner monad of the stream from Identity to any -- monad. -- -- Internal generally :: (IsStream t, Monad m) => t Identity a -> t m a -- | Lift the inner monad m of a stream t m a to tr -- m using the monad transformer tr. liftInner :: (Monad m, IsStream t, MonadTrans tr, Monad (tr m)) => t m a -> t (tr m) a -- | Run a stream transformation using a given environment. -- -- See also: map -- -- Internal usingReaderT :: (Monad m, IsStream t) => m r -> (t (ReaderT r m) a -> t (ReaderT r m) a) -> t m a -> t m a -- | Evaluate the inner monad of a stream as ReaderT. runReaderT :: (IsStream t, Monad m) => m s -> t (ReaderT s m) a -> t m a -- | Evaluate the inner monad of a stream as StateT. -- -- This is supported only for SerialT as concurrent state updation -- may not be safe. -- --
--   evalStateT s = Stream.map snd . Stream.runStateT s
--   
-- -- Internal evalStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m a -- | Run a stateful (StateT) stream transformation using a given state. -- -- This is supported only for SerialT as concurrent state updation -- may not be safe. -- --
--   usingStateT s f = evalStateT s . f . liftInner
--   
-- -- See also: scanl' -- -- Internal usingStateT :: Monad m => m s -> (SerialT (StateT s m) a -> SerialT (StateT s m) a) -> SerialT m a -> SerialT m a -- | Evaluate the inner monad of a stream as StateT and emit the -- resulting state and value pair after each step. -- -- This is supported only for SerialT as concurrent state updation -- may not be safe. runStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m (s, a) -- | sampleFromthen offset stride samples the element at -- offset index and then every element at strides of -- stride. -- --
--   >>> Stream.toList $ Stream.sampleFromThen 2 3 $ Stream.enumerateFromTo 0 10
--   [2,5,8]
--   
-- -- Pre-release sampleFromThen :: (IsStream t, Monad m, Functor (t m)) => Int -> Int -> t m a -> t m a -- | Like sampleInterval but samples at the beginning of the time -- window. -- --
--   sampleIntervalStart n = Stream.catMaybes . Stream.intervalsOf n Fold.one
--   
-- -- Pre-release sampleIntervalStart :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m a -> t m a -- | Continuously evaluate the input stream and sample the last event in -- time window of n seconds. -- -- This is also known as throttle in some libraries. -- --
--   sampleIntervalEnd n = Stream.catMaybes . Stream.intervalsOf n Fold.last
--   
-- -- Pre-release sampleIntervalEnd :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m a -> t m a -- | Like sampleBurstEnd but samples the event at the beginning of -- the burst instead of at the end of it. -- -- Pre-release sampleBurstStart :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m a -> t m a -- | Sample one event at the end of each burst of events. A burst is a -- group of events close together in time, it ends when an event is -- spaced by more than the specified time interval (in seconds) from the -- previous event. -- -- This is known as debounce in some libraries. -- -- The clock granularity is 10 ms. -- -- Pre-release sampleBurstEnd :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m a -> t m a -- | Sort the input stream using a supplied comparison function. -- -- O(n) space -- -- Note: this is not the fastest possible implementation as of now. -- -- Pre-release sortBy :: MonadCatch m => (a -> a -> Ordering) -> SerialT m a -> SerialT m a -- | intersectBy is essentially a filtering operation that retains -- only those elements in the first stream that are present in the second -- stream. -- --
--   >>> Stream.toList $ Stream.intersectBy (==) (Stream.fromList [1,2,2,4]) (Stream.fromList [2,1,1,3])
--   [1,2,2]
--   
-- --
--   >>> Stream.toList $ Stream.intersectBy (==) (Stream.fromList [2,1,1,3]) (Stream.fromList [1,2,2,4])
--   [2,1,1]
--   
-- -- intersectBy is similar to but not the same as joinInner: -- --
--   >>> Stream.toList $ fmap fst $ Stream.joinInner (==) (Stream.fromList [1,2,2,4]) (Stream.fromList [2,1,1,3])
--   [1,1,2,2]
--   
-- -- Space: O(n) where n is the number of elements in the second -- stream. -- -- Time: O(m x n) where m is the number of elements in the first -- stream and n is the number of elements in the second stream. -- -- Pre-release intersectBy :: (IsStream t, Monad m) => (a -> a -> Bool) -> t m a -> t m a -> t m a -- | Like intersectBy but works only on streams sorted in ascending -- order. -- -- Space: O(1) -- -- Time: O(m+n) -- -- Pre-release intersectBySorted :: (IsStream t, Monad m) => (a -> a -> Ordering) -> t m a -> t m a -> t m a -- | Delete first occurrences of those elements from the first stream that -- are present in the second stream. If an element occurs multiple times -- in the second stream as many occurrences of it are deleted from the -- first stream. -- --
--   >>> Stream.toList $ Stream.differenceBy (==) (Stream.fromList [1,2,2]) (Stream.fromList [1,2,3])
--   [2]
--   
-- -- The following laws hold: -- --
--   (s1 serial s2) `differenceBy eq` s1 === s2
--   (s1 wSerial s2) `differenceBy eq` s1 === s2
--   
-- -- Same as the list // operation. -- -- Space: O(m) where m is the number of elements in the first -- stream. -- -- Time: O(m x n) where m is the number of elements in the first -- stream and n is the number of elements in the second stream. -- -- Pre-release differenceBy :: (IsStream t, Monad m) => (a -> a -> Bool) -> t m a -> t m a -> t m a -- | Like differenceBy but works only on sorted streams. -- -- Space: O(1) -- -- Unimplemented mergeDifferenceBy :: (a -> a -> Ordering) -> t m a -> t m a -> t m a -- | This is essentially an append operation that appends all the extra -- occurrences of elements from the second stream that are not already -- present in the first stream. -- --
--   >>> Stream.toList $ Stream.unionBy (==) (Stream.fromList [1,2,2,4]) (Stream.fromList [1,1,2,3])
--   [1,2,2,4,3]
--   
-- -- Equivalent to the following except that s1 is evaluated only -- once: -- --
--   unionBy eq s1 s2 = s1 `serial` (s2 `differenceBy eq` s1)
--   
-- -- Similar to joinOuter but not the same. -- -- Space: O(n) -- -- Time: O(m x n) -- -- Pre-release unionBy :: (IsStream t, MonadAsync m, Semigroup (t m a)) => (a -> a -> Bool) -> t m a -> t m a -> t m a -- | Like unionBy but works only on sorted streams. -- -- Space: O(1) -- -- Unimplemented mergeUnionBy :: (a -> a -> Ordering) -> t m a -> t m a -> t m a -- | This is the same as outerProduct but less efficient. -- -- The second stream is evaluated multiple times. If the second stream is -- consume-once stream then it can be cached in an Array before -- calling this function. Caching may also improve performance if the -- stream is expensive to evaluate. -- -- Time: O(m x n) -- -- Pre-release crossJoin :: Monad (t m) => t m a -> t m b -> t m (a, b) -- | For all elements in t m a, for all elements in t m b -- if a and b are equal by the given equality pedicate -- then return the tuple (a, b). -- -- The second stream is evaluated multiple times. If the stream is a -- consume-once stream then the caller should cache it (e.g. in a -- Array) before calling this function. Caching may also improve -- performance if the stream is expensive to evaluate. -- -- For space efficiency use the smaller stream as the second stream. -- -- You should almost always use joinInnerMap instead of joinInner. -- joinInnerMap is an order of magnitude faster. joinInner may be used -- when the second stream is generated from a seed, therefore, need not -- be stored in memory and the amount of memory it takes is a concern. -- -- Space: O(n) assuming the second stream is cached in memory. -- -- Time: O(m x n) -- -- Pre-release joinInner :: forall (t :: (Type -> Type) -> Type -> Type) m a b. (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> t m (a, b) -- | Like joinInner but uses a Map for efficiency. -- -- If the input streams have duplicate keys, the behavior is undefined. -- -- For space efficiency use the smaller stream as the second stream. -- -- Space: O(n) -- -- Time: O(m + n) -- -- Pre-release joinInnerMap :: (IsStream t, Monad m, Ord k) => t m (k, a) -> t m (k, b) -> t m (k, a, b) -- | Like joinInner but works only on sorted streams. -- -- Space: O(1) -- -- Time: O(m + n) -- -- Unimplemented joinInnerMerge :: (a -> b -> Ordering) -> t m a -> t m b -> t m (a, b) -- | Like joinLeft but works only on sorted streams. -- -- Space: O(1) -- -- Time: O(m + n) -- -- Unimplemented mergeLeftJoin :: (a -> b -> Ordering) -> t m a -> t m b -> t m (a, Maybe b) -- | Like joinLeft but uses a hashmap for efficiency. -- -- Space: O(n) -- -- Time: O(m + n) -- -- Pre-release joinLeftMap :: (IsStream t, Ord k, Monad m) => t m (k, a) -> t m (k, b) -> t m (k, a, Maybe b) -- | Like joinOuter but works only on sorted streams. -- -- Space: O(1) -- -- Time: O(m + n) -- -- Unimplemented mergeOuterJoin :: (a -> b -> Ordering) -> t m a -> t m b -> t m (Maybe a, Maybe b) -- | Like joinOuter but uses a Map for efficiency. -- -- Space: O(m + n) -- -- Time: O(m + n) -- -- Pre-release joinOuterMap :: (IsStream t, Ord k, MonadIO m) => t m (k, a) -> t m (k, b) -> t m (k, Maybe a, Maybe b) -- | Specify the maximum number of threads that can be spawned concurrently -- for any concurrent combinator in a stream. A value of 0 resets the -- thread limit to default, a negative value means there is no limit. The -- default value is 1500. maxThreads does not affect -- ParallelT streams as they can use unbounded number of -- threads. -- -- When the actions in a stream are IO bound, having blocking IO calls, -- this option can be used to control the maximum number of in-flight IO -- requests. When the actions are CPU bound this option can be used to -- control the amount of CPU used by the stream. -- -- Since: 0.4.0 (Streamly) maxThreads :: IsStream t => Int -> t m a -> t m a -- | Specify the maximum size of the buffer for storing the results from -- concurrent computations. If the buffer becomes full we stop spawning -- more concurrent tasks until there is space in the buffer. A value of 0 -- resets the buffer size to default, a negative value means there is no -- limit. The default value is 1500. -- -- CAUTION! using an unbounded maxBuffer value (i.e. a negative -- value) coupled with an unbounded maxThreads value is a recipe -- for disaster in presence of infinite streams, or very large streams. -- Especially, it must not be used when pure is used in -- ZipAsyncM streams as pure in applicative zip streams -- generates an infinite stream causing unbounded concurrent generation -- with no limit on the buffer or threads. -- -- Since: 0.4.0 (Streamly) maxBuffer :: IsStream t => Int -> t m a -> t m a maxYields :: IsStream t => Maybe Int64 -> t m a -> t m a -- | Specify the pull rate of a stream. A Nothing value resets the -- rate to default which is unlimited. When the rate is specified, -- concurrent production may be ramped up or down automatically to -- achieve the specified yield rate. The specific behavior for different -- styles of Rate specifications is documented under Rate. -- The effective maximum production rate achieved by a stream is governed -- by: -- -- -- -- Since: 0.5.0 (Streamly) rate :: IsStream t => Maybe Rate -> t m a -> t m a -- | Same as rate (Just $ Rate (r/2) r (2*r) maxBound) -- -- Specifies the average production rate of a stream in number of yields -- per second (i.e. Hertz). Concurrent production is ramped up -- or down automatically to achieve the specified average yield rate. The -- rate can go down to half of the specified rate on the lower side and -- double of the specified rate on the higher side. -- -- Since: 0.5.0 (Streamly) avgRate :: IsStream t => Double -> t m a -> t m a -- | Same as rate (Just $ Rate r r (2*r) maxBound) -- -- Specifies the minimum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go below the -- specified rate, even though it may possibly go above it at times, the -- upper limit is double of the specified rate. -- -- Since: 0.5.0 (Streamly) minRate :: IsStream t => Double -> t m a -> t m a -- | Same as rate (Just $ Rate (r/2) r r maxBound) -- -- Specifies the maximum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go above the -- specified rate, even though it may possibly go below it at times, the -- lower limit is half of the specified rate. This can be useful in -- applications where certain resource usage must not be allowed to go -- beyond certain limits. -- -- Since: 0.5.0 (Streamly) maxRate :: IsStream t => Double -> t m a -> t m a -- | Same as rate (Just $ Rate r r r 0) -- -- Specifies a constant yield rate. If for some reason the actual rate -- goes above or below the specified rate we do not try to recover it by -- increasing or decreasing the rate in future. This can be useful in -- applications like graphics frame refresh where we need to maintain a -- constant refresh rate. -- -- Since: 0.5.0 (Streamly) constRate :: IsStream t => Double -> t m a -> t m a -- | Print debug information about an SVar when the stream ends -- -- Pre-release inspectMode :: IsStream t => t m a -> t m a printState :: MonadIO m => State Stream m a -> m () -- |
--   fromPure a = a `cons` nil
--   
-- -- Create a singleton stream from a pure value. -- -- The following holds in monadic streams, but not in Zip streams: -- --
--   fromPure = pure
--   fromPure = fromEffect . pure
--   
-- -- In Zip applicative streams fromPure is not the same as -- pure because in that case pure is equivalent to -- repeat instead. fromPure and pure are equally -- efficient, in other cases fromPure may be slightly more -- efficient than the other equivalent definitions. -- -- Since: 0.8.0 (Renamed yield to fromPure) fromPure :: IsStream t => a -> t m a -- |
--   fromEffect m = m `consM` nil
--   
-- -- Create a singleton stream from a monadic action. -- --
--   > Stream.toList $ Stream.fromEffect getLine
--   hello
--   ["hello"]
--   
-- -- Since: 0.8.0 (Renamed yieldM to fromEffect) fromEffect :: (Monad m, IsStream t) => m a -> t m a -- |
--   >>> repeatM = fix . consM
--   
--   >>> repeatM = cycle1 . fromEffect
--   
-- -- Generate a stream by repeatedly executing a monadic action forever. -- --
--   >>> :{
--   repeatAsync =
--          Stream.repeatM (threadDelay 1000000 >> print 1)
--        & Stream.take 10
--        & Stream.fromAsync
--        & Stream.drain
--   :}
--   
-- -- Concurrent, infinite (do not use with fromParallel) repeatM :: (IsStream t, MonadAsync m) => m a -> t m a -- | timesWith g returns a stream of time value tuples. The first -- component of the tuple is an absolute time reference (epoch) denoting -- the start of the stream and the second component is a time relative to -- the reference. -- -- The argument g specifies the granularity of the relative time -- in seconds. A lower granularity clock gives higher precision but is -- more expensive in terms of CPU usage. Any granularity lower than 1 ms -- is treated as 1 ms. -- --
--   >>> import Control.Concurrent (threadDelay)
--   
--   >>> import Streamly.Internal.Data.Stream.IsStream.Common as Stream (timesWith)
--   
--   >>> Stream.mapM_ (\x -> print x >> threadDelay 1000000) $ Stream.take 3 $ Stream.timesWith 0.01
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
--   
-- -- Note: This API is not safe on 32-bit machines. -- -- Pre-release timesWith :: (IsStream t, MonadAsync m) => Double -> t m (AbsTime, RelTime64) -- | absTimesWith g returns a stream of absolute timestamps using -- a clock of granularity g specified in seconds. A low -- granularity clock is more expensive in terms of CPU usage. Any -- granularity lower than 1 ms is treated as 1 ms. -- --
--   >>> Stream.mapM_ print $ Stream.delayPre 1 $ Stream.take 3 $ absTimesWith 0.01
--   AbsTime (TimeSpec {sec = ..., nsec = ...})
--   AbsTime (TimeSpec {sec = ..., nsec = ...})
--   AbsTime (TimeSpec {sec = ..., nsec = ...})
--   
-- -- Note: This API is not safe on 32-bit machines. -- -- Pre-release absTimesWith :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m AbsTime -- | relTimesWith g returns a stream of relative time values -- starting from 0, using a clock of granularity g specified in -- seconds. A low granularity clock is more expensive in terms of CPU -- usage. Any granularity lower than 1 ms is treated as 1 ms. -- --
--   >>> Stream.mapM_ print $ Stream.delayPre 1 $ Stream.take 3 $ Stream.relTimesWith 0.01
--   RelTime64 (NanoSecond64 ...)
--   RelTime64 (NanoSecond64 ...)
--   RelTime64 (NanoSecond64 ...)
--   
-- -- Note: This API is not safe on 32-bit machines. -- -- Pre-release relTimesWith :: (IsStream t, MonadAsync m, Functor (t m)) => Double -> t m RelTime64 -- | We can create higher order folds using foldContinue. We can -- fold a number of streams to a given fold efficiently with full stream -- fusion. For example, to fold a list of streams on the same sum fold: -- --
--   concatFold = Prelude.foldl Stream.foldContinue Fold.sum
--   
-- --
--   fold f = Fold.extractM . Stream.foldContinue f
--   
-- -- Internal foldContinue :: Monad m => Fold m a b -> SerialT m a -> Fold m a b -- | Fold a stream using the supplied left Fold and reducing the -- resulting expression strictly at each step. The behavior is similar to -- foldl'. A Fold can terminate early without consuming -- the full stream. See the documentation of individual Folds for -- termination behavior. -- --
--   >>> Stream.fold Fold.sum (Stream.enumerateFromTo 1 100)
--   5050
--   
-- -- Folds never fail, therefore, they produce a default value even when no -- input is provided. It means we can always fold an empty stream and get -- a valid result. For example: -- --
--   >>> Stream.fold Fold.sum Stream.nil
--   0
--   
-- -- However, foldMany on an empty stream results in an empty -- stream. Therefore, Stream.fold f is not the same as -- Stream.head . Stream.foldMany f. -- --
--   fold f = Stream.parse (Parser.fromFold f)
--   
fold :: Monad m => Fold m a b -> SerialT m a -> m b -- |
--   map = fmap
--   
-- -- Same as fmap. -- --
--   > D.toList $ D.map (+1) $ D.fromList [1,2,3]
--   [2,3,4]
--   
map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b -- | scanlMAfter' accumulate initial done stream is like -- scanlM' except that it provides an additional done -- function to be applied on the accumulator when the stream stops. The -- result of done is also emitted in the stream. -- -- This function can be used to allocate a resource in the beginning of -- the scan and release it when the stream ends or to flush the internal -- state of the scan at the end. -- -- Pre-release scanlMAfter' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> (b -> m b) -> t m a -> t m b postscanlMAfter' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> (b -> m b) -> t m a -> t m b -- | Like postscanl' but with a monadic step function and a -- monadic seed. -- --
--   >>> postscanlM' f z xs = Stream.drop 1 $ Stream.scanlM' f z xs
--   
-- -- Since: 0.7.0 -- -- Since: 0.8.0 (signature change) postscanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b -- | A stateful mapM, equivalent to a left scan, more like -- mapAccumL. Hopefully, this is a better alternative to scan. -- Separation of state from the output makes it easier to think in terms -- of a shared state, and also makes it easier to keep the state fully -- strict and the output lazy. -- -- See also: scanlM' -- -- Pre-release smapM :: (IsStream t, Monad m) => (s -> a -> m (s, b)) -> m s -> t m a -> t m b -- | Like foldMany but appends empty fold output if the fold and -- stream termination aligns: -- --
--   >>> f = Fold.take 2 Fold.sum
--   
--   >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList []
--   [0]
--   
--   >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList [1..9]
--   [3,7,11,15,9]
--   
--   >>> Stream.toList $ Stream.foldManyPost f $ Stream.fromList [1..10]
--   [3,7,11,15,19,0]
--   
-- -- Pre-release foldManyPost :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b -- | Take first n elements from the stream and discard the rest. take :: (IsStream t, Monad m) => Int -> t m a -> t m a -- | End the stream as soon as the predicate fails on an element. takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a takeEndBy :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a -- | Discard first n elements from the stream and take the rest. drop :: (IsStream t, Monad m) => Int -> t m a -> t m a -- | Find all the indices where the element in the stream satisfies the -- given predicate. -- --
--   findIndices = fold Fold.findIndices
--   
findIndices :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m Int -- | Insert an effect and its output before consuming an element of a -- stream except the first one. -- --
--   >>> Stream.toList $ Stream.trace putChar $ Stream.intersperseM (putChar '.' >> return ',') $ Stream.fromList "hello"
--   h.,e.,l.,l.,o"h,e,l,l,o"
--   
-- -- Be careful about the order of effects. In the above example we used -- trace after the intersperse, if we use it before the intersperse the -- output would be he.l.l.o."h,e,l,l,o". -- --
--   >>> Stream.toList $ Stream.intersperseM (putChar '.' >> return ',') $ Stream.trace putChar $ Stream.fromList "hello"
--   he.l.l.o."h,e,l,l,o"
--   
intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a -- | Intersperse a monadic action into the input stream after every -- n seconds. -- --
--   > import Control.Concurrent (threadDelay)
--   > Stream.drain $ Stream.interjectSuffix 1 (putChar ',') $ Stream.mapM (x -> threadDelay 1000000 >> putChar x) $ Stream.fromList "hello"
--   h,e,l,l,o
--   
-- -- Pre-release interjectSuffix :: (IsStream t, MonadAsync m) => Double -> m a -> t m a -> t m a -- | Returns the elements of the stream in reverse order. The stream must -- be finite. Note that this necessarily buffers the entire stream in -- memory. -- --
--   >>> reverse = Stream.foldlT (flip Stream.cons) Stream.nil
--   
-- -- Since 0.7.0 (Monad m constraint) -- -- Since: 0.1.1 reverse :: (IsStream t, Monad m) => t m a -> t m a -- | Like reverse but several times faster, requires a -- Storable instance. -- -- Pre-release reverse' :: (IsStream t, MonadIO m, Unbox a) => t m a -> t m a -- | Make the stream producer and consumer run concurrently by introducing -- a buffer between them. The producer thread evaluates the input stream -- until the buffer fills, it terminates if the buffer is full and a -- worker thread is kicked off again to evaluate the remaining stream -- when there is space in the buffer. The consumer consumes the stream -- lazily from the buffer. -- -- Since: 0.2.0 (Streamly) mkAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -- | Make the stream producer and consumer run concurrently by introducing -- a buffer between them. The producer thread evaluates the input stream -- until the buffer fills, it blocks if the buffer is full until there is -- space in the buffer. The consumer consumes the stream lazily from the -- buffer. -- --
--   mkParallel = IsStream.fromStreamD . mkParallelD . IsStream.toStreamD
--   
-- -- Pre-release mkParallel :: (IsStream t, MonadAsync m) => t m a -> t m a -- | Like parallel but stops the output as soon as the first -- stream stops. -- -- Pre-release parallelFst :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a -- | Given a stream value in the underlying monad, lift and join the -- underlying monad with the stream monad. -- --
--   >>> concatM = Stream.concat . Stream.fromEffect
--   
--   >>> concatM = Stream.concat . lift    -- requires (MonadTrans t)
--   
--   >>> concatM = join . lift             -- requires (MonadTrans t, Monad (t m))
--   
-- -- See also: concat, sequence -- -- Internal concatM :: (IsStream t, Monad m) => m (t m a) -> t m a -- | Map a stream producing monadic function on each element of the stream -- and then flatten the results into a single stream. Since the stream -- generation function is monadic, unlike concatMap, it can -- produce an effect at the beginning of each iteration of the inner -- loop. concatMapM :: (IsStream t, Monad m) => (a -> m (t m b)) -> t m a -> t m b -- | Map a stream producing function on each element of the stream and then -- flatten the results into a single stream. -- --
--   >>> concatMap f = Stream.concatMapM (return . f)
--   
--   >>> concatMap f = Stream.concatMapWith Stream.serial f
--   
--   >>> concatMap f = Stream.concat . Stream.map f
--   
concatMap :: (IsStream t, Monad m) => (a -> t m b) -> t m a -> t m b -- | Like splitOn but the separator is a sequence of elements -- instead of a single element. -- -- For illustration, let's define a function that operates on pure lists: -- --
--   >>> splitOnSeq' pat xs = Stream.toList $ Stream.splitOnSeq (Array.fromList pat) Fold.toList (Stream.fromList xs)
--   
-- --
--   >>> splitOnSeq' "" "hello"
--   ["h","e","l","l","o"]
--   
-- --
--   >>> splitOnSeq' "hello" ""
--   [""]
--   
-- --
--   >>> splitOnSeq' "hello" "hello"
--   ["",""]
--   
-- --
--   >>> splitOnSeq' "x" "hello"
--   ["hello"]
--   
-- --
--   >>> splitOnSeq' "h" "hello"
--   ["","ello"]
--   
-- --
--   >>> splitOnSeq' "o" "hello"
--   ["hell",""]
--   
-- --
--   >>> splitOnSeq' "e" "hello"
--   ["h","llo"]
--   
-- --
--   >>> splitOnSeq' "l" "hello"
--   ["he","","o"]
--   
-- --
--   >>> splitOnSeq' "ll" "hello"
--   ["he","o"]
--   
-- -- splitOnSeq is an inverse of intercalate. The following -- law always holds: -- --
--   intercalate . splitOnSeq == id
--   
-- -- The following law holds when the separator is non-empty and contains -- none of the elements present in the input lists: -- --
--   splitOnSeq . intercalate == id
--   
-- --
--   >>> splitOnSeq pat f = Stream.foldManyPost (Fold.takeEndBySeq_ pat f)
--   
-- -- Pre-release splitOnSeq :: (IsStream t, MonadIO m, Storable a, Unbox a, Enum a, Eq a) => Array a -> Fold m a b -> t m a -> t m b -- | Like zipWith but using a monadic zipping function. zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c -- | Stream a is evaluated first, followed by stream b, -- the resulting elements a and b are then zipped using -- the supplied zip function and the result c is yielded to the -- consumer. -- -- If stream a or stream b ends, the zipped stream -- ends. If stream b ends first, the element a from -- previous evaluation of stream a is discarded. -- --
--   > D.toList $ D.zipWith (+) (D.fromList [1,2,3]) (D.fromList [4,5,6])
--   [5,7,9]
--   
zipWith :: (IsStream t, Monad m) => (a -> b -> c) -> t m a -> t m b -> t m c -- | Same as fromPure yield :: IsStream t => a -> t m a -- | Same as fromEffect yieldM :: (Monad m, IsStream t) => m a -> t m a -- | Types that can be enumerated as a stream. The operations in this type -- class are equivalent to those in the Enum type class, except -- that these generate a stream instead of a list. Use the functions in -- Streamly.Internal.Data.Stream.Enumeration module to define new -- instances. class Enum a => Enumerable a -- | enumerateFrom from generates a stream starting with the -- element from, enumerating up to maxBound when the type -- is Bounded or generating an infinite stream when the type is -- not Bounded. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFrom (0 :: Int)
--   [0,1,2,3]
--   
-- -- For Fractional types, enumeration is numerically stable. -- However, no overflow or underflow checks are performed. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFrom 1.1
--   [1.1,2.1,3.1,4.1]
--   
enumerateFrom :: (Enumerable a, IsStream t, Monad m) => a -> t m a -- | Generate a finite stream starting with the element from, -- enumerating the type up to the value to. If to is -- smaller than from then an empty stream is returned. -- --
--   >>> Stream.toList $ Stream.enumerateFromTo 0 4
--   [0,1,2,3,4]
--   
-- -- For Fractional types, the last element is equal to the -- specified to value after rounding to the nearest integral -- value. -- --
--   >>> Stream.toList $ Stream.enumerateFromTo 1.1 4
--   [1.1,2.1,3.1,4.1]
--   
--   >>> Stream.toList $ Stream.enumerateFromTo 1.1 4.6
--   [1.1,2.1,3.1,4.1,5.1]
--   
enumerateFromTo :: (Enumerable a, IsStream t, Monad m) => a -> a -> t m a -- | enumerateFromThen from then generates a stream whose first -- element is from, the second element is then and the -- successive elements are in increments of then - from. -- Enumeration can occur downwards or upwards depending on whether -- then comes before or after from. For Bounded -- types the stream ends when maxBound is reached, for unbounded -- types it keeps enumerating infinitely. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 2
--   [0,2,4,6]
--   
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 (-2)
--   [0,-2,-4,-6]
--   
enumerateFromThen :: (Enumerable a, IsStream t, Monad m) => a -> a -> t m a -- | enumerateFromThenTo from then to generates a finite stream -- whose first element is from, the second element is -- then and the successive elements are in increments of -- then - from up to to. Enumeration can occur -- downwards or upwards depending on whether then comes before -- or after from. -- --
--   >>> Stream.toList $ Stream.enumerateFromThenTo 0 2 6
--   [0,2,4,6]
--   
--   >>> Stream.toList $ Stream.enumerateFromThenTo 0 (-2) (-6)
--   [0,-2,-4,-6]
--   
enumerateFromThenTo :: (Enumerable a, IsStream t, Monad m) => a -> a -> a -> t m a -- |
--   enumerate = enumerateFrom minBound
--   
-- -- Enumerate a Bounded type from its minBound to -- maxBound enumerate :: (IsStream t, Monad m, Bounded a, Enumerable a) => t m a -- |
--   enumerateTo = enumerateFromTo minBound
--   
-- -- Enumerate a Bounded type from its minBound to specified -- value. enumerateTo :: (IsStream t, Monad m, Bounded a, Enumerable a) => a -> t m a -- |
--   enumerateFromBounded = enumerateFromTo from maxBound
--   
-- -- enumerateFrom for Bounded Enum types. enumerateFromBounded :: (IsStream t, Monad m, Enumerable a, Bounded a) => a -> t m a -- | enumerateFromTo for Enum types not larger than -- Int. enumerateFromToSmall :: (IsStream t, Monad m, Enum a) => a -> a -> t m a -- | enumerateFromThenTo for Enum types not larger than -- Int. enumerateFromThenToSmall :: (IsStream t, Monad m, Enum a) => a -> a -> a -> t m a -- | enumerateFromThen for Enum types not larger than -- Int. -- -- Note: We convert the Enum to Int and enumerate the -- Int. If a type is bounded but does not have a Bounded -- instance then we can go on enumerating it beyond the legal values of -- the type, resulting in the failure of toEnum when converting -- back to Enum. Therefore we require a Bounded instance -- for this function to be safely used. enumerateFromThenSmallBounded :: (IsStream t, Monad m, Enumerable a, Bounded a) => a -> a -> t m a -- | Enumerate an Integral type. enumerateFromIntegral from -- generates a stream whose first element is from and the -- successive elements are in increments of 1. The stream is -- bounded by the size of the Integral type. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromIntegral (0 :: Int)
--   [0,1,2,3]
--   
enumerateFromIntegral :: (IsStream t, Monad m, Integral a, Bounded a) => a -> t m a -- | Enumerate an Integral type in steps. -- enumerateFromThenIntegral from then generates a stream whose -- first element is from, the second element is then -- and the successive elements are in increments of then - from. -- The stream is bounded by the size of the Integral type. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) 2
--   [0,2,4,6]
--   
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenIntegral (0 :: Int) (-2)
--   [0,-2,-4,-6]
--   
enumerateFromThenIntegral :: (IsStream t, Monad m, Integral a, Bounded a) => a -> a -> t m a -- | Enumerate an Integral type up to a given limit. -- enumerateFromToIntegral from to generates a finite stream -- whose first element is from and successive elements are in -- increments of 1 up to to. -- --
--   >>> Stream.toList $ Stream.enumerateFromToIntegral 0 4
--   [0,1,2,3,4]
--   
enumerateFromToIntegral :: (IsStream t, Monad m, Integral a) => a -> a -> t m a -- | Enumerate an Integral type in steps up to a given limit. -- enumerateFromThenToIntegral from then to generates a finite -- stream whose first element is from, the second element is -- then and the successive elements are in increments of -- then - from up to to. -- --
--   >>> Stream.toList $ Stream.enumerateFromThenToIntegral 0 2 6
--   [0,2,4,6]
--   
--   >>> Stream.toList $ Stream.enumerateFromThenToIntegral 0 (-2) (-6)
--   [0,-2,-4,-6]
--   
enumerateFromThenToIntegral :: (IsStream t, Monad m, Integral a) => a -> a -> a -> t m a -- | enumerateFromStepIntegral from step generates an infinite -- stream whose first element is from and the successive -- elements are in increments of step. -- -- CAUTION: This function is not safe for finite integral types. It does -- not check for overflow, underflow or bounds. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromStepIntegral 0 2
--   [0,2,4,6]
--   
--   >>> Stream.toList $ Stream.take 3 $ Stream.enumerateFromStepIntegral 0 (-2)
--   [0,-2,-4]
--   
enumerateFromStepIntegral :: (IsStream t, Monad m, Integral a) => a -> a -> t m a -- | Numerically stable enumeration from a Fractional number in -- steps of size 1. enumerateFromFractional from -- generates a stream whose first element is from and the -- successive elements are in increments of 1. No overflow or -- underflow checks are performed. -- -- This is the equivalent to enumFrom for Fractional types. -- For example: -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromFractional 1.1
--   [1.1,2.1,3.1,4.1]
--   
enumerateFromFractional :: (IsStream t, Monad m, Fractional a) => a -> t m a -- | Numerically stable enumeration from a Fractional number to a -- given limit. enumerateFromToFractional from to generates a -- finite stream whose first element is from and successive -- elements are in increments of 1 up to to. -- -- This is the equivalent of enumFromTo for Fractional -- types. For example: -- --
--   >>> Stream.toList $ Stream.enumerateFromToFractional 1.1 4
--   [1.1,2.1,3.1,4.1]
--   
--   >>> Stream.toList $ Stream.enumerateFromToFractional 1.1 4.6
--   [1.1,2.1,3.1,4.1,5.1]
--   
-- -- Notice that the last element is equal to the specified to -- value after rounding to the nearest integer. enumerateFromToFractional :: (IsStream t, Monad m, Fractional a, Ord a) => a -> a -> t m a -- | Numerically stable enumeration from a Fractional number in -- steps. enumerateFromThenFractional from then generates a -- stream whose first element is from, the second element is -- then and the successive elements are in increments of -- then - from. No overflow or underflow checks are performed. -- -- This is the equivalent of enumFromThen for Fractional -- types. For example: -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 2.1
--   [1.1,2.1,3.1,4.1]
--   
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThenFractional 1.1 (-2.1)
--   [1.1,-2.1,-5.300000000000001,-8.500000000000002]
--   
enumerateFromThenFractional :: (IsStream t, Monad m, Fractional a) => a -> a -> t m a -- | Numerically stable enumeration from a Fractional number in -- steps up to a given limit. enumerateFromThenToFractional from then -- to generates a finite stream whose first element is -- from, the second element is then and the successive -- elements are in increments of then - from up to to. -- -- This is the equivalent of enumFromThenTo for Fractional -- types. For example: -- --
--   >>> Stream.toList $ Stream.enumerateFromThenToFractional 0.1 2 6
--   [0.1,2.0,3.9,5.799999999999999]
--   
--   >>> Stream.toList $ Stream.enumerateFromThenToFractional 0.1 (-2) (-6)
--   [0.1,-2.0,-4.1000000000000005,-6.200000000000001]
--   
enumerateFromThenToFractional :: (IsStream t, Monad m, Fractional a, Ord a) => a -> a -> a -> t m a fromStream :: (IsStream t, Monad m) => Stream m a -> t m a toStream :: (IsStream t, Monad m) => t m a -> Stream m a module Streamly.Internal.Data.Unfold.Prelude -- | Run the alloc action a -> m c with async exceptions -- disabled but keeping blocking operations interruptible (see -- mask). Use the output c as input to Unfold m c -- b to generate an output stream. When unfolding use the supplied -- try operation forall s. m s -> m (Either e s) to -- catch synchronous exceptions. If an exception occurs run the exception -- handling unfold Unfold m (c, e) b. -- -- The cleanup action c -> m d, runs whenever the stream ends -- normally, due to a sync or async exception or if it gets garbage -- collected after a partial lazy evaluation. See bracket for the -- semantics of the cleanup action. -- -- gbracket can express all other exception handling combinators. -- -- Inhibits stream fusion -- -- Pre-release gbracket :: MonadRunInIO m => (a -> m c) -> (c -> m d) -> Unfold m (c, e) b -> (forall s. m s -> m (Either e s)) -> Unfold m c b -> Unfold m a b -- | Unfold the input a using Unfold m a b, run an action -- on a whenever the unfold stops normally, or if it is garbage -- collected after a partial lazy evaluation. -- -- The semantics of the action a -> m c are similar to the -- cleanup action semantics in bracket. -- -- See also after_ -- -- Pre-release after :: MonadRunInIO m => (a -> m c) -> Unfold m a b -> Unfold m a b -- | Unfold the input a using Unfold m a b, run an action -- on a whenever the unfold stops normally, aborts due to an -- exception or if it is garbage collected after a partial lazy -- evaluation. -- -- The semantics of the action a -> m c are similar to the -- cleanup action semantics in bracket. -- --
--   finally release = bracket return release
--   
-- -- See also finally_ -- -- Inhibits stream fusion -- -- Pre-release finally :: (MonadAsync m, MonadCatch m) => (a -> m c) -> Unfold m a b -> Unfold m a b -- | Run the alloc action a -> m c with async exceptions -- disabled but keeping blocking operations interruptible (see -- mask). Use the output c as input to Unfold m c -- b to generate an output stream. -- -- c is usually a resource under the state of monad m, -- e.g. a file handle, that requires a cleanup after use. The cleanup -- action c -> m d, runs whenever the stream ends normally, -- due to a sync or async exception or if it gets garbage collected after -- a partial lazy evaluation. -- -- bracket only guarantees that the cleanup action runs, and it -- runs with async exceptions enabled. The action must ensure that it can -- successfully cleanup the resource in the face of sync or async -- exceptions. -- -- When the stream ends normally or on a sync exception, cleanup action -- runs immediately in the current thread context, whereas in other cases -- it runs in the GC context, therefore, cleanup may be delayed until the -- GC gets to run. -- -- See also: bracket_, gbracket -- -- Inhibits stream fusion -- -- Pre-release bracket :: (MonadAsync m, MonadCatch m) => (a -> m c) -> (c -> m d) -> Unfold m c b -> Unfold m a b -- | Internal fromSVar :: MonadAsync m => Unfold m (SVar t m a) a -- | Internal fromProducer :: MonadAsync m => Unfold m (SVar t m a) a -- |

Overview

-- -- Use watchPaths with a list of file system paths you want to -- watch as argument. It returns a stream of Event representing -- the file system events occurring under the watched paths. -- --
--   Stream.mapM_ (putStrLn . showEvent) $ watchPaths [Array.fromList "dir"]
--   
-- -- Event is an opaque type. Accessor functions (e.g. -- showEvent above) provided in this module are used to determine -- the attributes of the event. -- -- Identical successive events may be coalesced into a single event. -- --

Design notes

-- -- For reference documentation see: -- -- -- -- We try to keep the macOS/Linux/Windows event handling APIs and -- defaults semantically and syntactically as close as possible. -- --

BUGs

-- -- When testing on Linux Kernel version 5.3.0-53-generic -- #47-Ubuntu, the last event for the root path seems to be delayed -- until one more event occurs. -- --

Differences between macOS and Linux APIs:

-- --
    --
  1. macOS watch is based on the path provided to it, if the path is -- deleted and recreated it will still be watched, if the path moves to -- another path it won't be watched anymore. Whereas Linux watch is based -- on a handle to the path, if the path is deleted and recreated it won't -- be watched, if the path moves to another it can still be watched -- (though this is configurable).
  2. --
-- --
    --
  1. macOS watches the directory hierarchy recursively, Linux watches -- only one level of dir, recursive watch has to be built in user space -- by watching for create events and adding the new directories to the -- watch. Not sure how this will scale for too many paths.
  2. --
  3. In macOS the path of the subject of the event is absolute, in -- Linux the path is the name of the object inside the dir being -- watched.
  4. --
  5. On Linux watchPaths fails if a path does not exist, on -- macOS it does not fail.
  6. --
module Streamly.Internal.FileSystem.Event.Linux -- | Watch configuration, used to specify the events of interest and the -- behavior of the watch. -- -- Pre-release data Config Config :: Bool -> Word32 -> Config [watchRec] :: Config -> Bool [createFlags] :: Config -> Word32 -- | The default configuration settings are: -- -- -- -- The tunable events enabled by default are: -- -- -- -- Pre-release defaultConfig :: Config -- | Watch the whole directory tree recursively instead of watching just -- one level of directory. -- -- default: False -- -- Pre-release setRecursiveMode :: Bool -> Config -> Config -- | If the pathname to be watched is a symbolic link then watch the target -- of the symbolic link instead of the symbolic link itself. -- -- Note that the path location in the events is through the original -- symbolic link path rather than the resolved path. -- -- default: True -- -- Pre-release setFollowSymLinks :: Bool -> Config -> Config -- | If an object moves out of the directory being watched then stop -- watching it. -- -- default: True -- -- Pre-release setUnwatchMoved :: Bool -> Config -> Config -- | Watch the object only for one event and then remove it from the watch. -- -- default: False -- -- Pre-release setOneShot :: Bool -> Config -> Config -- | Watch the object only if it is a directory. This provides a race-free -- way to ensure that the watched object is a directory. -- -- default: False -- -- Pre-release setOnlyDir :: Bool -> Config -> Config -- | What to do if a watch already exists when openWatch or -- addToWatch is called for a path. -- -- Pre-release data WhenExists -- | Do not set an existing setting to False only set to True AddIfExists :: WhenExists -- | Replace the existing settings with new settings ReplaceIfExists :: WhenExists -- | Fail the API FailIfExists :: WhenExists -- | When adding a new path to the watch, specify what to do if a watch -- already exists on that path. -- -- default: FailIfExists -- -- Pre-release setWhenExists :: WhenExists -> Config -> Config -- | Report when the watched path itself gets deleted. -- -- default: True -- -- Pre-release setRootDeleted :: Bool -> Config -> Config -- | Report when the watched root path itself gets renamed. -- -- default: True -- -- Pre-release setRootMoved :: Bool -> Config -> Config -- | Report when the watched root path itself gets deleted or renamed. -- -- default: True -- -- Pre-release setRootPathEvents :: Bool -> Config -> Config -- | Report when the metadata e.g. owner, permission modes, modifications -- times of an object changes. -- -- default: True -- -- Pre-release setAttrsModified :: Bool -> Config -> Config -- | Report when a file is accessed. -- -- default: True -- -- Pre-release setAccessed :: Bool -> Config -> Config -- | Report when a file is opened. -- -- default: True -- -- Pre-release setOpened :: Bool -> Config -> Config -- | Report when a file that was opened for writes is closed. -- -- default: True -- -- Pre-release setWriteClosed :: Bool -> Config -> Config -- | Report when a file that was opened for not writing is closed. -- -- default: True -- -- Pre-release setNonWriteClosed :: Bool -> Config -> Config -- | Report when a file is created. -- -- default: True -- -- Pre-release setCreated :: Bool -> Config -> Config -- | Report when a file is deleted. -- -- default: True -- -- Pre-release setDeleted :: Bool -> Config -> Config -- | Report the source of a move. -- -- default: True -- -- Pre-release setMovedFrom :: Bool -> Config -> Config -- | Report the target of a move. -- -- default: True -- -- Pre-release setMovedTo :: Bool -> Config -> Config -- | Report when a file is modified. -- -- default: True -- -- Pre-release setModified :: Bool -> Config -> Config -- | Set all tunable events True or False. Equivalent to -- setting: -- -- -- -- Pre-release setAllEvents :: Bool -> Config -> Config -- | Same as watchWith using defaultConfig and non-recursive mode. -- --
--   >>> watch = watchWith id
--   
-- -- Pre-release watch :: NonEmpty (Array Word8) -> Stream IO Event -- | Same as watchWith using defaultConfig and recursive -- mode. -- --
--   >>> watchRecursive = watchWith (setRecursiveMode True)
--   
-- -- See watchWith for pitfalls and bugs when using recursive watch -- on Linux. -- -- Pre-release watchRecursive :: NonEmpty (Array Word8) -> Stream IO Event -- | Start monitoring a list of file system paths for file system events -- with the supplied configuration operation over the -- defaultConfig. The paths could be files or directories. When -- recursive mode is set and the path is a directory, the whole directory -- tree under it is watched recursively. Monitoring starts from the -- current time onwards. The paths are specified as UTF-8 encoded -- Array of Word8. -- -- Non-existing Paths: the API fails if a watch is started on a -- non-exsting path. -- -- Performance: Note that recursive watch on a large directory -- tree could be expensive. When starting a watch, the whole tree must be -- read and watches are started on each directory in the tree. The -- initial time to start the watch as well as the memory required is -- proportional to the number of directories in the tree. -- -- Bugs: When new directories are created under the tree they are -- added to the watch on receiving the directory create event. However, -- the creation of a dir and adding a watch for it is not atomic. The -- implementation takes care of this and makes sure that watches are -- added for all directories. However, In the mean time, the directory -- may have received more events which may get lost. Handling of any such -- lost events is yet to be implemented. -- -- See the Linux inotify man page for more details. -- --
--   watchwith
--        (setFollowSymLinks True . setUnwatchMoved False)
--        [Array.fromList "dir"]
--   
-- -- Pre-release watchWith :: (Config -> Config) -> NonEmpty (Array Word8) -> Stream IO Event -- | addToWatch cfg watch root subpath adds subpath to -- the list of paths being monitored under root via the watch -- handle watch. root must be an absolute path and -- subpath must be relative to root. -- -- Pre-release addToWatch :: Config -> Watch -> Array Word8 -> Array Word8 -> IO () -- | Remove an absolute root path from a Watch, if a path was moved -- after adding you need to provide the original path which was used to -- add the Watch. -- -- Pre-release removeFromWatch :: Watch -> Array Word8 -> IO () -- | An Event generated by the file system. Use the accessor functions to -- examine the event. -- -- Pre-release data Event Event :: CInt -> Word32 -> Word32 -> Array Word8 -> IntMap (Array Word8, Array Word8) -> Event [eventWd] :: Event -> CInt [eventFlags] :: Event -> Word32 [eventCookie] :: Event -> Word32 [eventRelPath] :: Event -> Array Word8 [eventMap] :: Event -> IntMap (Array Word8, Array Word8) -- | Get the watch root corresponding to the Event. -- -- Note that if a path was moved after adding to the watch, this will -- give the original path and not the new path after moving. -- -- TBD: we can possibly update the watch root on a move self event. -- -- Pre-release getRoot :: Event -> Array Word8 -- | Get the file system object path for which the event is generated, -- relative to the watched root. The path is a "/" separated array of -- bytes. -- -- Pre-release getRelPath :: Event -> Array Word8 -- | Get the absolute file system object path for which the event is -- generated. -- -- When the watch root is a symlink, the absolute path returned is via -- the original symlink and not through the resolved path. -- -- Pre-release getAbsPath :: Event -> Array Word8 -- | Cookie is set when a rename occurs. The cookie value can be used to -- connect the isMovedFrom and isMovedTo events, if both -- the events belong to the same move operation then they will have the -- same cookie value. -- -- Pre-release getCookie :: Event -> Cookie -- | Determine whether the event indicates a change of path of the -- monitored object itself. Note that the object may become unreachable -- or deleted after a change of path. -- -- Occurs only for a watched path -- -- Pre-release isRootPathEvent :: Event -> Bool -- | A path was removed from the watch explicitly using -- removeFromWatch or automatically (file was deleted, or -- filesystem was unmounted). -- -- Note that in recursive watch mode all the subdirectories are watch -- roots, therefore, they will all generate this event. -- -- Occurs only for a watched path -- -- Pre-release isRootUnwatched :: Event -> Bool -- | Watched file/directory was itself deleted. (This event also occurs if -- an object is moved to another filesystem, since mv(1) in effect copies -- the file to the other filesystem and then deletes it from the original -- filesystem.) In addition, an isRootUnwatched event will -- subsequently be generated for the watch descriptor. -- -- Note that in recursive watch mode all the subdirectories are watch -- roots, therefore, they will all generate this event. -- -- Occurs only for a watched path -- -- Pre-release isRootDeleted :: Event -> Bool -- | Watched file/directory was itself moved within the file system. -- -- Note that in recursive watch mode all the subdirectories are watch -- roots, therefore, they will all generate this event. -- -- Occurs only for a watched path -- -- Pre-release isRootMoved :: Event -> Bool -- | Filesystem containing watched object was unmounted. In addition, an -- isRootUnwatched event will subsequently be generated for the -- watch descriptor. -- -- Occurs only for a watched path -- -- Pre-release isRootUnmounted :: Event -> Bool -- | Determine whether the event indicates inode metadata change for an -- object contained within the monitored path. -- -- Metadata change may include, permissions (e.g., chmod(2)), timestamps -- (e.g., utimensat(2)), extended attributes (setxattr(2)), link count -- (since Linux 2.6.25; e.g., for the target of link(2) and for -- unlink(2)), and user/group ID (e.g., chown(2)). -- -- Can occur for watched path or a file inside it -- -- Pre-release isAttrsModified :: Event -> Bool -- | File was accessed (e.g. read, execve). -- -- Occurs only for a file inside the watched directory -- -- Pre-release isAccessed :: Event -> Bool -- | File or directory was opened. -- -- Occurs only for a file inside the watched directory -- -- Pre-release isOpened :: Event -> Bool -- | File opened for writing was closed. -- -- Occurs only for a file inside the watched directory -- -- Pre-release isWriteClosed :: Event -> Bool -- | File or directory opened for read but not write was closed. -- -- Can occur for watched path or a file inside it -- -- Pre-release isNonWriteClosed :: Event -> Bool -- | File/directory created in watched directory (e.g., open(2) O_CREAT, -- mkdir(2), link(2), symlink(2), bind(2) on a UNIX domain socket). -- -- Occurs only for an object inside the watched directory -- -- Pre-release isCreated :: Event -> Bool -- | File/directory deleted from watched directory. -- -- Occurs only for an object inside the watched directory -- -- Pre-release isDeleted :: Event -> Bool -- | Generated for the original path when an object is moved from under a -- monitored directory. -- -- Occurs only for an object inside the watched directory -- -- Pre-release isMovedFrom :: Event -> Bool -- | Generated for the new path when an object is moved under a monitored -- directory. -- -- Occurs only for an object inside the watched directory -- -- Pre-release isMovedTo :: Event -> Bool -- | Generated for a path that is moved from or moved to the monitored -- directory. -- --
--   >>> isMoved ev = isMovedFrom ev || isMovedTo ev
--   
-- -- Occurs only for an object inside the watched directory -- -- Pre-release isMoved :: Event -> Bool -- | Determine whether the event indicates modification of an object within -- the monitored path. This event is generated only for files and not -- directories. -- -- Occurs only for an object inside the watched directory -- -- Pre-release isModified :: Event -> Bool -- | Determine whether the event is for a directory path. -- -- Pre-release isDir :: Event -> Bool -- | Event queue overflowed (WD is invalid for this event) and we may have -- lost some events.. The user application must scan everything under the -- watched paths to know the current state. -- -- Pre-release isEventsLost :: Event -> Bool -- | Convert an Event record to a String representation. showEvent :: Event -> String instance GHC.Show.Show Streamly.Internal.FileSystem.Event.Linux.WD instance GHC.Classes.Eq Streamly.Internal.FileSystem.Event.Linux.Cookie instance GHC.Show.Show Streamly.Internal.FileSystem.Event.Linux.Cookie instance GHC.Classes.Eq Streamly.Internal.FileSystem.Event.Linux.Event instance GHC.Classes.Ord Streamly.Internal.FileSystem.Event.Linux.Event instance GHC.Show.Show Streamly.Internal.FileSystem.Event.Linux.Event -- | File system event notification API portable across Linux, macOS and -- Windows platforms. -- -- Note that recursive directory tree watch does not work reliably on -- Linux (see notes in the Linux module), therefore, recursive watch API -- is not provided in this module. However, you can use it from the -- platform specific modules. -- -- For platform specific APIs please see the following modules: -- -- module Streamly.Internal.FileSystem.Event -- | Start monitoring a list of directories or symbolic links to -- directories for file system events. Monitoring starts from the current -- time onwards. The paths are specified as UTF-8 encoded Array of -- Word8. -- -- If a watch root is a symbolic link then the target of the link is -- watched. Fails if the watched path does not exist. If the user does -- not have permissions (read and execute?) on the watch root then no -- events are generated. No events are generated if the watch root itself -- is renamed or deleted. -- -- This API watches for changes in the watch root directory only, any -- changes in the subdirectories of the watch root are not watched. -- However, on macOS the watch is always recursive, but do not rely on -- that behavior, it may change without notice in future. If you want to -- use recursive watch please use platform specific modules. -- -- Pre-release watch :: NonEmpty (Array Word8) -> Stream IO Event -- | An Event generated by the file system. Use the accessor functions to -- examine the event. -- -- Pre-release data Event -- | Get the absolute path of the file system object for which the event is -- generated. The path is a UTF-8 encoded array of bytes. -- -- When the watch root is a symlink the behavior is different on -- different platforms: -- -- -- -- This API is subject to removal in future, to be replaced by a platform -- independent getRelPath. -- -- Pre-release getAbsPath :: Event -> Array Word8 -- | Determine whether the event indicates creation of an object within the -- monitored path. This event is generated when any file system object is -- created. -- -- For hard links the behavior is different on different operating -- systems. On macOS hard linking does not generate a create event, it -- generates an isInodeAttrsChanged event on the directory -- instead (see the Darwin module). On Linux and Windows hard linking -- generates a create event. -- -- Pre-release isCreated :: Event -> Bool -- | Determine whether the event indicates deletion of an object within the -- monitored path. On Linux and Windows hard link deletion generates a -- delete event. -- -- On Linux and Windows, this event does not occur when the watch root -- itself is deleted. On macOS it occurs on deleting the watch root when -- it is not a symbolic link. -- -- See also isRootDeleted event for Linux. -- -- Pre-release isDeleted :: Event -> Bool -- | Determine whether the event indicates rename of an object within the -- monitored path. This event is generated when an object is renamed -- within the watched directory or if it is moved out of or in the -- watched directory. Moving hard links is no different than other types -- of objects. -- -- Pre-release isMoved :: Event -> Bool -- | Determine whether the event indicates modification of an object within -- the monitored path. This event is generated on file modification on -- all platforms. -- -- On Linux and macOS this event is never generated for directories. On -- Windows (in recursive watch mode) this event is generated for -- directories as well when an object is created in or deleted from the -- directory. -- -- Pre-release isModified :: Event -> Bool -- | An event that indicates that some events before this may have been -- lost, therefore, we need to take some recovery action. -- -- Pre-release isEventsLost :: Event -> Bool -- | Convert an Event record to a String representation. Note that -- the output of this function may be different on different platforms -- because it may contain platform specific details. -- -- Internal showEvent :: Event -> String module Streamly.Internal.Network.Socket -- | Specify the socket protocol details. data SockSpec SockSpec :: !Family -> !SocketType -> !ProtocolNumber -> ![(SocketOption, Int)] -> SockSpec [sockFamily] :: SockSpec -> !Family [sockType] :: SockSpec -> !SocketType [sockProto] :: SockSpec -> !ProtocolNumber [sockOpts] :: SockSpec -> ![(SocketOption, Int)] -- | forSocketM action socket runs the monadic computation -- action passing the socket handle to it. The handle will be -- closed on exit from forSocketM, whether by normal termination -- or by raising an exception. If closing the handle raises an exception, -- then this exception will be raised by forSocketM rather than -- any exception raised by action. forSocketM :: (MonadMask m, MonadIO m) => (Socket -> m ()) -> Socket -> m () -- | Like forSocketM but runs a streaming computation instead of a -- monadic computation. -- -- Inhibits stream fusion -- -- Internal withSocket :: (MonadIO m, MonadCatch m) => Socket -> (Socket -> Stream m a) -> Stream m a -- | Start a TCP stream server that listens for connections on the supplied -- server address specification (address family, local interface IP -- address and port). The server generates a stream of connected sockets. -- The first argument is the maximum number of pending connections in the -- backlog. -- -- Pre-release accept :: MonadIO m => Int -> SockSpec -> SockAddr -> Stream m Socket -- | Unfold a three tuple (listenQLen, spec, addr) into a stream -- of connected protocol sockets corresponding to incoming connections. -- listenQLen is the maximum number of pending connections in -- the backlog. spec is the socket protocol and options -- specification and addr is the protocol address where the -- server listens for incoming connections. acceptor :: MonadIO m => Unfold m (Int, SockSpec, SockAddr) Socket -- | Connect to a remote host using the given socket specification and -- remote address. Returns a connected socket or throws an exception. -- -- Pre-release connect :: SockSpec -> SockAddr -> IO Socket -- | Connect to a remote host using the given socket specification, a local -- address to bind to and a remote address to connect to. Returns a -- connected socket or throws an exception. -- -- Pre-release connectFrom :: SockSpec -> SockAddr -> SockAddr -> IO Socket -- | Read a byte array from a file handle up to a maximum of the requested -- size. If no data is available on the handle it blocks until some data -- becomes available. If data is available then it immediately returns -- that data without blocking. getChunk :: Int -> Socket -> IO (Array Word8) -- | Generate a byte stream from a socket. -- --
--   >>> read = Socket.readWith defaultChunkSize
--   
-- -- Pre-release read :: MonadIO m => Socket -> Stream m Word8 -- | Generate a byte stream from a socket using a buffer of the given size. -- -- Pre-release readWith :: MonadIO m => Int -> Socket -> Stream m Word8 -- | Read a stream of byte arrays from a socket. The maximum size of a -- single array is limited to defaultChunkSize. -- --
--   >>> readChunks = Socket.readChunksWith defaultChunkSize
--   
-- -- Pre-release readChunks :: MonadIO m => Socket -> Stream m (Array Word8) -- | readChunksWith bufsize socket reads a stream of arrays from -- socket. The maximum size of a single array is limited to -- bufsize. -- -- Pre-release readChunksWith :: MonadIO m => Int -> Socket -> Stream m (Array Word8) -- | Unfolds a Socket into a byte stream. IO requests to the socket -- are performed in sizes of defaultChunkSize. reader :: MonadIO m => Unfold m Socket Word8 -- | Unfolds the tuple (bufsize, socket) into a byte stream, read -- requests to the socket are performed using buffers of -- bufsize. readerWith :: MonadIO m => Unfold m (Int, Socket) Word8 -- | Unfolds a socket into a stream of Word8 arrays. Requests to the -- socket are performed using a buffer of size defaultChunkSize. -- The size of arrays in the resulting stream are therefore less than or -- equal to defaultChunkSize. chunkReader :: MonadIO m => Unfold m Socket (Array Word8) -- | Unfold the tuple (bufsize, socket) into a stream of -- Word8 arrays. Read requests to the socket are performed using a -- buffer of size bufsize. The size of an array in the resulting -- stream is always less than or equal to bufsize. chunkReaderWith :: MonadIO m => Unfold m (Int, Socket) (Array Word8) -- | Write an Array to a socket. putChunk :: Unbox a => Socket -> Array a -> IO () -- | Write a byte stream to a socket. Accumulates the input in chunks of up -- to defaultChunkSize bytes before writing. -- --
--   >>> write = Socket.writeWith defaultChunkSize
--   
write :: MonadIO m => Socket -> Fold m Word8 () -- | Write a byte stream to a socket. Accumulates the input in chunks of -- specified number of bytes before writing. writeWith :: MonadIO m => Int -> Socket -> Fold m Word8 () -- | Write a stream of arrays to a socket. Each array in the stream is -- written to the socket as a separate IO request. writeChunks :: (MonadIO m, Unbox a) => Socket -> Fold m (Array a) () -- | writeChunksWith bufsize socket writes a stream of arrays to -- socket after coalescing the adjacent arrays in chunks of -- bufsize. Multiple arrays are coalesed as long as the total -- size remains below the specified size. It never splits an array, if a -- single array is bigger than the specified size it emitted as it is. writeChunksWith :: (MonadIO m, Unbox a) => Int -> Socket -> Fold m (Array a) () -- | Write a stream of Maybe values. Keep buffering the Just -- values in an array. Write the array to the Handle as soon as -- a Nothing is encountered or the buffer size exceeds the -- specified limit. -- -- Pre-release writeMaybesWith :: MonadIO m => Int -> Socket -> Fold m (Maybe Word8) () -- | Write a stream of arrays to a handle. putChunks :: (MonadIO m, Unbox a) => Socket -> Stream m (Array a) -> m () -- | Like write but provides control over the write buffer. Output -- will be written to the IO device as soon as we collect the specified -- number of input elements. putBytesWith :: MonadIO m => Int -> Socket -> Stream m Word8 -> m () -- | Write a byte stream to a file handle. Combines the bytes in chunks of -- size up to defaultChunkSize before writing. Note that the write -- behavior depends on the IOMode and the current seek position -- of the handle. putBytes :: MonadIO m => Socket -> Stream m Word8 -> m () -- | Same as readWith -- | Deprecated: Please use readerWith instead readWithBufferOf :: MonadIO m => Unfold m (Int, Socket) Word8 -- | Same as chunkReaderWith -- | Deprecated: Please use chunkReaderWith instead readChunksWithBufferOf :: MonadIO m => Unfold m (Int, Socket) (Array Word8) -- | Same as writeWith -- | Deprecated: Please use writeWith instead writeWithBufferOf :: MonadIO m => Int -> Socket -> Fold m Word8 () -- | Same as writeChunksWith -- | Deprecated: Please use writeChunksWith instead writeChunksWithBufferOf :: (MonadIO m, Unbox a) => Int -> Socket -> Fold m (Array a) () -- | Combinators to build Inet/TCP clients and servers. module Streamly.Internal.Network.Inet.TCP -- | Start a TCP stream server that binds on the IPV4 address -- 0.0.0.0 and listens for TCP connections from remote hosts on -- the specified server port. The server generates a stream of connected -- sockets. -- --
--   >>> accept = TCP.acceptOnAddr (0,0,0,0)
--   
-- -- Pre-release accept :: MonadIO m => PortNumber -> Stream m Socket -- | Like accept but binds on the localhost IPv4 address -- 127.0.0.1. The server can only be accessed from the local -- host, it cannot be accessed from other hosts on the network. -- --
--   >>> acceptLocal = TCP.acceptOnAddr (127,0,0,1)
--   
-- -- Pre-release acceptLocal :: MonadIO m => PortNumber -> Stream m Socket -- | Like accept but binds on the specified IPv4 address. -- --
--   >>> acceptOnAddr = TCP.acceptOnAddrWith []
--   
-- -- Pre-release acceptOnAddr :: MonadIO m => (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Socket -- | Like acceptOnAddr but with the ability to specify a list of -- socket options. -- -- Pre-release acceptOnAddrWith :: MonadIO m => [(SocketOption, Int)] -> (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Socket -- | Like acceptorOnAddr but binds on the IPv4 address -- 0.0.0.0 i.e. on all IPv4 addresses/interfaces of the machine -- and listens for TCP connections on the specified port. -- --
--   >>> acceptor = Unfold.first (0,0,0,0) TCP.acceptorOnAddr
--   
acceptor :: MonadIO m => Unfold m PortNumber Socket -- | Like acceptor but binds on the localhost IPv4 address -- 127.0.0.1. The server can only be accessed from the local -- host, it cannot be accessed from other hosts on the network. -- --
--   >>> acceptorLocal = Unfold.first (127,0,0,1) TCP.acceptorOnAddr
--   
acceptorLocal :: MonadIO m => Unfold m PortNumber Socket acceptorWith :: MonadIO m => [(SocketOption, Int)] -> Unfold m PortNumber Socket -- | Unfold a tuple (ipAddr, port) into a stream of connected TCP -- sockets. ipAddr is the local IP address and port is -- the local port on which connections are accepted. acceptorOnAddr :: MonadIO m => Unfold m ((Word8, Word8, Word8, Word8), PortNumber) Socket acceptorOnAddrWith :: MonadIO m => [(SocketOption, Int)] -> Unfold m ((Word8, Word8, Word8, Word8), PortNumber) Socket -- | Connect to the specified IP address and port number. Returns a -- connected socket or throws an exception. connect :: (Word8, Word8, Word8, Word8) -> PortNumber -> IO Socket -- | Connect to a remote host using IP address and port and run the -- supplied action on the resulting socket. withConnectionM makes -- sure that the socket is closed on normal termination or in case of an -- exception. If closing the socket raises an exception, then this -- exception will be raised by withConnectionM. -- -- Pre-release withConnectionM :: (MonadMask m, MonadIO m) => (Word8, Word8, Word8, Word8) -> PortNumber -> (Socket -> m ()) -> m () -- | Transform an Unfold from a Socket to an unfold from a -- remote IP address and port. The resulting unfold opens a socket, uses -- it using the supplied unfold and then makes sure that the socket is -- closed on normal termination or in case of an exception. If closing -- the socket raises an exception, then this exception will be raised by -- usingConnection. -- -- Pre-release usingConnection :: (MonadCatch m, MonadAsync m) => Unfold m Socket a -> Unfold m ((Word8, Word8, Word8, Word8), PortNumber) a -- | Read a stream from the supplied IPv4 host address and port number. reader :: (MonadCatch m, MonadAsync m) => Unfold m ((Word8, Word8, Word8, Word8), PortNumber) Word8 -- | withConnection addr port act opens a connection to the -- specified IPv4 host address and port and passes the resulting socket -- handle to the computation act. The handle will be closed on -- exit from withConnection, whether by normal termination or by -- raising an exception. If closing the handle raises an exception, then -- this exception will be raised by withConnection rather than any -- exception raised by act. -- -- Pre-release withConnection :: (MonadCatch m, MonadAsync m) => (Word8, Word8, Word8, Word8) -> PortNumber -> (Socket -> Stream m a) -> Stream m a -- | Read a stream from the supplied IPv4 host address and port number. -- -- Pre-release read :: (MonadCatch m, MonadAsync m) => (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Word8 -- | Write a stream to the supplied IPv4 host address and port number. write :: (MonadIO m, MonadCatch m) => (Word8, Word8, Word8, Word8) -> PortNumber -> Fold m Word8 () -- | Like write but provides control over the write buffer. Output -- will be written to the IO device as soon as we collect the specified -- number of input elements. writeWithBufferOf :: (MonadIO m, MonadCatch m) => Int -> (Word8, Word8, Word8, Word8) -> PortNumber -> Fold m Word8 () -- | Write a stream to the supplied IPv4 host address and port number. -- -- Pre-release putBytes :: (MonadCatch m, MonadAsync m) => (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Word8 -> m () -- | Like write but provides control over the write buffer. Output -- will be written to the IO device as soon as we collect the specified -- number of input elements. -- -- Pre-release putBytesWithBufferOf :: (MonadCatch m, MonadAsync m) => Int -> (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Word8 -> m () -- | Write a stream of arrays to the supplied IPv4 host address and port -- number. writeChunks :: (MonadIO m, MonadCatch m) => (Word8, Word8, Word8, Word8) -> PortNumber -> Fold m (Array Word8) () -- | Write a stream of arrays to the supplied IPv4 host address and port -- number. -- -- Pre-release putChunks :: (MonadCatch m, MonadAsync m) => (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m (Array Word8) -> m () -- | Send an input stream to a remote host and produce the output stream -- from the host. The server host just acts as a transformation function -- on the input stream. Both sending and receiving happen asynchronously. -- -- Pre-release pipeBytes :: (MonadAsync m, MonadCatch m) => (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Word8 -> Stream m Word8 -- | Deprecated: Use "acceptor" instead. acceptorOnPort :: MonadIO m => Unfold m PortNumber Socket -- | Deprecated: Use "acceptorLocal" instead. acceptorOnPortLocal :: MonadIO m => Unfold m PortNumber Socket module Streamly.Internal.Unicode.Char -- | Select alphabetic characters in the ascii character set. -- -- Pre-release isAsciiAlpha :: Char -> Bool data NormalizationMode -- | Canonical decomposition. NFD :: NormalizationMode -- | Compatibility decomposition. NFKD :: NormalizationMode -- | Canonical decomposition followed by canonical composition. NFC :: NormalizationMode -- | Compatibility decomposition followed by canonical composition. NFKC :: NormalizationMode normalize :: Monad m => NormalizationMode -> Stream m Char -> Stream m Char instance GHC.Enum.Enum Streamly.Internal.Unicode.Char.NormalizationMode instance GHC.Show.Show Streamly.Internal.Unicode.Char.NormalizationMode instance GHC.Classes.Eq Streamly.Internal.Unicode.Char.NormalizationMode module Streamly.Internal.Unicode.Utf8 -- | A space efficient, packed, unboxed Unicode container. data Utf8 pack :: String -> Utf8 unpack :: Utf8 -> String toArray :: Utf8 -> Array Word8 -- | Combinators to build Inet/IPv4/TCP clients and servers. -- --
--   >>> import qualified Streamly.Network.Inet.TCP as TCP
--   
-- --

Examples

-- -- Following is a short example of a concurrent echo server. -- --
--   >>> import Control.Monad.Catch (finally)
--   
--   >>> import Data.Function ((&))
--   
--   >>> import Network.Socket (Socket)
--   
--   >>> 
--   
--   >>> import qualified Network.Socket as Net
--   
--   >>> import qualified Streamly.Data.Fold as Fold
--   
--   >>> import qualified Streamly.Data.Stream.Prelude as Stream
--   
--   >>> import qualified Streamly.Network.Inet.TCP as TCP
--   
--   >>> import qualified Streamly.Network.Socket as Socket
--   
--   >>> 
--   
--   >>> :{
--   main :: IO ()
--   main =
--         TCP.accept 8091                            -- Stream IO Socket
--       & Stream.parMapM id (handleExceptions echo)  -- Stream IO ()
--       & Stream.fold Fold.drain                     -- IO ()
--       where
--       echo :: Socket -> IO ()
--       echo sk =
--             Socket.readChunksWith 32768 sk      -- Stream IO (Array Word8)
--           & Stream.fold (Socket.writeChunks sk) -- IO ()
--       handleExceptions :: (Socket -> IO ()) -> Socket -> IO ()
--       handleExceptions f sk = finally (f sk) (Net.close sk)
--   :}
--   
module Streamly.Network.Inet.TCP -- | Start a TCP stream server that binds on the IPV4 address -- 0.0.0.0 and listens for TCP connections from remote hosts on -- the specified server port. The server generates a stream of connected -- sockets. -- --
--   >>> accept = TCP.acceptOnAddr (0,0,0,0)
--   
-- -- Pre-release accept :: MonadIO m => PortNumber -> Stream m Socket -- | Like accept but binds on the localhost IPv4 address -- 127.0.0.1. The server can only be accessed from the local -- host, it cannot be accessed from other hosts on the network. -- --
--   >>> acceptLocal = TCP.acceptOnAddr (127,0,0,1)
--   
-- -- Pre-release acceptLocal :: MonadIO m => PortNumber -> Stream m Socket -- | Like accept but binds on the specified IPv4 address. -- --
--   >>> acceptOnAddr = TCP.acceptOnAddrWith []
--   
-- -- Pre-release acceptOnAddr :: MonadIO m => (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Socket -- | Like acceptOnAddr but with the ability to specify a list of -- socket options. -- -- Pre-release acceptOnAddrWith :: MonadIO m => [(SocketOption, Int)] -> (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Socket -- | Like acceptorOnAddr but binds on the IPv4 address -- 0.0.0.0 i.e. on all IPv4 addresses/interfaces of the machine -- and listens for TCP connections on the specified port. -- --
--   >>> acceptor = Unfold.first (0,0,0,0) TCP.acceptorOnAddr
--   
acceptor :: MonadIO m => Unfold m PortNumber Socket -- | Like acceptor but binds on the localhost IPv4 address -- 127.0.0.1. The server can only be accessed from the local -- host, it cannot be accessed from other hosts on the network. -- --
--   >>> acceptorLocal = Unfold.first (127,0,0,1) TCP.acceptorOnAddr
--   
acceptorLocal :: MonadIO m => Unfold m PortNumber Socket -- | Unfold a tuple (ipAddr, port) into a stream of connected TCP -- sockets. ipAddr is the local IP address and port is -- the local port on which connections are accepted. acceptorOnAddr :: MonadIO m => Unfold m ((Word8, Word8, Word8, Word8), PortNumber) Socket -- | Connect to the specified IP address and port number. Returns a -- connected socket or throws an exception. connect :: (Word8, Word8, Word8, Word8) -> PortNumber -> IO Socket -- | Deprecated: Use "acceptor" instead. acceptorOnPort :: MonadIO m => Unfold m PortNumber Socket -- | Deprecated: Use "acceptorLocal" instead. acceptorOnPortLocal :: MonadIO m => Unfold m PortNumber Socket -- | This module provides socket based streaming APIs to to receive -- connections from remote hosts, and to read and write from and to -- network sockets. -- -- For basic socket types and non-streaming operations please consult the -- Network.Socket module of the network package. -- --

Examples

-- -- To write a server, use the accept stream to start listening for -- connections from clients. accept generates a stream of -- connected sockets. We can map an effectful action on this socket -- stream to handle the connections. The action would typically use -- socket reading and writing operations to communicate with the remote -- host. We can read/write a stream of bytes or a stream of chunks of -- bytes (Array). -- -- Following is a short example of a concurrent echo server. Please note -- that this example can be written even more succinctly by using higher -- level operations from Streamly.Network.Inet.TCP module. -- --
--   >>> :set -XFlexibleContexts
--   
--   >>> 
--   
--   >>> import Data.Function ((&))
--   
--   >>> import Network.Socket
--   
--   >>> import Streamly.Network.Socket (SockSpec(..))
--   
--   >>> 
--   
--   >>> import qualified Streamly.Data.Fold as Fold
--   
--   >>> import qualified Streamly.Data.Stream.Prelude as Stream
--   
--   >>> import qualified Streamly.Network.Socket as Socket
--   
--   >>> 
--   
--   >>> :{
--    main :: IO ()
--    main = do
--         let spec = SockSpec
--                    { sockFamily = AF_INET
--                    , sockType   = Stream
--                    , sockProto  = defaultProtocol
--                    , sockOpts   = []
--                    }
--             addr = SockAddrInet 8090 (tupleToHostAddress (0,0,0,0))
--          in server spec addr
--         where
--         server spec addr =
--               Socket.accept maxListenQueue spec addr
--             & Stream.parMapM (Stream.eager True) (Socket.forSocketM echo)
--             & Stream.fold Fold.drain
--         echo sk =
--               Socket.readChunks sk -- Stream IO (Array Word8)
--             & Stream.fold (Socket.writeChunks sk) -- IO ()
--   :}
--   
-- --

Programmer Notes

-- -- Read IO requests to connected stream sockets are performed in chunks -- of defaultChunkSize. Unless specified otherwise in the API, -- writes are collected into chunks of defaultChunkSize before -- they are written to the socket. -- --
--   >>> import qualified Streamly.Network.Socket as Socket
--   
-- --

See Also

-- -- module Streamly.Network.Socket -- | Specify the socket protocol details. data SockSpec SockSpec :: !Family -> !SocketType -> !ProtocolNumber -> ![(SocketOption, Int)] -> SockSpec [sockFamily] :: SockSpec -> !Family [sockType] :: SockSpec -> !SocketType [sockProto] :: SockSpec -> !ProtocolNumber [sockOpts] :: SockSpec -> ![(SocketOption, Int)] -- | Start a TCP stream server that listens for connections on the supplied -- server address specification (address family, local interface IP -- address and port). The server generates a stream of connected sockets. -- The first argument is the maximum number of pending connections in the -- backlog. -- -- Pre-release accept :: MonadIO m => Int -> SockSpec -> SockAddr -> Stream m Socket -- | Unfold a three tuple (listenQLen, spec, addr) into a stream -- of connected protocol sockets corresponding to incoming connections. -- listenQLen is the maximum number of pending connections in -- the backlog. spec is the socket protocol and options -- specification and addr is the protocol address where the -- server listens for incoming connections. acceptor :: MonadIO m => Unfold m (Int, SockSpec, SockAddr) Socket -- | Read a byte array from a file handle up to a maximum of the requested -- size. If no data is available on the handle it blocks until some data -- becomes available. If data is available then it immediately returns -- that data without blocking. getChunk :: Int -> Socket -> IO (Array Word8) -- | Generate a byte stream from a socket. -- --
--   >>> read = Socket.readWith defaultChunkSize
--   
-- -- Pre-release read :: MonadIO m => Socket -> Stream m Word8 -- | Generate a byte stream from a socket using a buffer of the given size. -- -- Pre-release readWith :: MonadIO m => Int -> Socket -> Stream m Word8 -- | Read a stream of byte arrays from a socket. The maximum size of a -- single array is limited to defaultChunkSize. -- --
--   >>> readChunks = Socket.readChunksWith defaultChunkSize
--   
-- -- Pre-release readChunks :: MonadIO m => Socket -> Stream m (Array Word8) -- | readChunksWith bufsize socket reads a stream of arrays from -- socket. The maximum size of a single array is limited to -- bufsize. -- -- Pre-release readChunksWith :: MonadIO m => Int -> Socket -> Stream m (Array Word8) -- | Unfolds a Socket into a byte stream. IO requests to the socket -- are performed in sizes of defaultChunkSize. reader :: MonadIO m => Unfold m Socket Word8 -- | Unfolds the tuple (bufsize, socket) into a byte stream, read -- requests to the socket are performed using buffers of -- bufsize. readerWith :: MonadIO m => Unfold m (Int, Socket) Word8 -- | Unfolds a socket into a stream of Word8 arrays. Requests to the -- socket are performed using a buffer of size defaultChunkSize. -- The size of arrays in the resulting stream are therefore less than or -- equal to defaultChunkSize. chunkReader :: MonadIO m => Unfold m Socket (Array Word8) -- | Unfold the tuple (bufsize, socket) into a stream of -- Word8 arrays. Read requests to the socket are performed using a -- buffer of size bufsize. The size of an array in the resulting -- stream is always less than or equal to bufsize. chunkReaderWith :: MonadIO m => Unfold m (Int, Socket) (Array Word8) -- | Write an Array to a socket. putChunk :: Unbox a => Socket -> Array a -> IO () -- | Write a byte stream to a socket. Accumulates the input in chunks of up -- to defaultChunkSize bytes before writing. -- --
--   >>> write = Socket.writeWith defaultChunkSize
--   
write :: MonadIO m => Socket -> Fold m Word8 () -- | Write a byte stream to a socket. Accumulates the input in chunks of -- specified number of bytes before writing. writeWith :: MonadIO m => Int -> Socket -> Fold m Word8 () -- | Write a stream of arrays to a socket. Each array in the stream is -- written to the socket as a separate IO request. writeChunks :: (MonadIO m, Unbox a) => Socket -> Fold m (Array a) () -- | writeChunksWith bufsize socket writes a stream of arrays to -- socket after coalescing the adjacent arrays in chunks of -- bufsize. Multiple arrays are coalesed as long as the total -- size remains below the specified size. It never splits an array, if a -- single array is bigger than the specified size it emitted as it is. writeChunksWith :: (MonadIO m, Unbox a) => Int -> Socket -> Fold m (Array a) () -- | forSocketM action socket runs the monadic computation -- action passing the socket handle to it. The handle will be -- closed on exit from forSocketM, whether by normal termination -- or by raising an exception. If closing the handle raises an exception, -- then this exception will be raised by forSocketM rather than -- any exception raised by action. forSocketM :: (MonadMask m, MonadIO m) => (Socket -> m ()) -> Socket -> m () -- | Deprecated: Please use getChunk instead readChunk :: Int -> Socket -> IO (Array Word8) -- | Deprecated: Please use putChunk instead writeChunk :: Unbox a => Socket -> Array a -> IO () -- | Same as readWith -- | Deprecated: Please use readerWith instead readWithBufferOf :: MonadIO m => Unfold m (Int, Socket) Word8 -- | Same as chunkReaderWith -- | Deprecated: Please use chunkReaderWith instead readChunksWithBufferOf :: MonadIO m => Unfold m (Int, Socket) (Array Word8) -- | Same as writeWith -- | Deprecated: Please use writeWith instead writeWithBufferOf :: MonadIO m => Int -> Socket -> Fold m Word8 () -- | Same as writeChunksWith -- | Deprecated: Please use writeChunksWith instead writeChunksWithBufferOf :: (MonadIO m, Unbox a) => Int -> Socket -> Fold m (Array a) () -- | To run examples in this module: -- --
--   >>> import qualified Streamly.Data.Fold as Fold
--   
--   >>> import qualified Streamly.Prelude as Stream
--   
-- -- We will add some more imports in the examples as needed. -- -- For effectful streams we will use the following IO action that blocks -- for n seconds: -- --
--   >>> import Control.Concurrent (threadDelay)
--   
--   >>> :{
--    delay n = do
--        threadDelay (n * 1000000)   -- sleep for n seconds
--        putStrLn (show n ++ " sec") -- print "n sec"
--        return n                    -- IO Int
--   :}
--   
-- --
--   >>> delay 1
--   1 sec
--   1
--   
-- --

Overview

-- -- Streamly is a framework for modular data flow based programming and -- declarative concurrency. Powerful stream fusion framework in streamly -- allows high performance combinatorial programming even when using byte -- level streams. Streamly API is similar to Haskell lists. -- -- The basic stream type is SerialT. The type SerialT IO -- a is an effectful equivalent of a list [a] using the IO -- monad. Streams can be constructed like lists, except that they use -- nil instead of '[]' and cons instead of :. -- -- cons constructs a pure stream which is more or less the same as -- a list: -- --
--   >>> import Streamly.Prelude (SerialT, cons, consM, nil)
--   
--   >>> stream = 1 `cons` 2 `cons` nil :: SerialT IO Int
--   
--   >>> Stream.toList stream -- IO [Int]
--   [1,2]
--   
-- -- consM constructs a stream from effectful actions: -- --
--   >>> stream = delay 1 `consM` delay 2 `consM` nil
--   
--   >>> Stream.toList stream
--   1 sec
--   2 sec
--   [1,2]
--   
-- --

Console Echo Program

-- -- In the following example, repeatM generates an infinite stream -- of String by repeatedly performing the getLine IO -- action. mapM then applies putStrLn on each element in -- the stream converting it to stream of (). Finally, -- drain folds the stream to IO discarding the () values, thus -- producing only effects. -- --
--   >>> import Data.Function ((&))
--   
-- --
--   > :{
--    Stream.repeatM getLine      -- SerialT IO String
--        & Stream.mapM putStrLn  -- SerialT IO ()
--        & Stream.drain          -- IO ()
--   :}
--   
-- -- This is a console echo program. It is an example of a declarative loop -- written using streaming combinators. Compare it with an imperative -- while loop. -- -- Hopefully, this gives you an idea how we can program declaratively by -- representing loops using streams. In this module, you can find all -- Data.List like functions and many more powerful combinators to -- perform common programming tasks. Also see -- Streamly.Internal.Data.Stream.IsStream module for many more -- Pre-release combinators. See the -- https://github.com/composewell/streamly-examples repository for -- many more real world examples of stream programming. -- --

Polymorphic Combinators

-- -- Streamly has several stream types, SerialT is one type of -- stream with serial execution of actions, AsyncT is another with -- concurrent execution. The combinators in this module are polymorphic -- in stream type. For example, -- --
--   repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
--   
-- -- t is the stream type, m is the underlying -- Monad of the stream (e.g. IO) and a is the type of -- elements in the stream (e.g. Int). -- -- Stream elimination combinators accept a SerialT type instead of -- a polymorphic type to force a concrete monomorphic type by default, -- reducing type errors. That's why in the console echo example above the -- stream type is SerialT. -- --
--   drain :: Monad m => SerialT m a -> m ()
--   
-- -- We can force a certain stream type in polymorphic code by using -- "Stream Type Adaptors". For example, to force AsyncT: -- --
--   >>> Stream.drain $ Stream.fromAsync $ Stream.replicateM 10 $ delay 1
--   ...
--   
-- --

Combining two streams

-- -- Two streams can be combined to form a single stream in various -- interesting ways. serial (append), wSerial (interleave), -- ahead (concurrent, ordered append), async (lazy -- concurrent, unordered append) , wAsync (lazy concurrent, -- unordered interleave), parallel (strict concurrent merge), -- zipWith, zipAsyncWith (concurrent zip), mergeBy, -- mergeAsyncBy (concurrent merge) are some ways of combining two -- streams. -- -- For example, the parallel combinator schedules both the streams -- concurrently. -- --
--   >>> stream1 = Stream.fromListM [delay 3, delay 4]
--   
--   >>> stream2 = Stream.fromListM [delay 1, delay 2]
--   
--   >>> Stream.toList $ stream1 `parallel` stream2
--   ...
--   
-- -- We can chain the operations to combine more than two streams: -- --
--   >>> stream3 = Stream.fromListM [delay 1, delay 2]
--   
--   >>> Stream.toList $ stream1 `parallel` stream2 `parallel` stream3
--   ...
--   
-- -- Concurrent generation (consM) and concurrent merging of streams -- is the fundamental basis of all concurrency in streamly. -- --

Combining many streams

-- -- The concatMapWith combinator can be used to generalize the two -- stream combining combinators to n streams. For example, we -- can use concatMapWith parallel to read concurrently from all -- incoming network connections and combine the input streams into a -- single output stream: -- --
--   import qualified Streamly.Network.Inet.TCP as TCP
--   import qualified Streamly.Network.Socket as Socket
--   
--   Stream.unfold TCP.acceptOnPort 8090
--    & Stream.concatMapWith Stream.parallel (Stream.unfold Socket.read)
--   
-- -- See the streamly-examples repository for a full working -- example. -- --

Concurrent Nested Loops

-- -- The Monad instance of SerialT is an example of nested looping. -- It is in fact a list transformer. Different stream types provide -- different variants of nested looping. For example, the Monad -- instance of ParallelT uses concatMapWith parallel as -- its bind operation. Therefore, each iteration of the loop for -- ParallelT stream can run concurrently. See the documentation -- for individual stream types for the specific execution behavior of the -- stream as well as the behavior of Semigroup and Monad -- instances. -- --

Stream Types

-- -- Streamly has several stream types. These types differ in three -- fundamental operations, consM (IsStream instance), -- <> (Semigroup instance) and >>= -- (Monad instance). Below we will see how consM behaves -- for SerialT, AsyncT and AheadT stream types. -- -- SerialT executes actions serially, so the total delay in the -- following example is 2 + 1 = 3 seconds: -- --
--   >>> stream = delay 2 `consM` delay 1 `consM` nil
--   
--   >>> Stream.toList stream -- IO [Int]
--   2 sec
--   1 sec
--   [2,1]
--   
-- -- AsyncT executes the actions concurrently, so the total delay is -- max 2 1 = 2 seconds: -- --
--   >>> Stream.toList $ Stream.fromAsync stream -- IO [Int]
--   1 sec
--   2 sec
--   [1,2]
--   
-- -- AsyncT produces the results in the order in which execution -- finishes. Notice the order of elements in the list above, it is not -- the same as the order of actions in the stream. -- -- AheadT is similar to AsyncT but the order of results is -- the same as the order of actions, even though they execute -- concurrently: -- --
--   >>> Stream.toList $ Stream.fromAhead stream -- IO [Int]
--   1 sec
--   2 sec
--   [2,1]
--   
-- --

Semigroup Instance

-- -- Earlier we distinguished stream types based on the execution behavior -- of actions within a stream. Stream types are also distinguished based -- on how actions from different streams are scheduled for execution when -- two streams are combined together. -- -- For example, both SerialT and WSerialT execute actions -- within the stream serially, however, they differ in how actions from -- individual streams are executed when two streams are combined with -- <> (the Semigroup instance). -- -- For SerialT, <> has an appending behavior i.e. it -- executes the actions from the second stream after executing actions -- from the first stream: -- --
--   >>> stream1 = Stream.fromListM [delay 1, delay 2]
--   
--   >>> stream2 = Stream.fromListM [delay 3, delay 4]
--   
--   >>> Stream.toList $ stream1 <> stream2
--   1 sec
--   2 sec
--   3 sec
--   4 sec
--   [1,2,3,4]
--   
-- -- For WSerialT, <> has an interleaving behavior i.e. -- it executes one action from the first stream and then one action from -- the second stream and so on: -- --
--   >>> Stream.toList $ Stream.fromWSerial $ stream1 <> stream2
--   1 sec
--   3 sec
--   2 sec
--   4 sec
--   [1,3,2,4]
--   
-- -- The <> operation of SerialT and WSerialT is -- the same as serial and wSerial respectively. The -- serial combinator combines two streams of any type in the same -- way as a serial stream combines. -- --

Concurrent Combinators

-- -- Like consM, there are several other stream generation -- operations whose execution behavior depends on the stream type, they -- all follow behavior similar to consM. -- -- By default, folds like drain force the stream type to be -- SerialT, so replicateM in the following code runs -- serially, and takes 10 seconds: -- --
--   >>> Stream.drain $ Stream.replicateM 10 $ delay 1
--   ...
--   
-- -- We can use the fromAsync combinator to force the argument -- stream to be of AsyncT type, replicateM in the following -- example executes the replicated actions concurrently, thus taking only -- 1 second: -- --
--   >>> Stream.drain $ Stream.fromAsync $ Stream.replicateM 10 $ delay 1
--   ...
--   
-- -- We can use mapM to map an action concurrently: -- --
--   >>> f x = delay 1 >> return (x + 1)
--   
--   >>> Stream.toList $ Stream.fromAhead $ Stream.mapM f $ Stream.fromList [1..3]
--   ...
--   [2,3,4]
--   
-- -- fromAhead forces mapM to happen in AheadT style, thus -- all three actions take only one second even though each individual -- action blocks for a second. -- -- See the documentation of individual combinators to check if it is -- concurrent or not. The concurrent combinators necessarily have a -- MonadAsync m constraint. However, a MonadAsync m -- constraint does not necessarily mean that the combinator is -- concurrent. -- --

Automatic Concurrency Control

-- -- SerialT (and WSerialT) runs all tasks serially whereas -- ParallelT runs all tasks concurrently i.e. one thread per task. -- The stream types AsyncT, WAsyncT, and AheadT -- provide demand driven concurrency. It means that based on the rate at -- which the consumer is consuming the stream, it maintains the optimal -- number of threads to increase or decrease parallelism. -- -- However, the programmer can control the maximum number of threads -- using maxThreads. It provides an upper bound on the concurrent -- IO requests or CPU cores that can be used. maxBuffer limits the -- number of evaluated stream elements that we can buffer. See the -- "Concurrency Control" section for details. -- --

Caveats

-- -- When we use combinators like fromAsync on a piece of code, all -- combinators inside the argument of fromAsync become concurrent which -- is often counter productive. Therefore, we recommend that in a -- pipeline, you identify the combinators that you really want to be -- concurrent and add a fromSerial after those combinators so that -- the code following the combinator remains serial: -- --
--   Stream.fromAsync $ ... concurrent combinator here ... $ Stream.fromSerial $ ...
--   
-- --

Conventions

-- -- Functions with the suffix M are general functions that work -- on monadic arguments. The corresponding functions without the suffix -- M work on pure arguments and can in general be derived from -- their monadic versions but are provided for convenience and for -- consistency with other pure APIs in the base package. -- -- In many cases, short definitions of the combinators are provided in -- the documentation for illustration. The actual implementation may -- differ for performance reasons. -- | Deprecated: Please use Streamly.Data.Stream.Prelude from -- streamly package and Streamly.Data.Fold from streamly-core -- package instead. module Streamly.Prelude nil :: IsStream t => t m a -- | Construct a stream by adding a pure value at the head of an existing -- stream. For serial streams this is the same as (return a) `consM` -- r but more efficient. For concurrent streams this is not -- concurrent whereas consM is concurrent. For example: -- --
--   > toList $ 1 `cons` 2 `cons` 3 `cons` nil
--   [1,2,3]
--   
cons :: IsStream t => a -> t m a -> t m a infixr 5 `cons` -- | Operator equivalent of cons. -- --
--   > toList $ 1 .: 2 .: 3 .: nil
--   [1,2,3]
--   
(.:) :: IsStream t => a -> t m a -> t m a infixr 5 .: -- | Constructs a stream by adding a monadic action at the head of an -- existing stream. For example: -- --
--   > toList $ getLine `consM` getLine `consM` nil
--   hello
--   world
--   ["hello","world"]
--   
-- -- Concurrent (do not use fromParallel to construct infinite -- streams) consM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a infixr 5 `consM` -- | Operator equivalent of consM. We can read it as "parallel -- colon" to remember that | comes before :. -- --
--   > toList $ getLine |: getLine |: nil
--   hello
--   world
--   ["hello","world"]
--   
-- --
--   let delay = threadDelay 1000000 >> print 1
--   drain $ fromSerial  $ delay |: delay |: delay |: nil
--   drain $ fromParallel $ delay |: delay |: delay |: nil
--   
-- -- Concurrent (do not use fromParallel to construct infinite -- streams) (|:) :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a infixr 5 |: -- | Convert an Unfold into a stream by supplying it an input seed. -- --
--   >>> Stream.drain $ Stream.unfold Unfold.replicateM (3, putStrLn "hello")
--   hello
--   hello
--   hello
--   
-- -- Since: 0.7.0 unfold :: (IsStream t, Monad m) => Unfold m a b -> a -> t m b -- |
--   >>> :{
--   unfoldr step s =
--       case step s of
--           Nothing -> Stream.nil
--           Just (a, b) -> a `Stream.cons` unfoldr step b
--   :}
--   
-- -- Build a stream by unfolding a pure step function step -- starting from a seed s. The step function returns the next -- element in the stream and the next seed value. When it is done it -- returns Nothing and the stream ends. For example, -- --
--   >>> :{
--   let f b =
--           if b > 2
--           then Nothing
--           else Just (b, b + 1)
--   in Stream.toList $ Stream.unfoldr f 0
--   :}
--   [0,1,2]
--   
unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a -- | Build a stream by unfolding a monadic step function starting -- from a seed. The step function returns the next element in the stream -- and the next seed value. When it is done it returns Nothing and -- the stream ends. For example, -- --
--   >>> :{
--   let f b =
--           if b > 2
--           then return Nothing
--           else return (Just (b, b + 1))
--   in Stream.toList $ Stream.unfoldrM f 0
--   :}
--   [0,1,2]
--   
-- -- When run concurrently, the next unfold step can run concurrently with -- the processing of the output of the previous step. Note that more than -- one step cannot run concurrently as the next step depends on the -- output of the previous step. -- --
--   >>> :{
--   let f b =
--           if b > 2
--           then return Nothing
--           else threadDelay 1000000 >> return (Just (b, b + 1))
--   in Stream.toList $ Stream.delay 1 $ Stream.fromAsync $ Stream.unfoldrM f 0
--   :}
--   [0,1,2]
--   
-- -- Concurrent -- -- Since: 0.1.0 unfoldrM :: forall t m b a. (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a -- |
--   fromPure a = a `cons` nil
--   
-- -- Create a singleton stream from a pure value. -- -- The following holds in monadic streams, but not in Zip streams: -- --
--   fromPure = pure
--   fromPure = fromEffect . pure
--   
-- -- In Zip applicative streams fromPure is not the same as -- pure because in that case pure is equivalent to -- repeat instead. fromPure and pure are equally -- efficient, in other cases fromPure may be slightly more -- efficient than the other equivalent definitions. -- -- Since: 0.8.0 (Renamed yield to fromPure) fromPure :: IsStream t => a -> t m a -- |
--   fromEffect m = m `consM` nil
--   
-- -- Create a singleton stream from a monadic action. -- --
--   > Stream.toList $ Stream.fromEffect getLine
--   hello
--   ["hello"]
--   
-- -- Since: 0.8.0 (Renamed yieldM to fromEffect) fromEffect :: (Monad m, IsStream t) => m a -> t m a -- | Generate an infinite stream by repeating a pure value. repeat :: (IsStream t, Monad m) => a -> t m a -- |
--   >>> repeatM = fix . consM
--   
--   >>> repeatM = cycle1 . fromEffect
--   
-- -- Generate a stream by repeatedly executing a monadic action forever. -- --
--   >>> :{
--   repeatAsync =
--          Stream.repeatM (threadDelay 1000000 >> print 1)
--        & Stream.take 10
--        & Stream.fromAsync
--        & Stream.drain
--   :}
--   
-- -- Concurrent, infinite (do not use with fromParallel) repeatM :: (IsStream t, MonadAsync m) => m a -> t m a -- |
--   >>> replicate n = Stream.take n . Stream.repeat
--   
-- -- Generate a stream of length n by repeating a value n -- times. replicate :: (IsStream t, Monad m) => Int -> a -> t m a -- |
--   >>> replicateM n = Stream.take n . Stream.repeatM
--   
-- -- Generate a stream by performing a monadic action n times. -- Same as: -- --
--   >>> pr n = threadDelay 1000000 >> print n
--   
-- -- This runs serially and takes 3 seconds: -- --
--   >>> Stream.drain $ Stream.fromSerial $ Stream.replicateM 3 $ pr 1
--   1
--   1
--   1
--   
-- -- This runs concurrently and takes just 1 second: -- --
--   >>> Stream.drain $ Stream.fromAsync  $ Stream.replicateM 3 $ pr 1
--   1
--   1
--   1
--   
-- -- Concurrent replicateM :: forall t m a. (IsStream t, MonadAsync m) => Int -> m a -> t m a -- | Types that can be enumerated as a stream. The operations in this type -- class are equivalent to those in the Enum type class, except -- that these generate a stream instead of a list. Use the functions in -- Streamly.Internal.Data.Stream.Enumeration module to define new -- instances. class Enum a => Enumerable a -- | enumerateFrom from generates a stream starting with the -- element from, enumerating up to maxBound when the type -- is Bounded or generating an infinite stream when the type is -- not Bounded. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFrom (0 :: Int)
--   [0,1,2,3]
--   
-- -- For Fractional types, enumeration is numerically stable. -- However, no overflow or underflow checks are performed. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFrom 1.1
--   [1.1,2.1,3.1,4.1]
--   
enumerateFrom :: (Enumerable a, IsStream t, Monad m) => a -> t m a -- | Generate a finite stream starting with the element from, -- enumerating the type up to the value to. If to is -- smaller than from then an empty stream is returned. -- --
--   >>> Stream.toList $ Stream.enumerateFromTo 0 4
--   [0,1,2,3,4]
--   
-- -- For Fractional types, the last element is equal to the -- specified to value after rounding to the nearest integral -- value. -- --
--   >>> Stream.toList $ Stream.enumerateFromTo 1.1 4
--   [1.1,2.1,3.1,4.1]
--   
--   >>> Stream.toList $ Stream.enumerateFromTo 1.1 4.6
--   [1.1,2.1,3.1,4.1,5.1]
--   
enumerateFromTo :: (Enumerable a, IsStream t, Monad m) => a -> a -> t m a -- | enumerateFromThen from then generates a stream whose first -- element is from, the second element is then and the -- successive elements are in increments of then - from. -- Enumeration can occur downwards or upwards depending on whether -- then comes before or after from. For Bounded -- types the stream ends when maxBound is reached, for unbounded -- types it keeps enumerating infinitely. -- --
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 2
--   [0,2,4,6]
--   
--   >>> Stream.toList $ Stream.take 4 $ Stream.enumerateFromThen 0 (-2)
--   [0,-2,-4,-6]
--   
enumerateFromThen :: (Enumerable a, IsStream t, Monad m) => a -> a -> t m a -- | enumerateFromThenTo from then to generates a finite stream -- whose first element is from, the second element is -- then and the successive elements are in increments of -- then - from up to to. Enumeration can occur -- downwards or upwards depending on whether then comes before -- or after from. -- --
--   >>> Stream.toList $ Stream.enumerateFromThenTo 0 2 6
--   [0,2,4,6]
--   
--   >>> Stream.toList $ Stream.enumerateFromThenTo 0 (-2) (-6)
--   [0,-2,-4,-6]
--   
enumerateFromThenTo :: (Enumerable a, IsStream t, Monad m) => a -> a -> a -> t m a -- |
--   enumerate = enumerateFrom minBound
--   
-- -- Enumerate a Bounded type from its minBound to -- maxBound enumerate :: (IsStream t, Monad m, Bounded a, Enumerable a) => t m a -- |
--   enumerateTo = enumerateFromTo minBound
--   
-- -- Enumerate a Bounded type from its minBound to specified -- value. enumerateTo :: (IsStream t, Monad m, Bounded a, Enumerable a) => a -> t m a -- |
--   >>> iterate f x = x `Stream.cons` iterate f x
--   
-- -- Generate an infinite stream with x as the first element and -- each successive element derived by applying the function f on -- the previous element. -- --
--   >>> Stream.toList $ Stream.take 5 $ Stream.iterate (+1) 1
--   [1,2,3,4,5]
--   
iterate :: (IsStream t, Monad m) => (a -> a) -> a -> t m a -- |
--   >>> iterateM f m = m >>= \a -> return a `Stream.consM` iterateM f (f a)
--   
-- -- Generate an infinite stream with the first element generated by the -- action m and each successive element derived by applying the -- monadic function f on the previous element. -- --
--   >>> pr n = threadDelay 1000000 >> print n
--   
--   >>> :{
--   Stream.iterateM (\x -> pr x >> return (x + 1)) (return 0)
--       & Stream.take 3
--       & Stream.fromSerial
--       & Stream.toList
--   :}
--   0
--   1
--   [0,1,2]
--   
-- -- When run concurrently, the next iteration can run concurrently with -- the processing of the previous iteration. Note that more than one -- iteration cannot run concurrently as the next iteration depends on the -- output of the previous iteration. -- --
--   >>> :{
--   Stream.iterateM (\x -> pr x >> return (x + 1)) (return 0)
--       & Stream.delay 1
--       & Stream.take 3
--       & Stream.fromAsync
--       & Stream.toList
--   :}
--   0
--   1
--   ...
--   
-- -- Concurrent -- -- Since: 0.1.2 -- -- Since: 0.7.0 (signature change) iterateM :: forall t m a. (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a -- |
--   >>> fromIndices f = fmap f $ Stream.enumerateFrom 0
--   
--   >>> fromIndices f = let g i = f i `Stream.cons` g (i + 1) in g 0
--   
-- -- Generate an infinite stream, whose values are the output of a function -- f applied on the corresponding index. Index starts at 0. -- --
--   >>> Stream.toList $ Stream.take 5 $ Stream.fromIndices id
--   [0,1,2,3,4]
--   
fromIndices :: (IsStream t, Monad m) => (Int -> a) -> t m a -- |
--   >>> fromIndicesM f = Stream.mapM f $ Stream.enumerateFrom 0
--   
--   >>> fromIndicesM f = let g i = f i `Stream.consM` g (i + 1) in g 0
--   
-- -- Generate an infinite stream, whose values are the output of a monadic -- function f applied on the corresponding index. Index starts -- at 0. -- -- Concurrent fromIndicesM :: forall t m a. (IsStream t, MonadAsync m) => (Int -> m a) -> t m a -- |
--   fromList = foldr cons nil
--   
-- -- Construct a stream from a list of pure values. This is more efficient -- than fromFoldable for serial streams. fromList :: (Monad m, IsStream t) => [a] -> t m a -- |
--   >>> fromListM = Stream.fromFoldableM
--   
--   >>> fromListM = Stream.sequence . Stream.fromList
--   
--   >>> fromListM = Stream.mapM id . Stream.fromList
--   
--   >>> fromListM = Prelude.foldr Stream.consM Stream.nil
--   
-- -- Construct a stream from a list of monadic actions. This is more -- efficient than fromFoldableM for serial streams. fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a -- |
--   >>> fromFoldable = Prelude.foldr Stream.cons Stream.nil
--   
-- -- Construct a stream from a Foldable containing pure values: fromFoldable :: (IsStream t, Foldable f) => f a -> t m a -- |
--   >>> fromFoldableM = Prelude.foldr Stream.consM Stream.nil
--   
-- -- Construct a stream from a Foldable containing monadic actions. -- --
--   >>> pr n = threadDelay 1000000 >> print n
--   
--   >>> Stream.drain $ Stream.fromSerial $ Stream.fromFoldableM $ map pr [1,2,3]
--   1
--   2
--   3
--   
-- --
--   >>> Stream.drain $ Stream.fromAsync $ Stream.fromFoldableM $ map pr [1,2,3]
--   ...
--   ...
--   ...
--   
-- -- Concurrent (do not use with fromParallel on infinite -- containers) fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a -- | Fold a stream using the supplied left Fold and reducing the -- resulting expression strictly at each step. The behavior is similar to -- foldl'. A Fold can terminate early without consuming -- the full stream. See the documentation of individual Folds for -- termination behavior. -- --
--   >>> Stream.fold Fold.sum (Stream.enumerateFromTo 1 100)
--   5050
--   
-- -- Folds never fail, therefore, they produce a default value even when no -- input is provided. It means we can always fold an empty stream and get -- a valid result. For example: -- --
--   >>> Stream.fold Fold.sum Stream.nil
--   0
--   
-- -- However, foldMany on an empty stream results in an empty -- stream. Therefore, Stream.fold f is not the same as -- Stream.head . Stream.foldMany f. -- --
--   fold f = Stream.parse (Parser.fromFold f)
--   
fold :: Monad m => Fold m a b -> SerialT m a -> m b -- | Decompose a stream into its head and tail. If the stream is empty, -- returns Nothing. If the stream is non-empty, returns Just -- (a, ma), where a is the head of the stream and -- ma its tail. -- -- This can be used to do pretty much anything in an imperative manner, -- as it just breaks down the stream into individual elements and we can -- loop over them as we deem fit. For example, this can be used to -- convert a streamly stream into other stream types. -- -- All the folds in this module can be expressed in terms of -- uncons, however, this is generally less efficient than specific -- folds because it takes apart the stream one element at a time, -- therefore, does not take adavantage of stream fusion. uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a)) -- |
--   tail = fmap (fmap snd) . Stream.uncons
--   
-- -- Extract all but the first element of the stream, if any. tail :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a)) -- | Extract all but the last element of the stream, if any. init :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a)) -- | Right associative/lazy pull fold. foldrM build final stream -- constructs an output structure using the step function build. -- build is invoked with the next input element and the -- remaining (lazy) tail of the output structure. It builds a lazy output -- expression using the two. When the "tail structure" in the output -- expression is evaluated it calls build again thus lazily -- consuming the input stream until either the output expression -- built by build is free of the "tail" or the input is -- exhausted in which case final is used as the terminating case -- for the output structure. For more details see the description in the -- previous section. -- -- Example, determine if any element is odd in a stream: -- --
--   >>> Stream.foldrM (\x xs -> if odd x then return True else xs) (return False) $ Stream.fromList (2:4:5:undefined)
--   True
--   
-- -- Since: 0.7.0 (signature changed) -- -- Since: 0.2.0 (signature changed) -- -- Since: 0.1.0 foldrM :: Monad m => (a -> m b -> m b) -> m b -> SerialT m a -> m b -- | Right fold, lazy for lazy monads and pure streams, and strict for -- strict monads. -- -- Please avoid using this routine in strict monads like IO unless you -- need a strict right fold. This is provided only for use in lazy monads -- (e.g. Identity) or pure streams. Note that with this signature it is -- not possible to implement a lazy foldr when the monad m is -- strict. In that case it would be strict in its accumulator and -- therefore would necessarily consume all its input. foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b -- | Left associative/strict push fold. foldl' reduce initial -- stream invokes reduce with the accumulator and the next -- input in the input stream, using initial as the initial value -- of the current value of the accumulator. When the input is exhausted -- the current value of the accumulator is returned. Make sure to use a -- strict data structure for accumulator to not build unnecessary lazy -- expressions unless that's what you want. See the previous section for -- more details. foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b -- | Strict left fold, for non-empty streams, using first element as the -- starting value. Returns Nothing if the stream is empty. foldl1' :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a) -- | Like foldl' but with a monadic step function. -- -- Since: 0.2.0 -- -- Since: 0.8.0 (signature change) foldlM' :: Monad m => (b -> a -> m b) -> m b -> SerialT m a -> m b -- |
--   drain = mapM_ (\_ -> return ())
--   drain = Stream.fold Fold.drain
--   
-- -- Run a stream, discarding the results. By default it interprets the -- stream as SerialT, to run other types of streams use the type -- adapting combinators for example Stream.drain . -- fromAsync. drain :: Monad m => SerialT m a -> m () -- | Extract the last element of the stream, if any. -- --
--   last xs = xs !! (Stream.length xs - 1)
--   last = Stream.fold Fold.last
--   
last :: Monad m => SerialT m a -> m (Maybe a) -- | Determine the length of the stream. length :: Monad m => SerialT m a -> m Int -- | Determine the sum of all elements of a stream of numbers. Returns -- 0 when the stream is empty. Note that this is not numerically -- stable for floating point numbers. -- --
--   sum = Stream.fold Fold.sum
--   
sum :: (Monad m, Num a) => SerialT m a -> m a -- | Determine the product of all elements of a stream of numbers. Returns -- 1 when the stream is empty. -- --
--   product = Stream.fold Fold.product
--   
product :: (Monad m, Num a) => SerialT m a -> m a -- | Determine the maximum element in a stream using the supplied -- comparison function. -- --
--   maximumBy = Stream.fold Fold.maximumBy
--   
maximumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a) -- |
--   maximum = maximumBy compare
--   maximum = Stream.fold Fold.maximum
--   
-- -- Determine the maximum element in a stream. maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a) -- | Determine the minimum element in a stream using the supplied -- comparison function. -- --
--   minimumBy = Stream.fold Fold.minimumBy
--   
minimumBy :: Monad m => (a -> a -> Ordering) -> SerialT m a -> m (Maybe a) -- |
--   minimum = minimumBy compare
--   minimum = Stream.fold Fold.minimum
--   
-- -- Determine the minimum element in a stream. minimum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a) -- | Ensures that all the elements of the stream are identical and then -- returns that unique element. the :: (Eq a, Monad m) => SerialT m a -> m (Maybe a) -- |
--   drainN n = Stream.drain . Stream.take n
--   drainN n = Stream.fold (Fold.take n Fold.drain)
--   
-- -- Run maximum up to n iterations of a stream. drainN :: Monad m => Int -> SerialT m a -> m () -- |
--   drainWhile p = Stream.drain . Stream.takeWhile p
--   
-- -- Run a stream as long as the predicate holds true. drainWhile :: Monad m => (a -> Bool) -> SerialT m a -> m () -- | Lookup the element at the given index. (!!) :: Monad m => SerialT m a -> Int -> m (Maybe a) -- | Extract the first element of the stream, if any. -- --
--   head = (!! 0)
--   head = Stream.fold Fold.one
--   
head :: Monad m => SerialT m a -> m (Maybe a) -- | Returns the first element that satisfies the given predicate. -- --
--   findM = Stream.fold Fold.findM
--   
findM :: Monad m => (a -> m Bool) -> SerialT m a -> m (Maybe a) -- | Like findM but with a non-monadic predicate. -- --
--   find p = findM (return . p)
--   find = Stream.fold Fold.find
--   
find :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe a) -- | In a stream of (key-value) pairs (a, b), return the value -- b of the first pair where the key equals the given value -- a. -- --
--   lookup = snd <$> Stream.find ((==) . fst)
--   lookup = Stream.fold Fold.lookup
--   
lookup :: (Monad m, Eq a) => a -> SerialT m (a, b) -> m (Maybe b) -- | Returns the first index that satisfies the given predicate. -- --
--   findIndex = Stream.fold Fold.findIndex
--   
findIndex :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe Int) -- | Returns the first index where a given value is found in the stream. -- --
--   elemIndex a = Stream.findIndex (== a)
--   
elemIndex :: (Monad m, Eq a) => a -> SerialT m a -> m (Maybe Int) -- | Determine whether the stream is empty. -- --
--   null = Stream.fold Fold.null
--   
null :: Monad m => SerialT m a -> m Bool -- | Determine whether an element is present in the stream. -- --
--   elem = Stream.fold Fold.elem
--   
elem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool -- | Determine whether an element is not present in the stream. -- --
--   notElem = Stream.fold Fold.length
--   
notElem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool -- | Determine whether all elements of a stream satisfy a predicate. -- --
--   all = Stream.fold Fold.all
--   
all :: Monad m => (a -> Bool) -> SerialT m a -> m Bool -- | Determine whether any of the elements of a stream satisfy a predicate. -- --
--   any = Stream.fold Fold.any
--   
any :: Monad m => (a -> Bool) -> SerialT m a -> m Bool -- | Determines if all elements of a boolean stream are True. -- --
--   and = Stream.fold Fold.and
--   
and :: Monad m => SerialT m Bool -> m Bool -- | Determines whether at least one element of a boolean stream is True. -- --
--   or = Stream.fold Fold.or
--   
or :: Monad m => SerialT m Bool -> m Bool -- |
--   toList = Stream.foldr (:) []
--   
-- -- Convert a stream into a list in the underlying monad. The list can be -- consumed lazily in a lazy monad (e.g. Identity). In a strict -- monad (e.g. IO) the whole list is generated and buffered before it can -- be consumed. -- -- Warning! working on large lists accumulated as buffers in -- memory could be very inefficient, consider using Streamly.Array -- instead. toList :: Monad m => SerialT m a -> m [a] -- | Parallel fold application operator; applies a fold function t m a -- -> m b to a stream t m a concurrently; The the input -- stream is evaluated asynchronously in an independent thread yielding -- elements to a buffer and the folding action runs in another thread -- consuming the input from the buffer. -- -- If you read the signature as (t m a -> m b) -> (t m a -> -- m b) you can look at it as a transformation that converts a fold -- function to a buffered concurrent fold function. -- -- The . at the end of the operator is a mnemonic for -- termination of the stream. -- -- In the example below, each stage introduces a delay of 1 sec but -- output is printed every second because both stages are concurrent. -- --
--   >>> import Control.Concurrent (threadDelay)
--   
--   >>> import Streamly.Prelude ((|$.))
--   
--   >>> :{
--    Stream.foldlM' (\_ a -> threadDelay 1000000 >> print a) (return ())
--        |$. Stream.replicateM 3 (threadDelay 1000000 >> return 1)
--   :}
--   1
--   1
--   1
--   
-- -- Concurrent -- -- Since: 0.3.0 (Streamly) (|$.) :: (IsStream t, MonadAsync m) => (t m a -> m b) -> t m a -> m b infixr 0 |$. -- | Same as |$. but with arguments reversed. -- --
--   (|&.) = flip (|$.)
--   
-- -- Concurrent -- -- Since: 0.3.0 (Streamly) (|&.) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> m b) -> m b infixl 1 |&. -- | Compare two streams for equality using an equality function. eqBy :: (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> m Bool -- | Compare two streams lexicographically using a comparison function. cmpBy :: (IsStream t, Monad m) => (a -> b -> Ordering) -> t m a -> t m b -> m Ordering -- | Returns True if the first stream is the same as or a prefix of -- the second. A stream is a prefix of itself. -- --
--   >>> Stream.isPrefixOf (Stream.fromList "hello") (Stream.fromList "hello" :: SerialT IO Char)
--   True
--   
isPrefixOf :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m Bool -- | Returns True if all the elements of the first stream occur, in -- order, in the second stream. The elements do not have to occur -- consecutively. A stream is a subsequence of itself. -- --
--   >>> Stream.isSubsequenceOf (Stream.fromList "hlo") (Stream.fromList "hello" :: SerialT IO Char)
--   True
--   
isSubsequenceOf :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m Bool -- | stripPrefix prefix stream strips prefix from -- stream if it is a prefix of stream. Returns Nothing if -- the stream does not start with the given prefix, stripped stream -- otherwise. Returns Just nil when the prefix is the same as -- the stream. -- -- See also "Streamly.Internal.Data.Stream.IsStream.Nesting.dropPrefix". -- -- Space: O(1) stripPrefix :: (Eq a, IsStream t, Monad m) => t m a -> t m a -> m (Maybe (t m a)) -- |
--   map = fmap
--   
-- -- Same as fmap. -- --
--   > D.toList $ D.map (+1) $ D.fromList [1,2,3]
--   [2,3,4]
--   
map :: (IsStream t, Monad m) => (a -> b) -> t m a -> t m b -- |
--   sequence = mapM id
--   
-- -- Replace the elements of a stream of monadic actions with the outputs -- of those actions. -- --
--   >>> drain $ Stream.sequence $ Stream.fromList [putStr "a", putStr "b", putStrLn "c"]
--   abc
--   
--   >>> :{
--   drain $ Stream.replicateM 3 (return $ threadDelay 1000000 >> print 1)
--    & (fromSerial . Stream.sequence)
--   :}
--   1
--   1
--   1
--   
--   >>> :{
--   drain $ Stream.replicateM 3 (return $ threadDelay 1000000 >> print 1)
--    & (fromAsync . Stream.sequence)
--   :}
--   1
--   1
--   1
--   
-- -- Concurrent (do not use with fromParallel on infinite -- streams) sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a -- |
--   mapM f = sequence . map f
--   
-- -- Apply a monadic function to each element of the stream and replace it -- with the output of the resulting action. -- --
--   >>> drain $ Stream.mapM putStr $ Stream.fromList ["a", "b", "c"]
--   abc
--   
--   >>> :{
--      drain $ Stream.replicateM 10 (return 1)
--        & (fromSerial . Stream.mapM (x -> threadDelay 1000000 >> print x))
--   :}
--   1
--   ...
--   1
--   
--   > drain $ Stream.replicateM 10 (return 1)
--    & (fromAsync . Stream.mapM (x -> threadDelay 1000000 >> print x))
--   
-- -- Concurrent (do not use with fromParallel on infinite -- streams) mapM :: forall t m a b. (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b -- |
--   mapM_ = Stream.drain . Stream.mapM
--   
-- -- Apply a monadic action to each element of the stream and discard the -- output of the action. This is not really a pure transformation -- operation but a transformation followed by fold. mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m () -- | Apply a monadic function to each element flowing through the stream -- and discard the results. -- --
--   >>> Stream.drain $ Stream.trace print (Stream.enumerateFromTo 1 2)
--   1
--   2
--   
-- -- Compare with tap. trace :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m a -- | Tap the data flowing through a stream into a Fold. For example, -- you may add a tap to log the contents flowing through the stream. The -- fold is used only for effects, its result is discarded. -- --
--                     Fold m a b
--                         |
--   -----stream m a ---------------stream m a-----
--   
-- --
--   >>> Stream.drain $ Stream.tap (Fold.drainBy print) (Stream.enumerateFromTo 1 2)
--   1
--   2
--   
-- -- Compare with trace. tap :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m a -- | Introduce a delay of specified seconds before consuming an element of -- the stream except the first one. -- --
--   >>> Stream.mapM_ print $ Stream.timestamped $ Stream.delay 1 $ Stream.enumerateFromTo 1 3
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),1)
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),2)
--   (AbsTime (TimeSpec {sec = ..., nsec = ...}),3)
--   
delay :: (IsStream t, MonadIO m) => Double -> t m a -> t m a -- | Strict left scan. Like map, scanl' too is a one to one -- transformation, however it adds an extra element. -- --
--   >>> Stream.toList $ Stream.scanl' (+) 0 $ fromList [1,2,3,4]
--   [0,1,3,6,10]
--   
-- --
--   >>> Stream.toList $ Stream.scanl' (flip (:)) [] $ Stream.fromList [1,2,3,4]
--   [[],[1],[2,1],[3,2,1],[4,3,2,1]]
--   
-- -- The output of scanl' is the initial value of the accumulator -- followed by all the intermediate steps and the final result of -- foldl'. -- -- By streaming the accumulated state after each fold step, we can share -- the state across multiple stages of stream composition. Each stage can -- modify or extend the state, do some processing with it and emit it for -- the next stage, thus modularizing the stream processing. This can be -- useful in stateful or event-driven programming. -- -- Consider the following monolithic example, computing the sum and the -- product of the elements in a stream in one go using a foldl': -- --
--   >>> Stream.foldl' ((s, p) x -> (s + x, p * x)) (0,1) $ Stream.fromList 1,2,3,4
--   
-- -- Using scanl' we can make it modular by computing the sum in -- the first stage and passing it down to the next stage for computing -- the product: -- --
--   >>> :{
--     Stream.foldl' ((_, p) (s, x) -> (s, p * x)) (0,1)
--     $ Stream.scanl' ((s, _) x -> (s + x, x)) (0,1)
--     $ Stream.fromList [1,2,3,4]
--   :}
--   (10,24)
--   
-- -- IMPORTANT: scanl' evaluates the accumulator to WHNF. To avoid -- building lazy expressions inside the accumulator, it is recommended -- that a strict data structure is used for accumulator. -- --
--   >>> scanl' step z = scan (Fold.foldl' step z)
--   
--   >>> scanl' f z xs = scanlM' (\a b -> return (f a b)) (return z) xs
--   
--   >>> scanl' f z xs = z `Stream.cons` postscanl' f z xs
--   
-- -- See also: usingStateT scanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b -- | Like scanl' but with a monadic step function and a monadic -- seed. -- -- Since: 0.4.0 -- -- Since: 0.8.0 (signature change) scanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b -- | Like scanl' but does not stream the initial value of the -- accumulator. -- --
--   >>> postscanl' step z = postscan (Fold.foldl' step z)
--   
--   >>> postscanl' f z = postscanlM' (\a b -> return (f a b)) (return z)
--   
--   >>> postscanl' f z xs = Stream.drop 1 $ Stream.scanl' f z xs
--   
postscanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b -- | Like postscanl' but with a monadic step function and a -- monadic seed. -- --
--   >>> postscanlM' f z xs = Stream.drop 1 $ Stream.scanlM' f z xs
--   
-- -- Since: 0.7.0 -- -- Since: 0.8.0 (signature change) postscanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> m b -> t m a -> t m b -- | Like scanl' but for a non-empty stream. The first element of -- the stream is used as the initial value of the accumulator. Does -- nothing if the stream is empty. -- --
--   >>> Stream.toList $ Stream.scanl1' (+) $ fromList [1,2,3,4]
--   [1,3,6,10]
--   
scanl1' :: (IsStream t, Monad m) => (a -> a -> a) -> t m a -> t m a -- | Like scanl1' but with a monadic step function. scanl1M' :: (IsStream t, Monad m) => (a -> a -> m a) -> t m a -> t m a -- | Scan a stream using the given monadic fold. -- --
--   >>> Stream.toList $ Stream.takeWhile (< 10) $ Stream.scan Fold.sum (Stream.fromList [1..10])
--   [0,1,3,6]
--   
scan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b -- | Postscan a stream using the given monadic fold. -- -- The following example extracts the input stream up to a point where -- the running average of elements is no more than 10: -- --
--   >>> import Data.Maybe (fromJust)
--   
--   >>> let avg = Fold.teeWith (/) Fold.sum (fmap fromIntegral Fold.length)
--   
--   >>> :{
--    Stream.toList
--     $ Stream.map (fromJust . fst)
--     $ Stream.takeWhile (\(_,x) -> x <= 10)
--     $ Stream.postscan (Fold.tee Fold.last avg) (Stream.enumerateFromTo 1.0 100.0)
--   :}
--   [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0]
--   
postscan :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b -- | Deletes the first occurrence of the element in the stream that -- satisfies the given equality predicate. -- --
--   >>> Stream.toList $ Stream.deleteBy (==) 3 $ Stream.fromList [1,3,3,5]
--   [1,3,5]
--   
deleteBy :: (IsStream t, Monad m) => (a -> a -> Bool) -> a -> t m a -> t m a -- | Include only those elements that pass a predicate. filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a -- | Same as filter but with a monadic predicate. filterM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a -- | Drop repeated elements that are adjacent to each other. uniq :: (Eq a, IsStream t, Monad m) => t m a -> t m a -- | Take first n elements from the stream and discard the rest. take :: (IsStream t, Monad m) => Int -> t m a -> t m a -- | End the stream as soon as the predicate fails on an element. takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a -- | Same as takeWhile but with a monadic predicate. takeWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a -- | Discard first n elements from the stream and take the rest. drop :: (IsStream t, Monad m) => Int -> t m a -> t m a -- | Drop elements in the stream as long as the predicate succeeds and then -- take the rest of the stream. dropWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a -- | Same as dropWhile but with a monadic predicate. dropWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a -- | insertBy cmp elem stream inserts elem before the -- first element in stream that is less than elem when -- compared using cmp. -- --
--   insertBy cmp x = mergeBy cmp (fromPure x)
--   
-- --
--   >>> Stream.toList $ Stream.insertBy compare 2 $ Stream.fromList [1,3,5]
--   [1,2,3,5]
--   
insertBy :: (IsStream t, Monad m) => (a -> a -> Ordering) -> a -> t m a -> t m a -- | Insert an effect and its output before consuming an element of a -- stream except the first one. -- --
--   >>> Stream.toList $ Stream.trace putChar $ Stream.intersperseM (putChar '.' >> return ',') $ Stream.fromList "hello"
--   h.,e.,l.,l.,o"h,e,l,l,o"
--   
-- -- Be careful about the order of effects. In the above example we used -- trace after the intersperse, if we use it before the intersperse the -- output would be he.l.l.o."h,e,l,l,o". -- --
--   >>> Stream.toList $ Stream.intersperseM (putChar '.' >> return ',') $ Stream.trace putChar $ Stream.fromList "hello"
--   he.l.l.o."h,e,l,l,o"
--   
intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a -- | Insert a pure value between successive elements of a stream. -- --
--   >>> Stream.toList $ Stream.intersperse ',' $ Stream.fromList "hello"
--   "h,e,l,l,o"
--   
intersperse :: (IsStream t, MonadAsync m) => a -> t m a -> t m a -- | Returns the elements of the stream in reverse order. The stream must -- be finite. Note that this necessarily buffers the entire stream in -- memory. -- --
--   >>> reverse = Stream.foldlT (flip Stream.cons) Stream.nil
--   
-- -- Since 0.7.0 (Monad m constraint) -- -- Since: 0.1.1 reverse :: (IsStream t, Monad m) => t m a -> t m a -- |
--   indexed = Stream.postscanl' (\(i, _) x -> (i + 1, x)) (-1,undefined)
--   indexed = Stream.zipWith (,) (Stream.enumerateFrom 0)
--   
-- -- Pair each element in a stream with its index, starting from index 0. -- --
--   >>> Stream.toList $ Stream.indexed $ Stream.fromList "hello"
--   [(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')]
--   
indexed :: (IsStream t, Monad m) => t m a -> t m (Int, a) -- |
--   indexedR n = Stream.postscanl' (\(i, _) x -> (i - 1, x)) (n + 1,undefined)
--   indexedR n = Stream.zipWith (,) (Stream.enumerateFromThen n (n - 1))
--   
-- -- Pair each element in a stream with its index, starting from the given -- index n and counting down. -- --
--   >>> Stream.toList $ Stream.indexedR 10 $ Stream.fromList "hello"
--   [(10,'h'),(9,'e'),(8,'l'),(7,'l'),(6,'o')]
--   
indexedR :: (IsStream t, Monad m) => Int -> t m a -> t m (Int, a) -- | Find all the indices where the element in the stream satisfies the -- given predicate. -- --
--   findIndices = fold Fold.findIndices
--   
findIndices :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m Int -- | Find all the indices where the value of the element in the stream is -- equal to the given value. -- --
--   elemIndices a = findIndices (== a)
--   
elemIndices :: (IsStream t, Eq a, Monad m) => a -> t m a -> t m Int -- | Map a Maybe returning function to a stream, filter out the -- Nothing elements, and return a stream of values extracted from -- Just. -- -- Equivalent to: -- --
--   mapMaybe f = Stream.map fromJust . Stream.filter isJust . Stream.map f
--   
mapMaybe :: (IsStream t, Monad m) => (a -> Maybe b) -> t m a -> t m b -- | Like mapMaybe but maps a monadic function. -- -- Equivalent to: -- --
--   mapMaybeM f = Stream.map fromJust . Stream.filter isJust . Stream.mapM f
--   
-- -- Concurrent (do not use with fromParallel on infinite -- streams) mapMaybeM :: (IsStream t, MonadAsync m, Functor (t m)) => (a -> m (Maybe b)) -> t m a -> t m b -- | Parallel transform application operator; applies a stream -- transformation function t m a -> t m b to a stream t m -- a concurrently; the input stream is evaluated asynchronously in -- an independent thread yielding elements to a buffer and the -- transformation function runs in another thread consuming the input -- from the buffer. |$ is just like regular function application -- operator $ except that it is concurrent. -- -- If you read the signature as (t m a -> t m b) -> (t m a -- -> t m b) you can look at it as a transformation that converts -- a transform function to a buffered concurrent transform function. -- -- The following code prints a value every second even though each stage -- adds a 1 second delay. -- --
--   >>> :{
--   Stream.drain $
--      Stream.mapM (\x -> threadDelay 1000000 >> print x)
--        |$ Stream.replicateM 3 (threadDelay 1000000 >> return 1)
--   :}
--   1
--   1
--   1
--   
-- -- Concurrent -- -- Since: 0.3.0 (Streamly) (|$) :: (IsStream t, MonadAsync m) => (t m a -> t m b) -> t m a -> t m b infixr 0 |$ -- | Same as |$ but with arguments reversed. -- -- (|&) = flip (|$) -- -- Concurrent -- -- Since: 0.3.0 (Streamly) (|&) :: (IsStream t, MonadAsync m) => t m a -> (t m a -> t m b) -> t m b infixl 1 |& -- | Make the stream producer and consumer run concurrently by introducing -- a buffer between them. The producer thread evaluates the input stream -- until the buffer fills, it terminates if the buffer is full and a -- worker thread is kicked off again to evaluate the remaining stream -- when there is space in the buffer. The consumer consumes the stream -- lazily from the buffer. -- -- Since: 0.2.0 (Streamly) mkAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -- | Specify the maximum number of threads that can be spawned concurrently -- for any concurrent combinator in a stream. A value of 0 resets the -- thread limit to default, a negative value means there is no limit. The -- default value is 1500. maxThreads does not affect -- ParallelT streams as they can use unbounded number of -- threads. -- -- When the actions in a stream are IO bound, having blocking IO calls, -- this option can be used to control the maximum number of in-flight IO -- requests. When the actions are CPU bound this option can be used to -- control the amount of CPU used by the stream. -- -- Since: 0.4.0 (Streamly) maxThreads :: IsStream t => Int -> t m a -> t m a -- | Specify the maximum size of the buffer for storing the results from -- concurrent computations. If the buffer becomes full we stop spawning -- more concurrent tasks until there is space in the buffer. A value of 0 -- resets the buffer size to default, a negative value means there is no -- limit. The default value is 1500. -- -- CAUTION! using an unbounded maxBuffer value (i.e. a negative -- value) coupled with an unbounded maxThreads value is a recipe -- for disaster in presence of infinite streams, or very large streams. -- Especially, it must not be used when pure is used in -- ZipAsyncM streams as pure in applicative zip streams -- generates an infinite stream causing unbounded concurrent generation -- with no limit on the buffer or threads. -- -- Since: 0.4.0 (Streamly) maxBuffer :: IsStream t => Int -> t m a -> t m a data Rate Rate :: Double -> Double -> Double -> Int -> Rate [rateLow] :: Rate -> Double [rateGoal] :: Rate -> Double [rateHigh] :: Rate -> Double [rateBuffer] :: Rate -> Int -- | Specify the pull rate of a stream. A Nothing value resets the -- rate to default which is unlimited. When the rate is specified, -- concurrent production may be ramped up or down automatically to -- achieve the specified yield rate. The specific behavior for different -- styles of Rate specifications is documented under Rate. -- The effective maximum production rate achieved by a stream is governed -- by: -- -- -- -- Since: 0.5.0 (Streamly) rate :: IsStream t => Maybe Rate -> t m a -> t m a -- | Same as rate (Just $ Rate (r/2) r (2*r) maxBound) -- -- Specifies the average production rate of a stream in number of yields -- per second (i.e. Hertz). Concurrent production is ramped up -- or down automatically to achieve the specified average yield rate. The -- rate can go down to half of the specified rate on the lower side and -- double of the specified rate on the higher side. -- -- Since: 0.5.0 (Streamly) avgRate :: IsStream t => Double -> t m a -> t m a -- | Same as rate (Just $ Rate r r (2*r) maxBound) -- -- Specifies the minimum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go below the -- specified rate, even though it may possibly go above it at times, the -- upper limit is double of the specified rate. -- -- Since: 0.5.0 (Streamly) minRate :: IsStream t => Double -> t m a -> t m a -- | Same as rate (Just $ Rate (r/2) r r maxBound) -- -- Specifies the maximum rate at which the stream should yield values. As -- far as possible the yield rate would never be allowed to go above the -- specified rate, even though it may possibly go below it at times, the -- lower limit is half of the specified rate. This can be useful in -- applications where certain resource usage must not be allowed to go -- beyond certain limits. -- -- Since: 0.5.0 (Streamly) maxRate :: IsStream t => Double -> t m a -> t m a -- | Same as rate (Just $ Rate r r r 0) -- -- Specifies a constant yield rate. If for some reason the actual rate -- goes above or below the specified rate we do not try to recover it by -- increasing or decreasing the rate in future. This can be useful in -- applications like graphics frame refresh where we need to maintain a -- constant refresh rate. -- -- Since: 0.5.0 (Streamly) constRate :: IsStream t => Double -> t m a -> t m a -- | Appends two streams sequentially, yielding all elements from the first -- stream, and then all elements from the second stream. -- --
--   >>> import Streamly.Prelude (serial)
--   
--   >>> stream1 = Stream.fromList [1,2]
--   
--   >>> stream2 = Stream.fromList [3,4]
--   
--   >>> Stream.toList $ stream1 `serial` stream2
--   [1,2,3,4]
--   
-- -- This operation can be used to fold an infinite lazy container of -- streams. -- -- Since: 0.2.0 (Streamly) serial :: IsStream t => t m a -> t m a -> t m a infixr 6 `serial` -- | Interleaves two streams, yielding one element from each stream -- alternately. When one stream stops the rest of the other stream is -- used in the output stream. -- --
--   >>> import Streamly.Prelude (wSerial)
--   
--   >>> stream1 = Stream.fromList [1,2]
--   
--   >>> stream2 = Stream.fromList [3,4]
--   
--   >>> Stream.toList $ Stream.fromWSerial $ stream1 `wSerial` stream2
--   [1,3,2,4]
--   
-- -- Note, for singleton streams wSerial and serial are -- identical. -- -- Note that this operation cannot be used to fold a container of -- infinite streams but it can be used for very large streams as the -- state that it needs to maintain is proportional to the logarithm of -- the number of streams. -- -- Since: 0.2.0 (Streamly) wSerial :: IsStream t => t m a -> t m a -> t m a infixr 6 `wSerial` -- | Appends two streams, both the streams may be evaluated concurrently -- but the outputs are used in the same order as the corresponding -- actions in the original streams, side effects will happen in the order -- in which the streams are evaluated: -- --
--   >>> import Streamly.Prelude (ahead, SerialT)
--   
--   >>> stream1 = Stream.fromEffect (delay 4) :: SerialT IO Int
--   
--   >>> stream2 = Stream.fromEffect (delay 2) :: SerialT IO Int
--   
--   >>> Stream.toList $ stream1 `ahead` stream2 :: IO [Int]
--   2 sec
--   4 sec
--   [4,2]
--   
-- -- Multiple streams can be combined. With enough threads, all of them can -- be scheduled simultaneously: -- --
--   >>> stream3 = Stream.fromEffect (delay 1)
--   
--   >>> Stream.toList $ stream1 `ahead` stream2 `ahead` stream3
--   1 sec
--   2 sec
--   4 sec
--   [4,2,1]
--   
-- -- With 2 threads, only two can be scheduled at a time, when one of those -- finishes, the third one gets scheduled: -- --
--   >>> Stream.toList $ Stream.maxThreads 2 $ stream1 `ahead` stream2 `ahead` stream3
--   2 sec
--   1 sec
--   4 sec
--   [4,2,1]
--   
-- -- Only streams are scheduled for ahead evaluation, how actions within a -- stream are evaluated depends on the stream type. If it is a concurrent -- stream they will be evaluated concurrently. It may not make much sense -- combining serial streams using ahead. -- -- ahead can be safely used to fold an infinite lazy container of -- streams. -- -- Since: 0.3.0 (Streamly) ahead :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a infixr 6 `ahead` -- | Merges two streams, both the streams may be evaluated concurrently, -- outputs from both are used as they arrive: -- --
--   >>> import Streamly.Prelude (async)
--   
--   >>> stream1 = Stream.fromEffect (delay 4)
--   
--   >>> stream2 = Stream.fromEffect (delay 2)
--   
--   >>> Stream.toList $ stream1 `async` stream2
--   2 sec
--   4 sec
--   [2,4]
--   
-- -- Multiple streams can be combined. With enough threads, all of them can -- be scheduled simultaneously: -- --
--   >>> stream3 = Stream.fromEffect (delay 1)
--   
--   >>> Stream.toList $ stream1 `async` stream2 `async` stream3
--   ...
--   [1,2,4]
--   
-- -- With 2 threads, only two can be scheduled at a time, when one of those -- finishes, the third one gets scheduled: -- --
--   >>> Stream.toList $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3
--   ...
--   [2,1,4]
--   
-- -- With a single thread, it becomes serial: -- --
--   >>> Stream.toList $ Stream.maxThreads 1 $ stream1 `async` stream2 `async` stream3
--   ...
--   [4,2,1]
--   
-- -- Only streams are scheduled for async evaluation, how actions within a -- stream are evaluated depends on the stream type. If it is a concurrent -- stream they will be evaluated concurrently. -- -- In the following example, both the streams are scheduled for -- concurrent evaluation but each individual stream is evaluated -- serially: -- --
--   >>> stream1 = Stream.fromListM $ Prelude.map delay [3,3] -- SerialT IO Int
--   
--   >>> stream2 = Stream.fromListM $ Prelude.map delay [1,1] -- SerialT IO Int
--   
--   >>> Stream.toList $ stream1 `async` stream2 -- IO [Int]
--   ...
--   [1,1,3,3]
--   
-- -- If total threads are 2, the third stream is scheduled only after one -- of the first two has finished: -- --
--   stream3 = Stream.fromListM $ Prelude.map delay [2,2] -- SerialT IO Int
--   Stream.toList $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3 -- IO [Int]
--   
-- -- ... [1,1,3,2,3,2] -- -- Thus async goes deep in first few streams rather than going -- wide in all streams. It prefers to evaluate the leftmost streams as -- much as possible. Because of this behavior, async can be safely -- used to fold an infinite lazy container of streams. -- -- Since: 0.2.0 (Streamly) async :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a infixr 6 `async` -- | For singleton streams, wAsync is the same as async. See -- async for singleton stream behavior. For multi-element streams, -- while async is left biased i.e. it tries to evaluate the left -- side stream as much as possible, wAsync tries to schedule them -- both fairly. In other words, async goes deep while -- wAsync goes wide. However, outputs are always used as they -- arrive. -- -- With a single thread, async starts behaving like serial -- while wAsync starts behaving like wSerial. -- --
--   >>> import Streamly.Prelude (async, wAsync)
--   
--   >>> stream1 = Stream.fromList [1,2,3]
--   
--   >>> stream2 = Stream.fromList [4,5,6]
--   
--   >>> Stream.toList $ Stream.fromAsync $ Stream.maxThreads 1 $ stream1 `async` stream2
--   [1,2,3,4,5,6]
--   
-- --
--   >>> Stream.toList $ Stream.fromWAsync $ Stream.maxThreads 1 $ stream1 `wAsync` stream2
--   [1,4,2,5,3,6]
--   
-- -- With two threads available, and combining three streams: -- --
--   >>> stream3 = Stream.fromList [7,8,9]
--   
--   >>> Stream.toList $ Stream.fromAsync $ Stream.maxThreads 2 $ stream1 `async` stream2 `async` stream3
--   [1,2,3,4,5,6,7,8,9]
--   
-- --
--   >>> Stream.toList $ Stream.fromWAsync $ Stream.maxThreads 2 $ stream1 `wAsync` stream2 `wAsync` stream3
--   [1,4,2,7,5,3,8,6,9]
--   
-- -- This operation cannot be used to fold an infinite lazy container of -- streams, because it schedules all the streams in a round robin manner. -- -- Note that WSerialT and single threaded WAsyncT both -- interleave streams but the exact scheduling is slightly different in -- both cases. -- -- Since: 0.2.0 (Streamly) wAsync :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a infixr 6 `wAsync` -- | Like async except that the execution is much more strict. There -- is no limit on the number of threads. While async may not -- schedule a stream if there is no demand from the consumer, -- parallel always evaluates both the streams immediately. The -- only limit that applies to parallel is maxBuffer. -- Evaluation may block if the output buffer becomes full. -- --
--   >>> import Streamly.Prelude (parallel)
--   
--   >>> stream = Stream.fromEffect (delay 2) `parallel` Stream.fromEffect (delay 1)
--   
--   >>> Stream.toList stream -- IO [Int]
--   1 sec
--   2 sec
--   [1,2]
--   
-- -- parallel guarantees that all the streams are scheduled for -- execution immediately, therefore, we could use things like starting -- timers inside the streams and relying on the fact that all timers were -- started at the same time. -- -- Unlike async this operation cannot be used to fold an infinite -- lazy container of streams, because it schedules all the streams -- strictly concurrently. -- -- Since: 0.2.0 (Streamly) parallel :: (IsStream t, MonadAsync m) => t m a -> t m a -> t m a infixr 6 `parallel` -- | Merge two streams using a comparison function. The head elements of -- both the streams are compared and the smaller of the two elements is -- emitted, if both elements are equal then the element from the first -- stream is used first. -- -- If the streams are sorted in ascending order, the resulting stream -- would also remain sorted in ascending order. -- --
--   >>> Stream.toList $ Stream.mergeBy compare (Stream.fromList [1,3,5]) (Stream.fromList [2,4,6,8])
--   [1,2,3,4,5,6,8]
--   
-- -- See also: mergeByMFused mergeBy :: IsStream t => (a -> a -> Ordering) -> t m a -> t m a -> t m a -- | Like mergeBy but with a monadic comparison function. -- -- Merge two streams randomly: -- --
--   > randomly _ _ = randomIO >>= x -> return $ if x then LT else GT
--   > Stream.toList $ Stream.mergeByM randomly (Stream.fromList [1,1,1,1]) (Stream.fromList [2,2,2,2])
--   [2,1,2,2,2,1,1,1]
--   
-- -- Merge two streams in a proportion of 2:1: -- --
--   >>> :{
--   do
--    let proportionately m n = do
--         ref <- newIORef $ cycle $ Prelude.concat [Prelude.replicate m LT, Prelude.replicate n GT]
--         return $ _ _ -> do
--            r <- readIORef ref
--            writeIORef ref $ Prelude.tail r
--            return $ Prelude.head r
--    f <- proportionately 2 1
--    xs <- Stream.toList $ Stream.mergeByM f (Stream.fromList [1,1,1,1,1,1]) (Stream.fromList [2,2,2])
--    print xs
--   :}
--   [1,1,2,1,1,2,1,1,2]
--   
-- -- See also: mergeByMFused mergeByM :: (IsStream t, Monad m) => (a -> a -> m Ordering) -> t m a -> t m a -> t m a -- | Like mergeBy but merges concurrently (i.e. both the elements -- being merged are generated concurrently). mergeAsyncBy :: (IsStream t, MonadAsync m) => (a -> a -> Ordering) -> t m a -> t m a -> t m a -- | Like mergeByM but merges concurrently (i.e. both the elements -- being merged are generated concurrently). mergeAsyncByM :: (IsStream t, MonadAsync m) => (a -> a -> m Ordering) -> t m a -> t m a -> t m a -- | Stream a is evaluated first, followed by stream b, -- the resulting elements a and b are then zipped using -- the supplied zip function and the result c is yielded to the -- consumer. -- -- If stream a or stream b ends, the zipped stream -- ends. If stream b ends first, the element a from -- previous evaluation of stream a is discarded. -- --
--   > D.toList $ D.zipWith (+) (D.fromList [1,2,3]) (D.fromList [4,5,6])
--   [5,7,9]
--   
zipWith :: (IsStream t, Monad m) => (a -> b -> c) -> t m a -> t m b -> t m c -- | Like zipWith but using a monadic zipping function. zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c -- | Like zipWith but zips concurrently i.e. both the streams being -- zipped are evaluated concurrently using the ParallelT -- concurrent evaluation style. The maximum number of elements of each -- stream evaluated in advance can be controlled by maxBuffer. -- -- The stream ends if stream a or stream b ends. -- However, if stream b ends while we are still evaluating -- stream a and waiting for a result then stream will not end -- until after the evaluation of stream a finishes. This -- behavior can potentially be changed in future to end the stream -- immediately as soon as any of the stream end is detected. zipAsyncWith :: (IsStream t, MonadAsync m) => (a -> b -> c) -> t m a -> t m b -> t m c -- | Like zipAsyncWith but with a monadic zipping function. zipAsyncWithM :: (IsStream t, MonadAsync m) => (a -> b -> m c) -> t m a -> t m b -> t m c -- | Like concatMap but uses an Unfold for stream generation. -- Unlike concatMap this can fuse the Unfold code with the -- inner loop and therefore provide many times better performance. unfoldMany :: (IsStream t, Monad m) => Unfold m a b -> t m a -> t m b -- | intersperse followed by unfold and concat. -- --
--   intercalate unf a str = unfoldMany unf $ intersperse a str
--   intersperse = intercalate (Unfold.function id)
--   unwords = intercalate Unfold.fromList " "
--   
-- --
--   >>> Stream.toList $ Stream.intercalate Unfold.fromList " " $ Stream.fromList ["abc", "def", "ghi"]
--   "abc def ghi"
--   
intercalate :: (IsStream t, Monad m) => Unfold m b c -> b -> t m b -> t m c -- | intersperseMSuffix followed by unfold and concat. -- --
--   intercalateSuffix unf a str = unfoldMany unf $ intersperseMSuffix a str
--   intersperseMSuffix = intercalateSuffix (Unfold.function id)
--   unlines = intercalateSuffix Unfold.fromList "\n"
--   
-- --
--   >>> Stream.toList $ Stream.intercalateSuffix Unfold.fromList "\n" $ Stream.fromList ["abc", "def", "ghi"]
--   "abc\ndef\nghi\n"
--   
intercalateSuffix :: (IsStream t, Monad m) => Unfold m b c -> b -> t m b -> t m c -- | concatMapWith mixer generator stream is a two dimensional -- looping combinator. The generator function is used to -- generate streams from the elements in the input stream and -- the mixer function is used to merge those streams. -- -- Note we can merge streams concurrently by using a concurrent merge -- function. -- -- Since: 0.7.0 -- -- Since: 0.8.0 (signature change) concatMapWith :: IsStream t => (t m b -> t m b -> t m b) -> (a -> t m b) -> t m a -> t m b -- | Map a stream producing function on each element of the stream and then -- flatten the results into a single stream. -- --
--   >>> concatMap f = Stream.concatMapM (return . f)
--   
--   >>> concatMap f = Stream.concatMapWith Stream.serial f
--   
--   >>> concatMap f = Stream.concat . Stream.map f
--   
concatMap :: (IsStream t, Monad m) => (a -> t m b) -> t m a -> t m b -- | Map a stream producing monadic function on each element of the stream -- and then flatten the results into a single stream. Since the stream -- generation function is monadic, unlike concatMap, it can -- produce an effect at the beginning of each iteration of the inner -- loop. concatMapM :: (IsStream t, Monad m) => (a -> m (t m b)) -> t m a -> t m b -- | A variant of fold that allows you to fold a Foldable -- container of streams using the specified stream sum operation. -- --
--   concatFoldableWith async $ map return [1..3]
--   
-- -- Equivalent to: -- --
--   concatFoldableWith f = Prelude.foldr f D.nil
--   concatFoldableWith f = D.concatMapFoldableWith f id
--   
-- -- Since: 0.8.0 (Renamed foldWith to concatFoldableWith) -- -- Since: 0.1.0 (Streamly) concatFoldableWith :: (IsStream t, Foldable f) => (t m a -> t m a -> t m a) -> f (t m a) -> t m a -- | A variant of foldMap that allows you to map a monadic -- streaming action on a Foldable container and then fold it using -- the specified stream merge operation. -- --
--   concatMapFoldableWith async return [1..3]
--   
-- -- Equivalent to: -- --
--   concatMapFoldableWith f g = Prelude.foldr (f . g) S.nil
--   concatMapFoldableWith f g xs = S.concatMapWith f g (S.fromFoldable xs)
--   
-- -- Since: 0.8.0 (Renamed foldMapWith to concatMapFoldableWith) -- -- Since: 0.1.0 (Streamly) concatMapFoldableWith :: (IsStream t, Foldable f) => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b -- | Like concatMapFoldableWith but with the last two arguments -- reversed i.e. the monadic streaming function is the last argument. -- -- Equivalent to: -- --
--   concatForFoldableWith f xs g = Prelude.foldr (f . g) D.nil xs
--   concatForFoldableWith f = flip (D.concatMapFoldableWith f)
--   
-- -- Since: 0.8.0 (Renamed forEachWith to concatForFoldableWith) -- -- Since: 0.1.0 (Streamly) concatForFoldableWith :: (IsStream t, Foldable f) => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b -- | Apply a Fold repeatedly on a stream and emit the fold outputs -- in the output stream. -- -- To sum every two contiguous elements in a stream: -- --
--   >>> f = Fold.take 2 Fold.sum
--   
--   >>> Stream.toList $ Stream.foldMany f $ Stream.fromList [1..10]
--   [3,7,11,15,19]
--   
-- -- On an empty stream the output is empty: -- --
--   >>> Stream.toList $ Stream.foldMany f $ Stream.fromList []
--   []
--   
-- -- Note Stream.foldMany (Fold.take 0) would result in an -- infinite loop in a non-empty stream. foldMany :: (IsStream t, Monad m) => Fold m a b -> t m a -> t m b -- | Group the input stream into groups of n elements each and -- then fold each group using the provided fold function. -- --
--   >>> Stream.toList $ Stream.chunksOf 2 Fold.sum (Stream.enumerateFromTo 1 10)
--   [3,7,11,15,19]
--   
-- -- This can be considered as an n-fold version of take where we -- apply take repeatedly on the leftover stream until the stream -- exhausts. -- --
--   chunksOf n f = foldMany (FL.take n f)
--   
chunksOf :: (IsStream t, Monad m) => Int -> Fold m a b -> t m a -> t m b -- | Group the input stream into windows of n second each and then -- fold each group using the provided fold function. -- --
--   >>> Stream.toList $ Stream.take 5 $ Stream.intervalsOf 1 Fold.sum $ Stream.constRate 2 $ Stream.enumerateFrom 1
--   [...,...,...,...,...]
--   
intervalsOf :: (IsStream t, MonadAsync m) => Double -> Fold m a b -> t m a -> t m b -- | Split on an infixed separator element, dropping the separator. The -- supplied Fold is applied on the split segments. Splits the -- stream on separator elements determined by the supplied predicate, -- separator is considered as infixed between two segments: -- --
--   >>> splitOn' p xs = Stream.toList $ Stream.splitOn p Fold.toList (Stream.fromList xs)
--   
--   >>> splitOn' (== '.') "a.b"
--   ["a","b"]
--   
-- -- An empty stream is folded to the default value of the fold: -- --
--   >>> splitOn' (== '.') ""
--   [""]
--   
-- -- If one or both sides of the separator are missing then the empty -- segment on that side is folded to the default output of the fold: -- --
--   >>> splitOn' (== '.') "."
--   ["",""]
--   
-- --
--   >>> splitOn' (== '.') ".a"
--   ["","a"]
--   
-- --
--   >>> splitOn' (== '.') "a."
--   ["a",""]
--   
-- --
--   >>> splitOn' (== '.') "a..b"
--   ["a","","b"]
--   
-- -- splitOn is an inverse of intercalating single element: -- --
--   Stream.intercalate (Stream.fromPure '.') Unfold.fromList . Stream.splitOn (== '.') Fold.toList === id
--   
-- -- Assuming the input stream does not contain the separator: -- --
--   Stream.splitOn (== '.') Fold.toList . Stream.intercalate (Stream.fromPure '.') Unfold.fromList === id
--   
splitOn :: (IsStream t, Monad m) => (a -> Bool) -> Fold m a b -> t m a -> t m b -- | Split on a suffixed separator element, dropping the separator. The -- supplied Fold is applied on the split segments. -- --
--   >>> splitOnSuffix' p xs = Stream.toList $ Stream.splitOnSuffix p Fold.toList (Stream.fromList xs)
--   
--   >>> splitOnSuffix' (== '.') "a.b."
--   ["a","b"]
--   
-- --
--   >>> splitOnSuffix' (== '.') "a."
--   ["a"]
--   
-- -- An empty stream results in an empty output stream: -- --
--   >>> splitOnSuffix' (== '.') ""
--   []
--   
-- -- An empty segment consisting of only a suffix is folded to the default -- output of the fold: -- --
--   >>> splitOnSuffix' (== '.') "."
--   [""]
--   
-- --
--   >>> splitOnSuffix' (== '.') "a..b.."
--   ["a","","b",""]
--   
-- -- A suffix is optional at the end of the stream: -- --
--   >>> splitOnSuffix' (== '.') "a"
--   ["a"]
--   
-- --
--   >>> splitOnSuffix' (== '.') ".a"
--   ["","a"]
--   
-- --
--   >>> splitOnSuffix' (== '.') "a.b"
--   ["a","b"]
--   
-- --
--   lines = splitOnSuffix (== '\n')
--   
-- -- splitOnSuffix is an inverse of intercalateSuffix with -- a single element: -- --
--   Stream.intercalateSuffix (Stream.fromPure '.') Unfold.fromList . Stream.splitOnSuffix (== '.') Fold.toList === id
--   
-- -- Assuming the input stream does not contain the separator: -- --
--   Stream.splitOnSuffix (== '.') Fold.toList . Stream.intercalateSuffix (Stream.fromPure '.') Unfold.fromList === id
--   
splitOnSuffix :: (IsStream t, Monad m) => (a -> Bool) -> Fold m a b -> t m a -> t m b -- | Like splitOnSuffix but keeps the suffix attached to the -- resulting splits. -- --
--   >>> splitWithSuffix' p xs = Stream.toList $ splitWithSuffix p Fold.toList (Stream.fromList xs)
--   
-- --
--   >>> splitWithSuffix' (== '.') ""
--   []
--   
-- --
--   >>> splitWithSuffix' (== '.') "."
--   ["."]
--   
-- --
--   >>> splitWithSuffix' (== '.') "a"
--   ["a"]
--   
-- --
--   >>> splitWithSuffix' (== '.') ".a"
--   [".","a"]
--   
-- --
--   >>> splitWithSuffix' (== '.') "a."
--   ["a."]
--   
-- --
--   >>> splitWithSuffix' (== '.') "a.b"
--   ["a.","b"]
--   
-- --
--   >>> splitWithSuffix' (== '.') "a.b."
--   ["a.","b."]
--   
-- --
--   >>> splitWithSuffix' (== '.') "a..b.."
--   ["a.",".","b.","."]
--   
splitWithSuffix :: (IsStream t, Monad m) => (a -> Bool) -> Fold m a b -> t m a -> t m b -- | Like splitOn after stripping leading, trailing, and repeated -- separators. Therefore, ".a..b." with . as the -- separator would be parsed as ["a","b"]. In other words, its -- like parsing words from whitespace separated text. -- --
--   >>> wordsBy' p xs = Stream.toList $ Stream.wordsBy p Fold.toList (Stream.fromList xs)
--   
-- --
--   >>> wordsBy' (== ',') ""
--   []
--   
-- --
--   >>> wordsBy' (== ',') ","
--   []
--   
-- --
--   >>> wordsBy' (== ',') ",a,,b,"
--   ["a","b"]
--   
-- --
--   words = wordsBy isSpace
--   
wordsBy :: (IsStream t, Monad m) => (a -> Bool) -> Fold m a b -> t m a -> t m b -- |
--   groups = groupsBy (==)
--   groups = groupsByRolling (==)
--   
-- -- Groups contiguous spans of equal elements together in individual -- groups. -- --
--   >>> Stream.toList $ Stream.groups Fold.toList $ Stream.fromList [1,1,2,2]
--   [[1,1],[2,2]]
--   
groups :: (IsStream t, Monad m, Eq a) => Fold m a b -> t m a -> t m b -- | groupsBy cmp f $ S.fromList [a,b,c,...] assigns the element -- a to the first group, if b `cmp` a is True -- then b is also assigned to the same group. If c `cmp` -- a is True then c is also assigned to the same -- group and so on. When the comparison fails a new group is started. -- Each group is folded using the fold f and the result of the -- fold is emitted in the output stream. -- --
--   >>> Stream.toList $ Stream.groupsBy (>) Fold.toList $ Stream.fromList [1,3,7,0,2,5]
--   [[1,3,7],[0,2,5]]
--   
groupsBy :: (IsStream t, Monad m) => (a -> a -> Bool) -> Fold m a b -> t m a -> t m b -- | Unlike groupsBy this function performs a rolling comparison -- of two successive elements in the input stream. groupsByRolling -- cmp f $ S.fromList [a,b,c,...] assigns the element a to -- the first group, if a `cmp` b is True then b -- is also assigned to the same group. If b `cmp` c is -- True then c is also assigned to the same group and so -- on. When the comparison fails a new group is started. Each group is -- folded using the fold f. -- --
--   >>> Stream.toList $ Stream.groupsByRolling (\a b -> a + 1 == b) Fold.toList $ Stream.fromList [1,2,3,7,8,9]
--   [[1,2,3],[7,8,9]]
--   
groupsByRolling :: (IsStream t, Monad m) => (a -> a -> Bool) -> Fold m a b -> t m a -> t m b -- | Run the action m b before the stream yields its first -- element. -- -- Same as the following but more efficient due to fusion: -- --
--   >>> before action xs = Stream.nilM action <> xs
--   
--   >>> before action xs = Stream.concatMap (const xs) (Stream.fromEffect action)
--   
before :: (IsStream t, Monad m) => m b -> t m a -> t m a -- | Run the action m b whenever the stream t m a stops -- normally, or if it is garbage collected after a partial lazy -- evaluation. -- -- The semantics of the action m b are similar to the semantics -- of cleanup action in bracket. -- -- See also after_ after :: (IsStream t, MonadRunInIO m) => m b -> t m a -> t m a -- | Run the alloc action m b with async exceptions disabled but -- keeping blocking operations interruptible (see mask). Use the -- output b as input to b -> t m a to generate an -- output stream. -- -- b is usually a resource under the state of monad m, -- e.g. a file handle, that requires a cleanup after use. The cleanup -- action b -> m c, runs whenever the stream ends normally, -- due to a sync or async exception or if it gets garbage collected after -- a partial lazy evaluation. -- -- bracket only guarantees that the cleanup action runs, and it -- runs with async exceptions enabled. The action must ensure that it can -- successfully cleanup the resource in the face of sync or async -- exceptions. -- -- When the stream ends normally or on a sync exception, cleanup action -- runs immediately in the current thread context, whereas in other cases -- it runs in the GC context, therefore, cleanup may be delayed until the -- GC gets to run. -- -- See also: bracket_ -- -- Inhibits stream fusion bracket :: (IsStream t, MonadAsync m, MonadCatch m) => m b -> (b -> m c) -> (b -> t m a) -> t m a -- | Run the action m b if the stream aborts due to an exception. -- The exception is not caught, simply rethrown. -- -- Inhibits stream fusion onException :: (IsStream t, MonadCatch m) => m b -> t m a -> t m a -- | Run the action m b whenever the stream t m a stops -- normally, aborts due to an exception or if it is garbage collected -- after a partial lazy evaluation. -- -- The semantics of running the action m b are similar to the -- cleanup action semantics described in bracket. -- -- See also finally_ -- -- Inhibits stream fusion finally :: (IsStream t, MonadAsync m, MonadCatch m) => m b -> t m a -> t m a -- | When evaluating a stream if an exception occurs, stream evaluation -- aborts and the specified exception handler is run with the exception -- as argument. -- -- Inhibits stream fusion handle :: (IsStream t, MonadCatch m, Exception e) => (e -> t m a) -> t m a -> t m a -- | Lift the inner monad m of a stream t m a to tr -- m using the monad transformer tr. liftInner :: (Monad m, IsStream t, MonadTrans tr, Monad (tr m)) => t m a -> t (tr m) a -- | Evaluate the inner monad of a stream as ReaderT. runReaderT :: (IsStream t, Monad m) => m s -> t (ReaderT s m) a -> t m a -- | Evaluate the inner monad of a stream as StateT and emit the -- resulting state and value pair after each step. -- -- This is supported only for SerialT as concurrent state updation -- may not be safe. runStateT :: Monad m => m s -> SerialT (StateT s m) a -> SerialT m (s, a) -- | For SerialT streams: -- --
--   (<>) = serial                       -- Semigroup
--   (>>=) = flip . concatMapWith serial -- Monad
--   
-- -- A single Monad bind behaves like a for loop: -- --
--   >>> :{
--   IsStream.toList $ do
--        x <- IsStream.fromList [1,2] -- foreach x in stream
--        return x
--   :}
--   [1,2]
--   
-- -- Nested monad binds behave like nested for loops: -- --
--   >>> :{
--   IsStream.toList $ do
--       x <- IsStream.fromList [1,2] -- foreach x in stream
--       y <- IsStream.fromList [3,4] -- foreach y in stream
--       return (x, y)
--   :}
--   [(1,3),(1,4),(2,3),(2,4)]
--   
-- -- Since: 0.2.0 (Streamly) data SerialT m a -- | For WSerialT streams: -- --
--   (<>) = wSerial                       -- Semigroup
--   (>>=) = flip . concatMapWith wSerial -- Monad
--   
-- -- Note that <> is associative only if we disregard the -- ordering of elements in the resulting stream. -- -- A single Monad bind behaves like a for loop: -- --
--   >>> :{
--   IsStream.toList $ IsStream.fromWSerial $ do
--        x <- IsStream.fromList [1,2] -- foreach x in stream
--        return x
--   :}
--   [1,2]
--   
-- -- Nested monad binds behave like interleaved nested for loops: -- --
--   >>> :{
--   IsStream.toList $ IsStream.fromWSerial $ do
--       x <- IsStream.fromList [1,2] -- foreach x in stream
--       y <- IsStream.fromList [3,4] -- foreach y in stream
--       return (x, y)
--   :}
--   [(1,3),(2,3),(1,4),(2,4)]
--   
-- -- It is a result of interleaving all the nested iterations corresponding -- to element 1 in the first stream with all the nested -- iterations of element 2: -- --
--   >>> import Streamly.Prelude (wSerial)
--   
--   >>> IsStream.toList $ IsStream.fromList [(1,3),(1,4)] `IsStream.wSerial` IsStream.fromList [(2,3),(2,4)]
--   [(1,3),(2,3),(1,4),(2,4)]
--   
-- -- The W in the name stands for wide or breadth wise -- scheduling in contrast to the depth wise scheduling behavior of -- SerialT. -- -- Since: 0.2.0 (Streamly) data WSerialT m a -- | For AheadT streams: -- --
--   (<>) = ahead
--   (>>=) = flip . concatMapWith ahead
--   
-- -- A single Monad bind behaves like a for loop with -- iterations executed concurrently, ahead of time, producing side -- effects of iterations out of order, but results in order: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAhead $ do
--        x <- Stream.fromList [2,1] -- foreach x in stream
--        Stream.fromEffect $ delay x
--   :}
--   1 sec
--   2 sec
--   [2,1]
--   
-- -- Nested monad binds behave like nested for loops with nested -- iterations executed concurrently, ahead of time: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAhead $ do
--       x <- Stream.fromList [1,2] -- foreach x in stream
--       y <- Stream.fromList [2,4] -- foreach y in stream
--       Stream.fromEffect $ delay (x + y)
--   :}
--   3 sec
--   4 sec
--   5 sec
--   6 sec
--   [3,5,4,6]
--   
-- -- The behavior can be explained as follows. All the iterations -- corresponding to the element 1 in the first stream constitute -- one output stream and all the iterations corresponding to 2 -- constitute another output stream and these two output streams are -- merged using ahead. -- -- Since: 0.3.0 (Streamly) data AheadT m a -- | For AsyncT streams: -- --
--   (<>) = async
--   (>>=) = flip . concatMapWith async
--   
-- -- A single Monad bind behaves like a for loop with -- iterations of the loop executed concurrently a la the async -- combinator, producing results and side effects of iterations out of -- order: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAsync $ do
--        x <- Stream.fromList [2,1] -- foreach x in stream
--        Stream.fromEffect $ delay x
--   :}
--   1 sec
--   2 sec
--   [1,2]
--   
-- -- Nested monad binds behave like nested for loops with nested -- iterations executed concurrently, a la the async combinator: -- --
--   >>> :{
--   Stream.toList $ Stream.fromAsync $ do
--       x <- Stream.fromList [1,2] -- foreach x in stream
--       y <- Stream.fromList [2,4] -- foreach y in stream
--       Stream.fromEffect $ delay (x + y)
--   :}
--   3 sec
--   4 sec
--   5 sec
--   6 sec
--   [3,4,5,6]
--   
-- -- The behavior can be explained as follows. All the iterations -- corresponding to the element 1 in the first stream constitute -- one output stream and all the iterations corresponding to 2 -- constitute another output stream and these two output streams are -- merged using async. -- -- Since: 0.1.0 (Streamly) data AsyncT m a -- | For WAsyncT streams: -- --
--   (<>) = wAsync
--   (>>=) = flip . concatMapWith wAsync
--   
-- -- A single Monad bind behaves like a for loop with -- iterations of the loop executed concurrently a la the wAsync -- combinator, producing results and side effects of iterations out of -- order: -- --
--   >>> :{
--   Stream.toList $ Stream.fromWAsync $ do
--        x <- Stream.fromList [2,1] -- foreach x in stream
--        Stream.fromEffect $ delay x
--   :}
--   1 sec
--   2 sec
--   [1,2]
--   
-- -- Nested monad binds behave like nested for loops with nested -- iterations executed concurrently, a la the wAsync combinator: -- --
--   >>> :{
--   Stream.toList $ Stream.fromWAsync $ do
--       x <- Stream.fromList [1,2] -- foreach x in stream
--       y <- Stream.fromList [2,4] -- foreach y in stream
--       Stream.fromEffect $ delay (x + y)
--   :}
--   3 sec
--   4 sec
--   5 sec
--   6 sec
--   [3,4,5,6]
--   
-- -- The behavior can be explained as follows. All the iterations -- corresponding to the element 1 in the first stream constitute -- one WAsyncT output stream and all the iterations corresponding -- to 2 constitute another WAsyncT output stream and -- these two output streams are merged using wAsync. -- -- The W in the name stands for wide or breadth wise -- scheduling in contrast to the depth wise scheduling behavior of -- AsyncT. -- -- Since: 0.2.0 (Streamly) data WAsyncT m a -- | For ParallelT streams: -- --
--   (<>) = parallel
--   (>>=) = flip . concatMapWith parallel
--   
-- -- See AsyncT, ParallelT is similar except that all -- iterations are strictly concurrent while in AsyncT it depends -- on the consumer demand and available threads. See parallel -- for more details. -- -- Since: 0.1.0 (Streamly) -- -- Since: 0.7.0 (maxBuffer applies to ParallelT streams) data ParallelT m a -- | For ZipSerialM streams: -- --
--   (<>) = serial
--   (*) = 'Streamly.Prelude.serial.zipWith' id
--   
-- -- Applicative evaluates the streams being zipped serially: -- --
--   >>> s1 = Stream.fromFoldable [1, 2]
--   
--   >>> s2 = Stream.fromFoldable [3, 4]
--   
--   >>> s3 = Stream.fromFoldable [5, 6]
--   
--   >>> Stream.toList $ Stream.fromZipSerial $ (,,) <$> s1 <*> s2 <*> s3
--   [(1,3,5),(2,4,6)]
--   
-- -- Since: 0.2.0 (Streamly) data ZipSerialM m a -- | For ZipAsyncM streams: -- --
--   (<>) = serial
--   (*) = 'Streamly.Prelude.serial.zipAsyncWith' id
--   
-- -- Applicative evaluates the streams being zipped concurrently, the -- following would take half the time that it would take in serial -- zipping: -- --
--   >>> s = Stream.fromFoldableM $ Prelude.map delay [1, 1, 1]
--   
--   >>> Stream.toList $ Stream.fromZipAsync $ (,) <$> s <*> s
--   ...
--   [(1,1),(1,1),(1,1)]
--   
-- -- Since: 0.2.0 (Streamly) data ZipAsyncM m a -- | A serial IO stream of elements of type a. See SerialT -- documentation for more details. -- -- Since: 0.2.0 (Streamly) type Serial = SerialT IO -- | An interleaving serial IO stream of elements of type a. See -- WSerialT documentation for more details. -- -- Since: 0.2.0 (Streamly) type WSerial = WSerialT IO -- | A serial IO stream of elements of type a with concurrent -- lookahead. See AheadT documentation for more details. -- -- Since: 0.3.0 (Streamly) type Ahead = AheadT IO -- | A demand driven left biased parallely composing IO stream of elements -- of type a. See AsyncT documentation for more details. -- -- Since: 0.2.0 (Streamly) type Async = AsyncT IO -- | A round robin parallely composing IO stream of elements of type -- a. See WAsyncT documentation for more details. -- -- Since: 0.2.0 (Streamly) type WAsync = WAsyncT IO -- | A parallely composing IO stream of elements of type a. See -- ParallelT documentation for more details. -- -- Since: 0.2.0 (Streamly) type Parallel = ParallelT IO -- | An IO stream whose applicative instance zips streams serially. -- -- Since: 0.2.0 (Streamly) type ZipSerial = ZipSerialM IO -- | An IO stream whose applicative instance zips streams wAsyncly. -- -- Since: 0.2.0 (Streamly) type ZipAsync = ZipAsyncM IO -- | A monad that can perform concurrent or parallel IO operations. Streams -- that can be composed concurrently require the underlying monad to be -- MonadAsync. type MonadAsync m = (MonadIO m, MonadBaseControl IO m, MonadThrow m) fromStream :: (IsStream t, Monad m) => Stream m a -> t m a toStream :: (IsStream t, Monad m) => t m a -> Stream m a fromStreamK :: IsStream t => StreamK m a -> t m a toStreamK :: IsStream t => t m a -> StreamK m a -- | Class of types that can represent a stream of elements of some type -- a in some monad m. -- -- Since: 0.2.0 (Streamly) class (forall m a. MonadAsync m => Semigroup (t m a), forall m a. MonadAsync m => Monoid (t m a), forall m. Monad m => Functor (t m), forall m. MonadAsync m => Applicative (t m)) => IsStream t -- | Fix the type of a polymorphic stream as SerialT. -- -- Since: 0.1.0 (Streamly) fromSerial :: IsStream t => SerialT m a -> t m a -- | Fix the type of a polymorphic stream as WSerialT. -- -- Since: 0.2.0 (Streamly) fromWSerial :: IsStream t => WSerialT m a -> t m a -- | Fix the type of a polymorphic stream as AsyncT. -- -- Since: 0.1.0 (Streamly) fromAsync :: IsStream t => AsyncT m a -> t m a -- | Fix the type of a polymorphic stream as AheadT. -- -- Since: 0.3.0 (Streamly) fromAhead :: IsStream t => AheadT m a -> t m a -- | Fix the type of a polymorphic stream as WAsyncT. -- -- Since: 0.2.0 (Streamly) fromWAsync :: IsStream t => WAsyncT m a -> t m a -- | Fix the type of a polymorphic stream as ParallelT. -- -- Since: 0.1.0 (Streamly) fromParallel :: IsStream t => ParallelT m a -> t m a -- | Fix the type of a polymorphic stream as ZipSerialM. -- -- Since: 0.2.0 (Streamly) fromZipSerial :: IsStream t => ZipSerialM m a -> t m a -- | Fix the type of a polymorphic stream as ZipAsyncM. -- -- Since: 0.2.0 (Streamly) fromZipAsync :: IsStream t => ZipAsyncM m a -> t m a -- | Adapt any specific stream type to any other specific stream type. -- -- Since: 0.1.0 (Streamly) adapt :: (IsStream t1, IsStream t2) => t1 m a -> t2 m a -- | Same as fromPure yield :: IsStream t => a -> t m a -- | Same as fromEffect yieldM :: (Monad m, IsStream t) => m a -> t m a -- | Strict left scan with an extraction function. Like scanl', but -- applies a user supplied extraction function (the third argument) at -- each step. This is designed to work with the foldl library. -- The suffix x is a mnemonic for extraction. -- -- Since 0.2.0 -- -- Since: 0.7.0 (Monad m constraint) scanx :: (IsStream t, Monad m) => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b -- | Strict left fold with an extraction function. Like the standard strict -- left fold, but applies a user supplied extraction function (the third -- argument) to the folded value at the end. This is designed to work -- with the foldl library. The suffix x is a mnemonic -- for extraction. foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b -- | Like foldx, but with a monadic step function. foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b -- | Lazy right fold for non-empty streams, using first element as the -- starting value. Returns Nothing if the stream is empty. foldr1 :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a) -- | Run a stream, discarding the results. By default it interprets the -- stream as SerialT, to run other types of streams use the type -- adapting combinators for example runStream . -- fromAsync. runStream :: Monad m => SerialT m a -> m () -- |
--   runN n = runStream . take n
--   
-- -- Run maximum up to n iterations of a stream. runN :: Monad m => Int -> SerialT m a -> m () -- |
--   runWhile p = runStream . takeWhile p
--   
-- -- Run a stream as long as the predicate holds true. runWhile :: Monad m => (a -> Bool) -> SerialT m a -> m () -- | Read lines from an IO Handle into a stream of Strings. fromHandle :: (IsStream t, MonadIO m) => Handle -> t m String -- |
--   toHandle h = D.mapM_ $ hPutStrLn h
--   
-- -- Write a stream of Strings to an IO Handle. toHandle :: MonadIO m => Handle -> SerialT m String -> m () concatUnfold :: (IsStream t, Monad m) => Unfold m a b -> t m a -> t m b