HORIZON HASKELLDocslts/ghc-9.14.x45dd5372026-10-11Search names, modules, packages, or :: a typeCtrl K

GHC 9.14.1 · lts/ghc-9.14.x · 45dd537 · 2026-10-11

Modulestreamly-core-0.3.1Haskell2010

Streamly.Internal.Data.Scanl

Left scans.

Scanl vs Fold

Folds and scans both are consumers of streams. A left scan is a generalization of a fold. While the output of a fold is a singleton value, the output of a scan is a stream. A fold is equivalent to a left scan which produces only the final value in the output stream.

Like folds, a scan has an internal state. Unlike a fold, a scan produces an output on each input, the output is a function of the scan state and the input.

A Scanl m a b can represent a Fold m a b by discarding the intermediate outputs and keeping only the final output of the scan.

Since folds do not care about intermediate values, we do not need the extract function for folds. Because folds do not have a requirement for intermediate values, they can be used for implementing combinators like splitWith where intermediate values are not meaningful and are expensive to compute. Folds provide an applicative and monad behavior to consume the stream in parts and compose the folded results. Scans provide Category like composition and stream zip applicative behavior. The finalization function of a fold would return a single value whereas for scan it may be a stream draining the scan buffer. For these reasons, scans and folds are required as independent abstractions.

Scanl vs Pipe

A scan is a simpler version of the consumer side of pipes. A left scan always produces an output whereas a pipe has an additional ability to skip output. Scans are simpler abstractions to think about compared to pipes and easier for the compiler to optimize and fuse.

Compositions

Scans can be chained in the same way as function composition (Category) and can distribute input (tee Applicative). Folds provide an applicative and monad behavior to consume the stream in parts and compose the folded results. Folds are also a special case of parsers.

  • 3 types
  • 133 values

Imports

136 declarations
Example10 expressions
:m:set -XFlexibleContextsimport Control.Monad (void)import qualified Data.Foldable as Foldableimport Data.Bifunctor(bimap)import Data.Function ((&))import Data.Functor.Identity (Identity, runIdentity)import Data.IORef (newIORef, readIORef, writeIORef)import Data.Maybe (fromJust, isJust)import Data.Monoid (Endo(..), Last(..), Sum(..))
Example3 expressions
import Streamly.Data.Array (Array)import Streamly.Data.Fold (Fold, Tee(..))import Streamly.Data.Stream (Stream)
Example10 expressions
import qualified Data.Map as Mapimport qualified Data.Set as Setimport qualified Data.IntSet as IntSetimport qualified Streamly.Data.Array as Arrayimport qualified Streamly.Data.Fold as Foldimport qualified Streamly.Data.MutArray as MutArrayimport qualified Streamly.Data.Parser as Parserimport qualified Streamly.Data.Stream as Streamimport qualified Streamly.Data.StreamK as StreamKimport qualified Streamly.Data.Unfold as Unfold

For APIs that have not been released yet.

Example3 expressions
import qualified Streamly.Internal.Data.Fold as Foldimport qualified Streamly.Internal.Data.Scanl as Scanlimport qualified Streamly.Internal.Data.Stream as Stream
valuecatEithers :: Scanl m a b -> Scanl m (Either a a) b
#

Remove the either wrapper and flatten both lefts and as well as rights in the output stream.

Definition:

Example1 expression
catEithers = Scanl.lmap (either id id)

Pre-release

valuecatMaybes :: Monad m => Scanl m a b -> Scanl m (Maybe a) b
#

Modify a scan to receive a Maybe input, the Just values are unwrapped and sent to the original scan, Nothing values are discarded.

Example2 expressions
catMaybes = Scanl.mapMaybe idcatMaybes = Scanl.filter isJust . Scanl.lmap fromJust
valueconst :: Applicative m => b -> Scanl m a b
#

Make a scan that yields the supplied value on any input.

Pre-release

valueconstM :: Applicative m => m b -> Scanl m a b
#

Make a scan that runs the supplied effect once and then yields the result on any input.

Pre-release

valuedrain :: Monad m => Scanl m a ()
#

A scan that drains all its input, running the effects and discarding the results.

Example2 expressions
drain = Scanl.drainMapM (const (return ()))drain = Scanl.mkScanl (\_ _ -> ()) ()
valuefilter :: Monad m => (a -> Bool) -> Scanl m a r -> Scanl m a r
#

Include only those elements that pass a predicate.

Example1 expression
Stream.toList $ Stream.scanl (Scanl.filter (> 5) Scanl.sum) $ Stream.fromList [1..10][0,0,0,0,0,0,6,13,21,30,40]
Example3 expressions
filter p = Scanl.postscanlMaybe (Scanl.filtering p)filter p = Scanl.filterM (return . p)filter p = Scanl.mapMaybe (\x -> if p x then Just x else Nothing)
valuefilterM :: Monad m => (a -> m Bool) -> Scanl m a r -> Scanl m a r
#

Like filter but with a monadic predicate.

Example2 expressions
f p x = p x >>= \r -> return $ if r then Just x else NothingfilterM p = Scanl.mapMaybeM (f p)
valuegeneralizeInner :: Monad m => Scanl Identity a b -> Scanl m a b
#

Adapt a pure scan to any monad.

Example1 expression
generalizeInner = Scanl.morphInner (return . runIdentity)

Pre-release

valuegenericLength :: (Monad m, Num b) => Scanl m a b
#

Like length, except with a more general Num return value

Definition:

Example2 expressions
genericLength = fmap getSum $ Scanl.foldMap (Sum . const  1)genericLength = Scanl.mkScanl (\n _ -> n + 1) 0

Pre-release

valuelatest :: Monad m => Scanl m a (Maybe a)
#

Returns the latest element of the input stream, if any.

Example2 expressions
latest = Scanl.mkScanl1 (\_ x -> x)latest = fmap getLast $ Scanl.foldMap (Last . Just)
valuelength :: Monad m => Scanl m a Int
#

Determine the length of the input stream.

Definition:

Example2 expressions
length = Scanl.genericLengthlength = fmap getSum $ Scanl.foldMap (Sum . const  1)
valuelmap :: (a -> b) -> Scanl m b r -> Scanl m a r
#

lmap f scan maps the function f on the input of the scan.

Definition:

Example1 expression
lmap = Scanl.lmapM return

Example:

Example2 expressions
sumSquared = Scanl.lmap (\x -> x * x) Scanl.sumStream.toList $ Stream.scanl sumSquared (Stream.enumerateFromTo 1 10)[0,1,5,14,30,55,91,140,204,285,385]
valuelmapM :: Monad m => (a -> m b) -> Scanl m b r -> Scanl m a r
#

lmapM f scan maps the monadic function f on the input of the scan.

valuemaximum :: (Monad m, Ord a) => Scanl m a (Maybe a)
#

Determine the maximum element in a stream.

Definitions:

Example2 expressions
maximum = Scanl.maximumBy comparemaximum = Scanl.mkScanl1 max

Same as the following but without a default maximum. The Max Monoid uses the minBound as the default maximum:

Example1 expression
maximum = fmap Data.Semigroup.getMax $ Scanl.foldMap Data.Semigroup.Max
valueminimum :: (Monad m, Ord a) => Scanl m a (Maybe a)
#

Determine the minimum element in a stream using the supplied comparison function.

Definitions:

Example2 expressions
minimum = Scanl.minimumBy compareminimum = Scanl.mkScanl1 min

Same as the following but without a default minimum. The Min Monoid uses the maxBound as the default maximum:

Example1 expression
maximum = fmap Data.Semigroup.getMin $ Scanl.foldMap Data.Semigroup.Min
valuemkScanl :: Monad m => (b -> a -> b) -> b -> Scanl m a b
#

Make a scan from a left fold style pure step function and initial value of the accumulator.

If your Scanl returns only Partial (i.e. never returns a Done) then you can use mkScanl* constructors.

valuemkScanl1 :: Monad m => (a -> a -> a) -> Scanl m a (Maybe a)
#

Make a strict left scan, for non-empty streams, using first element as the starting value. Returns Nothing if the stream is empty.

Pre-release

valuemkScanlM :: Monad m => (b -> a -> m b) -> m b -> Scanl m a b
#

Make a scan from a left fold style monadic step function and initial value of the accumulator.

valuemkScanr :: Monad m => (a -> b -> b) -> b -> Scanl m a b
#

Make a scan using a right fold style step function and a terminal value. It performs a strict right fold via a left fold using function composition. Note that a strict right fold can only be useful for constructing strict structures in memory. For reductions this will be very inefficient.

Definitions:

Example2 expressions
mkScanr f z = fmap (flip appEndo z) $ Scanl.foldMap (Endo . f)mkScanr f z = fmap ($ z) $ Scanl.mkScanl (\g x -> g . f x) id

Example:

Example1 expression
Stream.toList $ Stream.scanl (Scanl.mkScanr (:) []) $ Stream.enumerateFromTo 1 5[[],[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4,5]]
valuemkScanrM :: Monad m => (a -> b -> m b) -> m b -> Scanl m a b
#

Like mkScanr but with a monadic step function.

Example:

Example1 expression
toList = Scanl.mkScanrM (\a xs -> return $ a : xs) (return [])

Pre-release

valuemkScant
  1. :: Monad m
  2. => s -> a -> Step s b
  3. -> Step s b
  4. -> s -> b
  5. -> Scanl m a b
#

Make a terminating scan using a pure step function, a pure initial state and a pure state extraction function.

Pre-release

valuemkScantM
  1. :: s -> a -> m (Step s b)
  2. -> m (Step s b)
  3. -> s -> m b
  4. -> Scanl m a b
#

Make a terminating scan with an effectful step function and initial state, and a state extraction function.

Example1 expression
mkScantM = Scanl.Scanl

We can just use Scanl but it is provided for completeness.

Pre-release

valuemorphInner :: (forall x. m x -> n x) -> Scanl m a b -> Scanl n a b
#

Change the underlying monad of a scan. Also known as hoist.

Pre-release

valuepostscanl :: Monad m => Scanl m a b -> Scanl m b c -> Scanl m a c
#

Postscan the input of a Scanl to change it in a stateful manner using another Scanl.

This is basically an append operation.

Pre-release

valuermapM :: Monad m => (b -> m c) -> Scanl m a b -> Scanl m a c
#

Map a monadic function on the output of a scan.

valuetake :: Monad m => Int -> Scanl m a b -> Scanl m a b
#

Take at most n input elements and scan them using the supplied scan. A negative count is treated as 0.

Example1 expression
Stream.toList $ Stream.scanl (Scanl.take 2 Scanl.toList) $ Stream.fromList [1..10][[],[1],[1,2]]
valuetakeEndBy :: Monad m => (a -> Bool) -> Scanl m a b -> Scanl m a b
#

Take the input, stop when the predicate succeeds taking the succeeding element as well.

Example:

Example3 expressions
input = Stream.fromList "hello\nthere\n"line = Scanl.takeEndBy (== '\n') Scanl.toListStream.toList $ Stream.scanl line input["","h","he","hel","hell","hello","hello\n"]
valuetakeEndBy_ :: Monad m => (a -> Bool) -> Scanl m a b -> Scanl m a b
#

Like takeEndBy but drops the element on which the predicate succeeds.

Example:

Example3 expressions
input = Stream.fromList "hello\nthere\n"line = Scanl.takeEndBy_ (== '\n') Scanl.toListStream.toList $ Stream.scanl line input["","h","he","hel","hell","hello","hello"]
valueteeWith
  1. :: Monad m
  2. => b -> c -> d
  3. -> Scanl m a b
  4. -> Scanl m a c
  5. -> Scanl m a d
#

teeWith k f1 f2 distributes its input to both f1 and f2 until any one of them terminates. The outputs of the two scans are combined using the function k.

Definition:

Example1 expression
teeWith k f1 f2 = fmap (uncurry k) (Scanl.tee f1 f2)

Example:

Example2 expressions
avg = Scanl.teeWith (/) Scanl.sum (fmap fromIntegral Scanl.length)Stream.toList $ Stream.postscanl avg $ Stream.fromList [1.0..10.0][1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5]

Note that nested applications of teeWith do not fuse.

Pre-release

valuetoList :: Monad m => Scanl m a [a]
#

Scans the input stream building a list.

Warning! working on large lists accumulated as buffers in memory could be very inefficient, consider using Streamly.Data.Array instead.

Example1 expression
toList = Scanl.mkScanr (:) []
valuetoStreamK :: Monad m => Scanl m a (StreamK n a)
#

Scans its input building a pure stream.

Example1 expression
toStreamK = fmap StreamK.reverse Scanl.toStreamKRev

Internal

valuetoStreamKRev :: Monad m => Scanl m a (StreamK n a)
#

Buffers the input stream to a pure stream in the reverse order of the input.

This is more efficient than toStreamK. toStreamK has exactly the same performance as reversing the stream after toStreamKRev.

Pre-release

datadata Step s b
#

Represents the result of the step of a Fold. Partial returns an intermediate state of the fold, the fold step can be called again with the state or the driver can use extract on the state to get the result out. Done returns the final result and the fold cannot be driven further.

Pre-release

Constructors

Instances2Bifunctor, Functor
  • Bifunctor StepDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Fold.Step

    first maps over the fold state and second maps over the fold result.

  • Functor (Step s)Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Fold.Step

    fmap maps over Done.

    fmap = second
    
datadata Scanl (m :: Type -> Type) a b
#

The type Scanl m a b represents a consumer of an input stream of values of type a and returning a final value of type b in Monad m. The constructor of a scan is Scanl step initial extract final.

The scan uses an internal state of type s. The initial value of the state s is created by initial. This function is called once and only once before the scan starts consuming input. Any resource allocation can be done in this function.

The step function is called on each input, it consumes an input and returns the next intermediate state (see Step) or the final result b if the scan terminates.

The extract function is used by the scan driver to map the current state s of the scan to the scan result. Thus extract can be called multiple times.

Before a scan terminates, final is called once and only once (unless the scan terminated in initial itself). Any resources allocated by initial can be released in final. In scan that do not require any cleanup extract and final are typically the same.

When implementing scan combinators, care should be taken to cleanup any state of the argument folds held by the fold by calling the respective final at all exit points of the scan. Also, final should not be called more than once. Note that if a scan terminates by Done constructor, there is no state to cleanup.

NOTE: The constructor is not yet released, smart constructors are provided to create scans.

Constructors

  • forall s. Scanl (s -> a -> m (Step s b)) (m (Step s b)) (s -> m b) (s -> m b)

    Scanl step initial extract final

Instances2Functor, Applicative
  • Functor m => Functor (Scanl m a)Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Scanl.Type

    Maps a function on the output of the scan (the type b).

  • Monad m => Applicative (Scanl m a)Defined in streamly-core-0.3.1 · Streamly.Internal.Data.Scanl.Type
valuecumulativeScan :: Scanl m (Incr a) b -> Scanl m a b
#

Convert an incremental scan to a cumulative scan using the entire input stream as a single window.

Example1 expression
cumulativeScan = Scanl.lmap Scanl.Insert
valueincrCount :: (Monad m, Num b) => Scanl m (Incr a) b
#

The number of elements in the rolling window.

This is the 0th power sum.

Example1 expression
incrCount = Scanl.incrPowerSum 0
valueincrMean :: (Monad m, Fractional a) => Scanl m (Incr a) a
#

Arithmetic mean of elements in a sliding window:

\mu = \frac{\sum_{i=1}^n x_{i}}{n}

This is also known as the Simple Moving Average (SMA) when used in the sliding window and Cumulative Moving Avergae (CMA) when used on the entire stream.

Example1 expression
incrMean = Scanl.teeWith (/) Scanl.incrSum Scanl.incrCount

Space: \mathcal{O}(1)

Time: \mathcal{O}(n)

valueincrPowerSum :: (Monad m, Num a) => Int -> Scanl m (Incr a) a
#

Sum of the kth power of all the elements in a rolling window:

S_k = \sum_{i=1}^n x_{i}^k

Example1 expression
incrPowerSum k = Scanl.lmap (fmap (^ k)) Scanl.incrSum

Space: \mathcal{O}(1)

Time: \mathcal{O}(n)

valueincrRollingMap
  1. :: Monad m
  2. => Maybe a -> a -> Maybe b
  3. -> Scanl m (Incr a) (Maybe b)
#

Apply a pure function on the latest and the oldest element of the window.

Example1 expression
incrRollingMap f = Scanl.incrRollingMapM (\x y -> return $ f x y)
valueincrRollingMapM
  1. :: Monad m
  2. => Maybe a -> a -> m (Maybe b)
  3. -> Scanl m (Incr a) (Maybe b)
#

Apply an effectful function on the entering and the exiting element of the window. The first argument of the mapped function is the exiting element and the second argument is the entering element.

valueincrScan :: (MonadIO m, Unbox a) => Int -> Scanl m (Incr a) b -> Scanl m a b
#

incrScan collector is an incremental sliding window scan that does not require all the intermediate elements in each step of the scan computation. This maintains n elements in the window, when a new element comes it slides out the oldest element. The new element along with the old element are supplied to the collector scan.

valueincrScanWith
  1. :: (MonadIO m, Unbox a)
  2. => Int
  3. -> Scanl m (Incr a, RingArray a) b
  4. -> Scanl m a b
#

Like incrScan but also provides the ring array to the scan. The ring array reflects the state of the ring after inserting the incoming element.

IMPORTANT NOTE: The ring is mutable, therefore, references to it should not be stored and used later, the state would have changed by then. If you need to store it then copy it to an array or another ring and store it.

valueincrSum :: (Monad m, Num a) => Scanl m (Incr a) a
#

Sum of all the elements in a rolling window:

S = \sum_{i=1}^n x_{i}

This is the first power sum.

Example1 expression
incrSum = Scanl.incrPowerSum 1

Uses Kahan-Babuska-Neumaier style summation for numerical stability of floating precision arithmetic.

Space: \mathcal{O}(1)

Time: \mathcal{O}(n)

valueincrSumInt :: (Monad m, Integral a) => Scanl m (Incr a) a
#

The sum of all the elements in a rolling window. The input elements are required to be integral numbers.

This was written in the hope that it would be a tiny bit faster than incrSum for Integral values. But turns out that incrSum is 2% faster than this even for integral values!

Internal

valuewindowMaximum :: (MonadIO m, Unbox a, Ord a) => Int -> Scanl m a (Maybe a)
#

The maximum element in a rolling window.

See the performance related comments in windowRange.

If you want to compute the maximum of the entire stream Streamly.Data.Scanl.maximum would be much faster.

Time: \mathcal{O}(n*w) where w is the window size.

valuewindowMinimum :: (MonadIO m, Unbox a, Ord a) => Int -> Scanl m a (Maybe a)
#

Find the minimum element in a rolling window.

See the performance related comments in windowRange.

If you want to compute the minimum of the entire stream Streamly.Data.Scanl.minimum is much faster.

Time: \mathcal{O}(n*w) where w is the window size.

valuewindowRange
  1. :: (MonadIO m, Unbox a, Ord a)
  2. => Int
  3. -> Scanl m a (Maybe (a, a))
#

Determine the maximum and minimum in a rolling window.

This implementation traverses the entire window buffer to compute the range whenever we demand it. It performs better than the dequeue based implementation in streamly-statistics package when the window size is small (< 30).

If you want to compute the range of the entire stream Streamly.Data.Scanl.range would be much faster.

Space: \mathcal{O}(n) where n is the window size.

Time: \mathcal{O}(n*w) where w is the window size.

datadata Incr a
#

Represents incremental input for a scan. Insert means a new element is being added to the collection, Replace means an old value in the collection is being replaced with a new value.

Constructors

Instances1Functor
  • Functor IncrDefined in streamly-core-0.3.1 · Streamly.Internal.Data.Scanl.Window
valuebottom :: (MonadIO m, Unbox a, Ord a) => Int -> Scanl m a (MutArray a)
#

Scan the input stream to bottom n elements.

Definition:

Example1 expression
bottom = Scanl.bottomBy compare
Example2 expressions
stream = Stream.fromList [2::Int,7,9,3,1,5,6,11,17]Stream.toList (Stream.scanl (Scanl.bottom 3) stream) >>= mapM MutArray.toList[[],[1],[1,2],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3],[1,2,3]]

Pre-release

valuedeleteBy :: Monad m => (a -> a -> Bool) -> a -> Scanl m a (Maybe a)
#

Returns the latest element omitting the first occurrence that satisfies the given equality predicate.

Example:

Example2 expressions
input = Stream.fromList [1,3,3,5]Stream.toList $ Stream.postscanlMaybe (Scanl.deleteBy (==) 3) input[1,3,5]
valuedistribute :: Monad m => [Scanl m a b] -> Scanl m a [b]
#

Distribute one copy of the stream to each scan and collect the results in a container.


                |-------Scanl m a b--------|
---stream m a---|                          |---m [b]
                |-------Scanl m a b--------|
                |                          |
                           ...
Example1 expression
Stream.toList $ Stream.scanl (Scanl.distribute [Scanl.sum, Scanl.length]) (Stream.enumerateFromTo 1 5)[[0,0],[1,1],[3,2],[6,3],[10,4],[15,5]]
Example1 expression
distribute = Prelude.foldr (Scanl.teeWith (:)) (Scanl.const [])

This is the consumer side dual of the producer side sequence operation.

Stops as soon as any of the scans stop.

valuedrainMapM :: Monad m => (a -> m b) -> Scanl m a ()
#

Definitions:

Example2 expressions
drainMapM f = Scanl.lmapM f Scanl.draindrainMapM f = Scanl.foldMapM (void . f)

Drain all input after passing it through a monadic function. This is the dual of mapM_ on stream producers.

valuedrainN :: Monad m => Int -> Scanl m a ()
#

A scan that drains the first n elements of its input, running the effects and discarding the results.

Definition:

Example1 expression
drainN n = Scanl.take n Scanl.drain

Pre-release

valueelemIndices :: (Monad m, Eq a) => a -> Scanl m a (Maybe Int)
#

Returns the index of the latest element if the element matches the given value.

Definition:

Example1 expression
elemIndices a = Scanl.findIndices (== a)
valuefoldMap :: (Monad m, Monoid b) => (a -> b) -> Scanl m a b
#

Definition:

Example1 expression
foldMap f = Scanl.lmap f Scanl.mconcat

Make a scan from a pure function that scans the output of the function using mappend and mempty.

Example2 expressions
sum = Scanl.foldMap Data.Monoid.SumStream.toList $ Stream.scanl sum $ Stream.enumerateFromTo 1 3[Sum {getSum = 0},Sum {getSum = 1},Sum {getSum = 3},Sum {getSum = 6}]
valuefoldMapM :: (Monad m, Monoid b) => (a -> m b) -> Scanl m a b
#

Definition:

Example1 expression
foldMapM f = Scanl.lmapM f Scanl.mconcat

Make a scan from a monadic function that scans the output of the function using mappend and mempty.

Example2 expressions
sum = Scanl.foldMapM (return . Data.Monoid.Sum)Stream.toList $ Stream.scanl sum $ Stream.enumerateFromTo 1 3[Sum {getSum = 0},Sum {getSum = 1},Sum {getSum = 3},Sum {getSum = 6}]
valueindexed :: Monad m => Scanl m (Int, a) b -> Scanl m a b
#

Pair each element of a scan input with its index, starting from index 0.

Example1 expression
indexed = Scanl.postscanlMaybe Scanl.indexing
valuemapMaybe :: Monad m => (a -> Maybe b) -> Scanl m b r -> Scanl m a r
#

mapMaybe f scan maps a Maybe returning function f on the input of the scan, filters out Nothing elements, and return the values extracted from Just.

Example2 expressions
mapMaybe f = Scanl.lmap f . Scanl.catMaybesmapMaybe f = Scanl.mapMaybeM (return . f)
Example3 expressions
f x = if even x then Just x else Nothingscn = Scanl.mapMaybe f Scanl.toListStream.toList $ Stream.scanl scn (Stream.enumerateFromTo 1 10)[[],[],[2],[2],[2,4],[2,4],[2,4,6],[2,4,6],[2,4,6,8],[2,4,6,8],[2,4,6,8,10]]
valuemapMaybeM :: Monad m => (a -> m (Maybe b)) -> Scanl m b r -> Scanl m a r
#
Example1 expression
mapMaybeM f = Scanl.lmapM f . Scanl.catMaybes
valuemconcat :: (Monad m, Monoid a) => Scanl m a a
#

Monoid concat. Scan an input stream consisting of monoidal elements using mappend and mempty.

Definition:

Example1 expression
mconcat = Scanl.sconcat mempty
Example2 expressions
monoids = fmap Data.Monoid.Sum $ Stream.enumerateFromTo 1 3Stream.toList $ Stream.scanl Scanl.mconcat monoids[Sum {getSum = 0},Sum {getSum = 1},Sum {getSum = 3},Sum {getSum = 6}]
valuemean :: (Monad m, Fractional a) => Scanl m a a
#

Compute a numerically stable arithmetic mean of all elements in the input stream.

valuepartition :: Monad m => Scanl m b x -> Scanl m c x -> Scanl m (Either b c) x
#

Compose two scans such that the combined scan accepts a stream of Either and routes the Left values to the first scan and Right values to the second scan.

Definition:

Example1 expression
partition = Scanl.partitionBy id
valuepartitionBy
  1. :: Monad m
  2. => a -> Either b c
  3. -> Scanl m b x
  4. -> Scanl m c x
  5. -> Scanl m a x
#

Same as partitionByM but with a pure partition function.

Example, count even and odd numbers in a stream:

Example1 expression
:{ let f = Scanl.partitionBy (\n -> if even n then Left n else Right n)                     (fmap (("Even " ++) . show) Scanl.length)                     (fmap (("Odd "  ++) . show) Scanl.length)  in Stream.toList $ Stream.postscanl f (Stream.enumerateFromTo 1 10):}["Odd 1","Even 1","Odd 2","Even 2","Odd 3","Even 3","Odd 4","Even 4","Odd 5","Even 5"]

Pre-release

valuepartitionByM
  1. :: Monad m
  2. => a -> m (Either b c)
  3. -> Scanl m b x
  4. -> Scanl m c x
  5. -> Scanl m a x
#

Partition the input over two scans using an Either partitioning predicate.


                                    |-------Scanl b x--------|
-----stream m a --> (Either b c)----|                        |----(x,y)
                                    |-------Scanl c y--------|

Example, send input to either scan randomly:

Example5 expressions
:set -package randomimport System.Random (randomIO)randomly a = randomIO >>= \x -> return $ if x then Left a else Right af = Scanl.partitionByM randomly Scanl.length Scanl.lengthStream.toList $ Stream.scanl f (Stream.enumerateFromTo 1 10)...

Example, send input to the two scans in a proportion of 2:1:

Example3 expressions
:set -fno-warn-unrecognised-warning-flags:set -fno-warn-x-partial:{proportionately m n = do ref <- newIORef $ cycle $ concat [replicate m Left, replicate n Right] return $ \a -> do     r <- readIORef ref     writeIORef ref $ tail r     return $ Prelude.head r a:}
Example1 expression
:{main = do g <- proportionately 2 1 let f = Scanl.partitionByM g Scanl.length Scanl.length r <- Stream.toList $ Stream.scanl f (Stream.enumerateFromTo (1 :: Int) 10) print r:}
Example1 expression
main...

This is the consumer side dual of the producer side mergeBy operation.

Terminates as soon as any of the scans terminate.

Pre-release

valueproduct :: (Monad m, Num a, Eq a) => Scanl m a a
#

Determine the product of all elements of a stream of numbers. Returns multiplicative identity (1) when the stream is empty. The scan terminates when it encounters (0) in its input.

Same as the following but terminates on multiplication by 0:

Example1 expression
product = fmap Data.Monoid.getProduct $ Scanl.foldMap Data.Monoid.Product
valueprune :: (a -> Bool) -> Scanl m a (Maybe a)
#

Strip all leading and trailing occurrences of an element passing a predicate and make all other consecutive occurrences uniq.

> prune p = Stream.dropWhileAround p $ Stream.uniqBy (x y -> p x && p y)
> Stream.prune isSpace (Stream.fromList "  hello      world!   ")
"hello world!"

Space: O(1)

Unimplemented

valuerollingHash :: (Monad m, Enum a) => Scanl m a Int64
#

Compute an Int sized polynomial rolling hash of a stream.

Example1 expression
rollingHash = Scanl.rollingHashWithSalt Scanl.defaultSalt
valuerollingHashFirstN :: (Monad m, Enum a) => Int -> Scanl m a Int64
#

Compute an Int sized polynomial rolling hash of the first n elements of a stream.

Example1 expression
rollingHashFirstN n = Scanl.take n Scanl.rollingHash

Pre-release

valuerollingMap :: Monad m => (Maybe a -> a -> b) -> Scanl m a b
#
Example1 expression
rollingMap f = Scanl.rollingMapM (\x y -> return $ f x y)
valuerollingMapM :: Monad m => (Maybe a -> a -> m b) -> Scanl m a 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 processing the very first element in the stream, the previous element is Nothing.

Pre-release

valuesampleFromthen :: Monad m => Int -> Int -> Scanl m a b -> Scanl m a b
#

sampleFromthen offset stride samples the element at offset index and then every element at strides of stride.

valuescanl :: Monad m => Scanl m a b -> Scanl m b c -> Scanl m a c
#

Scan the input of a Scanl to change it in a stateful manner using another Scanl. The scan stops as soon as any of the scans terminates.

This is basically an append operation.

Pre-release

valuescanlMany :: Monad m => Scanl m a b -> Scanl m b c -> Scanl m a c
#

Scan the input of a Scanl to change it in a stateful manner using another Scanl. The scan restarts with a fresh state if it terminates.

Pre-release

valuesconcat :: (Monad m, Semigroup a) => a -> Scanl m a a
#

Semigroup concat. Append the elements of an input stream to a provided starting value.

Definition:

Example1 expression
sconcat = Scanl.mkScanl (<>)
Example2 expressions
semigroups = fmap Data.Monoid.Sum $ Stream.enumerateFromTo 1 3Stream.toList $ Stream.scanl (Scanl.sconcat 3) semigroups[Sum {getSum = 3},Sum {getSum = 4},Sum {getSum = 6},Sum {getSum = 9}]
valuesum :: (Monad m, Num a) => Scanl m a a
#

Determine the sum of all elements of a stream of numbers. Returns additive identity (0) when the stream is empty. Note that this is not numerically stable for floating point numbers.

Example1 expression
sum = Scanl.cumulativeScan Scanl.incrSum

Same as following but numerically stable:

Example2 expressions
sum = Scanl.mkScanl (+) 0sum = fmap Data.Monoid.getSum $ Scanl.foldMap Data.Monoid.Sum
valuetee :: Monad m => Scanl m a b -> Scanl m a c -> Scanl m a (b, c)
#

Distribute one copy of the stream to each scan and zip the results.

                |-------Scanl m a b--------|
---stream m a---|                          |---m (b,c)
                |-------Scanl m a c--------|

Definition:

Example1 expression
tee = Scanl.teeWith (,)

Example:

Example2 expressions
t = Scanl.tee Scanl.sum Scanl.lengthStream.toList $ Stream.scanl t (Stream.enumerateFromTo 1.0 10.0)[(0.0,0),(1.0,1),(3.0,2),(6.0,3),(10.0,4),(15.0,5),(21.0,6),(28.0,7),(36.0,8),(45.0,9),(55.0,10)]
valuethe :: (Monad m, Eq a) => Scanl m a (Maybe a)
#

Terminates with Nothing as soon as it finds an element different than the previous one, returns the element if the entire input consists of the same element.

valuetoListRev :: Monad m => Scanl m a [a]
#

Buffers the input stream to a list in the reverse order of the input.

Definition:

Example1 expression
toListRev = Scanl.mkScanl (flip (:)) []

Warning! working on large lists accumulated as buffers in memory could be very inefficient, consider using Streamly.Array instead.

valuetoStream :: (Monad m, Monad n) => Scanl m a (Stream n a)
#

A scan that buffers its input to a pure stream.

Warning! working on large streams accumulated as buffers in memory could be very inefficient, consider using Streamly.Data.Array instead.

Example1 expression
toStream = fmap Stream.fromList Scanl.toList

Pre-release

valuetoStreamRev :: (Monad m, Monad n) => Scanl m a (Stream n a)
#

Buffers the input stream to a pure stream in the reverse order of the input.

Example1 expression
toStreamRev = fmap Stream.fromList Scanl.toListRev

Warning! working on large streams accumulated as buffers in memory could be very inefficient, consider using Streamly.Data.Array instead.

Pre-release

valuetop :: (MonadIO m, Unbox a, Ord a) => Int -> Scanl m a (MutArray a)
#

Scan the input stream to top n elements.

Definition:

Example1 expression
top = Scanl.topBy compare
Example2 expressions
stream = Stream.fromList [2::Int,7,9,3,1,5,6,11,17]Stream.toList (Stream.scanl (Scanl.top 3) stream) >>= mapM MutArray.toList[[],[17],[17,11],[17,11,9],[17,11,9],[17,11,9],[17,11,9],[17,11,9],[17,11,9],[17,11,9]]

Pre-release

valuetopBy
  1. :: (MonadIO m, Unbox a)
  2. => a -> a -> Ordering
  3. -> Int
  4. -> Scanl m a (MutArray a)
#

Get the top n elements using the supplied comparison function.

To get bottom n elements instead:

Example1 expression
bottomBy cmp = Scanl.topBy (flip cmp)

Example:

Example2 expressions
stream = Stream.fromList [2::Int,7,9,3,1,5,6,11,17]Stream.toList (Stream.scanl (Scanl.topBy compare 3) stream) >>= mapM MutArray.toList[[],[17],[17,11],[17,11,9],[17,11,9],[17,11,9],[17,11,9],[17,11,9],[17,11,9],[17,11,9]]

Pre-release

valueunfoldMany :: Monad m => Unfold m a b -> Scanl m b c -> Scanl m a c
#

Unfold and flatten the input stream of a scan.

Stream.scanl (unfoldMany u f) == Stream.scanl f . Stream.unfoldMany u

Pre-release

valueuniqBy :: Monad m => (a -> a -> Bool) -> Scanl m a (Maybe a)
#

Return the latest unique element using the supplied comparison function. Returns Nothing if the current element is same as the last element otherwise returns Just.

Example, strip duplicate path separators:

Example3 expressions
input = Stream.fromList "//a//b"f x y = x == '/' && y == '/'Stream.toList $ Stream.postscanlMaybe (Scanl.uniqBy f) input"/a/b"

Space: O(1)

Pre-release

valueunzip :: Monad m => Scanl m a x -> Scanl m b y -> Scanl m (a, b) (x, y)
#

Send the elements of tuples in a stream of tuples through two different scans.


                          |-------Scanl m a x--------|
---------stream of (a,b)--|                          |----m (x,y)
                          |-------Scanl m b y--------|

Definition:

Example1 expression
unzip = Scanl.unzipWith id

This is the consumer side dual of the producer side zip operation.

valueunzipWith
  1. :: Monad m
  2. => a -> (b, c)
  3. -> Scanl m b x
  4. -> Scanl m c y
  5. -> Scanl m a (x, y)
#

Split elements in the input stream into two parts using a pure splitter function, direct each part to a different scan and zip the results.

Definitions:

Example2 expressions
unzipWith f = Scanl.unzipWithM (return . f)unzipWith f fld1 fld2 = Scanl.lmap f (Scanl.unzip fld1 fld2)

This scan terminates as soon as any of the input scans terminate.

Pre-release

valueunzipWithM
  1. :: Monad m
  2. => a -> m (b, c)
  3. -> Scanl m b x
  4. -> Scanl m c y
  5. -> Scanl m a (x, y)
#

Like unzipWith but with a monadic splitter function.

Definition:

Example1 expression
unzipWithM k f1 f2 = Scanl.lmapM k (Scanl.unzip f1 f2)

Pre-release

valuewith
  1. :: Scanl m (s, a) b -> Scanl m a b
  2. -> ((s, a) -> c) -> Scanl m (s, a) b -> Scanl m (s, a) b
  3. -> (s, a) -> c
  4. -> Scanl m a b
  5. -> Scanl m a b
#

Change the predicate function of a Scanl from a -> b to accept an additional state input (s, a) -> b. Convenient to filter with an addiitonal index or time input.

Example1 expression
filterWithIndex = Scanl.with Scanl.indexed Scanl.filter
filterWithAbsTime = with timestamped filter
filterWithRelTime = with timeIndexed filter

Pre-release

valuezipStream :: Monad m => Stream m a -> Scanl m (a, b) x -> Scanl m b x
#

Zip a stream with the input of a scan.

Example1 expression
zip = Scanl.zipStreamWithM (curry return)

Unimplemented

valuezipStreamWithM
  1. :: a -> b -> m c
  2. -> Stream m a
  3. -> Scanl m c x
  4. -> Scanl m b x
#

Zip a stream with the input of a scan using the supplied function.

Unimplemented

valueclassify
  1. :: (MonadIO m, Ord k)
  2. => a -> k
  3. -> Scanl m a b
  4. -> Scanl m a (Maybe (k, b))
#

Scans the values for each key using the supplied scan.

Once the scan for a key terminates, any future values of the key are ignored.

Equivalent to the following except that the scan is not restarted:

Example1 expression
classify f fld = Scanl.demux f (const fld)
valueclassifyIO
  1. :: (MonadIO m, Ord k)
  2. => a -> k
  3. -> Scanl m a b
  4. -> Scanl m a (Maybe (k, b))
#

Same as classify except that it uses mutable IORef cells in the Map, providing better performance.

Equivalent to the following except that the scan is not restarted:

Example1 expression
classifyIO f fld = Scanl.demuxIO f (const fld)
valuecountDistinct :: (Monad m, Ord a) => Scanl m a Int
#

Count non-duplicate elements in the stream.

Definition:

Example2 expressions
countDistinct = fmap Set.size Scanl.toSetcountDistinct = Scanl.postscanl Scanl.nub $ Scanl.catMaybes $ Scanl.length

The memory used is proportional to the number of distinct elements in the stream, to guard against using too much memory use it as a scan and terminate if the count reaches more than a threshold.

Space: \mathcal{O}(n)

Pre-release

valuecountDistinctInt :: Monad m => Scanl m Int Int
#

Like countDistinct but specialized to a stream of Int, for better performance.

Definition:

Example2 expressions
countDistinctInt = fmap IntSet.size Scanl.toIntSetcountDistinctInt = Scanl.postscanl Scanl.nubInt $ Scanl.catMaybes $ Scanl.length

Pre-release

valuedemux
  1. :: (Monad m, Ord k)
  2. => a -> k
  3. -> k -> m (Maybe (Scanl m a b))
  4. -> Scanl m a (Maybe (k, b))
#

demux getKey getScan: In a key value stream, scan values corresponding to each key using a key specific scan. getScan is invoked to generate a key specific scan when a key is encountered for the first time in the stream. If a scan does not exist corresponding to the key then Nothing is returned otherwise the result of the scan is returned.

If a scan terminates, another instance of the scan is started upon receiving an input with that key, getScan is invoked again whenever the key is encountered again.

This can be used to scan a stream, splitting it based on different keys.

Since the scan generator function is monadic we can add scans dynamically. For example, we can maintain a Map of keys to scans in an IORef and lookup the scan from that corresponding to a key. This Map can be changed dynamically, scans for new keys can be added or scans for old keys can be deleted or modified.

Compare with classify, the scan in classify is a static scan.

Pre-release

valuedemuxGeneric
  1. :: (Monad m, IsMap f, Traversable f)
  2. => a -> Key f
  3. -> Key f -> m (Maybe (Scanl m a b))
  4. -> Scanl m a (m (f b), Maybe (Key f, b))
#

This is the most general of all demux, classify operations.

The first component of the output tuple is a key-value Map of in-progress scans. The scan returns the scan result as the second component of the output tuple.

See demux for documentation.

valuedemuxGenericIO
  1. :: (MonadIO m, IsMap f, Traversable f)
  2. => a -> Key f
  3. -> Key f -> m (Maybe (Scanl m a b))
  4. -> Scanl m a (m (f b), Maybe (Key f, b))
#

This is specialized version of demuxGeneric that uses mutable IO cells as scan accumulators for better performance.

Keep in mind that the values in the returned Map may be changed by the ongoing scan if you are using those concurrently in another thread.

valuedemuxIO
  1. :: (MonadIO m, Ord k)
  2. => a -> k
  3. -> k -> m (Maybe (Scanl m a b))
  4. -> Scanl m a (Maybe (k, b))
#

This is specialized version of demux that uses mutable IO cells as scan accumulators for better performance.

valuenub :: (Monad m, Ord a) => Scanl m a (Maybe a)
#

Returns Just for the first occurrence of an element, returns Nothing for any other occurrences.

Example:

Example2 expressions
stream = Stream.fromList [1::Int,1,2,3,4,4,5,1,5,7]Stream.toList $ Stream.postscanlMaybe Scanl.nub stream[1,2,3,4,5,7]

Pre-release

valuetoIntSet :: Monad m => Scanl m Int IntSet
#

Scan the input adding it to an int set. For integer inputs this performs better than toSet.

Definition:

Example1 expression
toIntSet = Scanl.mkScanl (flip IntSet.insert) IntSet.empty
valuetoSet :: (Monad m, Ord a) => Scanl m a (Set a)
#

Scan the input adding it to a set.

Definition:

Example1 expression
toSet = Scanl.mkScanl (flip Set.insert) Set.empty