1{-# LANGUAGE UndecidableInstances #-}
4-- Module : Streamly.Internal.Data.Stream.Zip
5-- Copyright : (c) 2017 Harendra Kumar
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.Prelude as P
57import qualified Streamly.Internal.Data.Stream.StreamK as K
58import qualified Streamly.Internal.Data.Stream.StreamD as D
59#ifdef USE_STREAMK_ONLY
60import qualified Streamly.Internal.Data.Stream.StreamK as S
62import qualified Streamly.Internal.Data.Stream.StreamD as S
65import Prelude hiding (map, repeat, zipWith, errorWithoutStackTrace)
67#include "Instances.hs"
69-- | Like 'zipWith' but using a monadic zipping function.
72{-# INLINABLE zipWithM #-}
73zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
74zipWithM f m1 m2 = P.fromStreamS $ S.zipWithM f (P.toStreamS m1) (P.toStreamS m2)
76-- | Zip two streams serially using a pure zipping function.
79-- > S.toList $ S.zipWith (+) (S.fromList [1,2,3]) (S.fromList [4,5,6])
84{-# INLINABLE zipWith #-}
85zipWith :: (IsStream t, Monad m) => (a -> b -> c) -> t m a -> t m b -> t m c
86zipWith f m1 m2 = P.fromStreamS $ S.zipWith f (P.toStreamS m1) (P.toStreamS m2)
88------------------------------------------------------------------------------
90------------------------------------------------------------------------------
92-- | Like 'zipWithM' but zips concurrently i.e. both the streams being zipped
93-- are generated concurrently.
96{-# INLINE zipAsyncWithM #-}
97zipAsyncWithM :: (IsStream t, MonadAsync m)
98 => (a -> b -> m c) -> t m a -> t m b -> t m c
99zipAsyncWithM f m1 m2 = D.fromStreamD $
100 D.zipWithM f (D.mkParallelD $ D.toStreamD m1)
101 (D.mkParallelD $ D.toStreamD m2)
103-- | Like 'zipWith' but zips concurrently i.e. both the streams being zipped
104-- are generated concurrently.
107{-# INLINE zipAsyncWith #-}
108zipAsyncWith :: (IsStream t, MonadAsync m)
109 => (a -> b -> c) -> t m a -> t m b -> t m c
110zipAsyncWith f = zipAsyncWithM (\a b -> return (f a b))
112------------------------------------------------------------------------------
113-- Serially Zipping Streams
114------------------------------------------------------------------------------
116-- | The applicative instance of 'ZipSerialM' zips a number of streams serially
117-- i.e. it produces one element from each stream serially and then zips all
121-- main = (toList . 'zipSerially' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
122-- where s1 = fromFoldable [1, 2]
123-- s2 = fromFoldable [3, 4]
124-- s3 = fromFoldable [5, 6]
130-- The 'Semigroup' instance of this type works the same way as that of
134newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: Stream m a}
135 deriving (Semigroup, Monoid)
139{-# DEPRECATED ZipStream "Please use 'ZipSerialM' instead." #-}
140type ZipStream = ZipSerialM
142-- | An IO stream whose applicative instance zips streams serially.
145type ZipSerial = ZipSerialM IO
147-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
150zipSerially :: IsStream t => ZipSerialM m a -> t m a
153-- | Same as 'zipSerially'.
156{-# DEPRECATED zipping "Please use zipSerially instead." #-}
157zipping :: IsStream t => ZipSerialM m a -> t m a
160consMZip :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
161consMZip m ms = fromStream $ K.consMStream m (toStream ms)
163instance IsStream ZipSerialM where
164 toStream = getZipSerialM
165 fromStream = ZipSerialM
168 {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
169 consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
173 {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
174 (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
177LIST_INSTANCES(ZipSerialM)
178NFDATA1_INSTANCE(ZipSerialM)
180instance Monad m => Functor (ZipSerialM m) where
182 fmap f (ZipSerialM m) = D.fromStreamD $ D.mapM (return . f) $ D.toStreamD m
184instance Monad m => Applicative (ZipSerialM m) where
185 pure = ZipSerialM . K.repeat
189FOLDABLE_INSTANCE(ZipSerialM)
190TRAVERSABLE_INSTANCE(ZipSerialM)
192------------------------------------------------------------------------------
193-- Parallely Zipping Streams
194------------------------------------------------------------------------------
196-- | Like 'ZipSerialM' but zips in parallel, it generates all the elements to
197-- be zipped concurrently.
200-- main = (toList . 'zipAsyncly' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
201-- where s1 = fromFoldable [1, 2]
202-- s2 = fromFoldable [3, 4]
203-- s3 = fromFoldable [5, 6]
209-- The 'Semigroup' instance of this type works the same way as that of
213newtype ZipAsyncM m a = ZipAsyncM {getZipAsyncM :: Stream m a}
214 deriving (Semigroup, Monoid)
216-- | An IO stream whose applicative instance zips streams wAsyncly.
219type ZipAsync = ZipAsyncM IO
221-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
224zipAsyncly :: IsStream t => ZipAsyncM m a -> t m a
227-- | Same as 'zipAsyncly'.
230{-# DEPRECATED zippingAsync "Please use zipAsyncly instead." #-}
231zippingAsync :: IsStream t => ZipAsyncM m a -> t m a
232zippingAsync = zipAsyncly
234consMZipAsync :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
235consMZipAsync m ms = fromStream $ K.consMStream m (toStream ms)
237instance IsStream ZipAsyncM where
238 toStream = getZipAsyncM
239 fromStream = ZipAsyncM
242 {-# SPECIALIZE consM :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
243 consM :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
244 consM = consMZipAsync
247 {-# SPECIALIZE (|:) :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
248 (|:) :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
251instance Monad m => Functor (ZipAsyncM m) where
253 fmap f (ZipAsyncM m) = D.fromStreamD $ D.mapM (return . f) $ D.toStreamD m
255instance MonadAsync m => Applicative (ZipAsyncM m) where
256 pure = ZipAsyncM . K.repeat
258 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