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 :: Monad m => Stream (Of Int) (Stream (Of String) m) ()
Like any fold,
toList takes no notice of the monad of effects.
toList :: Monad m => Stream (Of a) m r -> 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
:: 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)