1{-# LANGUAGE UndecidableInstances #-}
4-- Module : Streamly.Internal.Data.Stream.Zip
5-- Copyright : (c) 2017 Composewell Technologies
8-- Maintainer : streamly@composewell.com
9-- Stability : experimental
13module Streamly.Internal.Data.Stream.Zip
35import Control.Applicative (liftA2)
36import Control.DeepSeq (NFData(..))
37#if MIN_VERSION_deepseq(1,4,3)
38import Control.DeepSeq (NFData1(..))
40import Data.Foldable (Foldable(foldl'), fold)
41import Data.Functor.Identity (Identity(..), runIdentity)
42import Data.Maybe (fromMaybe)
43import Data.Semigroup (Endo(..))
44#if __GLASGOW_HASKELL__ < 808
45import Data.Semigroup (Semigroup(..))
47import GHC.Exts (IsList(..), IsString(..))
49 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
50 , readListPrecDefault)
51import Streamly.Internal.BaseCompat ((#.), errorWithoutStackTrace)
52import Streamly.Internal.Data.Stream.StreamK (IsStream(..), Stream)
53import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
54import Streamly.Internal.Data.SVar (MonadAsync)
56import qualified Streamly.Internal.Data.Stream.Parallel as Par
57import qualified Streamly.Internal.Data.Stream.Prelude as P
58 (cmpBy, eqBy, foldl', foldr, fromList, toList, fromStreamS, toStreamS)
59import qualified Streamly.Internal.Data.Stream.StreamK as K (repeat)
60import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
61import qualified Streamly.Internal.Data.Stream.StreamD as D (zipWithM)
62import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
63#ifdef USE_STREAMK_ONLY
64import qualified Streamly.Internal.Data.Stream.StreamK as S (zipWith, zipWithM)
66import qualified Streamly.Internal.Data.Stream.StreamD as S (zipWith, zipWithM)
69import Prelude hiding (map, repeat, zipWith, errorWithoutStackTrace)
71#include "Instances.hs"
73-- | Like 'zipWith' but using a monadic zipping function.
76{-# INLINABLE zipWithM #-}
77zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
78zipWithM f m1 m2 = P.fromStreamS $ S.zipWithM f (P.toStreamS m1) (P.toStreamS m2)
80-- | Zip two streams serially using a pure zipping function.
83-- > S.toList $ S.zipWith (+) (S.fromList [1,2,3]) (S.fromList [4,5,6])
88{-# INLINABLE zipWith #-}
89zipWith :: (IsStream t, Monad m) => (a -> b -> c) -> t m a -> t m b -> t m c
90zipWith f m1 m2 = P.fromStreamS $ S.zipWith f (P.toStreamS m1) (P.toStreamS m2)
92------------------------------------------------------------------------------
94------------------------------------------------------------------------------
96-- | Like 'zipWithM' but zips concurrently i.e. both the streams being zipped
97-- are generated concurrently.
100{-# INLINE zipAsyncWithM #-}
101zipAsyncWithM :: (IsStream t, MonadAsync m)
102 => (a -> b -> m c) -> t m a -> t m b -> t m c
103zipAsyncWithM f m1 m2 = D.fromStreamD $
104 D.zipWithM f (Par.mkParallelD $ D.toStreamD m1)
105 (Par.mkParallelD $ D.toStreamD m2)
107-- | Like 'zipWith' but zips concurrently i.e. both the streams being zipped
108-- are generated concurrently.
111{-# INLINE zipAsyncWith #-}
112zipAsyncWith :: (IsStream t, MonadAsync m)
113 => (a -> b -> c) -> t m a -> t m b -> t m c
114zipAsyncWith f = zipAsyncWithM (\a b -> return (f a b))
116------------------------------------------------------------------------------
117-- Serially Zipping Streams
118------------------------------------------------------------------------------
120-- | The applicative instance of 'ZipSerialM' zips a number of streams serially
121-- i.e. it produces one element from each stream serially and then zips all
125-- main = (toList . 'zipSerially' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
126-- where s1 = fromFoldable [1, 2]
127-- s2 = fromFoldable [3, 4]
128-- s3 = fromFoldable [5, 6]
134-- The 'Semigroup' instance of this type works the same way as that of
137-- /Since: 0.2.0 ("Streamly")/
140newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: Stream m a}
141 deriving (Semigroup, Monoid)
145{-# DEPRECATED ZipStream "Please use 'ZipSerialM' instead." #-}
146type ZipStream = ZipSerialM
148-- | An IO stream whose applicative instance zips streams serially.
150-- /Since: 0.2.0 ("Streamly")/
153type ZipSerial = ZipSerialM IO
155-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
157-- /Since: 0.2.0 ("Streamly")/
160zipSerially :: IsStream t => ZipSerialM m a -> t m a
163-- | Same as 'zipSerially'.
166{-# DEPRECATED zipping "Please use zipSerially instead." #-}
167zipping :: IsStream t => ZipSerialM m a -> t m a
170consMZip :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
171consMZip m ms = fromStream $ K.consMStream m (toStream ms)
173instance IsStream ZipSerialM where
174 toStream = getZipSerialM
175 fromStream = ZipSerialM
178 {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
179 consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
183 {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
184 (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
187LIST_INSTANCES(ZipSerialM)
188NFDATA1_INSTANCE(ZipSerialM)
190instance Monad m => Functor (ZipSerialM m) where
192 fmap f (ZipSerialM m) = D.fromStreamD $ D.mapM (return . f) $ D.toStreamD m
194instance Monad m => Applicative (ZipSerialM m) where
195 pure = ZipSerialM . K.repeat
199FOLDABLE_INSTANCE(ZipSerialM)
200TRAVERSABLE_INSTANCE(ZipSerialM)
202------------------------------------------------------------------------------
203-- Parallely Zipping Streams
204------------------------------------------------------------------------------
206-- | Like 'ZipSerialM' but zips in parallel, it generates all the elements to
207-- be zipped concurrently.
210-- main = (toList . 'zipAsyncly' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
211-- where s1 = fromFoldable [1, 2]
212-- s2 = fromFoldable [3, 4]
213-- s3 = fromFoldable [5, 6]
219-- The 'Semigroup' instance of this type works the same way as that of
222-- /Since: 0.2.0 ("Streamly")/
225newtype ZipAsyncM m a = ZipAsyncM {getZipAsyncM :: Stream m a}
226 deriving (Semigroup, Monoid)
228-- | An IO stream whose applicative instance zips streams wAsyncly.
230-- /Since: 0.2.0 ("Streamly")/
233type ZipAsync = ZipAsyncM IO
235-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
237-- /Since: 0.2.0 ("Streamly")/
240zipAsyncly :: IsStream t => ZipAsyncM m a -> t m a
243-- | Same as 'zipAsyncly'.
246{-# DEPRECATED zippingAsync "Please use zipAsyncly instead." #-}
247zippingAsync :: IsStream t => ZipAsyncM m a -> t m a
248zippingAsync = zipAsyncly
250consMZipAsync :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
251consMZipAsync m ms = fromStream $ K.consMStream m (toStream ms)
253instance IsStream ZipAsyncM where
254 toStream = getZipAsyncM
255 fromStream = ZipAsyncM
258 {-# SPECIALIZE consM :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
259 consM :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
260 consM = consMZipAsync
263 {-# SPECIALIZE (|:) :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
264 (|:) :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
267instance Monad m => Functor (ZipAsyncM m) where
269 fmap f (ZipAsyncM m) = D.fromStreamD $ D.mapM (return . f) $ D.toStreamD m
271instance MonadAsync m => Applicative (ZipAsyncM m) where
272 pure = ZipAsyncM . K.repeat
274 m1 <*> m2 = zipAsyncWith id m1 m2
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list