on master help sign in
Remove the Sink module
commit6726613bcaf4ac66b8ab2deabb5277cb35176e7c authorRanjeet Kumar Ranjan <ranjeetr@composewell.com> dateThu 17 Mar 2022, 17:46 (5 years ago) parent7886e14
5 files changed+2−278
benchmark/Streamly/Benchmark/Data/Fold.hs−2 core/src/Streamly/Internal/Data/Sink.hs−245 core/src/Streamly/Internal/Data/Sink/Type.hs−24 core/streamly-core.cabal−2 streamly.cabal+2−5
benchmark/Streamly/Benchmark/Data/Fold.hs−2
@@ -21,7 +21,6 @@ import Streamly.Internal.Data.Fold (Fold(..))
2121import qualified Data.Map.Strict as Map
2222import qualified Streamly.Internal.Data.Fold as FL
2323import qualified Streamly.Internal.Data.Pipe as Pipe
24−import qualified Streamly.Internal.Data.Sink as Sink
2524import qualified Streamly.Internal.Data.Stream.IsStream as IP
2625import qualified Streamly.Prelude as S
2726
@@ -247,7 +246,6 @@ o_1_space_serial_elimination value =
247246 [ benchIOSink value "drain" (S.fold FL.drain)
248247 , benchIOSink value "drainBy" (S.fold (FL.drainBy return))
249248 , benchIOSink value "drainN" (S.fold (FL.drainN value))
250− , benchIOSink value "sink" (S.fold $ Sink.toFold Sink.drain)
251249 , benchIOSink value "last" (S.fold FL.last)
252250 , benchIOSink value "length" (S.fold FL.length)
253251 , benchIOSink value "sum" (S.fold FL.sum)
core/src/Streamly/Internal/Data/Sink.hsdeleted−245
@@ -1,245 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Sink
3−-- Copyright : (c) 2019 Composewell Technologies
4−-- License : BSD3
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−--
9−--
10−-- The 'Sink' type is a just a special case of 'Fold' and we can do without
11−-- it. However, in some cases 'Sink' is a simpler type and may provide better
12−-- performance than 'Fold' because it does not maintain any state. Folds can
13−-- be used for both pure and monadic computations. Sinks are not applicable to
14−-- pure computations.
15−
16−module Streamly.Internal.Data.Sink
17− (
18− Sink (..)
19−
20− -- * Upgrading
21− , toFold
22−
23− -- * Composing Sinks
24− -- ** Distribute
25− , tee
26− , distribute
27−
28− -- ** Demultiplex
29− , demux
30−
31− -- ** Unzip
32− , unzipM
33− , unzip
34−
35− -- -- ** Group
36− -- , grouped
37−
38− -- -- ** Nest
39− -- , concatFold
40−
41− -- -- * Comonad
42− -- , duplicate
43−
44− -- * Input Transformation
45− -- | These are contravariant operations i.e. they apply on the input of the
46− -- 'Sink', for this reason they are prefixed with 'l' for 'left'.
47− , lmap
48− , lmapM
49− , lfilter
50− , lfilterM
51−
52− -- * Sinks
53− , drain
54− , drainM
55− -- , drainN
56− -- , drainWhile
57− )
58−where
59−
60−import Control.Monad ((>=>), when, void)
61−import Data.Map.Strict (Map)
62−import Prelude
63− hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
64− foldl, map, mapM, sequence, all, any, sum, product, elem,
65− notElem, maximum, minimum, head, last, tail, length, null,
66− reverse, iterate, init, and, or, lookup, foldr1, (!!),
67− scanl, scanl1, replicate, concatMap, mconcat, foldMap, unzip)
68−
69−import Streamly.Internal.Data.Fold.Type (Fold(..), Step(..))
70−import Streamly.Internal.Data.Sink.Type (Sink(..))
71−
72−import qualified Data.Map.Strict as Map
73−
74−------------------------------------------------------------------------------
75−-- Conversion
76−------------------------------------------------------------------------------
77−
78−-- | Convert a 'Sink' to a 'Fold'. When you want to compose sinks and folds
79−-- together, upgrade a sink to a fold before composing.
80−toFold :: Monad m => Sink m a -> Fold m a ()
81−toFold (Sink f) = Fold step begin done
82− where
83− begin = return $ Partial ()
84− step _ a = Partial <$> f a
85− done _ = return ()
86−
87−------------------------------------------------------------------------------
88−-- Composing with sinks
89−------------------------------------------------------------------------------
90−
91−-- | Distribute one copy each of the input to both the sinks.
92−--
93−-- @
94−-- |-------Sink m a
95−-- ---stream m a---|
96−-- |-------Sink m a
97−-- @
98−-- @
99−-- > let pr x = Sink.drainM (putStrLn . ((x ++ " ") ++) . show)
100−-- > sink (Sink.tee (pr \"L") (pr \"R")) (S.enumerateFromTo 1 2)
101−-- L 1
102−-- R 1
103−-- L 2
104−-- R 2
105−-- @
106−--
107−tee :: Monad m => Sink m a -> Sink m a -> Sink m a
108−tee (Sink fL) (Sink fR) = Sink (\a -> fL a >> fR a)
109−
110−-- | Distribute copies of the input to all the sinks in a container.
111−--
112−-- @
113−-- |-------Sink m a
114−-- ---stream m a---|
115−-- |-------Sink m a
116−-- |
117−-- ...
118−-- @
119−-- @
120−-- > let pr x = Sink.drainM (putStrLn . ((x ++ " ") ++) . show)
121−-- > sink (Sink.distribute [(pr \"L"), (pr \"R")]) (S.enumerateFromTo 1 2)
122−-- L 1
123−-- R 1
124−-- L 2
125−-- R 2
126−-- @
127−--
128−-- This is the consumer side dual of the producer side 'sequence_' operation.
129−{-# INLINE distribute #-}
130−distribute :: Monad m => [Sink m a] -> Sink m a
131−distribute ss = Sink (\a -> Prelude.mapM_ (\(Sink f) -> f a) ss)
132−
133−-- | Demultiplex to multiple consumers without collecting the results. Useful
134−-- to run different effectful computations depending on the value of the stream
135−-- elements, for example handling network packets of different types using
136−-- different handlers.
137−--
138−-- @
139−--
140−-- |-------Sink m a
141−-- -----stream m a-----Map-----|
142−-- |-------Sink m a
143−-- |
144−-- ...
145−-- @
146−--
147−-- @
148−-- > let pr x = Sink.drainM (putStrLn . ((x ++ " ") ++) . show)
149−-- > let table = Data.Map.fromList [(1, pr \"One"), (2, pr \"Two")]
150−-- in Sink.sink (Sink.demux id table) (S.enumerateFromTo 1 100)
151−-- One 1
152−-- Two 2
153−-- @
154−{-
155−demux :: (Monad m, Ord k) => (a -> k) -> Map k (Sink m a) -> Sink m a
156−demux f kv = Sink step
157−
158− where
159−
160− step a =
161− -- XXX should we raise an exception in Nothing case?
162− -- Ideally we should enforce that it is a total map over k so that look
163− -- up never fails
164− case Map.lookup (f a) kv of
165− Nothing -> return ()
166− Just (Sink g) -> g a
167−-}
168−
169−demux :: (Monad m, Ord k) => Map k (Sink m a) -> Sink m (a, k)
170−demux kv = Sink step
171−
172− where
173−
174− step (a, k) =
175− -- XXX should we raise an exception in Nothing case?
176− -- Ideally we should enforce that it is a total map over k so that look
177− -- up never fails
178− case Map.lookup k kv of
179− Nothing -> return ()
180− Just (Sink g) -> g a
181−
182−-- | Split elements in the input stream into two parts using a monadic unzip
183−-- function, direct each part to a different sink.
184−--
185−-- @
186−--
187−-- |-------Sink m b
188−-- -----Stream m a----(b,c)--|
189−-- |-------Sink m c
190−-- @
191−-- @
192−-- > let pr x = Sink.drainM (putStrLn . ((x ++ " ") ++) . show)
193−-- in Sink.sink (Sink.unzip return (pr \"L") (pr \"R")) (S.fromPure (1,2))
194−-- L 1
195−-- R 2
196−-- @
197−{-# INLINE unzipM #-}
198−unzipM :: Monad m => (a -> m (b,c)) -> Sink m b -> Sink m c -> Sink m a
199−unzipM f (Sink stepB) (Sink stepC) =
200− Sink (f >=> (\(b, c) -> stepB b >> stepC c))
201−
202−-- | Same as 'unzipM' but with a pure unzip function.
203−{-# INLINE unzip #-}
204−unzip :: Monad m => (a -> (b,c)) -> Sink m b -> Sink m c -> Sink m a
205−unzip f = unzipM (return . f)
206−
207−------------------------------------------------------------------------------
208−-- Input transformation
209−------------------------------------------------------------------------------
210−
211−-- | Map a pure function on the input of a 'Sink'.
212−{-# INLINABLE lmap #-}
213−lmap :: (a -> b) -> Sink m b -> Sink m a
214−lmap f (Sink step) = Sink (step . f)
215−
216−-- | Map a monadic function on the input of a 'Sink'.
217−{-# INLINABLE lmapM #-}
218−lmapM :: Monad m => (a -> m b) -> Sink m b -> Sink m a
219−lmapM f (Sink step) = Sink (f >=> step)
220−
221−-- | Filter the input of a 'Sink' using a pure predicate function.
222−{-# INLINABLE lfilter #-}
223−lfilter :: Monad m => (a -> Bool) -> Sink m a -> Sink m a
224−lfilter f (Sink step) = Sink (\a -> when (f a) $ step a)
225−
226−-- | Filter the input of a 'Sink' using a monadic predicate function.
227−{-# INLINABLE lfilterM #-}
228−lfilterM :: Monad m => (a -> m Bool) -> Sink m a -> Sink m a
229−lfilterM f (Sink step) = Sink (\a -> f a >>= \use -> when use $ step a)
230−
231−------------------------------------------------------------------------------
232−-- Sinks
233−------------------------------------------------------------------------------
234−
235−-- | Drain all input, running the effects and discarding the results.
236−drain :: Monad m => Sink m a
237−drain = Sink (\_ -> return ())
238−
239−-- |
240−-- > drainM f = lmapM f drain
241−--
242−-- Drain all input after passing it through a monadic function.
243−{-# INLINABLE drainM #-}
244−drainM :: Monad m => (a -> m b) -> Sink m a
245−drainM f = Sink (void . f)
core/src/Streamly/Internal/Data/Sink/Type.hsdeleted−24
@@ -1,24 +0,0 @@
1−-- |
2−-- Module : Streamly.Internal.Data.Sink.Type
3−-- Copyright : (c) 2019 Composewell Technologies
4−-- License : BSD3
5−-- Maintainer : streamly@composewell.com
6−-- Stability : experimental
7−-- Portability : GHC
8−
9−module Streamly.Internal.Data.Sink.Type
10− (
11− Sink (..)
12− )
13−where
14−
15−------------------------------------------------------------------------------
16−-- Sink
17−------------------------------------------------------------------------------
18−
19−-- | A 'Sink' is a special type of 'Fold' that does not accumulate any value,
20−-- but runs only effects. A 'Sink' has no state to maintain therefore can be a
21−-- bit more efficient than a 'Fold' with '()' as the state, especially when
22−-- 'Sink's are composed with other operations. A Sink can be upgraded to a
23−-- 'Fold', but a 'Fold' cannot be converted into a Sink.
24−newtype Sink m a = Sink (a -> m ())
core/streamly-core.cabal−2
@@ -251,7 +251,6 @@ library
251251 , Streamly.Internal.Data.Producer.Type
252252 , Streamly.Internal.Data.Producer
253253 , Streamly.Internal.Data.Producer.Source
254− , Streamly.Internal.Data.Sink.Type
255254 , Streamly.Internal.Data.Parser.ParserK.Type
256255 , Streamly.Internal.Data.Parser.ParserD.Type
257256 , Streamly.Internal.Data.Pipe.Type
@@ -286,7 +285,6 @@ library
286285 , Streamly.Internal.Data.Unfold.Enumeration
287286 , Streamly.Internal.Data.Fold.Tee
288287 , Streamly.Internal.Data.Fold
289− , Streamly.Internal.Data.Sink
290288 , Streamly.Internal.Data.Parser
291289 , Streamly.Internal.Data.Pipe
292290 , Streamly.Internal.Data.Stream.Serial
streamly.cabal+2−5
@@ -165,7 +165,6 @@ extra-source-files:
165165 core/src/Streamly/Internal/Data/Producer/Type.hs
166166 core/src/Streamly/Internal/Data/Producer.hs
167167 core/src/Streamly/Internal/Data/Producer/Source.hs
168− core/src/Streamly/Internal/Data/Sink/Type.hs
169168 core/src/Streamly/Internal/Data/Parser/ParserK/Type.hs
170169 core/src/Streamly/Internal/Data/Parser/ParserD/Type.hs
171170 core/src/Streamly/Internal/Data/Pipe/Type.hs
@@ -189,7 +188,7 @@ extra-source-files:
189188 core/src/Streamly/Internal/Data/Unfold/Enumeration.hs
190189 core/src/Streamly/Internal/Data/Fold/Tee.hs
191190 core/src/Streamly/Internal/Data/Fold.hs
192− core/src/Streamly/Internal/Data/Sink.hs
191+
193192 core/src/Streamly/Internal/Data/Parser.hs
194193 core/src/Streamly/Internal/Data/Pipe.hs
195194 core/src/Streamly/Internal/Data/Stream/Serial.hs
@@ -546,7 +545,7 @@ library
546545 , Streamly.Internal.Data.Producer.Type
547546 , Streamly.Internal.Data.Producer
548547 , Streamly.Internal.Data.Producer.Source
549− , Streamly.Internal.Data.Sink.Type
548+
550549 , Streamly.Internal.Data.Parser.ParserK.Type
551550 , Streamly.Internal.Data.Parser.ParserD.Type
552551 , Streamly.Internal.Data.Pipe.Type
@@ -572,7 +571,6 @@ library
572571 , Streamly.Internal.Data.Stream.StreamD
573572 , Streamly.Internal.Data.Stream.StreamDK
574573 , Streamly.Internal.Data.Stream.Common
575−
576574 , Streamly.Internal.Data.Parser.ParserD.Tee
577575 , Streamly.Internal.Data.Parser.ParserD
578576
@@ -581,7 +579,6 @@ library
581579 , Streamly.Internal.Data.Unfold.Enumeration
582580 , Streamly.Internal.Data.Fold.Tee
583581 , Streamly.Internal.Data.Fold
584− , Streamly.Internal.Data.Sink
585582 , Streamly.Internal.Data.Parser
586583 , Streamly.Internal.Data.Pipe
587584 , Streamly.Internal.Data.Stream.Serial