@@ -253,10 +253,10 @@ module Streamly.Internal.Prelude
253253 , mergeAsyncByM
254254
255255 -- ** Zipping
256− , zipWith
257− , zipWithM
258− , zipAsyncWith
259− , zipAsyncWithM
256+ , Z.zipWith
257+ , Z.zipWithM
258+ , Z.zipAsyncWith
259+ , Z.zipAsyncWithM
260260
261261 -- ** Nested Streams
262262 , concatMapM
@@ -446,14 +446,15 @@ import Streamly.Internal.Data.Fold.Types (Fold (..), Fold2 (..))
446446import Streamly.Internal.Data.Unfold.Types (Unfold)
447447import Streamly.Internal.Memory.Array.Types (Array, writeNUnsafe)
448448-- import Streamly.Memory.Ring (Ring)
449−import Streamly.Internal.Data.SVar (MonadAsync, State, defState, adaptState)
449+import Streamly.Internal.Data.SVar (MonadAsync, State, defState)
450450import Streamly.Internal.Data.Stream.Async (mkAsync')
451451import Streamly.Internal.Data.Stream.Combinators (inspectMode, maxYields)
452452import Streamly.Internal.Data.Stream.Prelude
453453 (fromStreamS, toStreamS, foldWith, foldMapWith, forEachWith)
454454import Streamly.Internal.Data.Stream.StreamD (fromStreamD, toStreamD)
455455import Streamly.Internal.Data.Stream.StreamK (IsStream((|:), consM))
456−import Streamly.Internal.Data.Stream.Serial (SerialT)
456+import Streamly.Internal.Data.Stream.Serial (SerialT, WSerialT)
457+import Streamly.Internal.Data.Stream.Zip (ZipSerialM)
457458import Streamly.Internal.Data.Pipe.Types (Pipe (..))
458459import Streamly.Internal.Data.Time.Units
459460 (AbsTime, MilliSecond64(..), addToAbsTime, diffAbsTime, toRelTime,
@@ -476,6 +477,7 @@ import qualified Streamly.Internal.Data.Stream.StreamD as S
476477
477478import qualified Streamly.Internal.Data.Stream.Serial as Serial
478479import qualified Streamly.Internal.Data.Stream.Parallel as Par
480+import qualified Streamly.Internal.Data.Stream.Zip as Z
479481
480482------------------------------------------------------------------------------
481483-- Deconstruction
@@ -571,6 +573,16 @@ unfoldrM = K.unfoldrM
571573unfoldrMSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
572574unfoldrMSerial = Serial.unfoldrM
573575
576+{-# RULES "unfoldrM wSerial" unfoldrM = unfoldrMWSerial #-}
577+{-# INLINE_EARLY unfoldrMWSerial #-}
578+unfoldrMWSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> WSerialT m a
579+unfoldrMWSerial = Serial.unfoldrM
580+
581+{-# RULES "unfoldrM zipSerial" unfoldrM = unfoldrMZipSerial #-}
582+{-# INLINE_EARLY unfoldrMZipSerial #-}
583+unfoldrMZipSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> ZipSerialM m a
584+unfoldrMZipSerial = Serial.unfoldrM
585+
574586-- | Convert an 'Unfold' into a stream by supplying it an input seed.
575587--
576588-- >>> unfold UF.replicateM 10 (putStrLn "hello")
@@ -2128,59 +2140,6 @@ indexed = fromStreamD . D.indexed . toStreamD
21282140indexedR :: (IsStream t, Monad m) => Int -> t m a -> t m (Int, a)
21292141indexedR n = fromStreamD . D.indexedR n . toStreamD
21302142
2131−-- | Like 'zipWith' but using a monadic zipping function.
2132−--
2133−-- @since 0.4.0
2134−{-# INLINABLE zipWithM #-}
2135−zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
2136−zipWithM f m1 m2 = fromStreamS $ S.zipWithM f (toStreamS m1) (toStreamS m2)
2137−
2138−-- | Zip two streams serially using a pure zipping function.
2139−--
2140−-- @
2141−-- > S.toList $ S.zipWith (+) (S.fromList [1,2,3]) (S.fromList [4,5,6])
2142−-- [5,7,9]
2143−-- @
2144−--
2145−-- @since 0.1.0
2146−{-# INLINABLE zipWith #-}
2147−zipWith :: (IsStream t, Monad m) => (a -> b -> c) -> t m a -> t m b -> t m c
2148−zipWith f m1 m2 = fromStreamS $ S.zipWith f (toStreamS m1) (toStreamS m2)
2149−
2150−------------------------------------------------------------------------------
2151−-- Parallel Zipping
2152−------------------------------------------------------------------------------
2153−
2154−-- The CPS version and the direct version of zipAsyncWithM below seem to have
2155−-- identical performane. However, we need to use the StreamD version of
2156−-- mkParallel which uses a direct implementation of fromSVar. In comparison to
2157−-- CPS version of fromSVar the direct version gives a 2x improvement.
2158−
2159−-- | Like 'zipWithM' but zips concurrently i.e. both the streams being zipped
2160−-- are generated concurrently.
2161−--
2162−-- @since 0.4.0
2163−{-# INLINE zipAsyncWithM #-}
2164−zipAsyncWithM :: (IsStream t, MonadAsync m)
2165− => (a -> b -> m c) -> t m a -> t m b -> t m c
2166−zipAsyncWithM f m1 m2 = K.mkStream $ \st stp sng yld -> do
2167− ma <- mkParallel (adaptState st) m1
2168− mb <- mkParallel (adaptState st) m2
2169− K.foldStream st stp sng yld $ zipWithM f ma mb
2170−{-
2171−zipAsyncWithM f m1 m2 =
2172− fromStreamD $ D.zipAsyncWithM f (toStreamD m1) (toStreamD m2)
2173−-}
2174−
2175−-- | Like 'zipWith' but zips concurrently i.e. both the streams being zipped
2176−-- are generated concurrently.
2177−--
2178−-- @since 0.1.0
2179−{-# INLINE zipAsyncWith #-}
2180−zipAsyncWith :: (IsStream t, MonadAsync m)
2181− => (a -> b -> c) -> t m a -> t m b -> t m c
2182−zipAsyncWith f = zipAsyncWithM (\a b -> return (f a b))
2183−
21842143------------------------------------------------------------------------------
21852144-- Comparison
21862145------------------------------------------------------------------------------