on master help sign in
Rename the resumable Unfold type to Producer
2a7e3ccHarendra Kumar
benchmark/Streamly/Benchmark/Data/Parser.hs+6−6
@@ -39,8 +39,8 @@ import qualified Streamly.Internal.Data.Array.Foreign as Array
39import qualified Streamly.Internal.Data.Fold as FL
39import qualified Streamly.Internal.Data.Fold as FL
40import qualified Streamly.Internal.Data.Parser as PR
40import qualified Streamly.Internal.Data.Parser as PR
41import qualified Streamly.Internal.Data.Stream.IsStream as IP
41import qualified Streamly.Internal.Data.Stream.IsStream as IP
42−import qualified Streamly.Internal.Data.Unfold.Resume as UnfoldR
42+import qualified Streamly.Internal.Data.Producer as Producer
43−import qualified Streamly.Internal.Data.Unfold.Source as Source
43+import qualified Streamly.Internal.Data.Producer.Source as Source
44
44
45import Gauge hiding (env)
45import Gauge hiding (env)
46import Streamly.Prelude (SerialT)
46import Streamly.Prelude (SerialT)
@@ -245,13 +245,13 @@ parseManyChunksOfSum n inh =
245{-# INLINE parseManyUnfoldArrays #-}
245{-# INLINE parseManyUnfoldArrays #-}
246parseManyUnfoldArrays :: Int -> [Array.Array Int] -> IO ()
246parseManyUnfoldArrays :: Int -> [Array.Array Int] -> IO ()
247parseManyUnfoldArrays count arrays = do
247parseManyUnfoldArrays count arrays = do
248− let src = Source.source (Just (UnfoldR.OuterLoop arrays))
248+ let src = Source.source (Just (Producer.OuterLoop arrays))
249 let parser = PR.fromFold (FL.takeLE count FL.drain)
249 let parser = PR.fromFold (FL.takeLE count FL.drain)
250 let readSrc =
250 let readSrc =
251− Source.read
251+ Source.producer
252− $ UnfoldR.concat UnfoldR.fromList Array.readResumable
252+ $ Producer.concat Producer.fromList Array.producer
253 let streamParser =
253 let streamParser =
254− UnfoldR.simplify (UnfoldR.parseMany parser readSrc)
254+ Producer.simplify (Producer.parseMany parser readSrc)
255 S.drain $ S.unfold streamParser src
255 S.drain $ S.unfold streamParser src
256
256
257-------------------------------------------------------------------------------
257-------------------------------------------------------------------------------
benchmark/Streamly/Benchmark/Data/Parser/ParserD.hs+6−6
@@ -29,9 +29,9 @@ import qualified Streamly.Prelude as S
29import qualified Streamly.Internal.Data.Array.Foreign as Array
29import qualified Streamly.Internal.Data.Array.Foreign as Array
30import qualified Streamly.Internal.Data.Fold as FL
30import qualified Streamly.Internal.Data.Fold as FL
31import qualified Streamly.Internal.Data.Parser.ParserD as PR
31import qualified Streamly.Internal.Data.Parser.ParserD as PR
32+import qualified Streamly.Internal.Data.Producer as Producer
33+import qualified Streamly.Internal.Data.Producer.Source as Source
32import qualified Streamly.Internal.Data.Stream.IsStream as IP
34import qualified Streamly.Internal.Data.Stream.IsStream as IP
33−import qualified Streamly.Internal.Data.Unfold.Resume as UnfoldR
34−import qualified Streamly.Internal.Data.Unfold.Source as Source
35
35
36import Gauge
36import Gauge
37import Streamly.Prelude (SerialT, MonadAsync, IsStream)
37import Streamly.Prelude (SerialT, MonadAsync, IsStream)
@@ -219,13 +219,13 @@ parseManyGroupsRolling b =
219{-# INLINE parseManyUnfoldArrays #-}
219{-# INLINE parseManyUnfoldArrays #-}
220parseManyUnfoldArrays :: Int -> [Array.Array Int] -> IO ()
220parseManyUnfoldArrays :: Int -> [Array.Array Int] -> IO ()
221parseManyUnfoldArrays count arrays = do
221parseManyUnfoldArrays count arrays = do
222− let src = Source.source (Just (UnfoldR.OuterLoop arrays))
222+ let src = Source.source (Just (Producer.OuterLoop arrays))
223 let parser = PR.fromFold (FL.takeLE count FL.drain)
223 let parser = PR.fromFold (FL.takeLE count FL.drain)
224 let readSrc =
224 let readSrc =
225− Source.read
225+ Source.producer
226− $ UnfoldR.concat UnfoldR.fromList Array.readResumable
226+ $ Producer.concat Producer.fromList Array.producer
227 let streamParser =
227 let streamParser =
228− UnfoldR.simplify (UnfoldR.parseManyD parser readSrc)
228+ Producer.simplify (Producer.parseManyD parser readSrc)
229 S.drain $ S.unfold streamParser src
229 S.drain $ S.unfold streamParser src
230
230
231-------------------------------------------------------------------------------
231-------------------------------------------------------------------------------
src/Streamly/Internal/Data/Array/Foreign.hs+6−6
@@ -68,7 +68,7 @@ module Streamly.Internal.Data.Array.Foreign
68 , A.toStream
68 , A.toStream
69 , A.toStreamRev
69 , A.toStreamRev
70 , read
70 , read
71− , readResumable
71+ , producer
72 , unsafeRead
72 , unsafeRead
73 , A.readRev
73 , A.readRev
74 -- , readChunksOf
74 -- , readChunksOf
@@ -160,6 +160,7 @@ import GHC.IO (IO(..))
160
160
161import Streamly.Internal.Data.Array.Foreign.Types (Array(..), length)
161import Streamly.Internal.Data.Array.Foreign.Types (Array(..), length)
162import Streamly.Internal.Data.Fold.Types (Fold(..))
162import Streamly.Internal.Data.Fold.Types (Fold(..))
163+import Streamly.Internal.Data.Producer.Type (Producer)
163import Streamly.Internal.Data.Stream.Serial (SerialT)
164import Streamly.Internal.Data.Stream.Serial (SerialT)
164import Streamly.Internal.Data.Tuple.Strict (Tuple3'(..))
165import Streamly.Internal.Data.Tuple.Strict (Tuple3'(..))
165import Streamly.Internal.Data.Unfold.Types (Unfold(..))
166import Streamly.Internal.Data.Unfold.Types (Unfold(..))
@@ -171,7 +172,7 @@ import qualified Streamly.Internal.Data.Stream.Prelude as P
171import qualified Streamly.Internal.Data.Stream.Serial as Serial
172import qualified Streamly.Internal.Data.Stream.Serial as Serial
172import qualified Streamly.Internal.Data.Stream.StreamD as D
173import qualified Streamly.Internal.Data.Stream.StreamD as D
173import qualified Streamly.Internal.Data.Unfold as Unfold
174import qualified Streamly.Internal.Data.Unfold as Unfold
174−import qualified Streamly.Internal.Data.Unfold.Resume.Type as UnfoldR
175+import qualified Streamly.Internal.Data.Producer.Type as Producer
175import qualified Streamly.Internal.Ring.Foreign as RB
176import qualified Streamly.Internal.Ring.Foreign as RB
176
177
177-------------------------------------------------------------------------------
178-------------------------------------------------------------------------------
@@ -214,10 +215,9 @@ fromStream = P.foldOnce A.write
214read :: forall m a. (Monad m, Storable a) => Unfold m (Array a) a
215read :: forall m a. (Monad m, Storable a) => Unfold m (Array a) a
215read = Unfold.lmap A.unsafeThaw MA.read
216read = Unfold.lmap A.unsafeThaw MA.read
216
217
217−{-# INLINE_NORMAL readResumable #-}
218+{-# INLINE_NORMAL producer #-}
218−readResumable :: forall m a. (Monad m, Storable a) =>
219+producer :: forall m a. (Monad m, Storable a) => Producer m (Array a) a
219− UnfoldR.Unfold m (Array a) a
220−readResumable = UnfoldR.lmap A.unsafeThaw A.unsafeFreeze MA.readResumable
220+producer = Producer.translate A.unsafeThaw A.unsafeFreeze MA.producer
221
221
222-- | Unfold an array into a stream, does not check the end of the array, the
222-- | Unfold an array into a stream, does not check the end of the array, the
223-- user is responsible for terminating the stream within the array bounds. For
223-- user is responsible for terminating the stream within the array bounds. For
src/Streamly/Internal/Data/Array/Foreign/Mut/Types.hs+8−8
@@ -78,7 +78,7 @@ module Streamly.Internal.Data.Array.Foreign.Mut.Types
78 , ReadUState
78 , ReadUState
79 , read
79 , read
80 , readRev
80 , readRev
81− , readResumable
81+ , producer
82 , flattenArrays
82 , flattenArrays
83 , flattenArraysRev
83 , flattenArraysRev
84
84
@@ -136,8 +136,9 @@ import GHC.ForeignPtr (ForeignPtr(..))
136import GHC.IO (IO(IO), unsafePerformIO)
136import GHC.IO (IO(IO), unsafePerformIO)
137import GHC.Ptr (Ptr(..))
137import GHC.Ptr (Ptr(..))
138import Streamly.Internal.Data.Fold.Types (Fold(..))
138import Streamly.Internal.Data.Fold.Types (Fold(..))
139−import Streamly.Internal.Data.Unfold.Types (Unfold(..))
139+import Streamly.Internal.Data.Producer.Type (Producer (..))
140import Streamly.Internal.Data.SVar (adaptState)
140import Streamly.Internal.Data.SVar (adaptState)
141+import Streamly.Internal.Data.Unfold.Types (Unfold(..))
141import Text.Read (readPrec, readListPrec, readListPrecDefault)
142import Text.Read (readPrec, readListPrec, readListPrecDefault)
142
143
143#ifdef DEVBUILD
144#ifdef DEVBUILD
@@ -145,9 +146,9 @@ import qualified Data.Foldable as F
145#endif
146#endif
146import qualified GHC.Exts as Exts
147import qualified GHC.Exts as Exts
147import qualified Streamly.Internal.Data.Fold.Types as FL
148import qualified Streamly.Internal.Data.Fold.Types as FL
149+import qualified Streamly.Internal.Data.Producer as Producer
148import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
150import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
149import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
151import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
150−import qualified Streamly.Internal.Data.Unfold.Resume as UnfoldR
151import qualified Streamly.Internal.Foreign.Malloc as Malloc
152import qualified Streamly.Internal.Foreign.Malloc as Malloc
152
153
153import Prelude hiding (length, foldr, read, unlines, splitAt)
154import Prelude hiding (length, foldr, read, unlines, splitAt)
@@ -502,10 +503,9 @@ data ReadUState a = ReadUState
502
503
503-- | Resumable unfold of an array.
504-- | Resumable unfold of an array.
504--
505--
505−{-# INLINE_NORMAL readResumable #-}
506+{-# INLINE_NORMAL producer #-}
506−readResumable :: forall m a. (Monad m, Storable a) =>
507+producer :: forall m a. (Monad m, Storable a) => Producer m (Array a) a
507− UnfoldR.Unfold m (Array a) a
508−readResumable = UnfoldR.Unfold step inject extract
508+producer = Producer step inject extract
509 where
509 where
510
510
511 inject (Array (ForeignPtr start contents) (Ptr end) _) =
511 inject (Array (ForeignPtr start contents) (Ptr end) _) =
@@ -534,7 +534,7 @@ readResumable = UnfoldR.Unfold step inject extract
534-- @since 0.7.0
534-- @since 0.7.0
535{-# INLINE_NORMAL read #-}
535{-# INLINE_NORMAL read #-}
536read :: forall m a. (Monad m, Storable a) => Unfold m (Array a) a
536read :: forall m a. (Monad m, Storable a) => Unfold m (Array a) a
537−read = UnfoldR.simplify readResumable
537+read = Producer.simplify producer
538
538
539-- | Unfold an array into a stream in reverse order.
539-- | Unfold an array into a stream in reverse order.
540--
540--
src/Streamly/Internal/Data/Unfold/Resume.hs → src/Streamly/Internal/Data/Producer.hsrenamed+40−36
@@ -1,31 +1,29 @@
1-- |
1-- |
2−-- Module : Streamly.Internal.Data.Unfold.Resume
2+-- Module : Streamly.Internal.Data.Producer
3-- Copyright : (c) 2021 Composewell Technologies
3-- Copyright : (c) 2021 Composewell Technologies
4-- License : BSD-3-Clause
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
5-- Maintainer : streamly@composewell.com
6-- Stability : experimental
6-- Stability : experimental
7-- Portability : GHC
7-- Portability : GHC
8--
8--
9−-- Unfolds in "Streamly.Internal.Data.Unfold" module run to completion, they
9+-- A 'Producer' is an 'Unfold' with an 'extract' function added to to extract
10−-- cannot be stopped and then resumed. In contrast, the unfolds in this module
10+-- the state. It is more powerful but less general than an Unfold.
11−-- allow extraction of the intermediate state which can be used to resume the
12−-- unfold later on.
13--
11--
14−-- For simple cases the seed itself can be used to represent the intermediate
12+-- A 'Producer' represents steps of a loop generating a sequence of elements.
15−-- state as well. For example, if we are iterating through a list or an array
13+-- While unfolds are closed representation of imperative loops with some opaque
16−-- we can return the remaining list or the remaining array slice as the
14+-- internal state, producers are open loops with the state being accesible to
17−-- state and resume from it later.
15+-- the user.
18--
16--
19−-- In general, the intermediate state could be different than the seed. Also,
17+-- Unlike an unfold, which runs a loop till completion, a producer can be
20−-- when unfolds are nested, for example using 'concat', then each nesting layer
18+-- stopped in the middle, its state can be extracted, examined, changed, and
21−-- would have its own state.
19+-- then it can be resumed later from the stopped state.
22−--
23−-- In imperative terms, an unfold is like a for loop (or an iterator), the
24−-- state of the unfold is the state of the loop. The state of the 'concat' of
25−-- unfolds is like the state of each loop in the nesting of loops.
26--
20--
21+-- A producer can be used in places where a CPS stream would otherwise be
22+-- needed, because the state of the loop can be passed around. However, it can
23+-- be much more efficient than CPS because it allows stream fusion and
24+-- unecessary function calls can be avoided.
27
25
28−module Streamly.Internal.Data.Unfold.Resume
26+module Streamly.Internal.Data.Producer
29 ( Unfold (..)
27 ( Unfold (..)
30
28
31 -- * Converting
29 -- * Converting
@@ -54,43 +52,43 @@ import Control.Monad.Catch (MonadThrow, throwM)
54import GHC.Exts (SpecConstrAnnotation(..))
52import GHC.Exts (SpecConstrAnnotation(..))
55import GHC.Types (SPEC(..))
53import GHC.Types (SPEC(..))
56import Streamly.Internal.Data.Parser.ParserD (ParseError(..), Step(..))
54import Streamly.Internal.Data.Parser.ParserD (ParseError(..), Step(..))
55+import Streamly.Internal.Data.Producer.Source (Source)
57import Streamly.Internal.Data.Stream.StreamD.Step (Step(..))
56import Streamly.Internal.Data.Stream.StreamD.Step (Step(..))
58import Streamly.Internal.Data.Stream.StreamD.Type (Stream(..))
57import Streamly.Internal.Data.Stream.StreamD.Type (Stream(..))
59import Streamly.Internal.Data.SVar (defState)
58import Streamly.Internal.Data.SVar (defState)
60−import Streamly.Internal.Data.Unfold.Source (Source)
59+import Streamly.Internal.Data.Unfold.Types (Unfold(..))
61
60
62import qualified Streamly.Internal.Data.Parser.ParserD as ParserD
61import qualified Streamly.Internal.Data.Parser.ParserD as ParserD
63import qualified Streamly.Internal.Data.Parser.ParserK.Types as ParserK
62import qualified Streamly.Internal.Data.Parser.ParserK.Types as ParserK
64−import qualified Streamly.Internal.Data.Unfold.Types as Unfold
63+import qualified Streamly.Internal.Data.Producer.Source as Source
65−import qualified Streamly.Internal.Data.Unfold.Source as Source
66
64
67−import Streamly.Internal.Data.Unfold.Resume.Type
65+import Streamly.Internal.Data.Producer.Type
68import Prelude hiding (concat)
66import Prelude hiding (concat)
69
67
70−-- XXX We should write unfolds as resumable unfolds where possible and define
68+-- XXX We should write unfolds as producers where possible and define
71−-- the regular unfolds using "simplify".
69+-- unfolds using "simplify".
72--
70--
73-------------------------------------------------------------------------------
71-------------------------------------------------------------------------------
74−-- Converting to regular unfolds
72+-- Converting to unfolds
75-------------------------------------------------------------------------------
73-------------------------------------------------------------------------------
76
74
77−-- | Simplify a resumable unfold to a regular unfold.
75+-- | Simplify a producer to an unfold.
78--
76--
79-- /Internal/
77-- /Internal/
80{-# INLINE simplify #-}
78{-# INLINE simplify #-}
81−simplify :: Unfold m a b -> Unfold.Unfold m a b
79+simplify :: Producer m a b -> Unfold m a b
82−simplify (Unfold step inject _) = Unfold.Unfold step inject
80+simplify (Producer step inject _) = Unfold step inject
83
81
84-------------------------------------------------------------------------------
82-------------------------------------------------------------------------------
85-- Unfolds
83-- Unfolds
86-------------------------------------------------------------------------------
84-------------------------------------------------------------------------------
87
85
88−-- | Convert a StreamD stream into an Unfold.
86+-- | Convert a StreamD stream into a producer.
89--
87--
90-- /Internal/
88-- /Internal/
91{-# INLINE_NORMAL fromStreamD #-}
89{-# INLINE_NORMAL fromStreamD #-}
92−fromStreamD :: Monad m => Unfold m (Stream m a) a
90+fromStreamD :: Monad m => Producer m (Stream m a) a
93−fromStreamD = Unfold step return return
91+fromStreamD = Producer step return return
94
92
95 where
93 where
96
94
@@ -106,6 +104,8 @@ fromStreamD = Unfold step return return
106-- Parsing
104-- Parsing
107-------------------------------------------------------------------------------
105-------------------------------------------------------------------------------
108
106
107+-- XXX This should probably be moved to the Source module?
108+--
109-- GHC parser does not accept {-# ANN type [] NoSpecConstr #-}, so we need
109-- GHC parser does not accept {-# ANN type [] NoSpecConstr #-}, so we need
110-- to make a newtype.
110-- to make a newtype.
111{-# ANN type List NoSpecConstr #-}
111{-# ANN type List NoSpecConstr #-}
@@ -115,12 +115,12 @@ newtype List a = List {getList :: [a]}
115parseD
115parseD
116 :: MonadThrow m
116 :: MonadThrow m
117 => ParserD.Parser m a b
117 => ParserD.Parser m a b
118− -> Unfold m (Source s a) a
118+ -> Producer m (Source s a) a
119 -> Source s a
119 -> Source s a
120 -> m (b, Source s a)
120 -> m (b, Source s a)
121parseD
121parseD
122 (ParserD.Parser pstep initial extract)
122 (ParserD.Parser pstep initial extract)
123− (Unfold ustep uinject uextract)
123+ (Producer ustep uinject uextract)
124 seed = do
124 seed = do
125
125
126 state <- uinject seed
126 state <- uinject seed
@@ -197,7 +197,7 @@ parseD
197parse
197parse
198 :: MonadThrow m
198 :: MonadThrow m
199 => ParserK.Parser m a b
199 => ParserK.Parser m a b
200− -> Unfold m (Source s a) a
200+ -> Producer m (Source s a) a
201 -> Source s a
201 -> Source s a
202 -> m (b, Source s a)
202 -> m (b, Source s a)
203parse = parseD . ParserK.fromParserK
203parse = parseD . ParserK.fromParserK
@@ -208,8 +208,10 @@ parse = parseD . ParserK.fromParserK
208
208
209{-# INLINE parseManyD #-}
209{-# INLINE parseManyD #-}
210parseManyD :: MonadThrow m =>
210parseManyD :: MonadThrow m =>
211− ParserD.Parser m a b -> Unfold m (Source x a) a -> Unfold m (Source x a) b
211+ ParserD.Parser m a b
212+ -> Producer m (Source x a) a
213+ -> Producer m (Source x a) b
212−parseManyD parser reader = Unfold step return return
214+parseManyD parser reader = Producer step return return
213
215
214 where
216 where
215
217
@@ -227,5 +229,7 @@ parseManyD parser reader = Unfold step return return
227-- /Internal/
229-- /Internal/
228{-# INLINE parseMany #-}
230{-# INLINE parseMany #-}
229parseMany :: MonadThrow m =>
231parseMany :: MonadThrow m =>
230− ParserK.Parser m a b -> Unfold m (Source x a) a -> Unfold m (Source x a) b
232+ ParserK.Parser m a b
233+ -> Producer m (Source x a) a
234+ -> Producer m (Source x a) b
231parseMany parser = parseManyD (ParserK.fromParserK parser)
235parseMany parser = parseManyD (ParserK.fromParserK parser)
src/Streamly/Internal/Data/Unfold/Source.hs → src/Streamly/Internal/Data/Producer/Source.hsrenamed+11−8
@@ -1,5 +1,5 @@
1-- |
1-- |
2−-- Module : Streamly.Internal.Data.Unfold.Source
2+-- Module : Streamly.Internal.Data.Producer.Source
3-- Copyright : (c) 2021 Composewell Technologies
3-- Copyright : (c) 2021 Composewell Technologies
4-- License : BSD-3-Clause
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
5-- Maintainer : streamly@composewell.com
@@ -11,7 +11,7 @@
11-- useful in parsing applications with backtracking.
11-- useful in parsing applications with backtracking.
12--
12--
13
13
14−module Streamly.Internal.Data.Unfold.Source
14+module Streamly.Internal.Data.Producer.Source
15 ( Source
15 ( Source
16
16
17 -- * Creation
17 -- * Creation
@@ -22,16 +22,19 @@ module Streamly.Internal.Data.Unfold.Source
22
22
23 -- * Consumption
23 -- * Consumption
24 , isEmpty
24 , isEmpty
25− , read
25+ , producer
26 )
26 )
27where
27where
28
28
29#include "inline.hs"
29#include "inline.hs"
30
30
31import Streamly.Internal.Data.Stream.StreamD.Step (Step(..))
31import Streamly.Internal.Data.Stream.StreamD.Step (Step(..))
32−import Streamly.Internal.Data.Unfold.Resume.Type (Unfold(..))
32+import Streamly.Internal.Data.Producer.Type (Producer(..))
33import Prelude hiding (read)
33import Prelude hiding (read)
34
34
35+-- XXX instead of a seed should we wrap a Producer in a source? Then we won't
36+-- have to supply a Producer for read.
37+--
35-- | An unfold seed with some buffered data. It allows us to 'unread' or return
38-- | An unfold seed with some buffered data. It allows us to 'unread' or return
36-- some data after reading it. Useful in backtracked parsing.
39-- some data after reading it. Useful in backtracked parsing.
37--
40--
@@ -44,13 +47,13 @@ data Source a b = Source [b] (Maybe a)
44source :: Maybe a -> Source a b
47source :: Maybe a -> Source a b
45source = Source []
48source = Source []
46
49
47−
48-- | Return some unused data back to the source. The data is prepended (or
50-- | Return some unused data back to the source. The data is prepended (or
49-- consed) to the source.
51-- consed) to the source.
50--
52--
51-- /Internal/
53-- /Internal/
52unread :: [b] -> Source a b -> Source a b
54unread :: [b] -> Source a b -> Source a b
53unread xs (Source ys seed) = Source (xs ++ ys) seed
55unread xs (Source ys seed) = Source (xs ++ ys) seed
56+
54isEmpty :: Source a b -> Bool
57isEmpty :: Source a b -> Bool
55isEmpty (Source [] Nothing) = True
58isEmpty (Source [] Nothing) = True
56isEmpty _ = False
59isEmpty _ = False
@@ -59,9 +62,9 @@ isEmpty _ = False
59-- first and then the seed is unfolded using the supplied unfold.
62-- first and then the seed is unfolded using the supplied unfold.
60--
63--
61-- /Internal/
64-- /Internal/
62−{-# INLINE_NORMAL read #-}
65+{-# INLINE_NORMAL producer #-}
63−read :: Monad m => Unfold m a b -> Unfold m (Source a b) b
66+producer :: Monad m => Producer m a b -> Producer m (Source a b) b
64−read (Unfold step1 inject1 extract1) = Unfold step inject extract
67+producer (Producer step1 inject1 extract1) = Producer step inject extract
65
68
66 where
69 where
67
70
src/Streamly/Internal/Data/Unfold/Resume/Type.hs → src/Streamly/Internal/Data/Producer/Type.hsrenamed+33−37
@@ -1,27 +1,27 @@
1-- |
1-- |
2−-- Module : Streamly.Internal.Data.Unfold.Resume.Type
2+-- Module : Streamly.Internal.Data.Producer.Type
3-- Copyright : (c) 2021 Composewell Technologies
3-- Copyright : (c) 2021 Composewell Technologies
4-- License : BSD-3-Clause
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
5-- Maintainer : streamly@composewell.com
6-- Stability : experimental
6-- Stability : experimental
7-- Portability : GHC
7-- Portability : GHC
8--
8--
9−-- Resumable unfolds. See "Streamly.Internal.Data.Unfold.Resume" for
9+-- See "Streamly.Internal.Data.Producer" for introduction.
10−-- introduction.
11--
10--
12
11
13−module Streamly.Internal.Data.Unfold.Resume.Type
12+module Streamly.Internal.Data.Producer.Type
14 (
13 (
15 -- * Type
14 -- * Type
16− Unfold (..)
15+ Producer (..)
17
16
18− -- * Unfolds
17+ -- * Producers
19 , nil
18 , nil
20 , nilM
19 , nilM
21 , unfoldrM
20 , unfoldrM
22 , fromList
21 , fromList
23
22
24 -- * Mapping
23 -- * Mapping
24+ , translate
25 , lmap
25 , lmap
26
26
27 -- * Nesting
27 -- * Nesting
@@ -40,33 +40,22 @@ import Prelude hiding (concat)
40-- Type
40-- Type
41------------------------------------------------------------------------------
41------------------------------------------------------------------------------
42
42
43−{-
44−-- Representing open loops.
45−-- Stepper/Iterator/Generator/Producer
46−-- | A function that can be called repeatedly to generate a sequence of values.
47−data Producer m a b = Producer (a -> m (Step a b))
48−
49−-- A similar concept for folds would be an accumulator/reducer/Consumer
50−-- | A function that can be called repeatedly to consume a sequence of values.
51−data Consumer m a b = Consumer (s -> a -> m (Step b))
52−-}
53−
54−-- | An @Unfold m a b@ is a generator of a stream of values of type @b@ from a
43+-- | A @Producer m a b@ is a generator of a stream of values of type @b@ from a
55-- seed of type 'a' in 'Monad' @m@.
44-- seed of type 'a' in 'Monad' @m@.
56--
45--
57-- /Internal/
46-- /Internal/
58
47
59−data Unfold m a b =
48+data Producer m a b =
60− -- | @Unfold step inject extract@
49+ -- | @Producer step inject extract@
61− forall s. Unfold (s -> m (Step s b)) (a -> m s) (s -> m a)
50+ forall s. Producer (s -> m (Step s b)) (a -> m s) (s -> m a)
62
51
63------------------------------------------------------------------------------
52------------------------------------------------------------------------------
64−-- Unfolds
53+-- Producers
65------------------------------------------------------------------------------
54------------------------------------------------------------------------------
66
55
67{-# INLINE nilM #-}
56{-# INLINE nilM #-}
68−nilM :: Monad m => (a -> m c) -> Unfold m a b
57+nilM :: Monad m => (a -> m c) -> Producer m a b
69−nilM f = Unfold step return return
58+nilM f = Producer step return return
70
59
71 where
60 where
72
61
@@ -74,12 +63,12 @@ nilM f = Unfold step return return
74 step x = f x >> return Stop
63 step x = f x >> return Stop
75
64
76{-# INLINE nil #-}
65{-# INLINE nil #-}
77−nil :: Monad m => Unfold m a b
66+nil :: Monad m => Producer m a b
78nil = nilM (\_ -> return ())
67nil = nilM (\_ -> return ())
79
68
80{-# INLINE unfoldrM #-}
69{-# INLINE unfoldrM #-}
81−unfoldrM :: Monad m => (a -> m (Maybe (b, a))) -> Unfold m a b
70+unfoldrM :: Monad m => (a -> m (Maybe (b, a))) -> Producer m a b
82−unfoldrM next = Unfold step return return
71+unfoldrM next = Producer step return return
83 where
72 where
84 {-# INLINE_LATE step #-}
73 {-# INLINE_LATE step #-}
85 step st = do
74 step st = do
@@ -92,8 +81,8 @@ unfoldrM next = Unfold step return return
92--
81--
93-- /Internal/
82-- /Internal/
94{-# INLINE_LATE fromList #-}
83{-# INLINE_LATE fromList #-}
95−fromList :: Monad m => Unfold m [a] a
84+fromList :: Monad m => Producer m [a] a
96−fromList = Unfold step return return
85+fromList = Producer step return return
97
86
98 where
87 where
99
88
@@ -105,14 +94,21 @@ fromList = Unfold step return return
105-- Mapping
94-- Mapping
106------------------------------------------------------------------------------
95------------------------------------------------------------------------------
107
96
108−-- | We can only lmap between two types that can be interconverted without
97+-- | Interconvert the producer between two interconvertible input types.
109−-- loss.
98+--
99+-- /Internal/
100+{-# INLINE_NORMAL translate #-}
101+translate :: Functor m =>
102+ (a -> c) -> (c -> a) -> Producer m c b -> Producer m a b
103+translate f g (Producer step inject extract) =
104+ Producer step (inject . f) (fmap g . extract)
105+
106+-- | Map the producer input to another value of the same type.
110--
107--
111-- /Internal/
108-- /Internal/
112{-# INLINE_NORMAL lmap #-}
109{-# INLINE_NORMAL lmap #-}
113−lmap :: Functor m => (a -> c) -> (c -> a) -> Unfold m c b -> Unfold m a b
110+lmap :: (a -> a) -> Producer m a b -> Producer m a b
114−lmap f g (Unfold ustep uinject uextract) =
111+lmap f (Producer step inject extract) = Producer step (inject . f) extract
115− Unfold ustep (uinject . f) (fmap g . uextract)
116
112
117------------------------------------------------------------------------------
113------------------------------------------------------------------------------
118-- Nesting
114-- Nesting
@@ -129,9 +125,9 @@ data NestedLoop s1 s2 = OuterLoop s1 | InnerLoop s1 s2
129--
125--
130{-# INLINE_NORMAL concat #-}
126{-# INLINE_NORMAL concat #-}
131concat :: Monad m =>
127concat :: Monad m =>
132− Unfold m a b -> Unfold m b c -> Unfold m (NestedLoop a b) c
128+ Producer m a b -> Producer m b c -> Producer m (NestedLoop a b) c
133−concat (Unfold step1 inject1 extract1) (Unfold step2 inject2 extract2) =
129+concat (Producer step1 inject1 extract1) (Producer step2 inject2 extract2) =
134− Unfold step inject extract
130+ Producer step inject extract
135
131
136 where
132 where
137
133
streamly.cabal+3−3
@@ -433,9 +433,9 @@ library
433 , Streamly.Internal.Data.Stream.StreamD.Type
433 , Streamly.Internal.Data.Stream.StreamD.Type
434 , Streamly.Internal.Data.Stream.StreamDK.Type
434 , Streamly.Internal.Data.Stream.StreamDK.Type
435 , Streamly.Internal.Data.Unfold.Types
435 , Streamly.Internal.Data.Unfold.Types
436− , Streamly.Internal.Data.Unfold.Resume.Type
436+ , Streamly.Internal.Data.Producer.Type
437− , Streamly.Internal.Data.Unfold.Resume
437+ , Streamly.Internal.Data.Producer
438− , Streamly.Internal.Data.Unfold.Source
438+ , Streamly.Internal.Data.Producer.Source
439 , Streamly.Internal.Data.Sink.Types
439 , Streamly.Internal.Data.Sink.Types
440 , Streamly.Internal.Data.Parser.ParserK.Types
440 , Streamly.Internal.Data.Parser.ParserK.Types
441 , Streamly.Internal.Data.Parser.ParserD.Types
441 , Streamly.Internal.Data.Parser.ParserD.Types
test/Streamly/Test/Data/Parser/ParserD.hs+6−6
@@ -15,10 +15,10 @@ import qualified Prelude
15import qualified Streamly.Internal.Data.Array.Foreign as A
15import qualified Streamly.Internal.Data.Array.Foreign as A
16import qualified Streamly.Internal.Data.Fold as FL
16import qualified Streamly.Internal.Data.Fold as FL
17import qualified Streamly.Internal.Data.Parser.ParserD as P
17import qualified Streamly.Internal.Data.Parser.ParserD as P
18+import qualified Streamly.Internal.Data.Producer.Source as Source
19+import qualified Streamly.Internal.Data.Producer as Producer
18import qualified Streamly.Internal.Data.Stream.IsStream as S
20import qualified Streamly.Internal.Data.Stream.IsStream as S
19import qualified Streamly.Internal.Data.Unfold as Unfold
21import qualified Streamly.Internal.Data.Unfold as Unfold
20−import qualified Streamly.Internal.Data.Unfold.Source as Source
21−import qualified Streamly.Internal.Data.Unfold.Resume as UnfoldR
22import qualified Test.Hspec as H
22import qualified Test.Hspec as H
23
23
24import Prelude hiding (sequence)
24import Prelude hiding (sequence)
@@ -621,13 +621,13 @@ parseUnfold = do
621 <*> chooseInt (1, len)) $ \(ls, clen, tlen) ->
621 <*> chooseInt (1, len)) $ \(ls, clen, tlen) ->
622 monadicIO $ do
622 monadicIO $ do
623 arrays <- S.toList $ S.arraysOf clen (S.fromList ls)
623 arrays <- S.toList $ S.arraysOf clen (S.fromList ls)
624− let src = Source.source (Just (UnfoldR.OuterLoop arrays))
624+ let src = Source.source (Just (Producer.OuterLoop arrays))
625 let parser = P.fromFold (FL.takeLE tlen FL.toList)
625 let parser = P.fromFold (FL.takeLE tlen FL.toList)
626 let readSrc =
626 let readSrc =
627− Source.read
627+ Source.producer
628− $ UnfoldR.concat UnfoldR.fromList A.readResumable
628+ $ Producer.concat Producer.fromList A.producer
629 let streamParser =
629 let streamParser =
630− UnfoldR.simplify (UnfoldR.parseManyD parser readSrc)
630+ Producer.simplify (Producer.parseManyD parser readSrc)
631 xs <- run
631 xs <- run
632 $ S.toList
632 $ S.toList
633 $ S.concatUnfold Unfold.fromList
633 $ S.concatUnfold Unfold.fromList