on master help sign in
Implement ZipStream using Data.Stream (#1811)
b8a1719Harendra Kumar
core/src/Streamly/Internal/Data/List.hs+6−22
@@ -70,7 +70,7 @@ import GHC.Exts (IsList(..), IsString(..))
70import Data.Semigroup (Semigroup(..))
70import Data.Semigroup (Semigroup(..))
71#endif
71#endif
72import Streamly.Internal.Data.Stream.Type (Stream)
72import Streamly.Internal.Data.Stream.Type (Stream)
73−import Streamly.Internal.Data.Stream.Zip (ZipSerialM(..))
73+import Streamly.Internal.Data.Stream.Zip (ZipStream(..))
74
74
75import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
75import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
76import qualified Streamly.Internal.Data.Stream.Type as Stream
76import qualified Streamly.Internal.Data.Stream.Type as Stream
@@ -94,20 +94,12 @@ newtype List a = List { toStream :: Stream Identity a }
94 deriving
94 deriving
95 ( Show, Read, Eq, Ord, NFData , NFData1
95 ( Show, Read, Eq, Ord, NFData , NFData1
96 , Semigroup, Monoid, Functor, Foldable
96 , Semigroup, Monoid, Functor, Foldable
97− , Applicative, Traversable, Monad)
97+ , Applicative, Traversable, Monad, IsList)
98
98
99instance (a ~ Char) => IsString (List a) where
99instance (a ~ Char) => IsString (List a) where
100 {-# INLINE fromString #-}
100 {-# INLINE fromString #-}
101 fromString = List . fromList
101 fromString = List . fromList
102
102
103−-- GHC versions 8.0 and below cannot derive IsList
104−instance IsList (List a) where
105− type (Item (List a)) = a
106− {-# INLINE fromList #-}
107− fromList = List . fromList
108− {-# INLINE toList #-}
109− toList = toList . toStream
110−
111------------------------------------------------------------------------------
103------------------------------------------------------------------------------
112-- Patterns
104-- Patterns
113------------------------------------------------------------------------------
105------------------------------------------------------------------------------
@@ -153,33 +145,25 @@ pattern Cons x xs <-
153-- and no 'Monad' instance.
145-- and no 'Monad' instance.
154--
146--
155-- @since 0.6.0
147-- @since 0.6.0
156−newtype ZipList a = ZipList { toZipSerial :: ZipSerialM Identity a }
148+newtype ZipList a = ZipList { toZipStream :: ZipStream Identity a }
157 deriving
149 deriving
158 ( Show, Read, Eq, Ord, NFData , NFData1
150 ( Show, Read, Eq, Ord, NFData , NFData1
159 , Semigroup, Monoid, Functor, Foldable
151 , Semigroup, Monoid, Functor, Foldable
160− , Applicative, Traversable
152+ , Applicative, Traversable, IsList
161 )
153 )
162
154
163instance (a ~ Char) => IsString (ZipList a) where
155instance (a ~ Char) => IsString (ZipList a) where
164 {-# INLINE fromString #-}
156 {-# INLINE fromString #-}
165 fromString = ZipList . fromList
157 fromString = ZipList . fromList
166
158
167−-- GHC versions 8.0 and below cannot derive IsList
168−instance IsList (ZipList a) where
169− type (Item (ZipList a)) = a
170− {-# INLINE fromList #-}
171− fromList = ZipList . fromList
172− {-# INLINE toList #-}
173− toList = toList . toZipSerial
174−
175-- | Convert a 'ZipList' to a regular 'List'
159-- | Convert a 'ZipList' to a regular 'List'
176--
160--
177-- @since 0.6.0
161-- @since 0.6.0
178fromZipList :: ZipList a -> List a
162fromZipList :: ZipList a -> List a
179−fromZipList (ZipList zs) = List $ Stream.fromStreamK $ getZipSerialM zs
163+fromZipList (ZipList zs) = List $ getZipStream zs
180
164
181-- | Convert a regular 'List' to a 'ZipList'
165-- | Convert a regular 'List' to a 'ZipList'
182--
166--
183-- @since 0.6.0
167-- @since 0.6.0
184toZipList :: List a -> ZipList a
168toZipList :: List a -> ZipList a
185−toZipList = ZipList . ZipSerialM . Stream.toStreamK . toStream
169+toZipList = ZipList . ZipStream . toStream
core/src/Streamly/Internal/Data/Stream/Zip.hs+48−51
@@ -1,3 +1,4 @@
1+{-# LANGUAGE StandaloneDeriving #-}
1{-# LANGUAGE UndecidableInstances #-}
2{-# LANGUAGE UndecidableInstances #-}
2
3
3-- |
4-- |
@@ -11,54 +12,41 @@
11--
12--
12-- To run examples in this module:
13-- To run examples in this module:
13--
14--
14−-- >>> import qualified Streamly.Prelude as Stream
15+-- >>> import qualified Streamly.Data.Fold as Fold
16+-- >>> import qualified Streamly.Data.Stream as Stream
17+-- >>> import qualified Streamly.Internal.Data.Stream.Zip as Stream
15--
18--
16module Streamly.Internal.Data.Stream.Zip
19module Streamly.Internal.Data.Stream.Zip
17 (
20 (
18− ZipSerialM (..)
21+ ZipStream (..)
22+ , ZipSerialM
19 , ZipSerial
23 , ZipSerial
20− , consMZip
21 , zipWithK
24 , zipWithK
22 , zipWithMK
25 , zipWithMK
23 )
26 )
24where
27where
25
28
26−import Control.Applicative (liftA2)
27import Control.DeepSeq (NFData(..), NFData1(..))
29import Control.DeepSeq (NFData(..), NFData1(..))
28−import Data.Foldable (Foldable(foldl'), fold)
29−import Data.Functor.Identity (Identity(..), runIdentity)
30+import Data.Functor.Identity (Identity(..))
30−import Data.Maybe (fromMaybe)
31−import Data.Semigroup (Endo(..))
32−#if __GLASGOW_HASKELL__ < 808
33−import Data.Semigroup (Semigroup(..))
34−#endif
35−import GHC.Exts (IsList(..), IsString(..), oneShot)
31+import GHC.Exts (IsList(..), IsString(..))
32+import Streamly.Internal.Data.Stream.Type (Stream, toStreamD, fromStreamD)
36import Text.Read
33import Text.Read
37 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
34 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
38 , readListPrecDefault)
35 , readListPrecDefault)
39−import Streamly.Internal.BaseCompat ((#.))
40−import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
41−import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
42
36
43−import qualified Streamly.Internal.Data.Stream.Common as P
37+import qualified Streamly.Internal.Data.Stream as Stream
44− (cmpBy, eqBy, foldl', foldr, fromList, toList)
45−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
46import qualified Streamly.Internal.Data.Stream.StreamD as D
38import qualified Streamly.Internal.Data.Stream.StreamD as D
47−import qualified Streamly.Internal.Data.Stream.Serial as Serial
48−import qualified Streamly.Internal.Data.Stream.Type as Stream
49−
50−import Prelude hiding (map, repeat, zipWith)
51−
52−#include "Instances.hs"
53
39
54-- $setup
40-- $setup
55−-- >>> import qualified Streamly.Prelude as Stream
41+-- >>> import qualified Streamly.Data.Fold as Fold
42+-- >>> import qualified Streamly.Data.Stream as Stream
43+-- >>> import qualified Streamly.Internal.Data.Stream.Zip as Stream
56
44
57{-# INLINE zipWithMK #-}
45{-# INLINE zipWithMK #-}
58zipWithMK :: Monad m =>
46zipWithMK :: Monad m =>
59 (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
47 (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
60zipWithMK f m1 m2 =
48zipWithMK f m1 m2 =
61− D.toStreamK $ D.zipWithM f (D.fromStreamK m1) (D.fromStreamK m2)
49+ fromStreamD $ D.zipWithM f (toStreamD m1) (toStreamD m2)
62
50
63{-# INLINE zipWithK #-}
51{-# INLINE zipWithK #-}
64zipWithK :: Monad m
52zipWithK :: Monad m
@@ -69,26 +57,48 @@ zipWithK f = zipWithMK (\a b -> return (f a b))
69-- Serially Zipping Streams
57-- Serially Zipping Streams
70------------------------------------------------------------------------------
58------------------------------------------------------------------------------
71
59
72−-- | For 'ZipSerialM' streams:
60+-- | For 'ZipStream':
73--
61--
74-- @
62-- @
75−-- (<>) = 'Streamly.Prelude.serial'
63+-- (<>) = 'Streamly.Data.Stream.append'
76−-- (<*>) = 'Streamly.Prelude.serial.zipWith' id
64+-- (<*>) = 'Streamly.Data.Stream.zipWith' id
77-- @
65-- @
78--
66--
79-- Applicative evaluates the streams being zipped serially:
67-- Applicative evaluates the streams being zipped serially:
80--
68--
81−-- >>> s1 = Stream.fromFoldable [1, 2]
69+-- >>> s1 = Stream.ZipStream $ Stream.fromFoldable [1, 2]
82−-- >>> s2 = Stream.fromFoldable [3, 4]
70+-- >>> s2 = Stream.ZipStream $ Stream.fromFoldable [3, 4]
83−-- >>> s3 = Stream.fromFoldable [5, 6]
71+-- >>> s3 = Stream.ZipStream $ Stream.fromFoldable [5, 6]
84−-- >>> Stream.toList $ Stream.fromZipSerial $ (,,) <$> s1 <*> s2 <*> s3
72+-- >>> s = (,,) <$> s1 <*> s2 <*> s3
73+-- >>> Stream.fold Fold.toList (Stream.getZipStream s)
85-- [(1,3,5),(2,4,6)]
74-- [(1,3,5),(2,4,6)]
86--
75--
87-- /Since: 0.2.0 ("Streamly")/
76-- /Since: 0.2.0 ("Streamly")/
88--
77--
89-- @since 0.8.0
78-- @since 0.8.0
90−newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: Stream m a}
79+newtype ZipStream m a = ZipStream {getZipStream :: Stream m a}
91− deriving (Semigroup, Monoid)
80+ deriving (Functor, Semigroup, Monoid)
81+
82+deriving instance NFData a => NFData (ZipStream Identity a)
83+deriving instance NFData1 (ZipStream Identity)
84+deriving instance IsList (ZipStream Identity a)
85+deriving instance (a ~ Char) => IsString (ZipStream Identity a)
86+deriving instance Eq a => Eq (ZipStream Identity a)
87+deriving instance Ord a => Ord (ZipStream Identity a)
88+deriving instance (Foldable m, Monad m) => Foldable (ZipStream m)
89+deriving instance Traversable (ZipStream Identity)
90+
91+instance Show a => Show (ZipStream Identity a) where
92+ showsPrec p dl = showParen (p > 10) $
93+ showString "fromList " . shows (toList dl)
94+
95+instance Read a => Read (ZipStream Identity a) where
96+ readPrec = parens $ prec 10 $ do
97+ Ident "fromList" <- lexP
98+ fromList <$> readPrec
99+ readListPrec = readListPrecDefault
100+
101+type ZipSerialM = ZipStream
92
102
93-- | An IO stream whose applicative instance zips streams serially.
103-- | An IO stream whose applicative instance zips streams serially.
94--
104--
@@ -97,21 +107,8 @@ newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: Stream m a}
97-- @since 0.8.0
107-- @since 0.8.0
98type ZipSerial = ZipSerialM IO
108type ZipSerial = ZipSerialM IO
99
109
100−consMZip :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
101−consMZip m (ZipSerialM r) = ZipSerialM $ K.consM m r
102−
103−LIST_INSTANCES(ZipSerialM)
104−NFDATA1_INSTANCE(ZipSerialM)
105−
106−instance Monad m => Functor (ZipSerialM m) where
107− {-# INLINE fmap #-}
108− fmap f (ZipSerialM m) = ZipSerialM $ Stream.toStreamK $ fmap f (Stream.fromStreamK m)
109−
110−instance Monad m => Applicative (ZipSerialM m) where
110+instance Monad m => Applicative (ZipStream m) where
111− pure = ZipSerialM . Stream.toStreamK . Serial.repeat
111+ pure = ZipStream . Stream.repeat
112
112
113 {-# INLINE (<*>) #-}
113 {-# INLINE (<*>) #-}
114− ZipSerialM m1 <*> ZipSerialM m2 = ZipSerialM $ zipWithK id m1 m2
114+ ZipStream m1 <*> ZipStream m2 = ZipStream $ zipWithK id m1 m2
115−
116−FOLDABLE_INSTANCE(ZipSerialM)
117−TRAVERSABLE_INSTANCE(ZipSerialM)
core/streamly-core.cabal−2
@@ -317,8 +317,6 @@ library
317 , Streamly.Internal.Data.Stream.Reduce
317 , Streamly.Internal.Data.Stream.Reduce
318 , Streamly.Internal.Data.Stream.Top
318 , Streamly.Internal.Data.Stream.Top
319 , Streamly.Internal.Data.Stream
319 , Streamly.Internal.Data.Stream
320− , Streamly.Internal.Data.Stream.Serial
321− , Streamly.Internal.Data.Stream.WSerial
322 , Streamly.Internal.Data.Stream.Zip
320 , Streamly.Internal.Data.Stream.Zip
323 , Streamly.Internal.Data.List
321 , Streamly.Internal.Data.List
324
322
src/Streamly/Internal/Data/Stream/Instances.hs+2−2
@@ -139,7 +139,7 @@ instance (Foldable m, Monad m) => Foldable (STREAM m) where { \
139 \
139 \
140 {-# INLINE maximum #-}; \
140 {-# INLINE maximum #-}; \
141 maximum = \
141 maximum = \
142− fromMaybe (errorWithoutStackTrace $ "maximum: empty stream") \
142+ fromMaybe (errorWithoutStackTrace "maximum: empty stream") \
143 . toMaybe \
143 . toMaybe \
144 . foldl' getMax Nothing' where { \
144 . foldl' getMax Nothing' where { \
145 getMax Nothing' x = Just' x; \
145 getMax Nothing' x = Just' x; \
@@ -147,7 +147,7 @@ instance (Foldable m, Monad m) => Foldable (STREAM m) where { \
147 \
147 \
148 {-# INLINE minimum #-}; \
148 {-# INLINE minimum #-}; \
149 minimum = \
149 minimum = \
150− fromMaybe (errorWithoutStackTrace $ "minimum: empty stream") \
150+ fromMaybe (errorWithoutStackTrace "minimum: empty stream") \
151 . toMaybe \
151 . toMaybe \
152 . foldl' getMin Nothing' where { \
152 . foldl' getMin Nothing' where { \
153 getMin Nothing' x = Just' x; \
153 getMin Nothing' x = Just' x; \
src/Streamly/Internal/Data/Stream/IsStream/Type.hs+9−5
@@ -107,7 +107,7 @@ import Streamly.Internal.Data.Stream.Async
107 (AsyncT(..), Async, WAsyncT(..), WAsync)
107 (AsyncT(..), Async, WAsyncT(..), WAsync)
108import Streamly.Internal.Data.Stream.Ahead (AheadT(..), Ahead)
108import Streamly.Internal.Data.Stream.Ahead (AheadT(..), Ahead)
109import Streamly.Internal.Data.Stream.Parallel (ParallelT(..), Parallel)
109import Streamly.Internal.Data.Stream.Parallel (ParallelT(..), Parallel)
110−import Streamly.Internal.Data.Stream.Zip (ZipSerialM(..), ZipSerial)
110+import Streamly.Internal.Data.Stream.Zip (ZipSerialM, ZipSerial)
111import Streamly.Internal.Data.Stream.ZipAsync (ZipAsyncM(..), ZipAsync)
111import Streamly.Internal.Data.Stream.ZipAsync (ZipAsyncM(..), ZipAsync)
112import Streamly.Internal.Data.SVar.Type (State, adaptState)
112import Streamly.Internal.Data.SVar.Type (State, adaptState)
113
113
@@ -567,6 +567,10 @@ instance IsStream ParallelT where
567-- Zip
567-- Zip
568-------------------------------------------------------------------------------
568-------------------------------------------------------------------------------
569
569
570+consMZip :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
571+consMZip m (Zip.ZipStream r) =
572+ Zip.ZipStream $ Stream.fromStreamK $ K.consM m (Stream.toStreamK r)
573+
570-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
574-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
571--
575--
572-- /Since: 0.2.0 ("Streamly")/
576-- /Since: 0.2.0 ("Streamly")/
@@ -575,18 +579,18 @@ instance IsStream ParallelT where
575fromZipSerial :: IsStream t => ZipSerialM m a -> t m a
579fromZipSerial :: IsStream t => ZipSerialM m a -> t m a
576fromZipSerial = adapt
580fromZipSerial = adapt
577instance IsStream ZipSerialM where
581instance IsStream ZipSerialM where
578− toStream = getZipSerialM
582+ toStream = Stream.toStreamK . Zip.getZipStream
579− fromStream = ZipSerialM
583+ fromStream = Zip.ZipStream . Stream.fromStreamK
580
584
581 {-# INLINE consM #-}
585 {-# INLINE consM #-}
582 {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
586 {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
583 consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
587 consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
584− consM = Zip.consMZip
588+ consM = consMZip
585
589
586 {-# INLINE (|:) #-}
590 {-# INLINE (|:) #-}
587 {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
591 {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
588 (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
592 (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
589− (|:) = Zip.consMZip
593+ (|:) = consMZip
590
594
591-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
595-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
592--
596--
core/src/Streamly/Internal/Data/Stream/Serial.hs → src/Streamly/Internal/Data/Stream/Serial.hsrenamed

The content is the same.

core/src/Streamly/Internal/Data/Stream/WSerial.hs → src/Streamly/Internal/Data/Stream/WSerial.hsrenamed

The content is the same.

streamly.cabal+2−3
@@ -188,7 +188,6 @@ extra-source-files:
188
188
189 core/src/Streamly/Internal/Data/Parser.hs
189 core/src/Streamly/Internal/Data/Parser.hs
190 core/src/Streamly/Internal/Data/Pipe.hs
190 core/src/Streamly/Internal/Data/Pipe.hs
191− core/src/Streamly/Internal/Data/Stream/Serial.hs
192 core/src/Streamly/Internal/Data/Stream.hs
191 core/src/Streamly/Internal/Data/Stream.hs
193 core/src/Streamly/Internal/Data/Stream/Bottom.hs
192 core/src/Streamly/Internal/Data/Stream/Bottom.hs
194 core/src/Streamly/Internal/Data/Stream/Eliminate.hs
193 core/src/Streamly/Internal/Data/Stream/Eliminate.hs
@@ -201,7 +200,6 @@ extra-source-files:
201 core/src/Streamly/Internal/Data/Stream/Top.hs
200 core/src/Streamly/Internal/Data/Stream/Top.hs
202 core/src/Streamly/Internal/Data/Stream/Transform.hs
201 core/src/Streamly/Internal/Data/Stream/Transform.hs
203 core/src/Streamly/Internal/Data/Stream/Type.hs
202 core/src/Streamly/Internal/Data/Stream/Type.hs
204− core/src/Streamly/Internal/Data/Stream/WSerial.hs
205 core/src/Streamly/Internal/Data/Stream/Zip.hs
203 core/src/Streamly/Internal/Data/Stream/Zip.hs
206 core/src/Streamly/Internal/Data/List.hs
204 core/src/Streamly/Internal/Data/List.hs
207 core/src/Streamly/Internal/Data/Array.hs
205 core/src/Streamly/Internal/Data/Array.hs
@@ -443,6 +441,8 @@ library
443 , Streamly.Internal.Data.Stream.SVar.Generate
441 , Streamly.Internal.Data.Stream.SVar.Generate
444 , Streamly.Internal.Data.Stream.SVar.Eliminate
442 , Streamly.Internal.Data.Stream.SVar.Eliminate
445
443
444+ , Streamly.Internal.Data.Stream.Serial
445+ , Streamly.Internal.Data.Stream.WSerial
446 , Streamly.Internal.Data.Stream.Async
446 , Streamly.Internal.Data.Stream.Async
447 , Streamly.Internal.Data.Stream.Parallel
447 , Streamly.Internal.Data.Stream.Parallel
448 , Streamly.Internal.Data.Stream.Ahead
448 , Streamly.Internal.Data.Stream.Ahead
@@ -599,7 +599,6 @@ library
599 , Streamly.Internal.Data.Stream.Lift
599 , Streamly.Internal.Data.Stream.Lift
600 , Streamly.Internal.Data.Stream.Top
600 , Streamly.Internal.Data.Stream.Top
601 , Streamly.Internal.Data.Stream
601 , Streamly.Internal.Data.Stream
602− , Streamly.Internal.Data.Stream.Serial
603 , Streamly.Internal.Data.Stream.Zip
602 , Streamly.Internal.Data.Stream.Zip
604 , Streamly.Internal.Data.List
603 , Streamly.Internal.Data.List
605
604
test/Streamly/Test/Data/List.hs+2−2
@@ -196,10 +196,10 @@ main = hspec $
196
196
197 it "Show instance" $ do
197 it "Show instance" $ do
198 show ([1..3] :: ZipList Int) `shouldBe`
198 show ([1..3] :: ZipList Int) `shouldBe`
199− "ZipList {toZipSerial = fromList [1,2,3]}"
199+ "ZipList {toZipStream = fromList [1,2,3]}"
200
200
201 it "Read instance" $ do
201 it "Read instance" $ do
202− (read "ZipList {toZipSerial = fromList [1,2,3]}" :: ZipList Int)
202+ (read "ZipList {toZipStream = fromList [1,2,3]}" :: ZipList Int)
203 `shouldBe` [1..3]
203 `shouldBe` [1..3]
204
204
205 it "Eq instance" $ do
205 it "Eq instance" $ do