-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Streaming, dataflow programming and declarative concurrency -- -- Streamly comprises 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 the missing functionality to quickly -- build general-purpose applications in Haskell. For high-level -- functionality built over streamly like streaming system 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.9.0 -- | 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 -- | Create an Array from the first N elements of a list. The array -- is allocated to size N, if the list terminates before N elements then -- the array may hold less than N elements. fromListN :: Unbox a => Int -> [a] -> Array a -- | Create an Array from a list. The list must be of finite size. fromList :: Unbox a => [a] -> Array a -- | writeN n folds a maximum of n elements from the -- input stream to an Array. writeN :: forall (m :: Type -> Type) a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a) -- | Fold the whole input to a single array. -- -- Caution! Do not use this on infinite streams. write :: forall (m :: Type -> Type) a. (MonadIO m, Unbox a) => Fold m a (Array a) -- | writeLastN n folds a maximum of n elements from the -- end of the input stream to an Array. writeLastN :: forall a (m :: Type -> Type). (Storable a, Unbox a, MonadIO m) => Int -> Fold m a (Array a) -- | Convert an Array into a list. toList :: Unbox a => Array a -> [a] -- | Convert an Array into a stream. -- -- Pre-release read :: forall (m :: Type -> Type) a. (Monad m, Unbox a) => Array a -> Stream m a -- | Convert an Array into a stream in reverse order. -- -- Pre-release readRev :: forall (m :: Type -> Type) a. (Monad m, Unbox a) => Array a -> Stream m a -- | Cast an array having elements of type a into an array having -- elements of type b. The length of the array should be a -- multiple of the size of the target element otherwise Nothing is -- returned. cast :: forall a b. Unbox b => Array a -> Maybe (Array b) -- | Cast an Array a into an Array Word8. asBytes :: Array a -> Array Word8 -- | O(1) Get the length of the array i.e. the number of elements in -- the array. length :: Unbox a => Array a -> Int -- | O(1) Lookup the element at the given index. Index starts from -- 0. 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 -- | Tee is a newtype wrapper over the Fold type providing -- distributing Applicative, Semigroup, Monoid, -- Num, Floating and Fractional instances. -- -- The input received by the composed Tee is replicated and -- distributed to the constituent folds of the Tee. -- -- For example, to compute the average of numbers in a stream without -- going through the stream twice: -- --
--   >>> avg = (/) <$> (Tee Fold.sum) <*> (Tee $ fmap fromIntegral Fold.length)
--   
--   >>> Stream.fold (unTee avg) $ Stream.fromList [1.0..100.0]
--   50.5
--   
-- -- Similarly, the Semigroup and Monoid instances of -- Tee distribute the input to both the folds and combine the -- outputs using Monoid or Semigroup instances of the output types: -- --
--   >>> import Data.Monoid (Sum(..))
--   
--   >>> t = Tee Fold.one <> Tee Fold.latest
--   
--   >>> Stream.fold (unTee t) (fmap Sum $ Stream.enumerateFromTo 1.0 100.0)
--   Just (Sum {getSum = 101.0})
--   
-- -- The Num, Floating, and Fractional instances work -- in the same way. 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 -- |

Processing Unicode Strings

-- -- A Char stream is the canonical representation to process -- Unicode strings. It can be processed efficiently using regular stream -- processing operations. A byte stream of Unicode text read from an IO -- device or from an Array in memory can be decoded into a -- Char stream using the decoding routines in this module. A -- String ([Char]) can be converted into a Char -- stream using fromList. An Array Char can be -- unfolded into a stream using the array read unfold. -- --

Storing Unicode Strings

-- -- A stream of Char can be encoded into a byte stream using the -- encoding routines in this module and then written to IO devices or to -- arrays in memory. -- -- If you have to store a Char stream in memory you can convert it -- into a String using toList or using the toList -- fold. The String type can be more efficient than pinned arrays -- for short and short lived strings. -- -- For longer or long lived streams you can fold the Char -- stream as Array Char using the array write fold. The -- Array type provides a more compact representation and pinned -- memory reducing GC overhead. If space efficiency is a concern you can -- use encodeUtf8' on the Char stream before writing it to -- an Array providing an even more compact representation. -- --

String Literals

-- -- Stream Identity Char and Array Char are instances of -- IsString and IsList, therefore, -- OverloadedStrings and OverloadedLists extensions can -- be used for convenience when specifying unicode strings literals using -- these types. -- --

Pitfalls

-- -- -- --

Experimental APIs

-- -- Some experimental APIs to conveniently process text using the -- Array Char represenation directly can be found in -- Streamly.Internal.Memory.Unicode.Array. -- | Deprecated: Please use Streamly.Unicode.Stream module from the -- streamly-core package. module Streamly.Data.Unicode.Stream -- | Decode a stream of bytes to Unicode characters by mapping each byte to -- a corresponding Unicode Char in 0-255 range. decodeLatin1 :: forall (m :: Type -> Type). Monad m => Stream m Word8 -> Stream m Char -- | Decode a UTF-8 encoded bytestream to a stream of Unicode characters. -- Any invalid codepoint encountered is replaced with the unicode -- replacement character. decodeUtf8 :: forall (m :: Type -> Type). Monad m => Stream m Word8 -> Stream m Char -- | Like encodeLatin1' but silently maps input codepoints beyond -- 255 to arbitrary Latin1 chars in 0-255 range. No error or exception is -- thrown when such mapping occurs. encodeLatin1 :: forall (m :: Type -> Type). Monad m => Stream m Char -> Stream m Word8 -- | Encode a stream of Unicode characters to a UTF-8 encoded bytestream. -- Any Invalid characters (U+D800-U+D8FF) in the input stream are -- replaced by the Unicode replacement character U+FFFD. encodeUtf8 :: forall (m :: Type -> Type). Monad m => Stream m Char -> Stream m Word8 -- | Same as decodeUtf8 decodeUtf8Lax :: forall (m :: Type -> Type). Monad m => Stream m Word8 -> Stream m Char -- | Same as encodeLatin1 encodeLatin1Lax :: forall (m :: Type -> Type). Monad m => Stream m Char -> Stream m Word8 -- | Same as encodeUtf8 encodeUtf8Lax :: forall (m :: Type -> Type). Monad m => Stream m Char -> Stream m Word8 -- | 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 LiftedRep) RunInIO :: (forall b. () => m b -> IO (StM m b)) -> RunInIO (m :: Type -> TYPE LiftedRep) [runInIO] :: RunInIO (m :: Type -> TYPE LiftedRep) -> 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 -- | 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 () -- | 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 module Streamly.Internal.Data.Fold.Async -- | 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 -- | A value associated with an IO action that is automatically called -- whenever the value is garbage collected. module Streamly.Internal.Data.IOFinalizer.Lifted -- | An IOFinalizer has an associated IO action that is -- automatically called whenever the finalizer is garbage collected. The -- action can be run and cleared prematurely. -- -- You can hold a reference to the finalizer in your data structure, if -- the data structure gets garbage collected the finalizer will be -- called. -- -- It is implemented using mkWeakIORef. -- -- Pre-release 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 -- | Run the action associated with the finalizer and deactivate it so that -- it never runs again. Note, the finalizing action runs with async -- exceptions masked. -- -- Pre-release 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) module Streamly.Internal.Data.SVar.Worker 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 () instance GHC.Show.Show Streamly.Internal.Data.SVar.Worker.Work module Streamly.Internal.Data.SVar.Dispatch 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 () module Streamly.Internal.Data.SVar.Pull 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 () module Streamly.Internal.Data.SVar 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.SVar -- | 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 () -- | A Channel is a place where streams join and new streams start. This -- module defines low level data structures and functions to build -- channels. For concrete Channels see the Channel modules of specific -- stream types. -- -- A Channel is a conduit to the output from multiple streams running -- concurrently and asynchronously. A channel can be thought of as an -- asynchronous IO handle. We can write any number of streams to a -- channel in a non-blocking manner and then read them back at any time -- at any pace. The channel would run the streams asynchronously and -- accumulate results. A channel may not really execute the stream -- completely and accumulate all the results. However, it ensures that -- the reader can read the results at whatever pace it wants to read. The -- channel monitors and adapts to the consumer's pace. -- -- A channel is a mini scheduler, it has an associated workLoop that -- holds the stream tasks to be picked and run by a pool of worker -- threads. It has an associated output queue where the output stream -- elements are placed by the worker threads. An outputDoorBell is used -- by the worker threads to intimate the consumer thread about -- availability of new results in the output queue. More workers are -- added to the channel by fromChannel on demand if the output -- produced is not keeping pace with the consumer. On bounded channels, -- workers block on the output queue to provide throttling of the -- producer when the consumer is not pulling fast enough. The number of -- workers may even get reduced depending on the consuming pace. module Streamly.Internal.Data.Stream.Channel.Types 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. With eager on workers -- are dispatched aggresively as long as there is more work to do -- irrespective of whether there is output pending to be processed. -- 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 -- | 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 -- | 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 () -- | concatMapDivK useTail useHead stream, divides the stream in -- head and tail, maps a stream generator on the head and maps an action -- on the tail of a stream. Returns the stream generated by the head. -- -- Used for concurrent evaluation of streams using a Channel. concatMapDivK :: Monad m => (StreamK m a -> m ()) -> (a -> StreamK m b) -> StreamK m a -> StreamK m b instance GHC.Classes.Ord Streamly.Internal.Data.Stream.Channel.Types.Count instance GHC.Real.Integral Streamly.Internal.Data.Stream.Channel.Types.Count instance GHC.Real.Real Streamly.Internal.Data.Stream.Channel.Types.Count instance GHC.Num.Num Streamly.Internal.Data.Stream.Channel.Types.Count instance GHC.Enum.Bounded Streamly.Internal.Data.Stream.Channel.Types.Count instance GHC.Enum.Enum Streamly.Internal.Data.Stream.Channel.Types.Count instance GHC.Show.Show Streamly.Internal.Data.Stream.Channel.Types.Count instance GHC.Read.Read Streamly.Internal.Data.Stream.Channel.Types.Count instance GHC.Classes.Eq Streamly.Internal.Data.Stream.Channel.Types.Count instance GHC.Show.Show Streamly.Internal.Data.Stream.Channel.Types.Limit instance GHC.Show.Show Streamly.Internal.Data.Stream.Channel.Types.ThreadAbort instance GHC.Show.Show Streamly.Internal.Data.Stream.Channel.Types.LatencyRange instance GHC.Exception.Type.Exception Streamly.Internal.Data.Stream.Channel.Types.ThreadAbort instance GHC.Classes.Eq Streamly.Internal.Data.Stream.Channel.Types.Limit instance GHC.Classes.Ord Streamly.Internal.Data.Stream.Channel.Types.Limit module Streamly.Internal.Data.Stream.Channel.Dispatcher -- | 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 -- | Collecting results from child workers in a streamed fashion module Streamly.Internal.Data.Stream.Channel.Worker 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 () instance GHC.Show.Show Streamly.Internal.Data.Stream.Channel.Worker.Work module Streamly.Internal.Data.Fold.Concurrent.Channel.Type 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 module Streamly.Internal.Data.Fold.Concurrent.Channel data 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 -- | 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 -- | Print debug information about the Channel when the stream -- ends. inspect :: Bool -> Config -> Config -- | Evaluate the fold asynchronously in a worker thread separate from the -- driver thread. parEval :: MonadAsync m => (Config -> Config) -> Fold m a b -> Fold m a b -- | Eval a fold asynchronously in a separate thread. -- -- Use multiple worker folds to fold a stream and collect the results -- using another fold, combine using a monoid. The results can be -- collected out-of-order or in-order. -- -- Concurrent append: if one fold's buffer becomes full then use the next -- one Concurrent interleave/partition: Round robin to n folds. -- Concurrent distribute to multiple folds. module Streamly.Internal.Data.Fold.Concurrent -- | 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 -- | Print debug information about the Channel when the stream -- ends. inspect :: Bool -> Config -> Config -- | Evaluate a stream asynchronously using a channel and serve the -- consumer from the evaluation buffer. -- --
--   >>> eval = Fold.parEval id
--   
eval :: MonadAsync m => Fold m a b -> Fold m a b -- | Evaluate the fold asynchronously in a worker thread separate from the -- driver thread. parEval :: MonadAsync m => (Config -> Config) -> Fold m a b -> Fold m a b module Streamly.Internal.Data.Stream.Concurrent.Channel.Type -- | 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 module Streamly.Internal.Data.Stream.Concurrent.Channel.Dispatcher 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 () module Streamly.Internal.Data.Stream.Concurrent.Channel.Operations -- | 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 module Streamly.Internal.Data.Stream.Concurrent.Channel.Consumer 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 module Streamly.Internal.Data.Stream.Concurrent.Channel.Interleave -- | 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 newChannel. newChannel :: MonadAsync m => (Config -> Config) -> m (Channel m a) -- | The functions in this module are separated from the combinators using -- these because of a GHC issue. We need to have newChannel specialized -- but not inlined. If we keep it in the same module as its users we -- cannot achieve that and the code becomes bloated. But if it is in a -- separate module we can use INLINABLE and SPECIALIZE on it which makes -- it specialized but it is not actually inlined. module Streamly.Internal.Data.Stream.Concurrent.Channel.Append -- | 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 newChannel. newChannel :: MonadRunInIO m => (Config -> Config) -> m (Channel m a) module Streamly.Internal.Data.Stream.Concurrent.Channel -- | 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 -- | 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 -- | 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 () -- | Stop the channel. Kill all running worker threads. stopChannel :: MonadIO m => Channel m a -> 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 -- | 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. With eager on workers -- are dispatched aggresively as long as there is more work to do -- irrespective of whether there is output pending to be processed. -- 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 -- | Non-parallelizable stream combinators like unfoldrM, iterateM etc. can -- be evaluated concurrently with the stream consumer by using -- eval. Parallelizable combinators like repeatM, replicateM can -- generate the stream concurrently using concatMap. module Streamly.Internal.Data.Stream.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) -- | 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 -- | 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. With eager on workers -- are dispatched aggresively as long as there is more work to do -- irrespective of whether there is output pending to be processed. -- 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. 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 -- | 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 -- | 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 -- | Print debug information about the Channel when the stream -- ends. inspect :: Bool -> Config -> Config -- | Evaluate a stream asynchronously. In a serial stream, each element of -- the stream is generated as it is demanded by the consumer. -- parEval evaluates multiple elements of the stream ahead of time -- and serves the results from a buffer. -- -- Note that the evaluation requires only one thread as only one stream -- needs to be evaluated. Therefore, the concurrency options that are -- relevant to multiple streams won't apply here e.g. maxThreads, eager, -- interleaved, ordered, stopWhen options won't have any effect. 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)
--   
-- -- Example, the following example finishes in 1 second as 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 -- |
--   >>> parSequence modifier = Stream.parMapM modifier id
--   
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 -- | Supplies a stream generating callback to a callback setter function. -- Each invocation of the callback results in a value being generated in -- the resulting stream. -- -- Pre-release fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> Stream m a tapCountD :: MonadAsync m => (a -> Bool) -> (Stream m Int -> m b) -> Stream m a -> Stream m a -- | tapCount predicate fold stream taps the count of those -- elements in the stream that pass the predicate. The resulting -- count stream is sent to another thread which folds it using -- fold. -- -- 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.tapCount (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 tapCount :: MonadAsync m => (a -> Bool) -> (Stream m Int -> m b) -> Stream m a -> Stream m a module Streamly.Internal.Data.Stream.Exception.Lifted -- | 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 m b with async exceptions disabled but -- keeping blocking operations interruptible (see mask). Use the -- output b as input to b -> Stream 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 :: (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. -- -- 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 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 MonadTrans Parallel
--       where {-# INLINE lift #-}
--             lift = Parallel . Stream.fromEffect
--   instance (Monad (Parallel m),
--             MonadThrow m) => MonadThrow (Parallel m)
--       where {-# INLINE throwM #-}
--             throwM = lift . 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, deriving all the usual instances. -- -- 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
--   
-- -- Example, create an applicative type with zipping apply: -- --
--   >>> :{
--    zipApply = Stream.zipWith ($)
--    $(mkZipType "ZipStream" "zipApply" False)
--   :}
--   
-- -- Example, create an applicative type with concurrent zipping apply: -- --
--   >>> :{
--    parApply = Stream.parApply id
--    $(mkZipType "ParZipStream" "parApply" True)
--   :}
--   
-- -- Example, create a monad type with an eager concurrent cross product -- bind: -- --
--   >>> :{
--    parBind = flip (Stream.parConcatMap (Stream.eager True))
--    $(mkCrossType "ParEagerStream" "parBind" 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. 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 MonadTrans Parallel
--       where {-# INLINE lift #-}
--             lift = Parallel . Stream.fromEffect
--   instance (Monad (Parallel m),
--             MonadThrow m) => MonadThrow (Parallel m)
--       where {-# INLINE throwM #-}
--             throwM = lift . 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.Base.MonadBase b m, GHC.Base.Monad m) => Control.Monad.Base.MonadBase b (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.Base.MonadBase b m, GHC.Base.Monad m) => Control.Monad.Base.MonadBase b (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) module Streamly.Internal.Data.Stream.SVar.Generate -- | 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 -- | Eliminate a stream by distributing it to multiple SVars concurrently. module Streamly.Internal.Data.Stream.SVar.Eliminate -- | 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 -- | 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 GHC.Base.Monad m => GHC.Base.Functor (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 (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 GHC.Base.Monad m => GHC.Base.Functor (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 (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 GHC.Base.Monad m => GHC.Base.Functor (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 (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 GHC.Base.Monad m => GHC.Base.Functor (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 (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.Time -- | 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.chunksOfTimeout 5 1 Fold.toList s
--   
-- -- Pre-release chunksOfTimeout :: 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 -- | This module re-exports the Streamly.Data.Stream module from the -- "streamly-core" package and additionally provides concurrency, time -- and lifted exception operations as well in a single module. -- -- Also see the following modules for more pre-release operations: -- -- 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. With eager on workers -- are dispatched aggresively as long as there is more work to do -- irrespective of whether there is output pending to be processed. -- 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 -- | Evaluate a stream asynchronously. In a serial stream, each element of -- the stream is generated as it is demanded by the consumer. -- parEval evaluates multiple elements of the stream ahead of time -- and serves the results from a buffer. -- -- Note that the evaluation requires only one thread as only one stream -- needs to be evaluated. Therefore, the concurrency options that are -- relevant to multiple streams won't apply here e.g. maxThreads, eager, -- interleaved, ordered, stopWhen options won't have any effect. 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 -- | Supplies a stream generating callback to a callback setter function. -- Each invocation of the callback results in a value being generated in -- the resulting stream. -- -- Pre-release fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> Stream m a -- | Definition: -- --
--   >>> parMapM modifier f = Stream.parConcatMap modifier (Stream.fromEffect . f)
--   
-- -- Example, the following example finishes in 1 second as 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 -- |
--   >>> parSequence modifier = Stream.parMapM modifier id
--   
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 -- | tapCount predicate fold stream taps the count of those -- elements in the stream that pass the predicate. The resulting -- count stream is sent to another thread which folds it using -- fold. -- -- 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.tapCount (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 tapCount :: 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 m b with async exceptions disabled but -- keeping blocking operations interruptible (see mask). Use the -- output b as input to b -> Stream 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 :: (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 -- | To run examples in this module: -- --
--   >>> import qualified Streamly.Prelude as Stream
--   
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 -- | Deprecated: Please use ZipSerialM instead. 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.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.Internal.Data.Stream as Stream
--   
--   >>> import qualified Streamly.Data.Fold as Fold
--   
module Streamly.Internal.Data.Stream.Zip.Concurrent newtype ZipConcurrent m a ZipConcurrent :: Stream m a -> ZipConcurrent m a [getZipConcurrent] :: ZipConcurrent m a -> Stream m a instance GHC.Base.Monad m => GHC.Base.Functor (Streamly.Internal.Data.Stream.Zip.Concurrent.ZipConcurrent m) instance Streamly.Internal.Control.Concurrent.MonadAsync m => GHC.Base.Applicative (Streamly.Internal.Data.Stream.Zip.Concurrent.ZipConcurrent m) -- | To run examples in this module: -- --
--   >>> import qualified Streamly.Prelude as Stream
--   
-- | Deprecated: Please use -- Streamly.Internal.Data.Stream.Zip.Concurrent 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) -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Type -- | 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 toStream :: IsStream t => t m a -> StreamK m a fromStream :: IsStream t => StreamK m a -> t m a -- | 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 |: newtype StreamK (m :: Type -> TYPE LiftedRep) 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 LiftedRep) a fromStreamD :: (IsStream t, Monad m) => Stream m a -> t m a toStreamD :: (IsStream t, Monad m) => t m a -> Stream m a 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 -- | 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 -- | 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 -- | 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 -- | 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 serial IO stream of elements of type a. See SerialT -- documentation for more details. -- -- Since: 0.2.0 (Streamly) type Serial = SerialT IO -- | Fix the type of a polymorphic stream as SerialT. -- -- Since: 0.1.0 (Streamly) fromSerial :: IsStream t => SerialT m a -> t 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 -- | 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 -- | Fix the type of a polymorphic stream as WSerialT. -- -- Since: 0.2.0 (Streamly) fromWSerial :: IsStream t => WSerialT m a -> t 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 -- | 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 -- | Fix the type of a polymorphic stream as AsyncT. -- -- Since: 0.1.0 (Streamly) fromAsync :: IsStream t => AsyncT m a -> t 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 -- | 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 -- | Fix the type of a polymorphic stream as WAsyncT. -- -- Since: 0.2.0 (Streamly) fromWAsync :: IsStream t => WAsyncT m a -> t 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 -- | 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 -- | Fix the type of a polymorphic stream as AheadT. -- -- Since: 0.3.0 (Streamly) fromAhead :: IsStream t => AheadT m a -> t 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 -- | 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 -- | Fix the type of a polymorphic stream as ParallelT. -- -- Since: 0.1.0 (Streamly) fromParallel :: IsStream t => ParallelT m a -> t 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 -- | An IO stream whose applicative instance zips streams serially. -- -- Since: 0.2.0 (Streamly) type ZipSerial = ZipSerialM IO -- | Fix the type of a polymorphic stream as ZipSerialM. -- -- Since: 0.2.0 (Streamly) fromZipSerial :: IsStream t => ZipSerialM m a -> t 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 -- | An IO stream whose applicative instance zips streams wAsyncly. -- -- Since: 0.2.0 (Streamly) type ZipAsync = ZipAsyncM IO -- | 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 fromPure :: IsStream t => a -> t m a fromEffect :: (Monad m, IsStream t) => m a -> t m a repeat :: IsStream t => a -> 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 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 drain :: (IsStream t, Monad m) => t m a -> m () -- |
--   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 -- | Convert a stream into a list in the underlying monad. toList :: (IsStream t, Monad m) => t m a -> m [a] foldrMx :: (IsStream t, Monad m) => (a -> m x -> m x) -> m x -> (m 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 -- | 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 associative fold. foldl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> m b fold :: (IsStream t, Monad m) => Fold m a b -> t m a -> m b -- | Compare two streams for equality eqBy :: (IsStream t, Monad m) => (a -> b -> Bool) -> t m a -> t m b -> m Bool -- | Compare two streams cmpBy :: (IsStream t, Monad m) => (a -> b -> Ordering) -> t m a -> t m b -> m Ordering instance Streamly.Internal.Data.Stream.IsStream.Type.IsStream Streamly.Internal.Data.Stream.Serial.SerialT instance Streamly.Internal.Data.Stream.IsStream.Type.IsStream Streamly.Internal.Data.Stream.Serial.WSerialT instance Streamly.Internal.Data.Stream.IsStream.Type.IsStream Streamly.Internal.Data.Stream.Async.AsyncT instance Streamly.Internal.Data.Stream.IsStream.Type.IsStream Streamly.Internal.Data.Stream.Async.WAsyncT instance Streamly.Internal.Data.Stream.IsStream.Type.IsStream Streamly.Internal.Data.Stream.Ahead.AheadT instance Streamly.Internal.Data.Stream.IsStream.Type.IsStream Streamly.Internal.Data.Stream.Parallel.ParallelT instance Streamly.Internal.Data.Stream.IsStream.Type.IsStream Streamly.Internal.Data.Stream.Zip.ZipSerialM instance Streamly.Internal.Data.Stream.IsStream.Type.IsStream Streamly.Internal.Data.Stream.ZipAsync.ZipAsyncM -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Lift -- | 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) -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Exception -- | 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 -- | The functions defined in this module should be rarely needed for -- direct use, try to use the operations from the Enumerable type -- class instances instead. -- -- This module provides an Enumerable type class to enumerate -- Enum types into a stream. The operations in this type class -- correspond to similar perations in the Enum type class, the -- only difference is that they produce a stream instead of a list. These -- operations cannot be defined generically based on the Enum type -- class. We provide instances for commonly used types. If instances for -- other types are needed convenience functions defined in this module -- can be used to define them. Alternatively, these functions can be used -- directly. -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Enumeration -- | 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 instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable () instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Types.Bool instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Types.Ordering instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Types.Char instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Types.Int instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Int.Int8 instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Int.Int16 instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Int.Int32 instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Int.Int64 instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Types.Word instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Word.Word8 instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Word.Word16 instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Word.Word32 instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Word.Word64 instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Num.Integer.Integer instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Num.Natural.Natural instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Types.Float instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable GHC.Types.Double instance Data.Fixed.HasResolution a => Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable (Data.Fixed.Fixed a) instance GHC.Real.Integral a => Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable (GHC.Real.Ratio a) instance Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable a => Streamly.Internal.Data.Stream.IsStream.Enumeration.Enumerable (Data.Functor.Identity.Identity a) -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Combinators -- | 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 () -- | Bottom level IsStream module that can be used by all other upper level -- IsStream modules. -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Common -- |
--   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 -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Transform -- | 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 -- | 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. -- -- Since: 0.5.0 (Streamly) 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 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 -- | Most of the combinators in this module can be implemented as unfolds. -- Some of them however can only be expressed in terms StreamK e.g. -- cons/consM, fromFoldable, mfix. We can possibly remove those from this -- module which can be expressed as unfolds. Unless we want to use -- rewrite rules to rewrite them as StreamK when StreamK is used, -- avoiding conversion to StreamD. Will that help? Are there any other -- reasons to keep these and not use unfolds? -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Generate 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 -- | This module contains functions ending in the shape: -- --
--   t m a -> m b
--   
-- -- We call them stream folding functions, they reduce a stream t m -- a to a monadic value m b. -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Eliminate -- | 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 -- | 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) -- | Parse a stream using the supplied ParserD Parser. -- -- Internal parseD :: Monad m => Parser a m b -> SerialT m a -> m (Either ParseError 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 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 -- | 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 -- |
--   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 () -- | 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 -- | 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 -- | 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) -- | 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)) -- | 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) -- | 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) -- | 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) -- | 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] -- |
--   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] -- | Convert a stream to a pure stream. -- --
--   toStream = Stream.foldr Stream.cons Stream.nil
--   
-- -- Pre-release toStream :: Monad m => SerialT m a -> m (SerialT n a) -- | 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) -- | Same as |$.. -- -- Internal foldAsync :: (IsStream t, MonadAsync m) => (t m a -> m b) -> t m a -> m b -- | 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 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)) -- | 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 () -- |
--   toHandle h = D.mapM_ $ hPutStrLn h
--   
-- -- Write a stream of Strings to an IO Handle. toHandle :: MonadIO m => Handle -> SerialT m String -> m () -- | Expand a stream by combining two or more streams or by combining -- streams with unfolds. -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Expand -- | 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 -- | Reduce streams by streams, folds or parsers. -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Reduce -- | 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) -- | Top level IsStream module that can use all other lower level IsStream -- modules. -- | Deprecated: Please use "Streamly.Data.Stream.*" instead. module Streamly.Internal.Data.Stream.IsStream.Top -- | 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) -- | 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 LiftedRep) 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 LiftedRep) 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 -- | 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 fromStream :: (IsStream t, Monad m) => Stream m a -> t m a toStream :: (IsStream t, Monad m) => t m a -> Stream m a -- | Lifted resource management primitives. module Streamly.Internal.Data.Unfold.Exception -- | 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 module Streamly.Internal.Data.Unfold.SVar -- | 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 -- | Like accept but binds on the specified IPv4 address of the -- machine and listens for TCP connections on the specified port. -- -- Pre-release acceptOnAddr :: MonadIO m => (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Socket acceptOnAddrWith :: MonadIO m => [(SocketOption, Int)] -> (Word8, Word8, Word8, Word8) -> PortNumber -> Stream m Socket -- | Like accept 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. -- --
--   acceptOnPort = acceptOnAddr (0,0,0,0)
--   
-- -- Pre-release acceptOnPort :: 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. -- --
--   acceptOnPortLocal = acceptOnAddr (127,0,0,1)
--   
-- -- Pre-release acceptOnPortLocal :: MonadIO m => PortNumber -> Stream m 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 -- | 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. -- --
--   acceptorOnPort = UF.first acceptorOnAddr (0,0,0,0)
--   
acceptorOnPort :: MonadIO m => Unfold m PortNumber Socket acceptorOnPortWith :: MonadIO m => [(SocketOption, Int)] -> Unfold m PortNumber Socket -- | Like acceptorOnAddr 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. -- --
--   acceptorOnPortLocal = UF.first acceptorOnAddr (127,0,0,1)
--   
acceptorOnPortLocal :: MonadIO m => Unfold m 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 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 -- | 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

-- -- 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.Array as A
--   
-- -- For experimental APIs see Streamly.Internal.Data.Array. -- | Deprecated: Use Streamly.Data.Array.Foreign instead module Streamly.Memory.Array data Array a -- | Create an Array from the first N elements of a list. The array -- is allocated to size N, if the list terminates before N elements then -- the array may hold less than N elements. fromListN :: Unbox a => Int -> [a] -> Array a -- | Create an Array from a list. The list must be of finite size. fromList :: Unbox a => [a] -> Array a -- | writeN n folds a maximum of n elements from the -- input stream to an Array. writeN :: forall (m :: Type -> Type) a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a) -- | Fold the whole input to a single array. -- -- Caution! Do not use this on infinite streams. write :: forall (m :: Type -> Type) a. (MonadIO m, Unbox a) => Fold m a (Array a) -- | Convert an Array into a list. toList :: Unbox a => Array a -> [a] -- | Convert an Array into a stream. -- -- Pre-release read :: forall (m :: Type -> Type) a. (Monad m, Unbox a) => Array a -> Stream m a -- | O(1) Get the length of the array i.e. the number of elements in -- the array. length :: Unbox a => Array a -> Int -- | Combinators to build Inet/TCP clients and servers. -- --
--   >>> import qualified Streamly.Network.Inet.TCP as TCP
--   
module Streamly.Network.Inet.TCP -- | 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 -- | 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. -- --
--   acceptorOnPort = UF.first acceptorOnAddr (0,0,0,0)
--   
acceptorOnPort :: MonadIO m => Unfold m PortNumber Socket -- | Like acceptorOnAddr 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. -- --
--   acceptorOnPortLocal = UF.first acceptorOnAddr (127,0,0,1)
--   
acceptorOnPortLocal :: MonadIO m => Unfold m 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: Please use acceptorOnAddr instead acceptOnAddr :: MonadIO m => Unfold m ((Word8, Word8, Word8, Word8), PortNumber) Socket -- | Deprecated: Please use acceptorOnPort instead acceptOnPort :: MonadIO m => Unfold m PortNumber Socket -- | Deprecated: Please use acceptorOnPortLocal instead acceptOnPortLocal :: 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 operations please consult the -- Network.Socket module of the network package. -- --

Examples

-- -- To write a server, use the acceptor unfold to start listening -- for connections from clients. acceptor 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 as Stream
--   
--   >>> 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 =
--               Stream.unfold Socket.acceptor (maxListenQueue, spec, addr)
--             & Stream.parMapM (Stream.eager True) (Socket.forSocketM echo)
--             & Stream.fold Fold.drain
--         echo sk =
--               Stream.unfold Socket.chunkReader 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)] -- | 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) -- | 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 acceptor instead accept :: MonadIO m => Unfold m (Int, SockSpec, SockAddr) Socket -- | Deprecated: Please use getChunk instead readChunk :: Int -> Socket -> IO (Array Word8) -- | Deprecated: Please use putChunk instead writeChunk :: Unbox a => Socket -> Array a -> IO () -- | Deprecated: Please use reader instead read :: MonadIO m => Unfold m Socket Word8 -- | Same as readWith -- | Deprecated: Please use readerWith instead readWithBufferOf :: MonadIO m => Unfold m (Int, Socket) Word8 -- | Deprecated: Please use chunkReader instead readChunks :: MonadIO m => Unfold m Socket (Array 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 -- | 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. -- -- Since: 0.5.0 (Streamly) 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 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 -- | Streamly is a general purpose programming framework using cocnurrent -- data flow programming paradigm. It can be considered as a -- generalization of Haskell lists to monadic streaming with concurrent -- composition capability. The serial stream type in streamly SerialT -- m a is like the list type [a] parameterized by the monad -- m. For example, SerialT IO a is a moral equivalent -- of [a] in the IO monad. Streams are constructed very much -- like lists, except that they use nil and cons instead of -- '[]' and :. -- --
--   > import Streamly
--   > import Streamly.Prelude (cons, consM)
--   > import qualified Streamly.Prelude as S
--   >
--   > S.toList $ 1 `cons` 2 `cons` 3 `cons` nil
--   [1,2,3]
--   
-- -- Unlike lists, streams can be constructed from monadic effects: -- --
--   > S.toList $ getLine `consM` getLine `consM` S.nil
--   hello
--   world
--   ["hello","world"]
--   
-- -- Streams are processed just like lists, with list like combinators, -- except that they are monadic and work in a streaming fashion. Here is -- a simple console echo program example: -- --
--   > S.drain $ S.repeatM getLine & S.mapM putStrLn
--   
-- -- SerialT Identity a is a moral equivalent of pure lists. -- Streamly utilizes fusion for high performance, therefore, we can -- represent and process strings as streams of Char, encode and -- decode the streams to/from UTF8 and serialize them to Array -- Word8 obviating the need for special purpose libraries like -- bytestring and text. -- -- For more details please see the Streamly.Tutorial module and -- the examples directory in this package. -- | Deprecated: Please use Streamly.Prelude instead. module Streamly -- | 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) -- | 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 -- | 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 |& -- | 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 |&. -- | Make a stream asynchronous, triggers the computation and returns a -- stream in the underlying monad representing the output generated by -- the original computation. The returned action is exhaustible and must -- be drained once. If not drained fully we may have a thread blocked -- forever and once exhausted it will always return empty. mkAsync :: (IsStream t, MonadAsync m) => t m a -> m (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` -- | 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 -- | 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. -- -- Since: 0.5.0 (Streamly) 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 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 -- | 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 serially :: IsStream t => SerialT m a -> t m a wSerially :: IsStream t => WSerialT m a -> t m a asyncly :: IsStream t => AsyncT m a -> t m a aheadly :: IsStream t => AheadT m a -> t m a wAsyncly :: IsStream t => WAsyncT m a -> t m a parallely :: IsStream t => ParallelT m a -> t m a zipSerially :: IsStream t => ZipSerialM m a -> t m a zipAsyncly :: 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 -- | 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 -- | Same as concatFoldableWith foldWith :: (IsStream t, Foldable f) => (t m a -> t m a -> t m a) -> f (t m a) -> t m a -- | Same as concatMapFoldableWith foldMapWith :: (IsStream t, Foldable f) => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b -- | Same as concatForFoldableWith forEachWith :: (IsStream t, Foldable f) => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b -- | The class of semigroups (types with an associative binary operation). -- -- Instances should satisfy the following: -- -- class Semigroup a -- | An associative operation. -- --
--   >>> [1,2,3] <> [4,5,6]
--   [1,2,3,4,5,6]
--   
(<>) :: Semigroup a => a -> a -> a -- | Reduce a non-empty list with <> -- -- The default definition should be sufficient, but this can be -- overridden for efficiency. -- --
--   >>> import Data.List.NonEmpty (NonEmpty (..))
--   
--   >>> sconcat $ "Hello" :| [" ", "Haskell", "!"]
--   "Hello Haskell!"
--   
sconcat :: Semigroup a => NonEmpty a -> a -- | Repeat a value n times. -- -- Given that this works on a Semigroup it is allowed to fail if -- you request 0 or fewer repetitions, and the default definition will do -- so. -- -- By making this a member of the class, idempotent semigroups and -- monoids can upgrade this to execute in <math> by picking -- stimes = stimesIdempotent or stimes = -- stimesIdempotentMonoid respectively. -- --
--   >>> stimes 4 [1]
--   [1,1,1,1]
--   
stimes :: (Semigroup a, Integral b) => b -> a -> a infixr 6 <> -- | Same as "Streamly.Prelude.runStream". runStream :: Monad m => SerialT m a -> m ()