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)