2{-# LANGUAGE ConstraintKinds #-}
3{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving#-}
6{-# LANGUAGE InstanceSigs #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE TypeFamilies #-}
9{-# LANGUAGE UndecidableInstances #-} -- XXX
12-- Module : Streamly.Internal.Data.Stream.Zip
13-- Copyright : (c) 2017 Harendra Kumar
16-- Maintainer : streamly@composewell.com
17-- Stability : experimental
21module Streamly.Internal.Data.Stream.Zip
43import Control.Applicative (liftA2)
44import Control.DeepSeq (NFData(..))
45#if MIN_VERSION_deepseq(1,4,3)
46import Control.DeepSeq (NFData1(..))
48import Data.Functor.Identity (Identity, runIdentity)
49import Data.Foldable (fold)
50#if __GLASGOW_HASKELL__ < 808
51import Data.Semigroup (Semigroup(..))
53import GHC.Exts (IsList(..), IsString(..))
54import Text.Read (Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec,
56import Prelude hiding (map, repeat, zipWith)
58import Streamly.Internal.Data.Stream.StreamK (IsStream(..), Stream)
59import Streamly.Internal.Data.SVar (MonadAsync)
61import qualified Streamly.Internal.Data.Stream.Prelude as P
62import qualified Streamly.Internal.Data.Stream.StreamK as K
63import qualified Streamly.Internal.Data.Stream.StreamD as D
65#ifdef USE_STREAMK_ONLY
66import qualified Streamly.Internal.Data.Stream.StreamK as S
68import qualified Streamly.Internal.Data.Stream.StreamD as S
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 (D.mkParallelD $ D.toStreamD m1)
105 (D.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
138newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: Stream m a}
139 deriving (Semigroup, Monoid)
143{-# DEPRECATED ZipStream "Please use 'ZipSerialM' instead." #-}
144type ZipStream = ZipSerialM
146-- | An IO stream whose applicative instance zips streams serially.
149type ZipSerial = ZipSerialM IO
151-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
154zipSerially :: IsStream t => ZipSerialM m a -> t m a
157-- | Same as 'zipSerially'.
160{-# DEPRECATED zipping "Please use zipSerially instead." #-}
161zipping :: IsStream t => ZipSerialM m a -> t m a
164consMZip :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
165consMZip m ms = fromStream $ K.consMStream m (toStream ms)
167instance IsStream ZipSerialM where
168 toStream = getZipSerialM
169 fromStream = ZipSerialM
172 {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
173 consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
177 {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
178 (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
181LIST_INSTANCES(ZipSerialM)
182NFDATA1_INSTANCE(ZipSerialM)
184instance Monad m => Functor (ZipSerialM m) where
186 fmap f (ZipSerialM m) = D.fromStreamD $ D.mapM (return . f) $ D.toStreamD m
188instance Monad m => Applicative (ZipSerialM m) where
189 pure = ZipSerialM . K.repeat
193FOLDABLE_INSTANCE(ZipSerialM)
194TRAVERSABLE_INSTANCE(ZipSerialM)
196------------------------------------------------------------------------------
197-- Parallely Zipping Streams
198------------------------------------------------------------------------------
200-- | Like 'ZipSerialM' but zips in parallel, it generates all the elements to
201-- be zipped concurrently.
204-- main = (toList . 'zipAsyncly' $ (,,) \<$\> s1 \<*\> s2 \<*\> s3) >>= print
205-- where s1 = fromFoldable [1, 2]
206-- s2 = fromFoldable [3, 4]
207-- s3 = fromFoldable [5, 6]
213-- The 'Semigroup' instance of this type works the same way as that of
217newtype ZipAsyncM m a = ZipAsyncM {getZipAsyncM :: Stream m a}
218 deriving (Semigroup, Monoid)
220-- | An IO stream whose applicative instance zips streams wAsyncly.
223type ZipAsync = ZipAsyncM IO
225-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
228zipAsyncly :: IsStream t => ZipAsyncM m a -> t m a
231-- | Same as 'zipAsyncly'.
234{-# DEPRECATED zippingAsync "Please use zipAsyncly instead." #-}
235zippingAsync :: IsStream t => ZipAsyncM m a -> t m a
236zippingAsync = zipAsyncly
238consMZipAsync :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
239consMZipAsync m ms = fromStream $ K.consMStream m (toStream ms)
241instance IsStream ZipAsyncM where
242 toStream = getZipAsyncM
243 fromStream = ZipAsyncM
246 {-# SPECIALIZE consM :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
247 consM :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
248 consM = consMZipAsync
251 {-# SPECIALIZE (|:) :: IO a -> ZipAsyncM IO a -> ZipAsyncM IO a #-}
252 (|:) :: Monad m => m a -> ZipAsyncM m a -> ZipAsyncM m a
255instance Monad m => Functor (ZipAsyncM m) where
257 fmap f (ZipAsyncM m) = D.fromStreamD $ D.mapM (return . f) $ D.toStreamD m
259instance MonadAsync m => Applicative (ZipAsyncM m) where
260 pure = ZipAsyncM . K.repeat
262 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