The standard way of inspecting the first item in a stream of elements, if the
stream is still 'running'. The Right case contains a
Haskell pair, where the more general inspect would return a left-strict pair.
There is no reason to prefer inspect since, if the Right case is exposed,
the first element in the pair will have been evaluated to whnf.
next :: Control.Monad m => Stream (Of a) m r %1-> m (Either r (a, Stream (Of a) m r))
inspect :: Control.Monad m => Stream (Of a) m r %1-> m (Either r (Of a (Stream (Of a) m r)))
Split a succession of layers after some number, returning a streaming or
effectful pair. This function is the same as the splitsAt exported by the
Streaming module, but since this module is imported qualified, it can
usurp a Prelude name. It specializes to:
splitAt :: Control.Monad m => Int -> Stream (Of a) m r %1-> Stream (Of a) m (Stream (Of a) m r)
Yield elements, using a fold to maintain state, until the accumulated
value satifies the supplied predicate. The fold will then be short-circuited
and the element that breaks it will be put after the break.
This function is easiest to use with purely
Given a stream on a sum of functors, make it a stream on the left functor,
with the streaming on the other functor as the governing monad. This is
useful for acting on one or the other functor with a fold, leaving the
other material for another treatment. It generalizes
partitionEithers, but actually streams properly.
>>> let odd_even = S.maps (S.distinguish even) $ S.each' [1..10::Int]
>>> :t separate odd_even
separate odd_even
:: Monad m => Stream (Of Int) (Stream (Of Int) m) ()
Now, for example, it is convenient to fold on the left and right values separately:
The catMaybes function takes a Stream of Maybes and returns
a Stream of all of the Just values. concat has the same behavior,
but is more general; it works for any foldable container type.
The mapMaybe function is a version of map which can throw out elements. In particular,
the functional argument returns something of type Maybe b. If this is Nothing, no element
is added on to the result Stream. If it is Just b, then b is included in the result Stream.
Change the effects of one monad to another with a transformation.
This is one of the fundamental transformations on streams.
Compare with maps:
maps :: (Control.Monad m, Control.Functor f) => (forall x. f x %1-> g x) -> Stream f m r %1-> Stream g m r
hoist :: (Control.Monad m, Control.Functor f) => (forall a. m a %1-> n a) -> Stream f m r %1-> Stream f n r
vvaluemap :: Monadm => (a -> b) -> Stream (Ofa) mr %1 -> Stream (Ofb) mr
Map layers of one functor to another with a transformation involving the base monad.
This function is completely functor-general. It is often useful with the more concrete type
mapped :: (forall x. Stream (Of a) IO x -> IO (Of b x)) -> Stream (Stream (Of a) IO) IO r -> Stream (Of b) IO r
to process groups which have been demarcated in an effectful, IO-based
stream by grouping functions like Streaming.Prelude.group,
Streaming.Prelude.split or Streaming.Prelude.breaks. Summary functions
like Streaming.Prelude.fold, Streaming.Prelude.foldM,
Streaming.Prelude.mconcat or Streaming.Prelude.toList are often used
to define the transformation argument. For example:
Streaming.Prelude.maps and Streaming.Prelude.mapped obey these rules:
maps id = id
mapped return = id
maps f . maps g = maps (f . g)
mapped f . mapped g = mapped (f <=< g)
maps f . mapped g = mapped (fmap f . g)
mapped f . maps g = mapped (f <=< fmap g)
where f and g are Control.Monads
Streaming.Prelude.maps is more fundamental than
Streaming.Prelude.mapped, which is best understood as a convenience for
effecting this frequent composition:
Map layers of one functor to another with a transformation. Compare
hoist, which has a similar effect on the monadic parameter.
mapsPost id = id
mapsPost f . mapsPost g = mapsPost (f . g)
mapsPost f = maps f
mapsPost is essentially the same as maps, but it imposes a Control.Functor constraint on
its target functor rather than its source functor. It should be preferred if fmap
is cheaper for the target functor than for the source functor.
Map layers of one functor to another with a transformation involving the base monad.
mapsMPost is essentially the same as mapsM, but it imposes a Control.Functor constraint on
its target functor rather than its source functor. It should be preferred if fmap
is cheaper for the target functor than for the source functor.
mapsPost is more fundamental than mapsMPost, which is best understood as a convenience
for effecting this frequent composition:
A version of mapped that imposes a Control.Functor constraint on the target functor rather
than the source functor. This version should be preferred if fmap on the target
functor is cheaper.
Replace each element in a stream of individual values with a functorial
layer of any sort. subst = flip with and is more convenient in
a sequence of compositions that transform a stream.
with = flip subst
for str f = concats $ subst f str
subst f = maps (\(a:>r) -> r <$ f a)
S.concat = concats . subst each
vvaluecopy :: Monadm => Stream (Ofa) mr %1 -> Stream (Ofa) (Stream (Ofa) m) r
Duplicate the content of a stream, so that it can be acted on twice in different ways,
but without breaking streaming. Thus, with each' [1,2] I might do:
>>> S.print $ each' ["one","two"]
"one"
"two"
>>> S.stdoutLn $ each' ["one","two"]
one
two
With copy, I can do these simultaneously:
>>> S.print $ S.stdoutLn $ S.copy $ each' ["one","two"]
"one"
one
"two"
two
copy should be understood together with effects and is subject to the rules
S.effects . S.copy = id
hoist S.effects . S.copy = id
The similar operations in Data.ByteString.Streaming obey the same rules.
Where the actions you are contemplating are each simple folds over
the elements, or a selection of elements, then the coupling of the
folds is often more straightforwardly effected with Control.Foldl,
e.g.
A Control.Foldl fold can be altered to act on a selection of elements by
using handles on an appropriate lens. Some such
manipulations are simpler and more Data.List-like, using copy:
But anything that fold of a Stream (Of a) m r into e.g. an m (Of b r)
that has a constraint on m that is carried over into Stream f m -
e.g. Control.Monad, Control.Functor, etc. can be used on the stream.
Thus, I can fold over different groupings of the original stream:
Here the sum (10) and the product (24) have been 'stored' for use when
finally we have traversed the stream with print . Needless to say,
a second pass is excluded conceptually, so the
folds that you apply successively with store are performed
simultaneously, and in constant memory -- as they would be if,
say, you linked them together with Control.Fold:
>>> L.impurely S.foldM (liftA3 (a b c -> (b, c)) (L.sink Prelude.print) (L.generalize L.sum) (L.generalize L.product)) $ each' [1..4]
1
2
3
4
(10,24) :> ()
Fusing folds after the fashion of Control.Foldl will generally be a bit faster
than the corresponding succession of uses of store, but by
constant factor that will be completely dwarfed when any IO is at issue.
But store / copy is much more powerful, as you can see by reflecting on
uses like this:
It will be clear that this cannot be reproduced with any combination of lenses,
Control.Fold folds, or the like. (See also the discussion of copy.)
It would conceivably be clearer to import a series of specializations of store.
It is intended to be used at types like this:
storeM :: (forall s m . Control.Monad m => Stream (Of a) m s %1-> m (Of b s))
-> (Control.Monad n => Stream (Of a) n r %1-> Stream (Of a) n (Of b r))
storeM = store
It is clear from this type that we are just using the general instance:
instance (Control.Functor f, Control.Monad m) => Control.Monad (Stream f m)
We thus can't be touching the elements of the stream, or the final return value.
It is the same with other constraints that Stream (Of a) inherits from the underlying monad.
Thus I can independently filter and write to one file, but
nub and write to another, or interact with a database and a logfile and the like:
Like the Data.List.sequence but streaming. The result type is a
stream of a's, but is not accumulated; the effects of the elements
of the original stream are interleaved in the resulting stream. Compare:
sequence :: Monad m => [m a] -> m [a]
sequence :: Control.Monad m => Stream (Of (m a)) m r %1-> Stream (Of a) m r
Strict left scan, accepting a monadic function. It can be used with
FoldMs from Control.Foldl using impurely. Here we yield
a succession of vectors each recording
>>> let v = L.impurely scanM L.vectorM $ each' [1..4::Int] :: Stream (Of (Vector Int)) IO ()
>>> S.print v
[]
[1]
[1,2]
[1,2,3]
[1,2,3,4]
slidingWindow accumulates the first n elements of a stream,
update thereafter to form a sliding window of length n.
It follows the behavior of the slidingWindow function in
conduit-combinators.
Before evaluating the monadic action returning the next step in the Stream, wrapEffect
extracts the value in a monadic computation m a and passes it to a computation a -> m y.