on master help sign in
Add composed benches for streamd/k and compare them
172efa6Harendra Kumar
benchmark/BaseStreams.hs+74−49
@@ -43,41 +43,52 @@ main =
43 -- , benchIO "fromFoldableM" D.sourceFromFoldableM
43 -- , benchIO "fromFoldableM" D.sourceFromFoldableM
44 ]
44 ]
45 , bgroup "elimination"
45 , bgroup "elimination"
46− [ benchIO "toNull" D.toNull D.sourceUnfoldrM
46+ [ benchIO "toNull" D.toNull D.sourceUnfoldrM
47− , benchIO "uncons" D.uncons D.sourceUnfoldrM
47+ , benchIO "uncons" D.uncons D.sourceUnfoldrM
48− , benchFold "tail" D.tail D.sourceUnfoldrM
48+ , benchFold "tail" D.tail D.sourceUnfoldrM
49 , benchIO "nullTail" D.nullTail D.sourceUnfoldrM
49 , benchIO "nullTail" D.nullTail D.sourceUnfoldrM
50 , benchIO "headTail" D.headTail D.sourceUnfoldrM
50 , benchIO "headTail" D.headTail D.sourceUnfoldrM
51 ]
51 ]
52 , bgroup "transformation"
52 , bgroup "transformation"
53+ [ benchIO "scan" (D.scan 1) D.sourceUnfoldrM
54+ , benchIO "map" (D.map 1) D.sourceUnfoldrM
55+ , benchIO "mapM" (D.mapM 1) D.sourceUnfoldrM
56+ ]
57+ , bgroup "transformationN"
53− [ benchIO "scanlM'" D.scan D.sourceUnfoldrM
58+ [ benchIO "scan" (D.scan 4) D.sourceUnfoldrM
54− , benchIO "map" D.map D.sourceUnfoldrM
59+ , benchIO "map" (D.map 4) D.sourceUnfoldrM
55− , benchIO "mapM" D.mapM D.sourceUnfoldrM
60+ , benchIO "mapM" (D.mapM 4) D.sourceUnfoldrM
56 ]
61 ]
57 , bgroup "filtering"
62 , bgroup "filtering"
58− [ benchIO "filter-even" D.filterEven D.sourceUnfoldrM
63+ [ benchIO "filter-even" (D.filterEven 1) D.sourceUnfoldrM
59− , benchIO "filter-all-out" D.filterAllOut D.sourceUnfoldrM
64+ , benchIO "filter-all-out" (D.filterAllOut 1) D.sourceUnfoldrM
60− , benchIO "filter-all-in" D.filterAllIn D.sourceUnfoldrM
65+ , benchIO "filter-all-in" (D.filterAllIn 1) D.sourceUnfoldrM
61− , benchIO "take-all" D.takeAll D.sourceUnfoldrM
66+ , benchIO "take-all" (D.takeAll 1) D.sourceUnfoldrM
62− , benchIO "takeWhile-true" D.takeWhileTrue D.sourceUnfoldrM
67+ , benchIO "takeWhile-true" (D.takeWhileTrue 1) D.sourceUnfoldrM
63− , benchIO "drop-all" D.dropAll D.sourceUnfoldrM
68+ , benchIO "drop-all" (D.dropAll 1) D.sourceUnfoldrM
64− , benchIO "dropWhile-true" D.dropWhileTrue D.sourceUnfoldrM
69+ , benchIO "dropWhile-true" (D.dropWhileTrue 1) D.sourceUnfoldrM
65 ]
70 ]
66− , benchIO "zip" D.zip D.sourceUnfoldrM
67− , bgroup "compose"
71+ , bgroup "filteringN"
68− [ benchIO "mapM" D.composeMapM D.sourceUnfoldrM
72+ [ benchIO "filter-even" (D.filterEven 4) D.sourceUnfoldrM
69−#if __GLASGOW_HASKELL__ != 802
73+ , benchIO "filter-all-out" (D.filterAllOut 4) D.sourceUnfoldrM
70− , benchIO "map-with-all-in-filter" D.composeMapAllInFilter D.sourceUnfoldrM
74+ , benchIO "filter-all-in" (D.filterAllIn 4) D.sourceUnfoldrM
71− , benchIO "all-in-filters" D.composeAllInFilters D.sourceUnfoldrM
75+ , benchIO "take-all" (D.takeAll 4) D.sourceUnfoldrM
72− , benchIO "all-out-filters" D.composeAllOutFilters D.sourceUnfoldrM
76+ , benchIO "takeWhile-true" (D.takeWhileTrue 4) D.sourceUnfoldrM
73−#endif
77+ , benchIO "drop-all" (D.dropAll 4) D.sourceUnfoldrM
78+ , benchIO "dropWhile-true" (D.dropWhileTrue 4) D.sourceUnfoldrM
74 ]
79 ]
75− -- Scaling with same operation in sequence
80+ , benchIO "zip" D.zip D.sourceUnfoldrM
76− , bgroup "compose-scaling"
81+ , bgroup "composed"
77− [ benchIO "1" (D.composeScaling 1) D.sourceUnfoldrM
82+ [ benchIO "scan-map" (D.scanMap 4) D.sourceUnfoldrM
78− , benchIO "2" (D.composeScaling 2) D.sourceUnfoldrM
83+ , benchIO "drop-map" (D.dropMap 4) D.sourceUnfoldrM
84+ , benchIO "drop-scan" (D.dropScan 4) D.sourceUnfoldrM
85+ , benchIO "take-drop" (D.takeDrop 4) D.sourceUnfoldrM
86+ , benchIO "take-scan" (D.takeScan 4) D.sourceUnfoldrM
87+ , benchIO "take-map" (D.takeMap 4) D.sourceUnfoldrM
79− , benchIO "3" (D.composeScaling 3) D.sourceUnfoldrM
88+ , benchIO "filter-drop" (D.filterDrop 4) D.sourceUnfoldrM
80− , benchIO "4" (D.composeScaling 4) D.sourceUnfoldrM
89+ , benchIO "filter-take" (D.filterTake 4) D.sourceUnfoldrM
90+ , benchIO "filter-scan" (D.filterScan 4) D.sourceUnfoldrM
91+ , benchIO "filter-map" (D.filterMap 4) D.sourceUnfoldrM
81 ]
92 ]
82 ]
93 ]
83 , bgroup "streamK"
94 , bgroup "streamK"
@@ -105,33 +116,47 @@ main =
105 , benchFold "last" K.last K.sourceUnfoldrM
116 , benchFold "last" K.last K.sourceUnfoldrM
106 ]
117 ]
107 , bgroup "transformation"
118 , bgroup "transformation"
119+ [ benchIO "scan" (K.scan 1) K.sourceUnfoldrM
120+ , benchIO "map" (K.map 1) K.sourceUnfoldrM
121+ , benchIO "mapM" (K.mapM 1) K.sourceUnfoldrM
122+ -- , benchIO "concat" K.concat K.sourceUnfoldrM
123+ ]
124+ , bgroup "transformationN"
108− [ benchIO "scan" K.scan K.sourceUnfoldrM
125+ [ benchIO "scan" (K.scan 4) K.sourceUnfoldrM
109− , benchIO "map" K.map K.sourceUnfoldrM
126+ , benchIO "map" (K.map 4) K.sourceUnfoldrM
110− , benchIO "mapM" K.mapM K.sourceUnfoldrM
127+ , benchIO "mapM" (K.mapM 4) K.sourceUnfoldrM
111 -- , benchIO "concat" K.concat K.sourceUnfoldrM
128 -- , benchIO "concat" K.concat K.sourceUnfoldrM
112 ]
129 ]
113 , bgroup "filtering"
130 , bgroup "filtering"
114− [ benchIO "filter-even" K.filterEven K.sourceUnfoldrM
131+ [ benchIO "filter-even" (K.filterEven 1) K.sourceUnfoldrM
115− , benchIO "filter-all-out" K.filterAllOut K.sourceUnfoldrM
132+ , benchIO "filter-all-out" (K.filterAllOut 1) K.sourceUnfoldrM
116− , benchIO "filter-all-in" K.filterAllIn K.sourceUnfoldrM
133+ , benchIO "filter-all-in" (K.filterAllIn 1) K.sourceUnfoldrM
117− , benchIO "take-all" K.takeAll K.sourceUnfoldrM
134+ , benchIO "take-all" (K.takeAll 1) K.sourceUnfoldrM
118− , benchIO "takeWhile-true" K.takeWhileTrue K.sourceUnfoldrM
135+ , benchIO "takeWhile-true" (K.takeWhileTrue 1) K.sourceUnfoldrM
119− , benchIO "drop-all" K.dropAll K.sourceUnfoldrM
136+ , benchIO "drop-all" (K.dropAll 1) K.sourceUnfoldrM
120− , benchIO "dropWhile-true" K.dropWhileTrue K.sourceUnfoldrM
137+ , benchIO "dropWhile-true" (K.dropWhileTrue 1) K.sourceUnfoldrM
121 ]
138 ]
122− , benchIO "zip" K.zip K.sourceUnfoldrM
123− , bgroup "compose"
139+ , bgroup "filteringN"
124− [ benchIO "mapM" K.composeMapM K.sourceUnfoldrM
140+ [ benchIO "filter-even" (K.filterEven 4) K.sourceUnfoldrM
125− , benchIO "map-with-all-in-filter" K.composeMapAllInFilter K.sourceUnfoldrM
141+ , benchIO "filter-all-out" (K.filterAllOut 4) K.sourceUnfoldrM
126− , benchIO "all-in-filters" K.composeAllInFilters K.sourceUnfoldrM
142+ , benchIO "filter-all-in" (K.filterAllIn 4) K.sourceUnfoldrM
127− , benchIO "all-out-filters" K.composeAllOutFilters K.sourceUnfoldrM
143+ , benchIO "take-all" (K.takeAll 4) K.sourceUnfoldrM
144+ , benchIO "takeWhile-true" (K.takeWhileTrue 4) K.sourceUnfoldrM
145+ , benchIO "drop-all" (K.dropAll 4) K.sourceUnfoldrM
146+ , benchIO "dropWhile-true" (K.dropWhileTrue 4) K.sourceUnfoldrM
128 ]
147 ]
129− -- Scaling with same operation in sequence
148+ , benchIO "zip" K.zip K.sourceUnfoldrM
130− , bgroup "compose-scaling"
149+ , bgroup "composed"
131− [ benchIO "1" (K.composeScaling 1) K.sourceUnfoldrM
150+ [ benchIO "scan-map" (K.scanMap 4) K.sourceUnfoldrM
132− , benchIO "2" (K.composeScaling 2) K.sourceUnfoldrM
151+ , benchIO "drop-map" (K.dropMap 4) K.sourceUnfoldrM
152+ , benchIO "drop-scan" (K.dropScan 4) K.sourceUnfoldrM
153+ , benchIO "take-drop" (K.takeDrop 4) K.sourceUnfoldrM
154+ , benchIO "take-scan" (K.takeScan 4) K.sourceUnfoldrM
155+ , benchIO "take-map" (K.takeMap 4) K.sourceUnfoldrM
133− , benchIO "3" (K.composeScaling 3) K.sourceUnfoldrM
156+ , benchIO "filter-drop" (K.filterDrop 4) K.sourceUnfoldrM
134− , benchIO "4" (K.composeScaling 4) K.sourceUnfoldrM
157+ , benchIO "filter-take" (K.filterTake 4) K.sourceUnfoldrM
158+ , benchIO "filter-scan" (K.filterScan 4) K.sourceUnfoldrM
159+ , benchIO "filter-map" (K.filterMap 4) K.sourceUnfoldrM
135 ]
160 ]
136 ]
161 ]
137 ]
162 ]
benchmark/Chart.hs+30−11
@@ -174,20 +174,39 @@ makeBaseGraphs cfg inputFile = do
174-- text reports
174-- text reports
175------------------------------------------------------------------------------
175------------------------------------------------------------------------------
176
176
177+selectBench :: (SortColumn -> Either String [(String, Double)]) -> [String]
178+selectBench f =
179+ reverse
180+ $ fmap fst
181+ $ either
182+ (const $ either error id $ f $ ColumnIndex 0)
183+ (sortOn snd)
184+ $ f $ ColumnIndex 1
185+
177benchShow Options{..} cfg func inp out =
186benchShow Options{..} cfg func inp out =
178 if genGraphs
187 if genGraphs
179 then func cfg {outputDir = Just out} inp
188 then func cfg {outputDir = Just out} inp
180− else
181− ignoringErr $ report inp Nothing $ cfg
189+ else ignoringErr $ report inp Nothing $ cfg
182− { selectBenchmarks =
190+ { selectBenchmarks = selectBench }
183− \f ->
191+
184− reverse
192+showStreamDVsK Options{..} cfg func inp out =
185− $ fmap fst
193+ let cfg' = cfg
186− $ either
194+ { classifyBenchmark = classify
187− (const $ either error id $ f $ ColumnIndex 0)
195+ , selectBenchmarks = selectBench
188− (sortOn snd)
189− $ f $ ColumnIndex 1
190 }
196 }
197+ in if genGraphs
198+ then ignoringErr $ graph inp "streamD-vs-streamK"
199+ cfg' {outputDir = Just out}
200+ else ignoringErr $ report inp Nothing cfg'
201+
202+ where
203+ classify b =
204+ if "streamD/" `isPrefixOf` b
205+ then fmap ("streamD",) $ stripPrefix "streamD/" b
206+ else
207+ if "streamK/" `isPrefixOf` b
208+ then fmap ("streamK",) $ stripPrefix "streamK/" b
209+ else Nothing
191
210
192main :: IO ()
211main :: IO ()
193main = do
212main = do
@@ -212,6 +231,6 @@ main = do
212 Nested -> benchShow opts cfg makeNestedGraphs
231 Nested -> benchShow opts cfg makeNestedGraphs
213 "charts/nested/results.csv"
232 "charts/nested/results.csv"
214 "charts/nested"
233 "charts/nested"
215− Base -> benchShow opts cfg makeBaseGraphs
234+ Base -> showStreamDVsK opts cfg makeBaseGraphs
216 "charts/base/results.csv"
235 "charts/base/results.csv"
217 "charts/base"
236 "charts/base"
benchmark/StreamDOps.hs+68−53
@@ -13,7 +13,8 @@ import Control.Monad (when)
13import Data.Maybe (isJust)
13import Data.Maybe (isJust)
14import Prelude
14import Prelude
15 (Monad, Int, (+), ($), (.), return, (>), even, (<=),
15 (Monad, Int, (+), ($), (.), return, (>), even, (<=),
16− subtract, undefined, Maybe(..), not, mapM_, (>>=))
16+ subtract, undefined, Maybe(..), not, mapM_, (>>=),
17+ maxBound)
17
18
18import qualified Streamly.Streams.StreamD as S
19import qualified Streamly.Streams.StreamD as S
19
20
@@ -28,33 +29,15 @@ maxValue = value + 1000
28{-# INLINE uncons #-}
29{-# INLINE uncons #-}
29{-# INLINE nullTail #-}
30{-# INLINE nullTail #-}
30{-# INLINE headTail #-}
31{-# INLINE headTail #-}
31−{-# INLINE scan #-}
32−{-# INLINE map #-}
33−{-# INLINE filterEven #-}
34−{-# INLINE filterAllOut #-}
35−{-# INLINE filterAllIn #-}
36−{-# INLINE takeOne #-}
37−{-# INLINE takeAll #-}
38−{-# INLINE takeWhileTrue #-}
39−{-# INLINE dropAll #-}
40−{-# INLINE dropWhileTrue #-}
41{-# INLINE zip #-}
32{-# INLINE zip #-}
42{-
33{-
43{-# INLINE concat #-}
34{-# INLINE concat #-}
44-}
35-}
45−{-# INLINE composeAllInFilters #-}
46−{-# INLINE composeAllOutFilters #-}
47−{-# INLINE composeMapAllInFilter #-}
48−uncons, nullTail, headTail, map, scan, filterEven, filterAllOut,
36+uncons, nullTail, headTail, zip
49− filterAllIn, takeOne, takeAll, takeWhileTrue, dropAll, dropWhileTrue, zip,
50 -- concat,
37 -- concat,
51− composeAllInFilters, composeAllOutFilters, composeMapAllInFilter
52 :: Monad m
38 :: Monad m
53 => Stream m Int -> m ()
39 => Stream m Int -> m ()
54
40
55−{-# INLINE composeMapM #-}
56−composeMapM :: Monad m => Stream m Int -> m ()
57−
58{-# INLINE toList #-}
41{-# INLINE toList #-}
59toList :: Monad m => Stream m Int -> m [Int]
42toList :: Monad m => Stream m Int -> m [Int]
60{-# INLINE foldl #-}
43{-# INLINE foldl #-}
@@ -63,8 +46,7 @@ foldl :: Monad m => Stream m Int -> m Int
63last :: Monad m => Stream m Int -> m (Maybe Int)
46last :: Monad m => Stream m Int -> m (Maybe Int)
64
47
65{-# INLINE toNull #-}
48{-# INLINE toNull #-}
66−{-# INLINE mapM #-}
67−toNull, mapM :: Monad m => Stream m Int -> m ()
49+toNull :: Monad m => Stream m Int -> m ()
68
50
69-------------------------------------------------------------------------------
51-------------------------------------------------------------------------------
70-- Stream generation and elimination
52-- Stream generation and elimination
@@ -144,17 +126,45 @@ last = S.last
144transform :: Monad m => Stream m a -> m ()
126transform :: Monad m => Stream m a -> m ()
145transform = runStream
127transform = runStream
146
128
129+{-# INLINE composeN #-}
130+composeN
131+ :: Monad m
132+ => Int -> (Stream m Int -> Stream m Int) -> Stream m Int -> m ()
133+composeN n f =
134+ case n of
147−scan = transform . S.scanlM' (\a b -> return (a + b)) 0
135+ 1 -> transform . f
136+ 2 -> transform . f . f
137+ 3 -> transform . f . f . f
138+ 4 -> transform . f . f . f . f
139+ _ -> undefined
140+
141+{-# INLINE scan #-}
142+{-# INLINE map #-}
143+{-# INLINE mapM #-}
144+{-# INLINE filterEven #-}
145+{-# INLINE filterAllOut #-}
146+{-# INLINE filterAllIn #-}
147+{-# INLINE takeOne #-}
148+{-# INLINE takeAll #-}
149+{-# INLINE takeWhileTrue #-}
150+{-# INLINE dropAll #-}
151+{-# INLINE dropWhileTrue #-}
152+scan, map, mapM, filterEven, filterAllOut,
153+ filterAllIn, takeOne, takeAll, takeWhileTrue, dropAll, dropWhileTrue
154+ :: Monad m
155+ => Int -> Stream m Int -> m ()
156+
157+scan n = composeN n $ S.scanl' (+) 0
148−map = transform . S.map (+1)
158+map n = composeN n $ S.map (+1)
149−mapM = transform . S.mapM return
159+mapM n = composeN n $ S.mapM return
150−filterEven = transform . S.filter even
160+filterEven n = composeN n $ S.filter even
151−filterAllOut = transform . S.filter (> maxValue)
161+filterAllOut n = composeN n $ S.filter (> maxValue)
152−filterAllIn = transform . S.filter (<= maxValue)
162+filterAllIn n = composeN n $ S.filter (<= maxValue)
153−takeOne = transform . S.take 1
163+takeOne n = composeN n $ S.take 1
154−takeAll = transform . S.take maxValue
164+takeAll n = composeN n $ S.take maxValue
155−takeWhileTrue = transform . S.takeWhile (<= maxValue)
165+takeWhileTrue n = composeN n $ S.takeWhile (<= maxValue)
156−dropAll = transform . S.drop maxValue
166+dropAll n = composeN n $ S.drop maxValue
157−dropWhileTrue = transform . S.dropWhile (<= maxValue)
167+dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
158
168
159-------------------------------------------------------------------------------
169-------------------------------------------------------------------------------
160-- Zipping and concat
170-- Zipping and concat
@@ -164,25 +174,30 @@ zip src = transform $ S.zipWith (,) src src
164-- concat _n = return ()
174-- concat _n = return ()
165
175
166-------------------------------------------------------------------------------
176-------------------------------------------------------------------------------
167−-- Composition
177+-- Mixed Composition
168-------------------------------------------------------------------------------
178-------------------------------------------------------------------------------
169
179
170−{-# INLINE compose #-}
180+{-# INLINE scanMap #-}
181+{-# INLINE dropMap #-}
182+{-# INLINE dropScan #-}
183+{-# INLINE takeDrop #-}
184+{-# INLINE takeScan #-}
185+{-# INLINE takeMap #-}
186+{-# INLINE filterDrop #-}
187+{-# INLINE filterTake #-}
188+{-# INLINE filterScan #-}
189+{-# INLINE filterMap #-}
190+scanMap, dropMap, dropScan, takeDrop, takeScan, takeMap, filterDrop,
191+ filterTake, filterScan, filterMap
171−compose :: Monad m => (Stream m Int -> Stream m Int) -> Stream m Int -> m ()
192+ :: Monad m => Int -> Stream m Int -> m ()
172−compose f = transform . f . f . f . f
193+
173−
194+scanMap n = composeN n $ S.map (subtract 1) . S.scanl' (+) 0
174−composeMapM = compose (S.mapM return)
195+dropMap n = composeN n $ S.map (subtract 1) . S.drop 1
175−composeAllInFilters = compose (S.filter (<= maxValue))
196+dropScan n = composeN n $ S.scanl' (+) 0 . S.drop 1
176−composeAllOutFilters = compose (S.filter (> maxValue))
197+takeDrop n = composeN n $ S.drop 1 . S.take maxValue
177−composeMapAllInFilter = compose (S.filter (<= maxValue) . S.map (subtract 1))
198+takeScan n = composeN n $ S.scanl' (+) 0 . S.take maxValue
178−
199+takeMap n = composeN n $ S.map (subtract 1) . S.take maxValue
179−{-# INLINE composeScaling #-}
200+filterDrop n = composeN n $ S.drop 1 . S.filter (<= maxValue)
180−composeScaling :: Monad m => Int -> Stream m Int -> m ()
201+filterTake n = composeN n $ S.take maxValue . S.filter (<= maxValue)
181−composeScaling m =
202+filterScan n = composeN n $ S.scanl' (+) 0 . S.filter (<= maxBound)
182− case m of
183− 1 -> transform . f
184− 2 -> transform . f . f
185− 3 -> transform . f . f . f
186− 4 -> transform . f . f . f . f
187− _ -> undefined
188− where f = S.filter (<= maxValue)
203+filterMap n = composeN n $ S.map (subtract 1) . S.filter (<= maxValue)
benchmark/StreamKOps.hs+69−55
@@ -13,7 +13,8 @@ import Control.Monad (when)
13import Data.Maybe (isJust)
13import Data.Maybe (isJust)
14import Prelude
14import Prelude
15 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=),
15 (Monad, Int, (+), ($), (.), return, fmap, even, (>), (<=),
16− subtract, undefined, Maybe(..), not, mapM_, (>>=))
16+ subtract, undefined, Maybe(..), not, mapM_, (>>=),
17+ maxBound)
17
18
18import qualified Streamly.Streams.StreamK as S
19import qualified Streamly.Streams.StreamK as S
19import qualified Streamly.Streams.Prelude as S
20import qualified Streamly.Streams.Prelude as S
@@ -31,31 +32,12 @@ maxValue = value + 1000
31{-# INLINE uncons #-}
32{-# INLINE uncons #-}
32{-# INLINE nullTail #-}
33{-# INLINE nullTail #-}
33{-# INLINE headTail #-}
34{-# INLINE headTail #-}
34−{-# INLINE scan #-}
35−{-# INLINE map #-}
36−{-# INLINE filterEven #-}
37−{-# INLINE filterAllOut #-}
38−{-# INLINE filterAllIn #-}
39−{-# INLINE takeOne #-}
40−{-# INLINE takeAll #-}
41−{-# INLINE takeWhileTrue #-}
42−{-# INLINE dropAll #-}
43−{-# INLINE dropWhileTrue #-}
44{-# INLINE zip #-}
35{-# INLINE zip #-}
45{-# INLINE concat #-}
36{-# INLINE concat #-}
46−{-# INLINE composeAllInFilters #-}
47−{-# INLINE composeAllOutFilters #-}
48−{-# INLINE composeMapAllInFilter #-}
49−toNull, uncons, nullTail, headTail, scan, map, filterEven, filterAllOut,
37+toNull, uncons, nullTail, headTail, zip, concat
50− filterAllIn, takeOne, takeAll, takeWhileTrue, dropAll, dropWhileTrue, zip,
51− concat, composeAllInFilters, composeAllOutFilters,
52− composeMapAllInFilter
53 :: Monad m
38 :: Monad m
54 => Stream m Int -> m ()
39 => Stream m Int -> m ()
55
40
56−{-# INLINE composeMapM #-}
57−composeMapM :: S.MonadAsync m => Stream m Int -> m ()
58−
59{-# INLINE toList #-}
41{-# INLINE toList #-}
60toList :: Monad m => Stream m Int -> m [Int]
42toList :: Monad m => Stream m Int -> m [Int]
61{-# INLINE foldl #-}
43{-# INLINE foldl #-}
@@ -63,9 +45,6 @@ foldl :: Monad m => Stream m Int -> m Int
63{-# INLINE last #-}
45{-# INLINE last #-}
64last :: Monad m => Stream m Int -> m (Maybe Int)
46last :: Monad m => Stream m Int -> m (Maybe Int)
65
47
66−{-# INLINE mapM #-}
67−mapM :: S.MonadAsync m => Stream m Int -> m ()
68−
69-------------------------------------------------------------------------------
48-------------------------------------------------------------------------------
70-- Stream generation and elimination
49-- Stream generation and elimination
71-------------------------------------------------------------------------------
50-------------------------------------------------------------------------------
@@ -165,17 +144,47 @@ last = S.last
165transform :: Monad m => Stream m a -> m ()
144transform :: Monad m => Stream m a -> m ()
166transform = runStream
145transform = runStream
167
146
168−scan = transform . S.scanl' (+) 0
147+{-# INLINE composeN #-}
148+composeN
149+ :: Monad m
150+ => Int -> (Stream m Int -> Stream m Int) -> Stream m Int -> m ()
151+composeN n f =
152+ case n of
153+ 1 -> transform . f
154+ 2 -> transform . f . f
155+ 3 -> transform . f . f . f
156+ 4 -> transform . f . f . f . f
157+ _ -> undefined
158+
159+{-# INLINE scan #-}
160+{-# INLINE map #-}
161+{-# INLINE filterEven #-}
162+{-# INLINE filterAllOut #-}
163+{-# INLINE filterAllIn #-}
164+{-# INLINE takeOne #-}
165+{-# INLINE takeAll #-}
166+{-# INLINE takeWhileTrue #-}
167+{-# INLINE dropAll #-}
168+{-# INLINE dropWhileTrue #-}
169+scan, map, filterEven, filterAllOut,
170+ filterAllIn, takeOne, takeAll, takeWhileTrue, dropAll, dropWhileTrue
171+ :: Monad m
172+ => Int -> Stream m Int -> m ()
173+
174+{-# INLINE mapM #-}
175+mapM :: S.MonadAsync m => Int -> Stream m Int -> m ()
176+
177+scan n = composeN n $ S.scanl' (+) 0
169−map = transform . fmap (+1)
178+map n = composeN n $ fmap (+1)
170−mapM = transform . S.mapM return
179+mapM n = composeN n $ S.mapM return
171−filterEven = transform . S.filter even
180+filterEven n = composeN n $ S.filter even
172−filterAllOut = transform . S.filter (> maxValue)
181+filterAllOut n = composeN n $ S.filter (> maxValue)
173−filterAllIn = transform . S.filter (<= maxValue)
182+filterAllIn n = composeN n $ S.filter (<= maxValue)
174−takeOne = transform . S.take 1
183+takeOne n = composeN n $ S.take 1
175−takeAll = transform . S.take maxValue
184+takeAll n = composeN n $ S.take maxValue
176−takeWhileTrue = transform . S.takeWhile (<= maxValue)
185+takeWhileTrue n = composeN n $ S.takeWhile (<= maxValue)
177−dropAll = transform . S.drop maxValue
186+dropAll n = composeN n $ S.drop maxValue
178−dropWhileTrue = transform . S.dropWhile (<= maxValue)
187+dropWhileTrue n = composeN n $ S.dropWhile (<= maxValue)
179
188
180-------------------------------------------------------------------------------
189-------------------------------------------------------------------------------
181-- Zipping and concat
190-- Zipping and concat
@@ -185,25 +194,30 @@ zip src = transform $ S.zipWith (,) src src
185concat _n = return ()
194concat _n = return ()
186
195
187-------------------------------------------------------------------------------
196-------------------------------------------------------------------------------
188−-- Composition
197+-- Mixed Composition
189-------------------------------------------------------------------------------
198-------------------------------------------------------------------------------
190
199
191−{-# INLINE compose #-}
200+{-# INLINE scanMap #-}
201+{-# INLINE dropMap #-}
202+{-# INLINE dropScan #-}
203+{-# INLINE takeDrop #-}
204+{-# INLINE takeScan #-}
205+{-# INLINE takeMap #-}
206+{-# INLINE filterDrop #-}
207+{-# INLINE filterTake #-}
208+{-# INLINE filterScan #-}
209+{-# INLINE filterMap #-}
210+scanMap, dropMap, dropScan, takeDrop, takeScan, takeMap, filterDrop,
211+ filterTake, filterScan, filterMap
192−compose :: Monad m => (Stream m Int -> Stream m Int) -> Stream m Int -> m ()
212+ :: Monad m => Int -> Stream m Int -> m ()
193−compose f = transform . f . f . f . f
213+
194−
214+scanMap n = composeN n $ S.map (subtract 1) . S.scanl' (+) 0
195−composeMapM = compose (S.mapM return)
215+dropMap n = composeN n $ S.map (subtract 1) . S.drop 1
196−composeAllInFilters = compose (S.filter (<= maxValue))
216+dropScan n = composeN n $ S.scanl' (+) 0 . S.drop 1
197−composeAllOutFilters = compose (S.filter (> maxValue))
217+takeDrop n = composeN n $ S.drop 1 . S.take maxValue
198−composeMapAllInFilter = compose (S.filter (<= maxValue) . fmap (subtract 1))
218+takeScan n = composeN n $ S.scanl' (+) 0 . S.take maxValue
199−
219+takeMap n = composeN n $ S.map (subtract 1) . S.take maxValue
200−{-# INLINABLE composeScaling #-}
220+filterDrop n = composeN n $ S.drop 1 . S.filter (<= maxValue)
201−composeScaling :: Monad m => Int -> Stream m Int -> m ()
221+filterTake n = composeN n $ S.take maxValue . S.filter (<= maxValue)
202−composeScaling m =
222+filterScan n = composeN n $ S.scanl' (+) 0 . S.filter (<= maxBound)
203− case m of
204− 1 -> transform . f
205− 2 -> transform . f . f
206− 3 -> transform . f . f . f
207− 4 -> transform . f . f . f . f
208− _ -> undefined
209− where f = S.filter (<= maxValue)
223+filterMap n = composeN n $ S.map (subtract 1) . S.filter (<= maxValue)
src/Streamly/Streams/StreamD.hs+5
@@ -93,6 +93,7 @@ module Streamly.Streams.StreamD
93 -- * Transformation
93 -- * Transformation
94 -- ** By folding (scans)
94 -- ** By folding (scans)
95 , scanlM'
95 , scanlM'
96+ , scanl'
96
97
97 -- * Filtering
98 -- * Filtering
98 , filter
99 , filter
@@ -500,6 +501,10 @@ postscanlM' fstep begin (Stream step state) =
500scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
501scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
501scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
502scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
502
503
504+{-# INLINE scanl' #-}
505+scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
506+scanl' f = scanlM' (\a b -> return (f a b))
507+
503-------------------------------------------------------------------------------
508-------------------------------------------------------------------------------
504-- Filtering
509-- Filtering
505-------------------------------------------------------------------------------
510-------------------------------------------------------------------------------