on master help sign in
Use an explicit state to represent nested loops
commit7c95ccaaad24a43787f330f16eb6cd684c363558 authorHarendra Kumar <harendra@composewell.com> dateTue 16 Feb 2021, 23:19 (6 years ago) parentc93bad0
5 files changed+39−25
benchmark/Streamly/Benchmark/Data/Parser.hs+1−1 benchmark/Streamly/Benchmark/Data/Parser/ParserD.hs+1−1 src/Streamly/Internal/Data/Unfold/Resume.hs+1 src/Streamly/Internal/Data/Unfold/Resume/Type.hs+35−22 test/Streamly/Test/Data/Parser/ParserD.hs+1−1
benchmark/Streamly/Benchmark/Data/Parser.hs+1−1
@@ -245,7 +245,7 @@ parseManyChunksOfSum n inh =
245245{-# INLINE parseManyUnfoldArrays #-}
246246parseManyUnfoldArrays :: Int -> [Array.Array Int] -> IO ()
247247parseManyUnfoldArrays count arrays = do
248− let src = Source.source (Just (arrays, Nothing))
248+ let src = Source.source (Just (UnfoldR.OuterLoop arrays))
249249 let parser = PR.fromFold (FL.takeLE count FL.drain)
250250 let readSrc =
251251 Source.read
benchmark/Streamly/Benchmark/Data/Parser/ParserD.hs+1−1
@@ -219,7 +219,7 @@ parseManyGroupsRolling b =
219219{-# INLINE parseManyUnfoldArrays #-}
220220parseManyUnfoldArrays :: Int -> [Array.Array Int] -> IO ()
221221parseManyUnfoldArrays count arrays = do
222− let src = Source.source (Just (arrays, Nothing))
222+ let src = Source.source (Just (UnfoldR.OuterLoop arrays))
223223 let parser = PR.fromFold (FL.takeLE count FL.drain)
224224 let readSrc =
225225 Source.read
src/Streamly/Internal/Data/Unfold/Resume.hs+1
@@ -39,6 +39,7 @@ module Streamly.Internal.Data.Unfold.Resume
3939 , fromList
4040
4141 -- * Combinators
42+ , NestedLoop (..)
4243 , concat
4344 , parse
4445 , parseMany
src/Streamly/Internal/Data/Unfold/Resume/Type.hs+35−22
@@ -25,6 +25,7 @@ module Streamly.Internal.Data.Unfold.Resume.Type
2525 , lmap
2626
2727 -- * Nesting
28+ , NestedLoop (..)
2829 , concat
2930 )
3031where
@@ -39,6 +40,17 @@ import Prelude hiding (concat)
3940-- Type
4041------------------------------------------------------------------------------
4142
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+
4254-- | An @Unfold m a b@ is a generator of a stream of values of type @b@ from a
4355-- seed of type 'a' in 'Monad' @m@.
4456--
@@ -81,9 +93,10 @@ unfoldrM next = Unfold step return return
8193-- /Internal/
8294{-# INLINE_LATE fromList #-}
8395fromList :: Monad m => Unfold m [a] a
84−fromList = Unfold step inject return
85− where
86− inject = return
96+fromList = Unfold step return return
97+
98+ where
99+
87100 {-# INLINE_LATE step #-}
88101 step (x:xs) = return $ Yield x xs
89102 step [] = return Stop
@@ -105,50 +118,50 @@ lmap f g (Unfold ustep uinject uextract) =
105118-- Nesting
106119------------------------------------------------------------------------------
107120
108−{-# ANN type ConcatState Fuse #-}
109−data ConcatState s1 s2 = ConcatOuter s1 | ConcatInner s1 s2
121+-- | State representing a nested loop.
122+{-# ANN type NestedLoop Fuse #-}
123+data NestedLoop s1 s2 = OuterLoop s1 | InnerLoop s1 s2
110124
111−-- XXX Use Either a (a,b) for extracted state.
112−--
113125-- | Apply the second unfold to each output element of the first unfold and
114126-- flatten the output in a single stream.
115127--
116128-- /Internal/
117129--
118130{-# INLINE_NORMAL concat #-}
119−concat :: Monad m => Unfold m a b -> Unfold m b c -> Unfold m (a, Maybe b) c
131+concat :: Monad m =>
132+ Unfold m a b -> Unfold m b c -> Unfold m (NestedLoop a b) c
120133concat (Unfold step1 inject1 extract1) (Unfold step2 inject2 extract2) =
121134 Unfold step inject extract
122135
123136 where
124137
125− inject (x, Nothing) = do
138+ inject (OuterLoop x) = do
126139 s <- inject1 x
127− return $ ConcatOuter s
128− inject (x, Just y) = do
140+ return $ OuterLoop s
141+ inject (InnerLoop x y) = do
129142 s1 <- inject1 x
130143 s2 <- inject2 y
131− return $ ConcatInner s1 s2
144+ return $ InnerLoop s1 s2
132145
133146 {-# INLINE_LATE step #-}
134− step (ConcatOuter st) = do
147+ step (OuterLoop st) = do
135148 r <- step1 st
136149 case r of
137150 Yield x s -> do
138151 innerSt <- inject2 x
139− return $ Skip (ConcatInner s innerSt)
140− Skip s -> return $ Skip (ConcatOuter s)
152+ return $ Skip (InnerLoop s innerSt)
153+ Skip s -> return $ Skip (OuterLoop s)
141154 Stop -> return Stop
142155
143− step (ConcatInner ost ist) = do
156+ step (InnerLoop ost ist) = do
144157 r <- step2 ist
145158 return $ case r of
146− Yield x s -> Yield x (ConcatInner ost s)
147− Skip s -> Skip (ConcatInner ost s)
148− Stop -> Skip (ConcatOuter ost)
159+ Yield x s -> Yield x (InnerLoop ost s)
160+ Skip s -> Skip (InnerLoop ost s)
161+ Stop -> Skip (OuterLoop ost)
149162
150− extract (ConcatOuter s1) = (,Nothing) <$> extract1 s1
151− extract (ConcatInner s1 s2) = do
163+ extract (OuterLoop s1) = OuterLoop <$> extract1 s1
164+ extract (InnerLoop s1 s2) = do
152165 r1 <- extract1 s1
153166 r2 <- extract2 s2
154− return (r1, Just r2)
167+ return (InnerLoop r1 r2)
test/Streamly/Test/Data/Parser/ParserD.hs+1−1
@@ -621,7 +621,7 @@ parseUnfold = do
621621 <*> chooseInt (1, len)) $ \(ls, clen, tlen) ->
622622 monadicIO $ do
623623 arrays <- S.toList $ S.arraysOf clen (S.fromList ls)
624− let src = Source.source (Just (arrays, Nothing))
624+ let src = Source.source (Just (UnfoldR.OuterLoop arrays))
625625 let parser = P.fromFold (FL.takeLE tlen FL.toList)
626626 let readSrc =
627627 Source.read