HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulelinear-base-0.4.0Haskell2010

Streaming.Linear.Internal.Many

This module contains all functions that do something with multiple streams as input or output. This includes combining streams, splitting a stream, etc.

  • 3 types
  • 12 values

Operations that use or return multiple Streams

0 declarations

Zips and Unzip

valueunzip
  1. :: Monad m
  2. => Stream (Of (a, b)) m r
  3. -> Stream (Of a) (Stream (Of b) m) r
#

The type

Data.List.unzip     :: [(a,b)] -> ([a],[b])

might lead us to expect

Streaming.unzip :: Stream (Of (a,b)) m r -> Stream (Of a) m (Stream (Of b) m r)

which would not stream, since it would have to accumulate the second stream (of bs). Of course, Data.List unzip doesn't stream either.

This unzip does stream, though of course you can spoil this by using e.g. toList:

>>> let xs = Prelude.map (x -> (x, Prelude.show x)) [1..5 :: Int]

>>> S.toList $ S.toList $ S.unzip (S.each' xs)
["1","2","3","4","5"] :> ([1,2,3,4,5] :> ())

>>> Prelude.unzip xs
([1,2,3,4,5],["1","2","3","4","5"])

Note the difference of order in the results. It may be of some use to think why. The first application of toList was applied to a stream of integers:

>>> :t S.unzip $ S.each' xs
S.unzip $ S.each' xs :: Control.Monad m => Stream (Of Int) (Stream (Of String) m) ()

Like any fold, toList takes no notice of the monad of effects.

toList :: Control.Monad m => Stream (Of a) m r %1-> m (Of [a] r)

In the case at hand (since I am in ghci) m = Stream (Of String) IO. So when I apply toList, I exhaust that stream of integers, folding it into a list:

>>> :t S.toList $ S.unzip $ S.each' xs
S.toList $ S.unzip $ S.each' xs
 :: Control.Monad m => Stream (Of String) m (Of [Int] ())

When I apply toList to this, I reduce everything to an ordinary action in IO, and return a list of strings:

>>> S.toList $ S.toList $ S.unzip (S.each' xs)
["1","2","3","4","5"] :> ([1,2,3,4,5] :> ())

unzip can be considered a special case of either unzips or expand:

 unzip = unzips . maps (((a,b) :> x) -> Compose (a :> b :> x))
 unzip = expand $ p ((a,b) :> abs) -> b :> p (a :> abs)
typetype ZipResidual a b (m :: Type -> Type) r1 r2 = Either3 (r1, r2) (r1, Stream (Of b) m r2) (Stream (Of a) m r1, r2)
#

The remainder of zipping two streams

typetype ZipResidual3 a b c (m :: Type -> Type) r1 r2 r3 = (Either r1 (Stream (Of a) m r1), Either r2 (Stream (Of b) m r2), Either r3 (Stream (Of c) m r3))
#

The (liberal) remainder of zipping three streams. This has the downside that the possibility of three remainders is allowed, though it will never occur.

valuezip
  1. :: Monad m
  2. => Stream (Of a) m r1
  3. -> Stream (Of b) m r2
  4. -> Stream (Of (a, b)) m (r1, r2)
#

zip zips two streams exhausing the remainder of the longer stream and consuming its effects.

valuezipR
  1. :: Monad m
  2. => Stream (Of a) m r1
  3. -> Stream (Of b) m r2
  4. -> Stream (Of (a, b)) m (ZipResidual a b m r1 r2)
#

zipR zips two streams keeping the remainder if there is one.

valuezipWith
  1. :: Monad m
  2. => a -> b -> c
  3. -> Stream (Of a) m r1
  4. -> Stream (Of b) m r2
  5. -> Stream (Of c) m (r1, r2)
#
valuezipWithR
  1. :: Monad m
  2. => a -> b -> c
  3. -> Stream (Of a) m r1
  4. -> Stream (Of b) m r2
  5. -> Stream (Of c) m (ZipResidual a b m r1 r2)
#

zipWithR zips two streams applying a function along the way, keeping the remainder of zipping if there is one. Note. If two streams have the same length, but one needs to perform some effects to obtain the end-of-stream result, that stream is treated as a residual.

valuezip3
  1. :: Monad m
  2. => Stream (Of a) m r1
  3. -> Stream (Of b) m r2
  4. -> Stream (Of c) m r3
  5. -> Stream (Of (a, b, c)) m (r1, r2, r3)
#

Like zipR but with three streams.

valuezip3R
  1. :: Monad m
  2. => Stream (Of a) m r1
  3. -> Stream (Of b) m r2
  4. -> Stream (Of c) m r3
  5. -> Stream (Of (a, b, c)) m (ZipResidual3 a b c m r1 r2 r3)
#

Like zipR but with three streams.

valuezipWith3
  1. :: Monad m
  2. => a -> b -> c -> d
  3. -> Stream (Of a) m r1
  4. -> Stream (Of b) m r2
  5. -> Stream (Of c) m r3
  6. -> Stream (Of d) m (r1, r2, r3)
#

Like zipWith but with three streams

valuezipWith3R
  1. :: Monad m
  2. => a -> b -> c -> d
  3. -> Stream (Of a) m r1
  4. -> Stream (Of b) m r2
  5. -> Stream (Of c) m r3
  6. -> Stream (Of d) m (ZipResidual3 a b c m r1 r2 r3)
#

Like zipWithR but with three streams.

datadata Either3 a b c where
#

Constructors

  • Left3 :: a -> Either3 a b c
  • Middle3 :: b -> Either3 a b c
  • Right3 :: c -> Either3 a b c

Merging

valuemerge
  1. :: (Monad m, Ord a)
  2. => Stream (Of a) m r
  3. -> Stream (Of a) m s
  4. -> Stream (Of a) m (r, s)
#

Merge two streams of elements ordered with their Ord instance.

The return values of both streams are returned.

>>> S.print $ merge (each [1,3,5]) (each [2,4])
1
2
3
4
5
((), ())
valuemergeOn
  1. :: (Monad m, Ord b)
  2. => a -> b
  3. -> Stream (Of a) m r
  4. -> Stream (Of a) m s
  5. -> Stream (Of a) m (r, s)
#

Merge two streams, ordering them by applying the given function to each element before comparing.

The return values of both streams are returned.

valuemergeBy
  1. :: Monad m
  2. => a -> a -> Ordering
  3. -> Stream (Of a) m r
  4. -> Stream (Of a) m s
  5. -> Stream (Of a) m (r, s)
#

Merge two streams, ordering the elements using the given comparison function.

The return values of both streams are returned.