on master help sign in
Implement ZipStream using Data.Stream (#1811)
commitb8a17190a8e82f4f593ae7a825f1a43d4ca91334 authorHarendra Kumar <harendra@composewell.com> dateThu 25 Aug 2022, 23:57 (4 years ago) parent6925dd0
9 files changed+69−87
core/src/Streamly/Internal/Data/List.hs+6−22 core/src/Streamly/Internal/Data/Stream/Zip.hs+48−51 core/streamly-core.cabal−2 src/Streamly/Internal/Data/Stream/Instances.hs+2−2 src/Streamly/Internal/Data/Stream/IsStream/Type.hs+9−5 core/src/Streamly/Internal/Data/Stream/Serial.hs → src/Streamly/Internal/Data/Stream/Serial.hs core/src/Streamly/Internal/Data/Stream/WSerial.hs → src/Streamly/Internal/Data/Stream/WSerial.hs streamly.cabal+2−3 test/Streamly/Test/Data/List.hs+2−2
core/src/Streamly/Internal/Data/List.hs+6−22
@@ -70,7 +70,7 @@ import GHC.Exts (IsList(..), IsString(..))
7070import Data.Semigroup (Semigroup(..))
7171#endif
7272import Streamly.Internal.Data.Stream.Type (Stream)
73−import Streamly.Internal.Data.Stream.Zip (ZipSerialM(..))
73+import Streamly.Internal.Data.Stream.Zip (ZipStream(..))
7474
7575import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
7676import qualified Streamly.Internal.Data.Stream.Type as Stream
@@ -94,20 +94,12 @@ newtype List a = List { toStream :: Stream Identity a }
9494 deriving
9595 ( Show, Read, Eq, Ord, NFData , NFData1
9696 , Semigroup, Monoid, Functor, Foldable
97− , Applicative, Traversable, Monad)
97+ , Applicative, Traversable, Monad, IsList)
9898
9999instance (a ~ Char) => IsString (List a) where
100100 {-# INLINE fromString #-}
101101 fromString = List . fromList
102102
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−
111103------------------------------------------------------------------------------
112104-- Patterns
113105------------------------------------------------------------------------------
@@ -153,33 +145,25 @@ pattern Cons x xs <-
153145-- and no 'Monad' instance.
154146--
155147-- @since 0.6.0
156−newtype ZipList a = ZipList { toZipSerial :: ZipSerialM Identity a }
148+newtype ZipList a = ZipList { toZipStream :: ZipStream Identity a }
157149 deriving
158150 ( Show, Read, Eq, Ord, NFData , NFData1
159151 , Semigroup, Monoid, Functor, Foldable
160− , Applicative, Traversable
152+ , Applicative, Traversable, IsList
161153 )
162154
163155instance (a ~ Char) => IsString (ZipList a) where
164156 {-# INLINE fromString #-}
165157 fromString = ZipList . fromList
166158
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−
175159-- | Convert a 'ZipList' to a regular 'List'
176160--
177161-- @since 0.6.0
178162fromZipList :: ZipList a -> List a
179−fromZipList (ZipList zs) = List $ Stream.fromStreamK $ getZipSerialM zs
163+fromZipList (ZipList zs) = List $ getZipStream zs
180164
181165-- | Convert a regular 'List' to a 'ZipList'
182166--
183167-- @since 0.6.0
184168toZipList :: 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 #-}
12{-# LANGUAGE UndecidableInstances #-}
23
34-- |
@@ -11,54 +12,41 @@
1112--
1213-- To run examples in this module:
1314--
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
1518--
1619module Streamly.Internal.Data.Stream.Zip
1720 (
18− ZipSerialM (..)
21+ ZipStream (..)
22+ , ZipSerialM
1923 , ZipSerial
20− , consMZip
2124 , zipWithK
2225 , zipWithMK
2326 )
2427where
2528
26−import Control.Applicative (liftA2)
2729import Control.DeepSeq (NFData(..), NFData1(..))
28−import Data.Foldable (Foldable(foldl'), fold)
29−import Data.Functor.Identity (Identity(..), runIdentity)
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)
30+import Data.Functor.Identity (Identity(..))
31+import GHC.Exts (IsList(..), IsString(..))
32+import Streamly.Internal.Data.Stream.Type (Stream, toStreamD, fromStreamD)
3633import Text.Read
3734 ( Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec
3835 , readListPrecDefault)
39−import Streamly.Internal.BaseCompat ((#.))
40−import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
41−import Streamly.Internal.Data.Stream.StreamK.Type (Stream)
4236
43−import qualified Streamly.Internal.Data.Stream.Common as P
44− (cmpBy, eqBy, foldl', foldr, fromList, toList)
45−import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
37+import qualified Streamly.Internal.Data.Stream as Stream
4638import 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"
5339
5440-- $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
5644
5745{-# INLINE zipWithMK #-}
5846zipWithMK :: Monad m =>
5947 (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
6048zipWithMK f m1 m2 =
61− D.toStreamK $ D.zipWithM f (D.fromStreamK m1) (D.fromStreamK m2)
49+ fromStreamD $ D.zipWithM f (toStreamD m1) (toStreamD m2)
6250
6351{-# INLINE zipWithK #-}
6452zipWithK :: Monad m
@@ -69,26 +57,48 @@ zipWithK f = zipWithMK (\a b -> return (f a b))
6957-- Serially Zipping Streams
7058------------------------------------------------------------------------------
7159
72−-- | For 'ZipSerialM' streams:
60+-- | For 'ZipStream':
7361--
7462-- @
75−-- (<>) = 'Streamly.Prelude.serial'
76−-- (<*>) = 'Streamly.Prelude.serial.zipWith' id
63+-- (<>) = 'Streamly.Data.Stream.append'
64+-- (<*>) = 'Streamly.Data.Stream.zipWith' id
7765-- @
7866--
7967-- Applicative evaluates the streams being zipped serially:
8068--
81−-- >>> s1 = Stream.fromFoldable [1, 2]
82−-- >>> s2 = Stream.fromFoldable [3, 4]
83−-- >>> s3 = Stream.fromFoldable [5, 6]
84−-- >>> Stream.toList $ Stream.fromZipSerial $ (,,) <$> s1 <*> s2 <*> s3
69+-- >>> s1 = Stream.ZipStream $ Stream.fromFoldable [1, 2]
70+-- >>> s2 = Stream.ZipStream $ Stream.fromFoldable [3, 4]
71+-- >>> s3 = Stream.ZipStream $ Stream.fromFoldable [5, 6]
72+-- >>> s = (,,) <$> s1 <*> s2 <*> s3
73+-- >>> Stream.fold Fold.toList (Stream.getZipStream s)
8574-- [(1,3,5),(2,4,6)]
8675--
8776-- /Since: 0.2.0 ("Streamly")/
8877--
8978-- @since 0.8.0
90−newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: Stream m a}
91− deriving (Semigroup, Monoid)
79+newtype ZipStream m a = ZipStream {getZipStream :: Stream m a}
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
92102
93103-- | An IO stream whose applicative instance zips streams serially.
94104--
@@ -97,21 +107,8 @@ newtype ZipSerialM m a = ZipSerialM {getZipSerialM :: Stream m a}
97107-- @since 0.8.0
98108type ZipSerial = ZipSerialM IO
99109
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
111− pure = ZipSerialM . Stream.toStreamK . Serial.repeat
110+instance Monad m => Applicative (ZipStream m) where
111+ pure = ZipStream . Stream.repeat
112112
113113 {-# INLINE (<*>) #-}
114− ZipSerialM m1 <*> ZipSerialM m2 = ZipSerialM $ zipWithK id m1 m2
115−
116−FOLDABLE_INSTANCE(ZipSerialM)
117−TRAVERSABLE_INSTANCE(ZipSerialM)
114+ ZipStream m1 <*> ZipStream m2 = ZipStream $ zipWithK id m1 m2
core/streamly-core.cabal−2
@@ -317,8 +317,6 @@ library
317317 , Streamly.Internal.Data.Stream.Reduce
318318 , Streamly.Internal.Data.Stream.Top
319319 , Streamly.Internal.Data.Stream
320− , Streamly.Internal.Data.Stream.Serial
321− , Streamly.Internal.Data.Stream.WSerial
322320 , Streamly.Internal.Data.Stream.Zip
323321 , Streamly.Internal.Data.List
324322
src/Streamly/Internal/Data/Stream/Instances.hs+2−2
@@ -139,7 +139,7 @@ instance (Foldable m, Monad m) => Foldable (STREAM m) where { \
139139 \
140140 {-# INLINE maximum #-}; \
141141 maximum = \
142− fromMaybe (errorWithoutStackTrace $ "maximum: empty stream") \
142+ fromMaybe (errorWithoutStackTrace "maximum: empty stream") \
143143 . toMaybe \
144144 . foldl' getMax Nothing' where { \
145145 getMax Nothing' x = Just' x; \
@@ -147,7 +147,7 @@ instance (Foldable m, Monad m) => Foldable (STREAM m) where { \
147147 \
148148 {-# INLINE minimum #-}; \
149149 minimum = \
150− fromMaybe (errorWithoutStackTrace $ "minimum: empty stream") \
150+ fromMaybe (errorWithoutStackTrace "minimum: empty stream") \
151151 . toMaybe \
152152 . foldl' getMin Nothing' where { \
153153 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
107107 (AsyncT(..), Async, WAsyncT(..), WAsync)
108108import Streamly.Internal.Data.Stream.Ahead (AheadT(..), Ahead)
109109import 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)
111111import Streamly.Internal.Data.Stream.ZipAsync (ZipAsyncM(..), ZipAsync)
112112import Streamly.Internal.Data.SVar.Type (State, adaptState)
113113
@@ -567,6 +567,10 @@ instance IsStream ParallelT where
567567-- Zip
568568-------------------------------------------------------------------------------
569569
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+
570574-- | Fix the type of a polymorphic stream as 'ZipSerialM'.
571575--
572576-- /Since: 0.2.0 ("Streamly")/
@@ -575,18 +579,18 @@ instance IsStream ParallelT where
575579fromZipSerial :: IsStream t => ZipSerialM m a -> t m a
576580fromZipSerial = adapt
577581instance IsStream ZipSerialM where
578− toStream = getZipSerialM
579− fromStream = ZipSerialM
582+ toStream = Stream.toStreamK . Zip.getZipStream
583+ fromStream = Zip.ZipStream . Stream.fromStreamK
580584
581585 {-# INLINE consM #-}
582586 {-# SPECIALIZE consM :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
583587 consM :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
584− consM = Zip.consMZip
588+ consM = consMZip
585589
586590 {-# INLINE (|:) #-}
587591 {-# SPECIALIZE (|:) :: IO a -> ZipSerialM IO a -> ZipSerialM IO a #-}
588592 (|:) :: Monad m => m a -> ZipSerialM m a -> ZipSerialM m a
589− (|:) = Zip.consMZip
593+ (|:) = consMZip
590594
591595-- | Fix the type of a polymorphic stream as 'ZipAsyncM'.
592596--
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:
188188
189189 core/src/Streamly/Internal/Data/Parser.hs
190190 core/src/Streamly/Internal/Data/Pipe.hs
191− core/src/Streamly/Internal/Data/Stream/Serial.hs
192191 core/src/Streamly/Internal/Data/Stream.hs
193192 core/src/Streamly/Internal/Data/Stream/Bottom.hs
194193 core/src/Streamly/Internal/Data/Stream/Eliminate.hs
@@ -201,7 +200,6 @@ extra-source-files:
201200 core/src/Streamly/Internal/Data/Stream/Top.hs
202201 core/src/Streamly/Internal/Data/Stream/Transform.hs
203202 core/src/Streamly/Internal/Data/Stream/Type.hs
204− core/src/Streamly/Internal/Data/Stream/WSerial.hs
205203 core/src/Streamly/Internal/Data/Stream/Zip.hs
206204 core/src/Streamly/Internal/Data/List.hs
207205 core/src/Streamly/Internal/Data/Array.hs
@@ -443,6 +441,8 @@ library
443441 , Streamly.Internal.Data.Stream.SVar.Generate
444442 , Streamly.Internal.Data.Stream.SVar.Eliminate
445443
444+ , Streamly.Internal.Data.Stream.Serial
445+ , Streamly.Internal.Data.Stream.WSerial
446446 , Streamly.Internal.Data.Stream.Async
447447 , Streamly.Internal.Data.Stream.Parallel
448448 , Streamly.Internal.Data.Stream.Ahead
@@ -599,7 +599,6 @@ library
599599 , Streamly.Internal.Data.Stream.Lift
600600 , Streamly.Internal.Data.Stream.Top
601601 , Streamly.Internal.Data.Stream
602− , Streamly.Internal.Data.Stream.Serial
603602 , Streamly.Internal.Data.Stream.Zip
604603 , Streamly.Internal.Data.List
605604
test/Streamly/Test/Data/List.hs+2−2
@@ -196,10 +196,10 @@ main = hspec $
196196
197197 it "Show instance" $ do
198198 show ([1..3] :: ZipList Int) `shouldBe`
199− "ZipList {toZipSerial = fromList [1,2,3]}"
199+ "ZipList {toZipStream = fromList [1,2,3]}"
200200
201201 it "Read instance" $ do
202− (read "ZipList {toZipSerial = fromList [1,2,3]}" :: ZipList Int)
202+ (read "ZipList {toZipStream = fromList [1,2,3]}" :: ZipList Int)
203203 `shouldBe` [1..3]
204204
205205 it "Eq instance" $ do