on master help sign in
Make polymorphic semigroup ops wSerial, etc same fixity as <>.
0a8d13dPranay Sashank
Changelog.md+2
@@ -6,6 +6,8 @@
6 accumulator monadic.
6 accumulator monadic.
7* Change the signature of `concatMapWith` to ensure that it can be
7* Change the signature of `concatMapWith` to ensure that it can be
8 used with a wide variety of combining functions.
8 used with a wide variety of combining functions.
9+* Change the associativity of combinators `serial`, `wSerial`,
10+ `ahead`, `async`, `wAsync`, `parallel` to be the same as `<>`.
9* Drop support for GHC 7.10.3.
11* Drop support for GHC 7.10.3.
10
12
11### Bug Fixes
13### Bug Fixes
src/Streamly/Internal/Data/Stream/Ahead.hs+2
@@ -582,6 +582,8 @@ forkSVarAhead m1 m2 = mkStream $ \st yld sng stp -> do
582 liftIO $ enqueue (fromJust $ streamVar st) mb
582 liftIO $ enqueue (fromJust $ streamVar st) mb
583 foldStream st yld sng stp ma
583 foldStream st yld sng stp ma
584
584
585+infixr 6 `ahead`
586+
585-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AheadT'.
587-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AheadT'.
586-- Merges two streams sequentially but with concurrent lookahead.
588-- Merges two streams sequentially but with concurrent lookahead.
587--
589--
src/Streamly/Internal/Data/Stream/Async.hs+4
@@ -628,6 +628,8 @@ joinStreamVarAsync style m1 m2 = mkStream $ \st yld sng stp ->
628-- Semigroup and Monoid style compositions for parallel actions
628-- Semigroup and Monoid style compositions for parallel actions
629------------------------------------------------------------------------------
629------------------------------------------------------------------------------
630
630
631+infixr 6 `async`
632+
631-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AsyncT'.
633-- | Polymorphic version of the 'Semigroup' operation '<>' of 'AsyncT'.
632-- Merges two streams possibly concurrently, preferring the
634-- Merges two streams possibly concurrently, preferring the
633-- elements from the left one when available.
635-- elements from the left one when available.
@@ -802,6 +804,8 @@ MONAD_COMMON_INSTANCES(AsyncT, MONADPARALLEL)
802consMWAsync :: MonadAsync m => m a -> WAsyncT m a -> WAsyncT m a
804consMWAsync :: MonadAsync m => m a -> WAsyncT m a -> WAsyncT m a
803consMWAsync m r = fromStream $ K.yieldM m `wAsync` (toStream r)
805consMWAsync m r = fromStream $ K.yieldM m `wAsync` (toStream r)
804
806
807+infixr 6 `wAsync`
808+
805-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WAsyncT'.
809-- | Polymorphic version of the 'Semigroup' operation '<>' of 'WAsyncT'.
806-- Merges two streams concurrently choosing elements from both fairly.
810-- Merges two streams concurrently choosing elements from both fairly.
807--
811--
src/Streamly/Internal/Data/Stream/Parallel.hs+2
@@ -205,6 +205,8 @@ joinStreamVarPar style ss m1 m2 = mkStream $ \st yld sng stp ->
205consMParallel :: MonadAsync m => m a -> ParallelT m a -> ParallelT m a
205consMParallel :: MonadAsync m => m a -> ParallelT m a -> ParallelT m a
206consMParallel m r = fromStream $ K.yieldM m `parallel` (toStream r)
206consMParallel m r = fromStream $ K.yieldM m `parallel` (toStream r)
207
207
208+infixr 6 `parallel`
209+
208-- | Execute two streams concurrently and merge their outputs. For example, if
210-- | Execute two streams concurrently and merge their outputs. For example, if
209-- stream @a@ is a serial stream consisting of @a1, a2, a3@ and stream @b@ is a
211-- stream @a@ is a serial stream consisting of @a1, a2, a3@ and stream @b@ is a
210-- serial stream consisting of @b1, b2, b3@ then stream @a `parallel` b@ may
212-- serial stream consisting of @b1, b2, b3@ then stream @a `parallel` b@ may
src/Streamly/Internal/Data/Stream/Serial.hs+2
@@ -358,6 +358,8 @@ instance IsStream WSerialT where
358-- Semigroup
358-- Semigroup
359------------------------------------------------------------------------------
359------------------------------------------------------------------------------
360
360
361+infixr 6 `wSerial`
362+
361-- Additionally we can have m elements yield from the first stream and n
363-- Additionally we can have m elements yield from the first stream and n
362-- elements yielding from the second stream. We can also have time slicing
364-- elements yielding from the second stream. We can also have time slicing
363-- variants of positional interleaving, e.g. run first stream for m seconds and
365-- variants of positional interleaving, e.g. run first stream for m seconds and
src/Streamly/Internal/Data/Stream/StreamK/Type.hs+2
@@ -755,6 +755,8 @@ foldrMKWith f step acc g = go g
755-- Semigroup
755-- Semigroup
756------------------------------------------------------------------------------
756------------------------------------------------------------------------------
757
757
758+infixr 6 `serial`
759+
758-- | Polymorphic version of the 'Semigroup' operation '<>' of 'SerialT'.
760-- | Polymorphic version of the 'Semigroup' operation '<>' of 'SerialT'.
759-- Appends two streams sequentially, yielding all elements from the first
761-- Appends two streams sequentially, yielding all elements from the first
760-- stream, and then all elements from the second stream.
762-- stream, and then all elements from the second stream.
test/Streamly/Test/Prelude.hs−1
@@ -544,7 +544,6 @@ foldFromList constr op eq = transformFromList constr eq id op
544-- XXX concatenate streams of multiple elements rather than single elements
544-- XXX concatenate streams of multiple elements rather than single elements
545semigroupOps
545semigroupOps
546 :: (IsStream t
546 :: (IsStream t
547−
548#if __GLASGOW_HASKELL__ < 804
547#if __GLASGOW_HASKELL__ < 804
549 , Semigroup (t IO Int)
548 , Semigroup (t IO Int)
550#endif
549#endif
test/Streamly/Test/Prelude/Ahead.hs+22−1
@@ -12,14 +12,34 @@ module Streamly.Test.Prelude.Ahead where
12#if __GLASGOW_HASKELL__ < 808
12#if __GLASGOW_HASKELL__ < 808
13import Data.Semigroup ((<>))
13import Data.Semigroup ((<>))
14#endif
14#endif
15+import Test.QuickCheck (Property)
15import Test.Hspec.QuickCheck
16import Test.Hspec.QuickCheck
17+import Test.QuickCheck.Monadic (monadicIO, run)
16import Test.Hspec as H
18import Test.Hspec as H
17
19
18import Streamly
20import Streamly
19import qualified Streamly.Prelude as S
21import qualified Streamly.Prelude as S
20
22
23+import Streamly.Test.Common
21import Streamly.Test.Prelude
24import Streamly.Test.Prelude
22
25
26+associativityCheck
27+ :: String
28+ -> (AheadT IO Int -> SerialT IO Int)
29+ -> Spec
30+associativityCheck desc t = prop desc assocCheckProp
31+ where
32+ assocCheckProp :: [Int] -> [Int] -> [Int] -> Property
33+ assocCheckProp xs ys zs =
34+ monadicIO $ do
35+ let xStream = S.fromList xs
36+ yStream = S.fromList ys
37+ zStream = S.fromList zs
38+ infixAssocstream <-
39+ run $ S.toList $ t $ xStream `ahead` yStream `ahead` zStream
40+ assocStream <- run $ S.toList $ t $ xStream <> yStream <> zStream
41+ listEquals (==) infixAssocstream assocStream
42+
23main :: IO ()
43main :: IO ()
24main = hspec
44main = hspec
25 $ H.parallel
45 $ H.parallel
@@ -44,7 +64,8 @@ main = hspec
44 aheadOps $ monoidOps "aheadly" mempty (==)
64 aheadOps $ monoidOps "aheadly" mempty (==)
45
65
46 describe "Semigroup operations" $ do
66 describe "Semigroup operations" $ do
47− aheadOps $ semigroupOps "aheadly" (==)
67+ aheadOps $ semigroupOps "aheadly" (==)
68+ aheadOps $ associativityCheck "ahead == <>"
48
69
49 describe "Applicative operations" $ do
70 describe "Applicative operations" $ do
50 aheadOps $ applicativeOps S.fromFoldable "aheadly applicative" (==)
71 aheadOps $ applicativeOps S.fromFoldable "aheadly applicative" (==)
test/Streamly/Test/Prelude/Serial.hs+19−1
@@ -145,6 +145,23 @@ testGroupsBySep =
145 $ S.fromList vec
145 $ S.fromList vec
146 assert $ decreasing a == True
146 assert $ decreasing a == True
147
147
148+associativityCheck
149+ :: String
150+ -> (SerialT IO Int -> SerialT IO Int)
151+ -> Spec
152+associativityCheck desc t = prop desc assocCheckProp
153+ where
154+ assocCheckProp :: [Int] -> [Int] -> [Int] -> Property
155+ assocCheckProp xs ys zs =
156+ monadicIO $ do
157+ let xStream = S.fromList xs
158+ yStream = S.fromList ys
159+ zStream = S.fromList zs
160+ infixAssocstream <-
161+ run $ S.toList $ t $ xStream `serial` yStream `serial` zStream
162+ assocStream <- run $ S.toList $ t $ xStream <> yStream <> zStream
163+ listEquals (==) infixAssocstream assocStream
164+
148main :: IO ()
165main :: IO ()
149main = hspec
166main = hspec
150 $ H.parallel
167 $ H.parallel
@@ -199,7 +216,8 @@ main = hspec
199 serialOps $ monoidOps "serially" mempty (==)
216 serialOps $ monoidOps "serially" mempty (==)
200
217
201 describe "Semigroup operations" $ do
218 describe "Semigroup operations" $ do
202− serialOps $ semigroupOps "serially" (==)
219+ serialOps $ semigroupOps "serially" (==)
220+ serialOps $ associativityCheck "serial == <>"
203
221
204 describe "Applicative operations" $ do
222 describe "Applicative operations" $ do
205 -- The tests using sorted equality are weaker tests
223 -- The tests using sorted equality are weaker tests
test/Streamly/Test/Prelude/WSerial.hs+22−1
@@ -12,14 +12,34 @@ module Streamly.Test.Prelude.WSerial where
12#if __GLASGOW_HASKELL__ < 808
12#if __GLASGOW_HASKELL__ < 808
13import Data.Semigroup ((<>))
13import Data.Semigroup ((<>))
14#endif
14#endif
15+import Test.QuickCheck (Property)
15import Test.Hspec.QuickCheck
16import Test.Hspec.QuickCheck
17+import Test.QuickCheck.Monadic (monadicIO, run)
16import Test.Hspec as H
18import Test.Hspec as H
17
19
18import Streamly
20import Streamly
19import qualified Streamly.Prelude as S
21import qualified Streamly.Prelude as S
20
22
23+import Streamly.Test.Common
21import Streamly.Test.Prelude
24import Streamly.Test.Prelude
22
25
26+associativityCheck
27+ :: String
28+ -> (WSerialT IO Int -> SerialT IO Int)
29+ -> Spec
30+associativityCheck desc t = prop desc assocCheckProp
31+ where
32+ assocCheckProp :: [Int] -> [Int] -> [Int] -> Property
33+ assocCheckProp xs ys zs =
34+ monadicIO $ do
35+ let xStream = S.fromList xs
36+ yStream = S.fromList ys
37+ zStream = S.fromList zs
38+ infixAssocstream <-
39+ run $ S.toList $ t $ xStream `wSerial` yStream `wSerial` zStream
40+ assocStream <- run $ S.toList $ t $ xStream <> yStream <> zStream
41+ listEquals (==) infixAssocstream assocStream
42+
23main :: IO ()
43main :: IO ()
24main = hspec
44main = hspec
25 $ H.parallel
45 $ H.parallel
@@ -45,7 +65,8 @@ main = hspec
45 wSerialOps $ monoidOps "wSerially" mempty sortEq
65 wSerialOps $ monoidOps "wSerially" mempty sortEq
46
66
47 describe "Semigroup operations" $ do
67 describe "Semigroup operations" $ do
48− wSerialOps $ semigroupOps "wSerially" (==)
68+ wSerialOps $ semigroupOps "wSerially" (==)
69+ wSerialOps $ associativityCheck "wSerial == <>"
49
70
50 describe "Applicative operations" $ do
71 describe "Applicative operations" $ do
51 wSerialOps $ applicativeOps S.fromFoldable "wSerially applicative" sortEq
72 wSerialOps $ applicativeOps S.fromFoldable "wSerially applicative" sortEq