@@ -13,7 +13,12 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
13 -- * Transformation
13 -- * Transformation
16− -- ** By folding (scans)
16+ -- ** By folding
18 , scanlMAfter'
23 , scanlMAfter'
@@ -40,6 +45,10 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
40 , postscanOnce
45 , postscanOnce
41 , scanOnce
46 , scanOnce
43 -- * Filtering
52 -- * Filtering
@@ -60,6 +69,13 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
60 , rollingMap
69 , rollingMap
61 , rollingMapM
70 , rollingMapM
63 -- * Inserting
79 -- * Inserting
64 , intersperseM
80 , intersperseM
65 , intersperseM_
81 , intersperseM_
@@ -82,6 +98,10 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
83 , zipWithM
99 , zipWithM
85 -- * Merging
105 -- * Merging
86 , mergeBy
106 , mergeBy
87 , mergeByM
107 , mergeByM
@@ -89,25 +109,58 @@ module Streamly.Internal.Data.Stream.StreamD.Transform
89 -- * Concurrent Application
109 -- * Concurrent Application
90 , mkParallel
110 , mkParallel
91 , mkParallelD
111 , mkParallelD
114+ -- | Transform a stream into another type.
95−import Control.Monad (void)
125+import Control.Concurrent (killThread, myThreadId, takeMVar, threadDelay)
126+import Control.Exception (assert, AsyncException)
127+import Control.Monad (void, when)
128+import Control.Monad.Catch (MonadCatch, MonadThrow, throwM)
96import Control.Monad.IO.Class (MonadIO(..))
129import Control.Monad.IO.Class (MonadIO(..))
130+import Control.Monad.Trans.Class (MonadTrans(lift))
131+import Control.Monad.Trans.Reader (ReaderT)
132+import Control.Monad.Trans.State.Strict (StateT)
97import Data.Functor.Identity (Identity(..))
133import Data.Functor.Identity (Identity(..))
134+import Data.IORef (newIORef, mkWeakIORef)
98import Data.Maybe (fromJust, isJust)
135import Data.Maybe (fromJust, isJust)
136+import Foreign.Storable (Storable(..))
137+import Fusion.Plugin.Types (Fuse(..))
138+import GHC.Types (SPEC(..))
139+import qualified Control.Monad.Catch as MC
140+import qualified Control.Monad.Trans.Reader as Reader
141+import qualified Control.Monad.Trans.State.Strict as State
99−import Streamly.Internal.Data.Time.Units
143+import Streamly.Internal.Data.Fold.Types (Fold(..))
100− (TimeUnit64, toRelTime64, diffAbsTime64)
144+import Streamly.Internal.Data.Parser (ParseError(..))
101import Streamly.Internal.Data.Pipe.Types (Pipe(..), PipeState(..))
145import Streamly.Internal.Data.Pipe.Types (Pipe(..), PipeState(..))
146+import Streamly.Internal.Data.Stream.SVar (fromConsumer, pushToFold)
102import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
147import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
148+import Streamly.Internal.Data.Time.Units
149+ (TimeUnit64, toRelTime64, diffAbsTime64)
104−import qualified Streamly.Internal.Data.Pipe.Types as Pipe
151+import qualified Streamly.Internal.Data.Array.Storable.Foreign.Types as A
105import qualified Streamly.Internal.Data.Fold as FL
152import qualified Streamly.Internal.Data.Fold as FL
153+import qualified Streamly.Internal.Data.IORef.Prim as Prim
154+import qualified Streamly.Internal.Data.Parser as PR
155+import qualified Streamly.Internal.Data.Parser.ParserD as PRD
156+import qualified Streamly.Internal.Data.Pipe.Types as Pipe
106import qualified Streamly.Internal.Data.Stream.StreamK as K
157import qualified Streamly.Internal.Data.Stream.StreamK as K
159+import qualified Prelude
108import Prelude hiding
160import Prelude hiding
109− ( drop, dropWhile, filter, map, mapM
161+ ( drop, dropWhile, filter, map, mapM, reverse
110 , scanl, scanl1, sequence, take, takeWhile, zipWith)
162 , scanl, scanl1, sequence, take, takeWhile, zipWith)
111import Streamly.Internal.Data.Stream.StreamD.Type
164import Streamly.Internal.Data.Stream.StreamD.Type
112import Streamly.Internal.Data.SVar
165import Streamly.Internal.Data.SVar
@@ -142,9 +195,47 @@ transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
142 Pipe.Continue pst' -> return $ Skip (pst', st)
195 Pipe.Continue pst' -> return $ Skip (pst', st)
144------------------------------------------------------------------------------
197------------------------------------------------------------------------------
145−-- Transformation by Folding (Scans)
198+-- Transformation by Folding
146------------------------------------------------------------------------------
199------------------------------------------------------------------------------
201+------------------------------------------------------------------------------
203+------------------------------------------------------------------------------
205+{-# INLINE_NORMAL foldlT #-}
206+foldlT :: (Monad m, Monad (s m), MonadTrans s)
207+ => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
208+foldlT fstep begin (Stream step state) = go SPEC begin state
211+ r <- lift $ step defState st
213+ Yield x s -> go SPEC (fstep acc x) s
214+ Skip s -> go SPEC acc s
217+-- Note, this is going to have horrible performance, because of the nature of
218+-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
219+-- likely be practically unusable.
220+{-# INLINE_NORMAL foldlS #-}
222+ => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
223+foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
225+ step' gst (Left (st, acc)) = do
226+ r <- step (adaptState gst) st
228+ Yield x s -> Skip (Left (s, fstep acc x))
229+ Skip s -> Skip (Left (s, acc))
230+ Stop -> Skip (Right acc)
232+ step' gst (Right (Stream stp stt)) = do
233+ r <- stp (adaptState gst) stt
235+ Yield x s -> Yield x (Right (Stream stp s))
236+ Skip s -> Skip (Right (Stream stp s))
148------------------------------------------------------------------------------
239------------------------------------------------------------------------------
149-- Prescans
240-- Prescans
150------------------------------------------------------------------------------
241------------------------------------------------------------------------------
@@ -456,6 +547,68 @@ rollingMapM f (Stream step1 state1) = Stream step (RollingMapInit state1)
456rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
547rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
457rollingMap f = rollingMapM (\x y -> return $ f x y)
548rollingMap f = rollingMapM (\x y -> return $ f x y)
550+------------------------------------------------------------------------------
552+------------------------------------------------------------------------------
554+-- We can implement reverse as:
556+-- > reverse = foldlS (flip cons) nil
558+-- However, this implementation is unusable because of the horrible performance
559+-- of cons. So we just convert it to a list first and then stream from the
562+-- XXX Maybe we can use an Array instead of a list here?
563+{-# INLINE_NORMAL reverse #-}
564+reverse :: Monad m => Stream m a -> Stream m a
565+reverse m = Stream step Nothing
567+ {-# INLINE_LATE step #-}
569+ xs <- foldl' (flip (:)) [] m
570+ return $ Skip (Just xs)
571+ step _ (Just (x:xs)) = return $ Yield x (Just xs)
572+ step _ (Just []) = return Stop
574+-- Much faster reverse for Storables
575+{-# INLINE_NORMAL reverse' #-}
576+reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
578+-- This commented implementation copies the whole stream into one single array
579+-- and then streams from that array, this is 3-4x faster than the chunked code
580+-- that follows. Though this could be problematic due to unbounded large
581+-- allocations. We need to figure out why the chunked code is slower and if we
582+-- can optimize the chunked code to work as fast as this one. It may be a
584+import Foreign.ForeignPtr (touchForeignPtr)
585+import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
586+import Foreign.Ptr (Ptr, plusPtr)
587+reverse' m = Stream step Nothing
589+ {-# INLINE_LATE step #-}
591+ arr <- A.fromStreamD m
592+ let p = aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
593+ return $ Skip $ Just (aStart arr, p)
595+ step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
597+ step _ (Just (start, p)) = do
598+ let !x = A.unsafeInlineIO $ do
600+ touchForeignPtr start
602+ next = p `plusPtr` negate (sizeOf (undefined :: a))
603+ return $ Yield x (Just (start, next))
610+ $ A.fromStreamDArraysOf A.defaultChunkSize m
459-------------------------------------------------------------------------------
612-------------------------------------------------------------------------------
460-- Filtering
613-- Filtering
461-------------------------------------------------------------------------------
614-------------------------------------------------------------------------------
@@ -572,6 +725,237 @@ sequence (Stream step state) = Stream step' state
572 Skip s -> return $ Skip s
725 Skip s -> return $ Skip s
573 Stop -> return Stop
726 Stop -> return Stop
728+------------------------------------------------------------------------------
729+-- Tapping/Distributing
730+------------------------------------------------------------------------------
732+data TapState fs st a
733+ = TapInit | Tapping !fs st | TapDone st
735+-- XXX Multiple yield points
737+tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
738+tap (Fold fstep initial extract) (Stream step state) = Stream step' TapInit
742+ step' _ TapInit = do
744+ return $ Skip (Tapping r state)
745+ step' gst (Tapping acc st) = do
748+ -- XXX Abstract Yield?
754+ FL.Partial fs -> Tapping fs s
755+ FL.Done _ -> TapDone s
756+ Skip s -> return $ Skip (Tapping acc s)
760+ step' gst (TapDone st) = do
764+ Yield x s -> Yield x (TapDone s)
765+ Skip s -> Skip (TapDone s)
768+data TapOffState fs s a
770+ | TapOffTapping !fs s Int
773+-- XXX Multiple yield points
774+{-# INLINE_NORMAL tapOffsetEvery #-}
775+tapOffsetEvery :: Monad m
776+ => Int -> Int -> Fold m a b -> Stream m a -> Stream m a
777+tapOffsetEvery offset n (Fold fstep initial extract) (Stream step state) =
778+ Stream step' TapOffInit
782+ {-# INLINE_LATE step' #-}
783+ step' _ TapOffInit = do
785+ return $ Skip $ TapOffTapping r state (offset `mod` n)
786+ step' gst (TapOffTapping acc st count) = do
797+ TapOffTapping sres s (n - 1)
798+ FL.Done _ -> TapOffDone s
799+ else return $ TapOffTapping acc s (count - 1)
800+ return $ Yield x next
801+ Skip s -> return $ Skip (TapOffTapping acc s count)
805+ step' gst (TapOffDone st) = do
809+ Yield x s -> Yield x (TapOffDone s)
810+ Skip s -> Skip (TapOffDone s)
813+{-# INLINE_NORMAL pollCounts #-}
817+ -> (Stream m Int -> Stream m Int)
821+pollCounts predicate transf fld (Stream step state) = Stream step' Nothing
824+ {-# INLINE_LATE step' #-}
825+ step' _ Nothing = do
826+ -- As long as we are using an "Int" for counts lockfree reads from
827+ -- Var should work correctly on both 32-bit and 64-bit machines.
828+ -- However, an Int on a 32-bit machine may overflow quickly.
829+ countVar <- liftIO $ Prim.newIORef (0 :: Int)
831+ $ void $ foldOnce fld
832+ $ transf $ fromPrimIORef countVar
833+ return $ Skip (Just (countVar, tid, state))
835+ step' gst (Just (countVar, tid, st)) = do
839+ when (predicate x) $ liftIO $ Prim.modifyIORef' countVar (+ 1)
840+ return $ Yield x (Just (countVar, tid, s))
841+ Skip s -> return $ Skip (Just (countVar, tid, s))
843+ liftIO $ killThread tid
846+{-# INLINE_NORMAL tapRate #-}
848+ (MonadAsync m, MonadCatch m)
853+tapRate samplingRate action (Stream step state) = Stream step' Nothing
855+ {-# NOINLINE loop #-}
856+ loop countVar prev = do
859+ (do liftIO $ threadDelay (round $ samplingRate * 1000000)
860+ i <- liftIO $ Prim.readIORef countVar
861+ let !diff = i - prev
864+ (\(e :: AsyncException) -> do
865+ i <- liftIO $ Prim.readIORef countVar
866+ let !diff = i - prev
868+ throwM (MC.toException e))
871+ {-# INLINE_LATE step' #-}
872+ step' _ Nothing = do
873+ countVar <- liftIO $ Prim.newIORef 0
874+ tid <- fork $ loop countVar 0
875+ ref <- liftIO $ newIORef ()
876+ _ <- liftIO $ mkWeakIORef ref (killThread tid)
877+ return $ Skip (Just (countVar, tid, state, ref))
879+ step' gst (Just (countVar, tid, st, ref)) = do
883+ liftIO $ Prim.modifyIORef' countVar (+ 1)
884+ return $ Yield x (Just (countVar, tid, s, ref))
885+ Skip s -> return $ Skip (Just (countVar, tid, s, ref))
887+ liftIO $ killThread tid
890+-------------------------------------------------------------------------------
892+-------------------------------------------------------------------------------
894+-- | Create an SVar with a fold consumer that will fold any elements sent to it
895+-- using the supplied fold function.
896+{-# INLINE newFoldSVar #-}
897+newFoldSVar :: MonadAsync m => State t m a -> Fold m a b -> m (SVar t m a)
898+newFoldSVar stt f = do
899+ -- Buffer size for the SVar is derived from the current state
900+ sv <- newParallelVar StopAny (adaptState stt)
901+ -- Add the producer thread-id to the SVar.
902+ liftIO myThreadId >>= modifyThread sv
903+ void $ doFork (work sv) (svarMrun sv) (handleFoldException sv)
908+ {-# NOINLINE work #-}
909+ work sv = void $ foldOnce f $ fromProducer sv
911+{-# INLINE_NORMAL tapAsync #-}
912+tapAsync :: MonadAsync m => Fold m a b -> Stream m a -> Stream m a
913+tapAsync f (Stream step1 state1) = Stream step TapInit
917+ -- In general, a Stop event would come equipped with the result
918+ -- of the fold. It is not used here but it would be useful in
919+ -- applicative and distribute.
920+ done <- fromConsumer svr
921+ when (not done) $ do
922+ liftIO $ withDiagMVar svr "teeToSVar: waiting to drain"
923+ $ takeMVar (outputDoorBellFromConsumer svr)
927+ liftIO $ sendStop svr Nothing
928+ -- drain/wait until a stop event arrives from the fold.
931+ {-# INLINE_LATE step #-}
932+ step gst TapInit = do
933+ sv <- newFoldSVar gst f
934+ return $ Skip (Tapping sv state1)
936+ step gst (Tapping sv st) = do
940+ done <- pushToFold sv a
943+ -- XXX we do not need to wait synchronously here
945+ return $ Yield a (TapDone s)
946+ else return $ Yield a (Tapping sv s)
947+ Skip s -> return $ Skip (Tapping sv s)
952+ step gst (TapDone st) = do
955+ Yield a s -> Yield a (TapDone s)
956+ Skip s -> Skip (TapDone s)
575------------------------------------------------------------------------------
959------------------------------------------------------------------------------
576-- Inserting
960-- Inserting
577------------------------------------------------------------------------------
961------------------------------------------------------------------------------
@@ -812,6 +1196,227 @@ zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
812zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
1196zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
813zipWith f = zipWithM (\a b -> return (f a b))
1197zipWith f = zipWithM (\a b -> return (f a b))
1199+------------------------------------------------------------------------------
1201+------------------------------------------------------------------------------
1203+{-# ANN type ParseChunksState Fuse #-}
1204+data ParseChunksState x inpBuf st pst =
1205+ ParseChunksInit inpBuf st
1206+ | ParseChunksInitLeftOver inpBuf
1207+ | ParseChunksStream st inpBuf !pst
1208+ | ParseChunksBuf inpBuf st inpBuf !pst
1209+ | ParseChunksYield x (ParseChunksState x inpBuf st pst)
1211+{-# INLINE_NORMAL parseMany #-}
1214+ => PRD.Parser m a b
1217+parseMany (PRD.Parser pstep initial extract) (Stream step state) =
1218+ Stream stepOuter (ParseChunksInit [] state)
1222+ {-# INLINE_LATE stepOuter #-}
1223+ -- Buffer is empty, get the first element from the stream, initialize the
1224+ -- fold and then go to stream processing loop.
1225+ stepOuter gst (ParseChunksInit [] st) = do
1226+ r <- step (adaptState gst) st
1228+ Yield x s -> initial >>= return . Skip . ParseChunksBuf [x] s []
1229+ Skip s -> return $ Skip $ ParseChunksInit [] s
1230+ Stop -> return Stop
1232+ -- Buffer is not empty, go to buffered processing loop
1233+ stepOuter _ (ParseChunksInit src st) = do
1234+ initial >>= return . Skip . ParseChunksBuf src st []
1236+ -- XXX we just discard any leftover input at the end
1237+ stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1239+ -- Buffer is empty, process elements from the stream
1240+ stepOuter gst (ParseChunksStream st buf pst) = do
1241+ r <- step (adaptState gst) st
1244+ pRes <- pstep pst x
1246+ PR.Partial 0 pst1 ->
1247+ return $ Skip $ ParseChunksStream s [] pst1
1248+ PR.Partial n pst1 -> do
1249+ assert (n <= length (x:buf)) (return ())
1250+ let src0 = Prelude.take n (x:buf)
1251+ src = Prelude.reverse src0
1252+ return $ Skip $ ParseChunksBuf src s [] pst1
1253+ PR.Continue 0 pst1 ->
1254+ return $ Skip $ ParseChunksStream s (x:buf) pst1
1255+ PR.Continue n pst1 -> do
1256+ assert (n <= length (x:buf)) (return ())
1257+ let (src0, buf1) = splitAt n (x:buf)
1258+ src = Prelude.reverse src0
1259+ return $ Skip $ ParseChunksBuf src s buf1 pst1
1262+ ParseChunksYield b (ParseChunksInit [] s)
1264+ assert (n <= length (x:buf)) (return ())
1265+ let src = Prelude.reverse (Prelude.take n (x:buf))
1267+ ParseChunksYield b (ParseChunksInit src s)
1268+ PR.Error err -> throwM $ ParseError err
1269+ Skip s -> return $ Skip $ ParseChunksStream s buf pst
1272+ let src = Prelude.reverse buf
1274+ ParseChunksYield b (ParseChunksInitLeftOver src)
1276+ -- go back to stream processing mode
1277+ stepOuter _ (ParseChunksBuf [] s buf pst) =
1278+ return $ Skip $ ParseChunksStream s buf pst
1280+ -- buffered processing loop
1281+ stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1282+ pRes <- pstep pst x
1284+ PR.Partial 0 pst1 ->
1285+ return $ Skip $ ParseChunksBuf xs s [] pst1
1286+ PR.Partial n pst1 -> do
1287+ assert (n <= length (x:buf)) (return ())
1288+ let src0 = Prelude.take n (x:buf)
1289+ src = Prelude.reverse src0 ++ xs
1290+ return $ Skip $ ParseChunksBuf src s [] pst1
1291+ PR.Continue 0 pst1 ->
1292+ return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1293+ PR.Continue n pst1 -> do
1294+ assert (n <= length (x:buf)) (return ())
1295+ let (src0, buf1) = splitAt n (x:buf)
1296+ src = Prelude.reverse src0 ++ xs
1297+ return $ Skip $ ParseChunksBuf src s buf1 pst1
1299+ return $ Skip $ ParseChunksYield b (ParseChunksInit xs s)
1301+ assert (n <= length (x:buf)) (return ())
1302+ let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1303+ return $ Skip $ ParseChunksYield b (ParseChunksInit src s)
1304+ PR.Error err -> throwM $ ParseError err
1306+ stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1308+{-# ANN type ConcatParseState Fuse #-}
1309+data ConcatParseState x inpBuf st p =
1310+ ConcatParseInit inpBuf st p
1311+ | ConcatParseInitLeftOver inpBuf
1312+ | ConcatParseStream st inpBuf p
1313+ | ConcatParseBuf inpBuf st inpBuf p
1314+ | ConcatParseYield x (ConcatParseState x inpBuf st p)
1316+{-# INLINE_NORMAL parseIterate #-}
1319+ => (b -> PRD.Parser m a b)
1323+parseIterate func seed (Stream step state) =
1324+ Stream stepOuter (ConcatParseInit [] state (func seed))
1328+ {-# INLINE_LATE stepOuter #-}
1329+ -- Buffer is empty, go to stream processing loop
1330+ stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1331+ initial >>= \r -> return $ Skip $ ConcatParseStream st []
1332+ (PRD.Parser pstep (return r) extract)
1334+ -- Buffer is not empty, go to buffered processing loop
1335+ stepOuter _ (ConcatParseInit src st
1336+ (PRD.Parser pstep initial extract)) = do
1337+ initial >>= \r -> return $ Skip $ ConcatParseBuf src st []
1338+ (PRD.Parser pstep (return r) extract)
1340+ -- XXX we just discard any leftover input at the end
1341+ stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1343+ -- Buffer is empty process elements from the stream
1344+ stepOuter gst (ConcatParseStream st buf
1345+ p@(PRD.Parser pstep initial extract)) = do
1346+ r <- step (adaptState gst) st
1350+ pRes <- pstep pst x
1352+ PR.Partial 0 pst1 ->
1353+ return $ Skip $ ConcatParseStream s []
1354+ (PRD.Parser pstep (return pst1) extract)
1355+ PR.Partial n pst1 -> do
1356+ assert (n <= length (x:buf)) (return ())
1357+ let src0 = Prelude.take n (x:buf)
1358+ src = Prelude.reverse src0
1359+ return $ Skip $ ConcatParseBuf src s []
1360+ (PRD.Parser pstep (return pst1) extract)
1361+ -- PR.Continue 0 pst1 ->
1362+ -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1363+ PR.Continue n pst1 -> do
1364+ assert (n <= length (x:buf)) (return ())
1365+ let (src0, buf1) = splitAt n (x:buf)
1366+ src = Prelude.reverse src0
1367+ return $ Skip $ ConcatParseBuf src s buf1
1368+ (PRD.Parser pstep (return pst1) extract)
1369+ -- XXX Specialize for Stop 0 common case?
1371+ assert (n <= length (x:buf)) (return ())
1372+ let src = Prelude.reverse (Prelude.take n (x:buf))
1374+ ConcatParseYield b (ConcatParseInit src s (func b))
1375+ PR.Error err -> throwM $ ParseError err
1376+ Skip s -> return $ Skip $ ConcatParseStream s buf p
1380+ let src = Prelude.reverse buf
1382+ ConcatParseYield b (ConcatParseInitLeftOver src)
1384+ -- go back to stream processing mode
1385+ stepOuter _ (ConcatParseBuf [] s buf p) =
1386+ return $ Skip $ ConcatParseStream s buf p
1388+ -- buffered processing loop
1389+ stepOuter _ (ConcatParseBuf (x:xs) s buf
1390+ (PRD.Parser pstep initial extract)) = do
1392+ pRes <- pstep pst x
1394+ PR.Partial 0 pst1 ->
1395+ return $ Skip $ ConcatParseBuf xs s []
1396+ (PRD.Parser pstep (return pst1) extract)
1397+ PR.Partial n pst1 -> do
1398+ assert (n <= length (x:buf)) (return ())
1399+ let src0 = Prelude.take n (x:buf)
1400+ src = Prelude.reverse src0 ++ xs
1401+ return $ Skip $ ConcatParseBuf src s []
1402+ (PRD.Parser pstep (return pst1) extract)
1403+ -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1404+ PR.Continue n pst1 -> do
1405+ assert (n <= length (x:buf)) (return ())
1406+ let (src0, buf1) = splitAt n (x:buf)
1407+ src = Prelude.reverse src0 ++ xs
1408+ return $ Skip $ ConcatParseBuf src s buf1
1409+ (PRD.Parser pstep (return pst1) extract)
1410+ -- XXX Specialize for Stop 0 common case?
1412+ assert (n <= length (x:buf)) (return ())
1413+ let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1414+ return $ Skip $ ConcatParseYield b
1415+ (ConcatParseInit src s (func b))
1416+ PR.Error err -> throwM $ ParseError err
1418+ stepOuter _ (ConcatParseYield a next) = return $ Yield a next
815------------------------------------------------------------------------------
1420------------------------------------------------------------------------------
816-- Merging
1421-- Merging
817------------------------------------------------------------------------------
1422------------------------------------------------------------------------------
@@ -982,3 +1587,75 @@ dropByTime duration (Stream step1 state1) = Stream step (DropByTimeInit state1)
982 Yield x s -> Yield x (DropByTimeYield s)
1587 Yield x s -> Yield x (DropByTimeYield s)
983 Skip s -> Skip (DropByTimeYield s)
1588 Skip s -> Skip (DropByTimeYield s)
984 Stop -> Stop
1589 Stop -> Stop
1591+-------------------------------------------------------------------------------
1592+-- Hoisting the inner monad
1593+-------------------------------------------------------------------------------
1595+{-# INLINE_NORMAL hoist #-}
1596+hoist :: Monad n => (forall x. m x -> n x) -> Stream m a -> Stream n a
1597+hoist f (Stream step state) = (Stream step' state)
1599+ {-# INLINE_LATE step' #-}
1601+ r <- f $ step (adaptState gst) st
1603+ Yield x s -> Yield x s
1607+{-# INLINE generally #-}
1608+generally :: Monad m => Stream Identity a -> Stream m a
1609+generally = hoist (return . runIdentity)
1611+{-# INLINE_NORMAL liftInner #-}
1612+liftInner :: (Monad m, MonadTrans t, Monad (t m))
1613+ => Stream m a -> Stream (t m) a
1614+liftInner (Stream step state) = Stream step' state
1616+ {-# INLINE_LATE step' #-}
1618+ r <- lift $ step (adaptState gst) st
1620+ Yield x s -> Yield x s
1624+{-# INLINE_NORMAL runReaderT #-}
1625+runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
1626+runReaderT env (Stream step state) = Stream step' (state, env)
1628+ {-# INLINE_LATE step' #-}
1629+ step' gst (st, action) = do
1631+ r <- Reader.runReaderT (step (adaptState gst) st) sv
1633+ Yield x s -> Yield x (s, return sv)
1634+ Skip s -> Skip (s, return sv)
1637+{-# INLINE_NORMAL evalStateT #-}
1638+evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
1639+evalStateT initial (Stream step state) = Stream step' (state, initial)
1641+ {-# INLINE_LATE step' #-}
1642+ step' gst (st, action) = do
1644+ (r, sv') <- State.runStateT (step (adaptState gst) st) sv
1646+ Yield x s -> Yield x (s, return sv')
1647+ Skip s -> Skip (s, return sv')
1650+{-# INLINE_NORMAL runStateT #-}
1651+runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
1652+runStateT initial (Stream step state) = Stream step' (state, initial)
1654+ {-# INLINE_LATE step' #-}
1655+ step' gst (st, action) = do
1657+ (r, sv') <- State.runStateT (step (adaptState gst) st) sv
1659+ Yield x s -> Yield (sv', x) (s, return sv')
1660+ Skip s -> Skip (s, return sv')