on a84e6cf help sign in
4719 lines 167 kB history raw
1#include "inline.hs"
3-- |
4-- Module : Streamly.Internal.Data.Stream.StreamD
5-- Copyright : (c) 2018 Harendra Kumar
6-- (c) Roman Leshchinskiy 2008-2010
7-- (c) The University of Glasgow, 2009
8--
9-- License : BSD3
10-- Maintainer : streamly@composewell.com
11-- Stability : experimental
12-- Portability : GHC
13--
14-- Direct style re-implementation of CPS style stream in StreamK module. The
15-- symbol or suffix 'D' in this module denotes the "Direct" style. GHC is able
16-- to INLINE and fuse direct style better, providing better performance than
17-- CPS implementation.
18--
19-- @
20-- import qualified Streamly.Internal.Data.Stream.StreamD as D
21-- @
23-- Some of the functions in this file have been adapted from the vector
24-- library, https://hackage.haskell.org/package/vector.
26module Streamly.Internal.Data.Stream.StreamD
27 (
28 -- * The stream type
29 Step (..)
30 , Stream (Stream, UnStream)
32 -- * Construction
33 , nil
34 , nilM
35 , cons
37 -- * Deconstruction
38 , uncons
40 -- * Generation
41 -- ** Unfolds
42 , unfoldr
43 , unfoldrM
44 , unfold
46 -- ** Specialized Generation
47 -- | Generate a monadic stream from a seed.
48 , repeat
49 , repeatM
50 , replicate
51 , replicateM
52 , fromIndices
53 , fromIndicesM
54 , generate
55 , generateM
56 , iterate
57 , iterateM
59 -- ** Enumerations
60 , enumerateFromStepIntegral
61 , enumerateFromIntegral
62 , enumerateFromThenIntegral
63 , enumerateFromToIntegral
64 , enumerateFromThenToIntegral
66 , enumerateFromStepNum
67 , numFrom
68 , numFromThen
69 , enumerateFromToFractional
70 , enumerateFromThenToFractional
72 -- ** Time
73 , times
75 -- ** Conversions
76 -- | Transform an input structure into a stream.
77 -- | Direct style stream does not support @fromFoldable@.
78 , yield
79 , yieldM
80 , fromList
81 , fromListM
82 , fromStreamK
83 , fromStreamD
84 , fromPrimIORef
85 , fromSVar
87 -- * Elimination
88 -- ** General Folds
89 , foldrS
90 , foldrT
91 , foldrM
92 , foldrMx
93 , foldr
94 , foldr1
96 , foldl'
97 , foldlM'
98 , foldlS
99 , foldlT
100 , reverse
101 , reverse'
103 , foldlx'
104 , foldlMx'
105 , runFold
107 , parselMx'
108 , parseMany
109 , parseIterate
111 -- ** Specialized Folds
112 , tap
113 , tapOffsetEvery
114 , tapAsync
115 , tapRate
116 , pollCounts
117 , drain
118 , null
119 , head
120 , headElse
121 , tail
122 , last
123 , elem
124 , notElem
125 , all
126 , any
127 , maximum
128 , maximumBy
129 , minimum
130 , minimumBy
131 , findIndices
132 , lookup
133 , findM
134 , find
135 , (!!)
136 , toSVarParallel
138 -- ** Flattening nested streams
139 , concatMapM
140 , concatMap
141 , ConcatMapUState (..)
142 , concatMapU
143 , ConcatUnfoldInterleaveState (..)
144 , concatUnfoldInterleave
145 , concatUnfoldRoundrobin
146 , AppendState(..)
147 , append
148 , InterleaveState(..)
149 , interleave
150 , interleaveMin
151 , interleaveSuffix
152 , interleaveInfix
153 , roundRobin -- interleaveFair?/ParallelFair
154 , gintercalateSuffix
155 , interposeSuffix
156 , gintercalate
157 , interpose
159 -- ** Grouping
160 , groupsOf
161 , groupsOf2
162 , groupsBy
163 , groupsRollingBy
165 -- ** Splitting
166 , splitBy
167 , splitSuffixBy
168 , wordsBy
169 , splitSuffixBy'
171 , splitOn
172 , splitSuffixOn
174 , splitInnerBy
175 , splitInnerBySuffix
177 -- ** Substreams
178 , isPrefixOf
179 , isSubsequenceOf
180 , stripPrefix
182 -- ** Map and Fold
183 , mapM_
185 -- ** Conversions
186 -- | Transform a stream into another type.
187 , toList
188 , toListRev
189 , toStreamK
190 , toStreamD
192 , hoist
193 , generally
195 , liftInner
196 , runReaderT
197 , evalStateT
198 , runStateT
200 -- * Transformation
201 , transform
203 -- ** By folding (scans)
204 , scanlM'
205 , scanlMAfter'
206 , scanl'
207 , scanlM
208 , scanl
209 , scanl1M'
210 , scanl1'
211 , scanl1M
212 , scanl1
214 , prescanl'
215 , prescanlM'
217 , postscanl
218 , postscanlM
219 , postscanl'
220 , postscanlM'
221 , postscanlMAfter'
223 , postscanlx'
224 , postscanlMx'
225 , scanlMx'
226 , scanlx'
228 -- * Filtering
229 , filter
230 , filterM
231 , uniq
232 , take
233 , takeByTime
234 , takeWhile
235 , takeWhileM
236 , drop
237 , dropByTime
238 , dropWhile
239 , dropWhileM
241 -- * Mapping
242 , map
243 , mapM
244 , sequence
245 , rollingMap
246 , rollingMapM
248 -- * Inserting
249 , intersperseM
250 , intersperseM_
251 , intersperse
252 , intersperseSuffix
253 , intersperseSuffix_
254 , intersperseSuffixBySpan
255 , insertBy
257 -- * Deleting
258 , deleteBy
260 -- ** Map and Filter
261 , mapMaybe
262 , mapMaybeM
264 -- * Zipping
265 , indexed
266 , indexedR
267 , zipWith
268 , zipWithM
270 -- * Comparisons
271 , eqBy
272 , cmpBy
274 -- * Merging
275 , mergeBy
276 , mergeByM
278 -- * Transformation comprehensions
279 , the
281 -- * Exceptions
282 , newFinalizedIORef
283 , runIORefFinalizer
284 , withIORefFinalizer
285 , gbracket_
286 , gbracket
287 , before
288 , after_
289 , after
290 , bracket_
291 , bracket
292 , onException
293 , finally_
294 , finally
295 , ghandle
296 , handle
298 -- * Concurrent Application
299 , mkParallel
300 , mkParallelD
301 , newCallbackStream
303 , lastN
304 )
305where
307import Control.Concurrent (killThread, myThreadId, takeMVar, threadDelay)
308import Control.Exception
309 (assert, Exception, SomeException, AsyncException, fromException, mask_)
310import Control.Monad (void, when, forever)
311import Control.Monad.Catch (MonadCatch, MonadThrow, throwM)
312import Control.Monad.IO.Class (MonadIO(..))
313import Control.Monad.Trans.Reader (ReaderT)
314import Control.Monad.Trans.State.Strict (StateT)
315import Control.Monad.Trans.Class (MonadTrans(lift))
316import Control.Monad.Trans.Control (MonadBaseControl, liftBaseOp_, control)
317import Data.Bits (shiftR, shiftL, (.|.), (.&.))
318import Data.Functor.Identity (Identity(..))
319import Data.Int (Int64)
320import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef, IORef)
321import Data.Maybe (fromJust, isJust, isNothing)
322import Data.Word (Word32)
323import Foreign.Ptr (Ptr)
324import Foreign.Storable (Storable(..))
325import GHC.Types (SPEC(..))
326import System.Mem (performMajorGC)
327import Fusion.Plugin.Types (Fuse(..))
328import Streamly.Internal.Data.IORef.Prim (Prim)
329import Streamly.Internal.Data.Time.Units
330 (TimeUnit64, toRelTime64, diffAbsTime64, RelTime64)
331import Streamly.Internal.Data.Atomics (atomicModifyIORefCAS_)
332import Streamly.Internal.Memory.Array.Types (Array(..))
333import Streamly.Internal.Data.Fold.Types (Fold(..))
334import Streamly.Internal.Data.Parser (ParseError(..))
335import Streamly.Internal.Data.Pipe.Types (Pipe(..), PipeState(..))
336import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
337import Streamly.Internal.Data.Time.Units
338 (MicroSecond64(..), fromAbsTime, toAbsTime, AbsTime)
339import Streamly.Internal.Data.Unfold.Types (Unfold(..))
340import Streamly.Internal.Data.Tuple.Strict (Tuple3'(..))
341import Streamly.Internal.Data.Stream.SVar (fromConsumer, pushToFold)
343import qualified Streamly.Internal.Data.IORef.Prim as Prim
344import qualified Streamly.Internal.Data.Pipe.Types as Pipe
345import qualified Streamly.Internal.Memory.Array.Types as A
346import qualified Streamly.Internal.Memory.Mutable.Array.Types as MA
347import qualified Streamly.Internal.Data.Fold as FL
348import qualified Streamly.Memory.Ring as RB
349import qualified Streamly.Internal.Data.Stream.StreamK as K
350import qualified Streamly.Internal.Data.Parser as PR
351import qualified Streamly.Internal.Data.Parser.ParserD as PRD
352import qualified Control.Monad.Catch as MC
353import qualified Control.Monad.Trans.Reader as Reader
354import qualified Control.Monad.Trans.State.Strict as State
355import qualified Prelude
357import Prelude hiding
358 ( map, mapM, mapM_, repeat, foldr, last, take, filter
359 , takeWhile, drop, dropWhile, all, any, maximum, minimum, elem
360 , notElem, null, head, tail, zipWith, lookup, foldr1, sequence
361 , (!!), scanl, scanl1, concatMap, replicate, enumFromTo, concat
362 , reverse, iterate, splitAt)
363import Streamly.Internal.Data.Stream.StreamD.Type
364import Streamly.Internal.Data.SVar
366------------------------------------------------------------------------------
367-- Construction
368------------------------------------------------------------------------------
370-- | An empty 'Stream'.
371{-# INLINE_NORMAL nil #-}
372nil :: Monad m => Stream m a
373nil = Stream (\_ _ -> return Stop) ()
375-- | An empty 'Stream' with a side effect.
376{-# INLINE_NORMAL nilM #-}
377nilM :: Monad m => m b -> Stream m a
378nilM m = Stream (\_ _ -> m >> return Stop) ()
380{-# INLINE_NORMAL consM #-}
381consM :: Monad m => m a -> Stream m a -> Stream m a
382consM m (Stream step state) = Stream step1 Nothing
383 where
384 {-# INLINE_LATE step1 #-}
385 step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
386 step1 gst (Just st) = do
387 r <- step gst st
388 return $
389 case r of
390 Yield a s -> Yield a (Just s)
391 Skip s -> Skip (Just s)
392 Stop -> Stop
394-- XXX implement in terms of consM?
395-- cons x = consM (return x)
396--
397-- | Can fuse but has O(n^2) complexity.
398{-# INLINE_NORMAL cons #-}
399cons :: Monad m => a -> Stream m a -> Stream m a
400cons x (Stream step state) = Stream step1 Nothing
401 where
402 {-# INLINE_LATE step1 #-}
403 step1 _ Nothing = return $ Yield x (Just state)
404 step1 gst (Just st) = do
405 r <- step gst st
406 return $
407 case r of
408 Yield a s -> Yield a (Just s)
409 Skip s -> Skip (Just s)
410 Stop -> Stop
412-------------------------------------------------------------------------------
413-- Deconstruction
414-------------------------------------------------------------------------------
416-- Does not fuse, has the same performance as the StreamK version.
417{-# INLINE_NORMAL uncons #-}
418uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
419uncons (UnStream step state) = go state
420 where
421 go st = do
422 r <- step defState st
423 case r of
424 Yield x s -> return $ Just (x, Stream step s)
425 Skip s -> go s
426 Stop -> return Nothing
428------------------------------------------------------------------------------
429-- Generation by unfold
430------------------------------------------------------------------------------
432{-# INLINE_NORMAL unfoldrM #-}
433unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
434unfoldrM next state = Stream step state
435 where
436 {-# INLINE_LATE step #-}
437 step _ st = do
438 r <- next st
439 return $ case r of
440 Just (x, s) -> Yield x s
441 Nothing -> Stop
443{-# INLINE_LATE unfoldr #-}
444unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
445unfoldr f = unfoldrM (return . f)
447-- | Convert an 'Unfold' into a 'Stream' by supplying it a seed.
448--
449{-# INLINE_NORMAL unfold #-}
450unfold :: Monad m => Unfold m a b -> a -> Stream m b
451unfold (Unfold ustep inject) seed = Stream step Nothing
452 where
453 {-# INLINE_LATE step #-}
454 step _ Nothing = inject seed >>= return . Skip . Just
455 step _ (Just st) = do
456 r <- ustep st
457 return $ case r of
458 Yield x s -> Yield x (Just s)
459 Skip s -> Skip (Just s)
460 Stop -> Stop
462------------------------------------------------------------------------------
463-- Specialized Generation
464------------------------------------------------------------------------------
466{-# INLINE_NORMAL repeatM #-}
467repeatM :: Monad m => m a -> Stream m a
468repeatM x = Stream (\_ _ -> x >>= \r -> return $ Yield r ()) ()
470{-# INLINE_NORMAL repeat #-}
471repeat :: Monad m => a -> Stream m a
472repeat x = Stream (\_ _ -> return $ Yield x ()) ()
474{-# INLINE_NORMAL iterateM #-}
475iterateM :: Monad m => (a -> m a) -> m a -> Stream m a
476iterateM step = Stream (\_ st -> st >>= \x -> return $ Yield x (step x))
478{-# INLINE_NORMAL iterate #-}
479iterate :: Monad m => (a -> a) -> a -> Stream m a
480iterate step st = iterateM (return . step) (return st)
482{-# INLINE_NORMAL replicateM #-}
483replicateM :: forall m a. Monad m => Int -> m a -> Stream m a
484replicateM n p = Stream step n
485 where
486 {-# INLINE_LATE step #-}
487 step _ (i :: Int)
488 | i <= 0 = return Stop
489 | otherwise = do
490 x <- p
491 return $ Yield x (i - 1)
493{-# INLINE_NORMAL replicate #-}
494replicate :: Monad m => Int -> a -> Stream m a
495replicate n x = replicateM n (return x)
497-- This would not work properly for floats, therefore we put an Integral
498-- constraint.
499-- | Can be used to enumerate unbounded integrals. This does not check for
500-- overflow or underflow for bounded integrals.
501{-# INLINE_NORMAL enumerateFromStepIntegral #-}
502enumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
503enumerateFromStepIntegral from stride =
504 from `seq` stride `seq` Stream step from
505 where
506 {-# INLINE_LATE step #-}
507 step _ !x = return $ Yield x $! (x + stride)
509-- We are assuming that "to" is constrained by the type to be within
510-- max/min bounds.
511{-# INLINE enumerateFromToIntegral #-}
512enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
513enumerateFromToIntegral from to =
514 takeWhile (<= to) $ enumerateFromStepIntegral from 1
516{-# INLINE enumerateFromIntegral #-}
517enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
518enumerateFromIntegral from = enumerateFromToIntegral from maxBound
520data EnumState a = EnumInit | EnumYield a a a | EnumStop
522{-# INLINE_NORMAL enumerateFromThenToIntegralUp #-}
523enumerateFromThenToIntegralUp
524 :: (Monad m, Integral a)
525 => a -> a -> a -> Stream m a
526enumerateFromThenToIntegralUp from next to = Stream step EnumInit
527 where
528 {-# INLINE_LATE step #-}
529 step _ EnumInit =
530 return $
531 if to < next
532 then if to < from
533 then Stop
534 else Yield from EnumStop
535 else -- from <= next <= to
536 let stride = next - from
537 in Skip $ EnumYield from stride (to - stride)
539 step _ (EnumYield x stride toMinus) =
540 return $
541 if x > toMinus
542 then Yield x EnumStop
543 else Yield x $ EnumYield (x + stride) stride toMinus
545 step _ EnumStop = return Stop
547{-# INLINE_NORMAL enumerateFromThenToIntegralDn #-}
548enumerateFromThenToIntegralDn
549 :: (Monad m, Integral a)
550 => a -> a -> a -> Stream m a
551enumerateFromThenToIntegralDn from next to = Stream step EnumInit
552 where
553 {-# INLINE_LATE step #-}
554 step _ EnumInit =
555 return $ if to > next
556 then if to > from
557 then Stop
558 else Yield from EnumStop
559 else -- from >= next >= to
560 let stride = next - from
561 in Skip $ EnumYield from stride (to - stride)
563 step _ (EnumYield x stride toMinus) =
564 return $
565 if x < toMinus
566 then Yield x EnumStop
567 else Yield x $ EnumYield (x + stride) stride toMinus
569 step _ EnumStop = return Stop
571{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
572enumerateFromThenToIntegral
573 :: (Monad m, Integral a)
574 => a -> a -> a -> Stream m a
575enumerateFromThenToIntegral from next to
576 | next >= from = enumerateFromThenToIntegralUp from next to
577 | otherwise = enumerateFromThenToIntegralDn from next to
579{-# INLINE_NORMAL enumerateFromThenIntegral #-}
580enumerateFromThenIntegral
581 :: (Monad m, Integral a, Bounded a)
582 => a -> a -> Stream m a
583enumerateFromThenIntegral from next =
584 if next > from
585 then enumerateFromThenToIntegralUp from next maxBound
586 else enumerateFromThenToIntegralDn from next minBound
588-- For floating point numbers if the increment is less than the precision then
589-- it just gets lost. Therefore we cannot always increment it correctly by just
590-- repeated addition.
591-- 9007199254740992 + 1 + 1 :: Double => 9.007199254740992e15
592-- 9007199254740992 + 2 :: Double => 9.007199254740994e15
594-- Instead we accumulate the increment counter and compute the increment
595-- every time before adding it to the starting number.
596--
597-- This works for Integrals as well as floating point numbers, but
598-- enumerateFromStepIntegral is faster for integrals.
599{-# INLINE_NORMAL enumerateFromStepNum #-}
600enumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
601enumerateFromStepNum from stride = Stream step 0
602 where
603 {-# INLINE_LATE step #-}
604 step _ !i = return $ (Yield $! (from + i * stride)) $! (i + 1)
606{-# INLINE_NORMAL numFrom #-}
607numFrom :: (Monad m, Num a) => a -> Stream m a
608numFrom from = enumerateFromStepNum from 1
610{-# INLINE_NORMAL numFromThen #-}
611numFromThen :: (Monad m, Num a) => a -> a -> Stream m a
612numFromThen from next = enumerateFromStepNum from (next - from)
614-- We cannot write a general function for Num. The only way to write code
615-- portable between the two is to use a 'Real' constraint and convert between
616-- Fractional and Integral using fromRational which is horribly slow.
617{-# INLINE_NORMAL enumerateFromToFractional #-}
618enumerateFromToFractional
619 :: (Monad m, Fractional a, Ord a)
620 => a -> a -> Stream m a
621enumerateFromToFractional from to =
622 takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
624{-# INLINE_NORMAL enumerateFromThenToFractional #-}
625enumerateFromThenToFractional
626 :: (Monad m, Fractional a, Ord a)
627 => a -> a -> a -> Stream m a
628enumerateFromThenToFractional from next to =
629 takeWhile predicate $ numFromThen from next
630 where
631 mid = (next - from) / 2
632 predicate | next >= from = (<= to + mid)
633 | otherwise = (>= to + mid)
635-------------------------------------------------------------------------------
636-- Generation by Conversion
637-------------------------------------------------------------------------------
639{-# INLINE_NORMAL fromIndicesM #-}
640fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
641fromIndicesM gen = Stream step 0
642 where
643 {-# INLINE_LATE step #-}
644 step _ i = do
645 x <- gen i
646 return $ Yield x (i + 1)
648{-# INLINE fromIndices #-}
649fromIndices :: Monad m => (Int -> a) -> Stream m a
650fromIndices gen = fromIndicesM (return . gen)
652{-# INLINE_NORMAL generateM #-}
653generateM :: Monad m => Int -> (Int -> m a) -> Stream m a
654generateM n gen = n `seq` Stream step 0
655 where
656 {-# INLINE_LATE step #-}
657 step _ i | i < n = do
658 x <- gen i
659 return $ Yield x (i + 1)
660 | otherwise = return Stop
662{-# INLINE generate #-}
663generate :: Monad m => Int -> (Int -> a) -> Stream m a
664generate n gen = generateM n (return . gen)
666-- XXX we need the MonadAsync constraint because of a rewrite rule.
667-- | Convert a list of monadic actions to a 'Stream'
668{-# INLINE_LATE fromListM #-}
669fromListM :: MonadAsync m => [m a] -> Stream m a
670fromListM = Stream step
671 where
672 {-# INLINE_LATE step #-}
673 step _ (m:ms) = m >>= \x -> return $ Yield x ms
674 step _ [] = return Stop
676{-# INLINE toStreamD #-}
677toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
678toStreamD = fromStreamK . K.toStream
680{-# INLINE_NORMAL fromPrimIORef #-}
681fromPrimIORef :: (MonadIO m, Prim a) => Prim.IORef a -> Stream m a
682fromPrimIORef var = Stream step ()
683 where
684 {-# INLINE_LATE step #-}
685 step _ () = liftIO (Prim.readIORef var) >>= \x -> return $ Yield x ()
687-------------------------------------------------------------------------------
688-- Generation from SVar
689-------------------------------------------------------------------------------
691data FromSVarState t m a =
692 FromSVarInit
693 | FromSVarRead (SVar t m a)
694 | FromSVarLoop (SVar t m a) [ChildEvent a]
695 | FromSVarDone (SVar t m a)
697{-# INLINE_NORMAL fromSVar #-}
698fromSVar :: (MonadAsync m) => SVar t m a -> Stream m a
699fromSVar svar = Stream step FromSVarInit
700 where
702 {-# INLINE_LATE step #-}
703 step _ FromSVarInit = do
704 ref <- liftIO $ newIORef ()
705 _ <- liftIO $ mkWeakIORef ref hook
706 -- when this copy of svar gets garbage collected "ref" will get
707 -- garbage collected and our GC hook will be called.
708 let sv = svar{svarRef = Just ref}
709 return $ Skip (FromSVarRead sv)
711 where
713 {-# NOINLINE hook #-}
714 hook = do
715 when (svarInspectMode svar) $ do
716 r <- liftIO $ readIORef (svarStopTime (svarStats svar))
717 when (isNothing r) $
718 printSVar svar "SVar Garbage Collected"
719 cleanupSVar svar
720 -- If there are any SVars referenced by this SVar a GC will prompt
721 -- them to be cleaned up quickly.
722 when (svarInspectMode svar) performMajorGC
724 step _ (FromSVarRead sv) = do
725 list <- readOutputQ sv
726 -- Reversing the output is important to guarantee that we process the
727 -- outputs in the same order as they were generated by the constituent
728 -- streams.
729 return $ Skip $ FromSVarLoop sv (Prelude.reverse list)
731 step _ (FromSVarLoop sv []) = do
732 done <- postProcess sv
733 return $ Skip $ if done
734 then (FromSVarDone sv)
735 else (FromSVarRead sv)
737 step _ (FromSVarLoop sv (ev : es)) = do
738 case ev of
739 ChildYield a -> return $ Yield a (FromSVarLoop sv es)
740 ChildStop tid e -> do
741 accountThread sv tid
742 case e of
743 Nothing -> do
744 stop <- shouldStop tid
745 if stop
746 then do
747 liftIO (cleanupSVar sv)
748 return $ Skip (FromSVarDone sv)
749 else return $ Skip (FromSVarLoop sv es)
750 Just ex ->
751 case fromException ex of
752 Just ThreadAbort ->
753 return $ Skip (FromSVarLoop sv es)
754 Nothing -> liftIO (cleanupSVar sv) >> throwM ex
755 where
757 shouldStop tid =
758 case svarStopStyle sv of
759 StopNone -> return False
760 StopAny -> return True
761 StopBy -> do
762 sid <- liftIO $ readIORef (svarStopBy sv)
763 return $ if tid == sid then True else False
765 step _ (FromSVarDone sv) = do
766 when (svarInspectMode sv) $ do
767 t <- liftIO $ getTime Monotonic
768 liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
769 liftIO $ printSVar sv "SVar Done"
770 return Stop
772-------------------------------------------------------------------------------
773-- Process events received by a fold consumer from a stream producer
774-------------------------------------------------------------------------------
776{-# INLINE_NORMAL fromProducer #-}
777fromProducer :: (MonadAsync m) => SVar t m a -> Stream m a
778fromProducer svar = Stream step (FromSVarRead svar)
779 where
781 {-# INLINE_LATE step #-}
782 step _ (FromSVarRead sv) = do
783 list <- readOutputQ sv
784 -- Reversing the output is important to guarantee that we process the
785 -- outputs in the same order as they were generated by the constituent
786 -- streams.
787 return $ Skip $ FromSVarLoop sv (Prelude.reverse list)
789 step _ (FromSVarLoop sv []) = return $ Skip $ FromSVarRead sv
790 step _ (FromSVarLoop sv (ev : es)) = do
791 case ev of
792 ChildYield a -> return $ Yield a (FromSVarLoop sv es)
793 ChildStop tid e -> do
794 accountThread sv tid
795 case e of
796 Nothing -> do
797 sendStopToProducer sv
798 return $ Skip (FromSVarDone sv)
799 Just _ -> error "Bug: fromProducer: received exception"
801 step _ (FromSVarDone sv) = do
802 when (svarInspectMode sv) $ do
803 t <- liftIO $ getTime Monotonic
804 liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
805 liftIO $ printSVar sv "SVar Done"
806 return Stop
808 step _ FromSVarInit = undefined
810-------------------------------------------------------------------------------
811-- Hoisting the inner monad
812-------------------------------------------------------------------------------
814{-# INLINE_NORMAL hoist #-}
815hoist :: Monad n => (forall x. m x -> n x) -> Stream m a -> Stream n a
816hoist f (Stream step state) = (Stream step' state)
817 where
818 {-# INLINE_LATE step' #-}
819 step' gst st = do
820 r <- f $ step (adaptState gst) st
821 return $ case r of
822 Yield x s -> Yield x s
823 Skip s -> Skip s
824 Stop -> Stop
826{-# INLINE generally #-}
827generally :: Monad m => Stream Identity a -> Stream m a
828generally = hoist (return . runIdentity)
830{-# INLINE_NORMAL liftInner #-}
831liftInner :: (Monad m, MonadTrans t, Monad (t m))
832 => Stream m a -> Stream (t m) a
833liftInner (Stream step state) = Stream step' state
834 where
835 {-# INLINE_LATE step' #-}
836 step' gst st = do
837 r <- lift $ step (adaptState gst) st
838 return $ case r of
839 Yield x s -> Yield x s
840 Skip s -> Skip s
841 Stop -> Stop
843{-# INLINE_NORMAL runReaderT #-}
844runReaderT :: Monad m => m s -> Stream (ReaderT s m) a -> Stream m a
845runReaderT env (Stream step state) = Stream step' (state, env)
846 where
847 {-# INLINE_LATE step' #-}
848 step' gst (st, action) = do
849 sv <- action
850 r <- Reader.runReaderT (step (adaptState gst) st) sv
851 return $ case r of
852 Yield x s -> Yield x (s, return sv)
853 Skip s -> Skip (s, return sv)
854 Stop -> Stop
856{-# INLINE_NORMAL evalStateT #-}
857evalStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m a
858evalStateT initial (Stream step state) = Stream step' (state, initial)
859 where
860 {-# INLINE_LATE step' #-}
861 step' gst (st, action) = do
862 sv <- action
863 (r, sv') <- State.runStateT (step (adaptState gst) st) sv
864 return $ case r of
865 Yield x s -> Yield x (s, return sv')
866 Skip s -> Skip (s, return sv')
867 Stop -> Stop
869{-# INLINE_NORMAL runStateT #-}
870runStateT :: Monad m => m s -> Stream (StateT s m) a -> Stream m (s, a)
871runStateT initial (Stream step state) = Stream step' (state, initial)
872 where
873 {-# INLINE_LATE step' #-}
874 step' gst (st, action) = do
875 sv <- action
876 (r, sv') <- State.runStateT (step (adaptState gst) st) sv
877 return $ case r of
878 Yield x s -> Yield (sv', x) (s, return sv')
879 Skip s -> Skip (s, return sv')
880 Stop -> Stop
882------------------------------------------------------------------------------
883-- Elimination by Folds
884------------------------------------------------------------------------------
886------------------------------------------------------------------------------
887-- Right Folds
888------------------------------------------------------------------------------
890{-# INLINE_NORMAL foldr1 #-}
891foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
892foldr1 f m = do
893 r <- uncons m
894 case r of
895 Nothing -> return Nothing
896 Just (h, t) -> fmap Just (foldr f h t)
898------------------------------------------------------------------------------
899-- Left Folds
900------------------------------------------------------------------------------
902{-# INLINE_NORMAL foldlT #-}
903foldlT :: (Monad m, Monad (s m), MonadTrans s)
904 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
905foldlT fstep begin (Stream step state) = go SPEC begin state
906 where
907 go !_ acc st = do
908 r <- lift $ step defState st
909 case r of
910 Yield x s -> go SPEC (fstep acc x) s
911 Skip s -> go SPEC acc s
912 Stop -> acc
914-- Note, this is going to have horrible performance, because of the nature of
915-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
916-- likely be practically unusable.
917{-# INLINE_NORMAL foldlS #-}
918foldlS :: Monad m
919 => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
920foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
921 where
922 step' gst (Left (st, acc)) = do
923 r <- step (adaptState gst) st
924 return $ case r of
925 Yield x s -> Skip (Left (s, fstep acc x))
926 Skip s -> Skip (Left (s, acc))
927 Stop -> Skip (Right acc)
929 step' gst (Right (Stream stp stt)) = do
930 r <- stp (adaptState gst) stt
931 return $ case r of
932 Yield x s -> Yield x (Right (Stream stp s))
933 Skip s -> Skip (Right (Stream stp s))
934 Stop -> Stop
936------------------------------------------------------------------------------
937-- Parses
938------------------------------------------------------------------------------
940-- Inlined definition. Without the inline "serially/parser/take" benchmark
941-- degrades and parseMany does not fuse. Even using "inline" at the callsite
942-- does not help.
943{-# INLINE splitAt #-}
944splitAt :: Int -> [a] -> ([a],[a])
945splitAt n ls
946 | n <= 0 = ([], ls)
947 | otherwise = splitAt' n ls
948 where
949 splitAt' :: Int -> [a] -> ([a], [a])
950 splitAt' _ [] = ([], [])
951 splitAt' 1 (x:xs) = ([x], xs)
952 splitAt' m (x:xs) = (x:xs', xs'')
953 where
954 (xs', xs'') = splitAt' (m - 1) xs
956-- | Run a 'Parse' over a stream.
957{-# INLINE_NORMAL parselMx' #-}
958parselMx'
959 :: MonadThrow m
960 => (s -> a -> m (PR.Step s b))
961 -> m s
962 -> (s -> m b)
963 -> Stream m a
964 -> m b
965parselMx' pstep initial extract (Stream step state) = do
966 initial >>= go SPEC state []
968 where
970 -- XXX currently we are using a dumb list based approach for backtracking
971 -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
972 -- That will allow us more efficient random back and forth movement.
973 {-# INLINE go #-}
974 go !_ st buf !pst = do
975 r <- step defState st
976 case r of
977 Yield x s -> do
978 pRes <- pstep pst x
979 case pRes of
980 PR.Partial 0 pst1 -> go SPEC s [] pst1
981 PR.Partial n pst1 -> do
982 assert (n <= length (x:buf)) (return ())
983 let src0 = Prelude.take n (x:buf)
984 src = Prelude.reverse src0
985 gobuf SPEC s [] src pst1
986 PR.Continue 0 pst1 -> go SPEC s (x:buf) pst1
987 PR.Continue n pst1 -> do
988 assert (n <= length (x:buf)) (return ())
989 let (src0, buf1) = splitAt n (x:buf)
990 src = Prelude.reverse src0
991 gobuf SPEC s buf1 src pst1
992 PR.Done _ b -> return b
993 PR.Error err -> throwM $ ParseError err
994 Skip s -> go SPEC s buf pst
995 Stop -> extract pst
997 gobuf !_ s buf [] !pst = go SPEC s buf pst
998 gobuf !_ s buf (x:xs) !pst = do
999 pRes <- pstep pst x
1000 case pRes of
1001 PR.Partial 0 pst1 ->
1002 gobuf SPEC s [] xs pst1
1003 PR.Partial n pst1 -> do
1004 assert (n <= length (x:buf)) (return ())
1005 let src0 = Prelude.take n (x:buf)
1006 src = Prelude.reverse src0 ++ xs
1007 gobuf SPEC s [] src pst1
1008 PR.Continue 0 pst1 -> gobuf SPEC s (x:buf) xs pst1
1009 PR.Continue n pst1 -> do
1010 assert (n <= length (x:buf)) (return ())
1011 let (src0, buf1) = splitAt n (x:buf)
1012 src = Prelude.reverse src0 ++ xs
1013 gobuf SPEC s buf1 src pst1
1014 PR.Done _ b -> return b
1015 PR.Error err -> throwM $ ParseError err
1017------------------------------------------------------------------------------
1018-- Repeated parsing
1019------------------------------------------------------------------------------
1021{-# ANN type ParseChunksState Fuse #-}
1022data ParseChunksState x inpBuf st pst =
1023 ParseChunksInit inpBuf st
1024 | ParseChunksInitLeftOver inpBuf
1025 | ParseChunksStream st inpBuf pst
1026 | ParseChunksBuf inpBuf st inpBuf pst
1027 | ParseChunksYield x (ParseChunksState x inpBuf st pst)
1029{-# INLINE_NORMAL parseMany #-}
1030parseMany
1031 :: MonadThrow m
1032 => PRD.Parser m a b
1033 -> Stream m a
1034 -> Stream m b
1035parseMany (PRD.Parser pstep initial extract) (Stream step state) =
1036 Stream stepOuter (ParseChunksInit [] state)
1038 where
1040 {-# INLINE_LATE stepOuter #-}
1041 -- Buffer is empty, go to stream processing loop
1042 stepOuter _ (ParseChunksInit [] st) = do
1043 initial >>= return . Skip . ParseChunksStream st []
1045 -- Buffer is not empty, go to buffered processing loop
1046 stepOuter _ (ParseChunksInit src st) = do
1047 initial >>= return . Skip . ParseChunksBuf src st []
1049 -- XXX we just discard any leftover input at the end
1050 stepOuter _ (ParseChunksInitLeftOver _) = return Stop
1052 -- Buffer is empty process elements from the stream
1053 stepOuter gst (ParseChunksStream st buf pst) = do
1054 r <- step (adaptState gst) st
1055 case r of
1056 Yield x s -> do
1057 pRes <- pstep pst x
1058 case pRes of
1059 PR.Partial 0 pst1 ->
1060 return $ Skip $ ParseChunksStream s [] pst1
1061 PR.Partial n pst1 -> do
1062 assert (n <= length (x:buf)) (return ())
1063 let src0 = Prelude.take n (x:buf)
1064 src = Prelude.reverse src0
1065 return $ Skip $ ParseChunksBuf src s [] pst1
1066 -- PR.Continue 0 pst1 ->
1067 -- return $ Skip $ ParseChunksStream s (x:buf) pst1
1068 PR.Continue n pst1 -> do
1069 assert (n <= length (x:buf)) (return ())
1070 let (src0, buf1) = splitAt n (x:buf)
1071 src = Prelude.reverse src0
1072 return $ Skip $ ParseChunksBuf src s buf1 pst1
1073 -- XXX Specialize for Stop 0 common case?
1074 PR.Done n b -> do
1075 assert (n <= length (x:buf)) (return ())
1076 let src = Prelude.reverse (Prelude.take n (x:buf))
1077 return $ Skip $
1078 ParseChunksYield b (ParseChunksInit src s)
1079 PR.Error err -> throwM $ ParseError err
1080 Skip s -> return $ Skip $ ParseChunksStream s buf pst
1081 Stop -> do
1082 b <- extract pst
1083 let src = Prelude.reverse buf
1084 return $ Skip $
1085 ParseChunksYield b (ParseChunksInitLeftOver src)
1087 -- go back to stream processing mode
1088 stepOuter _ (ParseChunksBuf [] s buf pst) =
1089 return $ Skip $ ParseChunksStream s buf pst
1091 -- buffered processing loop
1092 stepOuter _ (ParseChunksBuf (x:xs) s buf pst) = do
1093 pRes <- pstep pst x
1094 case pRes of
1095 PR.Partial 0 pst1 ->
1096 return $ Skip $ ParseChunksBuf xs s [] pst1
1097 PR.Partial n pst1 -> do
1098 assert (n <= length (x:buf)) (return ())
1099 let src0 = Prelude.take n (x:buf)
1100 src = Prelude.reverse src0 ++ xs
1101 return $ Skip $ ParseChunksBuf src s [] pst1
1102 -- PR.Continue 0 pst1 -> return $ Skip $ ParseChunksBuf xs s (x:buf) pst1
1103 PR.Continue n pst1 -> do
1104 assert (n <= length (x:buf)) (return ())
1105 let (src0, buf1) = splitAt n (x:buf)
1106 src = Prelude.reverse src0 ++ xs
1107 return $ Skip $ ParseChunksBuf src s buf1 pst1
1108 -- XXX Specialize for Stop 0 common case?
1109 PR.Done n b -> do
1110 assert (n <= length (x:buf)) (return ())
1111 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1112 return $ Skip $ ParseChunksYield b (ParseChunksInit src s)
1113 PR.Error err -> throwM $ ParseError err
1115 stepOuter _ (ParseChunksYield a next) = return $ Yield a next
1117{-# ANN type ConcatParseState Fuse #-}
1118data ConcatParseState x inpBuf st p =
1119 ConcatParseInit inpBuf st p
1120 | ConcatParseInitLeftOver inpBuf
1121 | ConcatParseStream st inpBuf p
1122 | ConcatParseBuf inpBuf st inpBuf p
1123 | ConcatParseYield x (ConcatParseState x inpBuf st p)
1125{-# INLINE_NORMAL parseIterate #-}
1126parseIterate
1127 :: MonadThrow m
1128 => (b -> PRD.Parser m a b)
1129 -> b
1130 -> Stream m a
1131 -> Stream m b
1132parseIterate func seed (Stream step state) =
1133 Stream stepOuter (ConcatParseInit [] state (func seed))
1135 where
1137 {-# INLINE_LATE stepOuter #-}
1138 -- Buffer is empty, go to stream processing loop
1139 stepOuter _ (ConcatParseInit [] st (PRD.Parser pstep initial extract)) = do
1140 initial >>= \r -> return $ Skip $ ConcatParseStream st []
1141 (PRD.Parser pstep (return r) extract)
1143 -- Buffer is not empty, go to buffered processing loop
1144 stepOuter _ (ConcatParseInit src st
1145 (PRD.Parser pstep initial extract)) = do
1146 initial >>= \r -> return $ Skip $ ConcatParseBuf src st []
1147 (PRD.Parser pstep (return r) extract)
1149 -- XXX we just discard any leftover input at the end
1150 stepOuter _ (ConcatParseInitLeftOver _) = return Stop
1152 -- Buffer is empty process elements from the stream
1153 stepOuter gst (ConcatParseStream st buf
1154 p@(PRD.Parser pstep initial extract)) = do
1155 r <- step (adaptState gst) st
1156 case r of
1157 Yield x s -> do
1158 pst <- initial
1159 pRes <- pstep pst x
1160 case pRes of
1161 PR.Partial 0 pst1 ->
1162 return $ Skip $ ConcatParseStream s []
1163 (PRD.Parser pstep (return pst1) extract)
1164 PR.Partial n pst1 -> do
1165 assert (n <= length (x:buf)) (return ())
1166 let src0 = Prelude.take n (x:buf)
1167 src = Prelude.reverse src0
1168 return $ Skip $ ConcatParseBuf src s []
1169 (PRD.Parser pstep (return pst1) extract)
1170 -- PR.Continue 0 pst1 ->
1171 -- return $ Skip $ ConcatParseStream s (x:buf) pst1
1172 PR.Continue n pst1 -> do
1173 assert (n <= length (x:buf)) (return ())
1174 let (src0, buf1) = splitAt n (x:buf)
1175 src = Prelude.reverse src0
1176 return $ Skip $ ConcatParseBuf src s buf1
1177 (PRD.Parser pstep (return pst1) extract)
1178 -- XXX Specialize for Stop 0 common case?
1179 PR.Done n b -> do
1180 assert (n <= length (x:buf)) (return ())
1181 let src = Prelude.reverse (Prelude.take n (x:buf))
1182 return $ Skip $
1183 ConcatParseYield b (ConcatParseInit src s (func b))
1184 PR.Error err -> throwM $ ParseError err
1185 Skip s -> return $ Skip $ ConcatParseStream s buf p
1186 Stop -> do
1187 pst <- initial
1188 b <- extract pst
1189 let src = Prelude.reverse buf
1190 return $ Skip $
1191 ConcatParseYield b (ConcatParseInitLeftOver src)
1193 -- go back to stream processing mode
1194 stepOuter _ (ConcatParseBuf [] s buf p) =
1195 return $ Skip $ ConcatParseStream s buf p
1197 -- buffered processing loop
1198 stepOuter _ (ConcatParseBuf (x:xs) s buf
1199 (PRD.Parser pstep initial extract)) = do
1200 pst <- initial
1201 pRes <- pstep pst x
1202 case pRes of
1203 PR.Partial 0 pst1 ->
1204 return $ Skip $ ConcatParseBuf xs s []
1205 (PRD.Parser pstep (return pst1) extract)
1206 PR.Partial n pst1 -> do
1207 assert (n <= length (x:buf)) (return ())
1208 let src0 = Prelude.take n (x:buf)
1209 src = Prelude.reverse src0 ++ xs
1210 return $ Skip $ ConcatParseBuf src s []
1211 (PRD.Parser pstep (return pst1) extract)
1212 -- PR.Continue 0 pst1 -> return $ Skip $ ConcatParseBuf xs s (x:buf) pst1
1213 PR.Continue n pst1 -> do
1214 assert (n <= length (x:buf)) (return ())
1215 let (src0, buf1) = splitAt n (x:buf)
1216 src = Prelude.reverse src0 ++ xs
1217 return $ Skip $ ConcatParseBuf src s buf1
1218 (PRD.Parser pstep (return pst1) extract)
1219 -- XXX Specialize for Stop 0 common case?
1220 PR.Done n b -> do
1221 assert (n <= length (x:buf)) (return ())
1222 let src = Prelude.reverse (Prelude.take n (x:buf)) ++ xs
1223 return $ Skip $ ConcatParseYield b
1224 (ConcatParseInit src s (func b))
1225 PR.Error err -> throwM $ ParseError err
1227 stepOuter _ (ConcatParseYield a next) = return $ Yield a next
1229------------------------------------------------------------------------------
1230-- Specialized Folds
1231------------------------------------------------------------------------------
1233-- | Run a streaming composition, discard the results.
1234{-# INLINE_LATE drain #-}
1235drain :: Monad m => Stream m a -> m ()
1236-- drain = foldrM (\_ xs -> xs) (return ())
1237drain (Stream step state) = go SPEC state
1238 where
1239 go !_ st = do
1240 r <- step defState st
1241 case r of
1242 Yield _ s -> go SPEC s
1243 Skip s -> go SPEC s
1244 Stop -> return ()
1246{-# INLINE_NORMAL null #-}
1247null :: Monad m => Stream m a -> m Bool
1248null m = foldrM (\_ _ -> return False) (return True) m
1250{-# INLINE_NORMAL head #-}
1251head :: Monad m => Stream m a -> m (Maybe a)
1252head m = foldrM (\x _ -> return (Just x)) (return Nothing) m
1254{-# INLINE_NORMAL headElse #-}
1255headElse :: Monad m => a -> Stream m a -> m a
1256headElse a m = foldrM (\x _ -> return x) (return a) m
1258-- Does not fuse, has the same performance as the StreamK version.
1259{-# INLINE_NORMAL tail #-}
1260tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
1261tail (UnStream step state) = go state
1262 where
1263 go st = do
1264 r <- step defState st
1265 case r of
1266 Yield _ s -> return (Just $ Stream step s)
1267 Skip s -> go s
1268 Stop -> return Nothing
1270-- XXX will it fuse? need custom impl?
1271{-# INLINE_NORMAL last #-}
1272last :: Monad m => Stream m a -> m (Maybe a)
1273last = foldl' (\_ y -> Just y) Nothing
1275{-# INLINE_NORMAL elem #-}
1276elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
1277-- elem e m = foldrM (\x xs -> if x == e then return True else xs) (return False) m
1278elem e (Stream step state) = go state
1279 where
1280 go st = do
1281 r <- step defState st
1282 case r of
1283 Yield x s
1284 | x == e -> return True
1285 | otherwise -> go s
1286 Skip s -> go s
1287 Stop -> return False
1289{-# INLINE_NORMAL notElem #-}
1290notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
1291notElem e s = fmap not (elem e s)
1293{-# INLINE_NORMAL all #-}
1294all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
1295-- all p m = foldrM (\x xs -> if p x then xs else return False) (return True) m
1296all p (Stream step state) = go state
1297 where
1298 go st = do
1299 r <- step defState st
1300 case r of
1301 Yield x s
1302 | p x -> go s
1303 | otherwise -> return False
1304 Skip s -> go s
1305 Stop -> return True
1307{-# INLINE_NORMAL any #-}
1308any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
1309-- any p m = foldrM (\x xs -> if p x then return True else xs) (return False) m
1310any p (Stream step state) = go state
1311 where
1312 go st = do
1313 r <- step defState st
1314 case r of
1315 Yield x s
1316 | p x -> return True
1317 | otherwise -> go s
1318 Skip s -> go s
1319 Stop -> return False
1321{-# INLINE_NORMAL maximum #-}
1322maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
1323maximum (Stream step state) = go Nothing state
1324 where
1325 go Nothing st = do
1326 r <- step defState st
1327 case r of
1328 Yield x s -> go (Just x) s
1329 Skip s -> go Nothing s
1330 Stop -> return Nothing
1331 go (Just acc) st = do
1332 r <- step defState st
1333 case r of
1334 Yield x s
1335 | acc <= x -> go (Just x) s
1336 | otherwise -> go (Just acc) s
1337 Skip s -> go (Just acc) s
1338 Stop -> return (Just acc)
1340{-# INLINE_NORMAL maximumBy #-}
1341maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
1342maximumBy cmp (Stream step state) = go Nothing state
1343 where
1344 go Nothing st = do
1345 r <- step defState st
1346 case r of
1347 Yield x s -> go (Just x) s
1348 Skip s -> go Nothing s
1349 Stop -> return Nothing
1350 go (Just acc) st = do
1351 r <- step defState st
1352 case r of
1353 Yield x s -> case cmp acc x of
1354 GT -> go (Just acc) s
1355 _ -> go (Just x) s
1356 Skip s -> go (Just acc) s
1357 Stop -> return (Just acc)
1359{-# INLINE_NORMAL minimum #-}
1360minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
1361minimum (Stream step state) = go Nothing state
1362 where
1363 go Nothing st = do
1364 r <- step defState st
1365 case r of
1366 Yield x s -> go (Just x) s
1367 Skip s -> go Nothing s
1368 Stop -> return Nothing
1369 go (Just acc) st = do
1370 r <- step defState st
1371 case r of
1372 Yield x s
1373 | acc <= x -> go (Just acc) s
1374 | otherwise -> go (Just x) s
1375 Skip s -> go (Just acc) s
1376 Stop -> return (Just acc)
1378{-# INLINE_NORMAL minimumBy #-}
1379minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
1380minimumBy cmp (Stream step state) = go Nothing state
1381 where
1382 go Nothing st = do
1383 r <- step defState st
1384 case r of
1385 Yield x s -> go (Just x) s
1386 Skip s -> go Nothing s
1387 Stop -> return Nothing
1388 go (Just acc) st = do
1389 r <- step defState st
1390 case r of
1391 Yield x s -> case cmp acc x of
1392 GT -> go (Just x) s
1393 _ -> go (Just acc) s
1394 Skip s -> go (Just acc) s
1395 Stop -> return (Just acc)
1397{-# INLINE_NORMAL (!!) #-}
1398(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
1399(Stream step state) !! i = go i state
1400 where
1401 go n st = do
1402 r <- step defState st
1403 case r of
1404 Yield x s | n < 0 -> return Nothing
1405 | n == 0 -> return $ Just x
1406 | otherwise -> go (n - 1) s
1407 Skip s -> go n s
1408 Stop -> return Nothing
1410{-# INLINE_NORMAL lookup #-}
1411lookup :: (Monad m, Eq a) => a -> Stream m (a, b) -> m (Maybe b)
1412lookup e m = foldrM (\(a, b) xs -> if e == a then return (Just b) else xs)
1413 (return Nothing) m
1415{-# INLINE_NORMAL findM #-}
1416findM :: Monad m => (a -> m Bool) -> Stream m a -> m (Maybe a)
1417findM p m = foldrM (\x xs -> p x >>= \r -> if r then return (Just x) else xs)
1418 (return Nothing) m
1420{-# INLINE find #-}
1421find :: Monad m => (a -> Bool) -> Stream m a -> m (Maybe a)
1422find p = findM (return . p)
1424{-# INLINE_NORMAL findIndices #-}
1425findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
1426findIndices p (Stream step state) = Stream step' (state, 0)
1427 where
1428 {-# INLINE_LATE step' #-}
1429 step' gst (st, i) = i `seq` do
1430 r <- step (adaptState gst) st
1431 return $ case r of
1432 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
1433 Skip s -> Skip (s, i)
1434 Stop -> Stop
1436{-# INLINE toListRev #-}
1437toListRev :: Monad m => Stream m a -> m [a]
1438toListRev = foldl' (flip (:)) []
1440-- We can implement reverse as:
1442-- > reverse = foldlS (flip cons) nil
1444-- However, this implementation is unusable because of the horrible performance
1445-- of cons. So we just convert it to a list first and then stream from the
1446-- list.
1448-- XXX Maybe we can use an Array instead of a list here?
1449{-# INLINE_NORMAL reverse #-}
1450reverse :: Monad m => Stream m a -> Stream m a
1451reverse m = Stream step Nothing
1452 where
1453 {-# INLINE_LATE step #-}
1454 step _ Nothing = do
1455 xs <- toListRev m
1456 return $ Skip (Just xs)
1457 step _ (Just (x:xs)) = return $ Yield x (Just xs)
1458 step _ (Just []) = return Stop
1460-- Much faster reverse for Storables
1461{-# INLINE_NORMAL reverse' #-}
1462reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
1464-- This commented implementation copies the whole stream into one single array
1465-- and then streams from that array, this is 3-4x faster than the chunked code
1466-- that follows. Though this could be problematic due to unbounded large
1467-- allocations. We need to figure out why the chunked code is slower and if we
1468-- can optimize the chunked code to work as fast as this one. It may be a
1469-- fusion issue?
1470import Foreign.ForeignPtr (touchForeignPtr)
1471import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
1472import Foreign.Ptr (Ptr, plusPtr)
1473reverse' m = Stream step Nothing
1474 where
1475 {-# INLINE_LATE step #-}
1476 step _ Nothing = do
1477 arr <- A.fromStreamD m
1478 let p = aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
1479 return $ Skip $ Just (aStart arr, p)
1481 step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
1483 step _ (Just (start, p)) = do
1484 let !x = A.unsafeInlineIO $ do
1485 r <- peek p
1486 touchForeignPtr start
1487 return r
1488 next = p `plusPtr` negate (sizeOf (undefined :: a))
1489 return $ Yield x (Just (start, next))
1491reverse' m =
1492 A.flattenArraysRev
1493 $ fromStreamK
1494 $ K.reverse
1495 $ toStreamK
1496 $ A.fromStreamDArraysOf A.defaultChunkSize m
1499------------------------------------------------------------------------------
1500-- Grouping/Splitting
1501------------------------------------------------------------------------------
1503{-# INLINE_NORMAL splitSuffixBy' #-}
1504splitSuffixBy' :: Monad m
1505 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1506splitSuffixBy' predicate f (Stream step state) =
1507 Stream (stepOuter f) (Just state)
1509 where
1511 {-# INLINE_LATE stepOuter #-}
1512 stepOuter (Fold fstep initial done) gst (Just st) = do
1513 res <- step (adaptState gst) st
1514 case res of
1515 Yield x s -> do
1516 acc <- initial
1517 acc' <- fstep acc x
1518 if (predicate x)
1519 then done acc' >>= \val -> return $ Yield val (Just s)
1520 else go SPEC s acc'
1522 Skip s -> return $ Skip $ Just s
1523 Stop -> return Stop
1525 where
1527 go !_ stt !acc = do
1528 res <- step (adaptState gst) stt
1529 case res of
1530 Yield x s -> do
1531 acc' <- fstep acc x
1532 if (predicate x)
1533 then done acc' >>= \val -> return $ Yield val (Just s)
1534 else go SPEC s acc'
1535 Skip s -> go SPEC s acc
1536 Stop -> done acc >>= \val -> return $ Yield val Nothing
1538 stepOuter _ _ Nothing = return Stop
1540{-# INLINE_NORMAL groupsBy #-}
1541groupsBy :: Monad m
1542 => (a -> a -> Bool)
1543 -> Fold m a b
1544 -> Stream m a
1545 -> Stream m b
1546groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
1548 where
1550 {-# INLINE_LATE stepOuter #-}
1551 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1552 res <- step (adaptState gst) st
1553 case res of
1554 Yield x s -> do
1555 acc <- initial
1556 acc' <- fstep acc x
1557 go SPEC x s acc'
1559 Skip s -> return $ Skip $ (Just s, Nothing)
1560 Stop -> return Stop
1562 where
1564 go !_ prev stt !acc = do
1565 res <- step (adaptState gst) stt
1566 case res of
1567 Yield x s -> do
1568 if cmp x prev
1569 then do
1570 acc' <- fstep acc x
1571 go SPEC prev s acc'
1572 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1573 Skip s -> go SPEC prev s acc
1574 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1576 stepOuter (Fold fstep initial done) gst (Just st, Just prev) = do
1577 acc <- initial
1578 acc' <- fstep acc prev
1579 go SPEC st acc'
1581 where
1583 -- XXX code duplicated from the previous equation
1584 go !_ stt !acc = do
1585 res <- step (adaptState gst) stt
1586 case res of
1587 Yield x s -> do
1588 if cmp x prev
1589 then do
1590 acc' <- fstep acc x
1591 go SPEC s acc'
1592 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1593 Skip s -> go SPEC s acc
1594 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1596 stepOuter _ _ (Nothing,_) = return Stop
1598{-# INLINE_NORMAL groupsRollingBy #-}
1599groupsRollingBy :: Monad m
1600 => (a -> a -> Bool)
1601 -> Fold m a b
1602 -> Stream m a
1603 -> Stream m b
1604groupsRollingBy cmp f (Stream step state) =
1605 Stream (stepOuter f) (Just state, Nothing)
1606 where
1608 {-# INLINE_LATE stepOuter #-}
1609 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1610 res <- step (adaptState gst) st
1611 case res of
1612 Yield x s -> do
1613 acc <- initial
1614 acc' <- fstep acc x
1615 go SPEC x s acc'
1617 Skip s -> return $ Skip $ (Just s, Nothing)
1618 Stop -> return Stop
1620 where
1621 go !_ prev stt !acc = do
1622 res <- step (adaptState gst) stt
1623 case res of
1624 Yield x s -> do
1625 if cmp prev x
1626 then do
1627 acc' <- fstep acc x
1628 go SPEC x s acc'
1629 else
1630 done acc >>= \r -> return $ Yield r (Just s, Just x)
1631 Skip s -> go SPEC prev s acc
1632 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1634 stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1635 acc <- initial
1636 acc' <- fstep acc prev'
1637 go SPEC prev' st acc'
1639 where
1640 go !_ prevv stt !acc = do
1641 res <- step (adaptState gst) stt
1642 case res of
1643 Yield x s -> do
1644 if cmp prevv x
1645 then do
1646 acc' <- fstep acc x
1647 go SPEC x s acc'
1648 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1649 Skip s -> go SPEC prevv s acc
1650 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1652 stepOuter _ _ (Nothing, _) = return Stop
1654{-# INLINE_NORMAL splitBy #-}
1655splitBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1656splitBy predicate f (Stream step state) = Stream (step' f) (Just state)
1658 where
1660 {-# INLINE_LATE step' #-}
1661 step' (Fold fstep initial done) gst (Just st) = initial >>= go SPEC st
1663 where
1665 go !_ stt !acc = do
1666 res <- step (adaptState gst) stt
1667 case res of
1668 Yield x s -> do
1669 if predicate x
1670 then done acc >>= \r -> return $ Yield r (Just s)
1671 else do
1672 acc' <- fstep acc x
1673 go SPEC s acc'
1674 Skip s -> go SPEC s acc
1675 Stop -> done acc >>= \r -> return $ Yield r Nothing
1677 step' _ _ Nothing = return Stop
1679-- XXX requires -funfolding-use-threshold=150 in lines-unlines benchmark
1680{-# INLINE_NORMAL splitSuffixBy #-}
1681splitSuffixBy :: Monad m
1682 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1683splitSuffixBy predicate f (Stream step state) = Stream (step' f) (Just state)
1685 where
1687 {-# INLINE_LATE step' #-}
1688 step' (Fold fstep initial done) gst (Just st) = do
1689 res <- step (adaptState gst) st
1690 case res of
1691 Yield x s -> do
1692 acc <- initial
1693 if predicate x
1694 then done acc >>= \val -> return $ Yield val (Just s)
1695 else do
1696 acc' <- fstep acc x
1697 go SPEC s acc'
1699 Skip s -> return $ Skip $ Just s
1700 Stop -> return Stop
1702 where
1704 go !_ stt !acc = do
1705 res <- step (adaptState gst) stt
1706 case res of
1707 Yield x s -> do
1708 if predicate x
1709 then done acc >>= \r -> return $ Yield r (Just s)
1710 else do
1711 acc' <- fstep acc x
1712 go SPEC s acc'
1713 Skip s -> go SPEC s acc
1714 Stop -> done acc >>= \r -> return $ Yield r Nothing
1716 step' _ _ Nothing = return Stop
1718{-# INLINE_NORMAL wordsBy #-}
1719wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1720wordsBy predicate f (Stream step state) = Stream (stepOuter f) (Just state)
1722 where
1724 {-# INLINE_LATE stepOuter #-}
1725 stepOuter (Fold fstep initial done) gst (Just st) = do
1726 res <- step (adaptState gst) st
1727 case res of
1728 Yield x s -> do
1729 if predicate x
1730 then return $ Skip (Just s)
1731 else do
1732 acc <- initial
1733 acc' <- fstep acc x
1734 go SPEC s acc'
1736 Skip s -> return $ Skip $ Just s
1737 Stop -> return Stop
1739 where
1741 go !_ stt !acc = do
1742 res <- step (adaptState gst) stt
1743 case res of
1744 Yield x s -> do
1745 if predicate x
1746 then done acc >>= \r -> return $ Yield r (Just s)
1747 else do
1748 acc' <- fstep acc x
1749 go SPEC s acc'
1750 Skip s -> go SPEC s acc
1751 Stop -> done acc >>= \r -> return $ Yield r Nothing
1753 stepOuter _ _ Nothing = return Stop
1755-- String search algorithms:
1756-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1759-- TODO can we unify the splitting operations using a splitting configuration
1760-- like in the split package.
1762data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1764data SplitOptions = SplitOptions
1765 { style :: SplitStyle
1766 , withSep :: Bool -- ^ keep the separators in output
1767 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1768 -- , trimHead :: Bool -- ^ drop blank at head
1769 -- , trimTail :: Bool -- ^ drop blank at tail
1773data SplitOnState s a =
1774 GO_START
1775 | GO_EMPTY_PAT s
1776 | GO_SINGLE_PAT s a
1777 | GO_SHORT_PAT s
1778 | GO_KARP_RABIN s !(RB.Ring a) !(Ptr a)
1779 | GO_DONE
1781{-# INLINE_NORMAL splitOn #-}
1782splitOn
1783 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1784 => Array a
1785 -> Fold m a b
1786 -> Stream m a
1787 -> Stream m b
1788splitOn patArr (Fold fstep initial done) (Stream step state) =
1789 Stream stepOuter GO_START
1791 where
1793 patLen = A.length patArr
1794 maxIndex = patLen - 1
1795 elemBits = sizeOf (undefined :: a) * 8
1797 {-# INLINE_LATE stepOuter #-}
1798 stepOuter _ GO_START =
1799 if patLen == 0
1800 then return $ Skip $ GO_EMPTY_PAT state
1801 else if patLen == 1
1802 then do
1803 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1804 return $ Skip $ GO_SINGLE_PAT state r
1805 else if sizeOf (undefined :: a) * patLen
1806 <= sizeOf (undefined :: Word)
1807 then return $ Skip $ GO_SHORT_PAT state
1808 else do
1809 (rb, rhead) <- liftIO $ RB.new patLen
1810 return $ Skip $ GO_KARP_RABIN state rb rhead
1812 stepOuter gst (GO_SINGLE_PAT stt pat) = initial >>= go SPEC stt
1814 where
1816 go !_ st !acc = do
1817 res <- step (adaptState gst) st
1818 case res of
1819 Yield x s -> do
1820 if pat == x
1821 then do
1822 r <- done acc
1823 return $ Yield r (GO_SINGLE_PAT s pat)
1824 else fstep acc x >>= go SPEC s
1825 Skip s -> go SPEC s acc
1826 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1828 stepOuter gst (GO_SHORT_PAT stt) = initial >>= go0 SPEC 0 (0 :: Word) stt
1830 where
1832 mask :: Word
1833 mask = (1 `shiftL` (elemBits * patLen)) - 1
1835 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1837 patWord :: Word
1838 patWord = mask .&. A.foldl' addToWord 0 patArr
1840 go0 !_ !idx wrd st !acc = do
1841 res <- step (adaptState gst) st
1842 case res of
1843 Yield x s -> do
1844 let wrd' = addToWord wrd x
1845 if idx == maxIndex
1846 then do
1847 if wrd' .&. mask == patWord
1848 then do
1849 r <- done acc
1850 return $ Yield r (GO_SHORT_PAT s)
1851 else go1 SPEC wrd' s acc
1852 else go0 SPEC (idx + 1) wrd' s acc
1853 Skip s -> go0 SPEC idx wrd s acc
1854 Stop -> do
1855 acc' <- if idx /= 0
1856 then go2 wrd idx acc
1857 else return acc
1858 done acc' >>= \r -> return $ Yield r GO_DONE
1860 {-# INLINE go1 #-}
1861 go1 !_ wrd st !acc = do
1862 res <- step (adaptState gst) st
1863 case res of
1864 Yield x s -> do
1865 let wrd' = addToWord wrd x
1866 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1867 acc' <- fstep acc (toEnum $ fromIntegral old)
1868 if wrd' .&. mask == patWord
1869 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1870 else go1 SPEC wrd' s acc'
1871 Skip s -> go1 SPEC wrd s acc
1872 Stop -> do
1873 acc' <- go2 wrd patLen acc
1874 done acc' >>= \r -> return $ Yield r GO_DONE
1876 go2 !wrd !n !acc | n > 0 = do
1877 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1878 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1879 go2 _ _ acc = return acc
1881 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1882 initial >>= go0 SPEC 0 rhead stt
1884 where
1886 k = 2891336453 :: Word32
1887 coeff = k ^ patLen
1888 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1889 deltaCksum cksum old new =
1890 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1892 -- XXX shall we use a random starting hash or 1 instead of 0?
1893 patHash = A.foldl' addCksum 0 patArr
1895 -- rh == ringHead
1896 go0 !_ !idx !rh st !acc = do
1897 res <- step (adaptState gst) st
1898 case res of
1899 Yield x s -> do
1900 rh' <- liftIO $ RB.unsafeInsert rb rh x
1901 if idx == maxIndex
1902 then do
1903 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1904 let !ringHash = fold addCksum 0 rb
1905 if ringHash == patHash
1906 then go2 SPEC ringHash rh' s acc
1907 else go1 SPEC ringHash rh' s acc
1908 else go0 SPEC (idx + 1) rh' s acc
1909 Skip s -> go0 SPEC idx rh s acc
1910 Stop -> do
1911 !acc' <- if idx /= 0
1912 then RB.unsafeFoldRingM rh fstep acc rb
1913 else return acc
1914 done acc' >>= \r -> return $ Yield r GO_DONE
1916 -- XXX Theoretically this code can do 4 times faster if GHC generates
1917 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1918 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1919 -- the generated code changes drastically and becomes 4x slower. Need
1920 -- to investigate what is going on with GHC.
1921 {-# INLINE go1 #-}
1922 go1 !_ !cksum !rh st !acc = do
1923 res <- step (adaptState gst) st
1924 case res of
1925 Yield x s -> do
1926 old <- liftIO $ peek rh
1927 let cksum' = deltaCksum cksum old x
1928 acc' <- fstep acc old
1930 if (cksum' == patHash)
1931 then do
1932 rh' <- liftIO (RB.unsafeInsert rb rh x)
1933 go2 SPEC cksum' rh' s acc'
1934 else do
1935 rh' <- liftIO (RB.unsafeInsert rb rh x)
1936 go1 SPEC cksum' rh' s acc'
1937 Skip s -> go1 SPEC cksum rh s acc
1938 Stop -> do
1939 acc' <- RB.unsafeFoldRingFullM rh fstep acc rb
1940 done acc' >>= \r -> return $ Yield r GO_DONE
1942 go2 !_ !cksum' !rh' s !acc' = do
1943 if RB.unsafeEqArray rb rh' patArr
1944 then do
1945 r <- done acc'
1946 return $ Yield r (GO_KARP_RABIN s rb rhead)
1947 else go1 SPEC cksum' rh' s acc'
1949 stepOuter gst (GO_EMPTY_PAT st) = do
1950 res <- step (adaptState gst) st
1951 case res of
1952 Yield x s -> do
1953 acc <- initial
1954 acc' <- fstep acc x
1955 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1956 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1957 Stop -> return Stop
1959 stepOuter _ GO_DONE = return Stop
1961{-# INLINE_NORMAL splitSuffixOn #-}
1962splitSuffixOn
1963 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1964 => Bool
1965 -> Array a
1966 -> Fold m a b
1967 -> Stream m a
1968 -> Stream m b
1969splitSuffixOn withSep patArr (Fold fstep initial done)
1970 (Stream step state) =
1971 Stream stepOuter GO_START
1973 where
1975 patLen = A.length patArr
1976 maxIndex = patLen - 1
1977 elemBits = sizeOf (undefined :: a) * 8
1979 {-# INLINE_LATE stepOuter #-}
1980 stepOuter _ GO_START =
1981 if patLen == 0
1982 then return $ Skip $ GO_EMPTY_PAT state
1983 else if patLen == 1
1984 then do
1985 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1986 return $ Skip $ GO_SINGLE_PAT state r
1987 else if sizeOf (undefined :: a) * patLen
1988 <= sizeOf (undefined :: Word)
1989 then return $ Skip $ GO_SHORT_PAT state
1990 else do
1991 (rb, rhead) <- liftIO $ RB.new patLen
1992 return $ Skip $ GO_KARP_RABIN state rb rhead
1994 stepOuter gst (GO_SINGLE_PAT stt pat) = do
1995 -- This first part is the only difference between splitOn and
1996 -- splitSuffixOn.
1997 -- If the last element is a separator do not issue a blank segment.
1998 res <- step (adaptState gst) stt
1999 case res of
2000 Yield x s -> do
2001 acc <- initial
2002 if pat == x
2003 then do
2004 acc' <- if withSep then fstep acc x else return acc
2005 done acc' >>= \r -> return $ Yield r (GO_SINGLE_PAT s pat)
2006 else fstep acc x >>= go SPEC s
2007 Skip s -> return $ Skip $ (GO_SINGLE_PAT s pat)
2008 Stop -> return Stop
2010 where
2012 -- This is identical for splitOn and splitSuffixOn
2013 go !_ st !acc = do
2014 res <- step (adaptState gst) st
2015 case res of
2016 Yield x s -> do
2017 if pat == x
2018 then do
2019 acc' <- if withSep then fstep acc x else return acc
2020 r <- done acc'
2021 return $ Yield r (GO_SINGLE_PAT s pat)
2022 else fstep acc x >>= go SPEC s
2023 Skip s -> go SPEC s acc
2024 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
2026 stepOuter gst (GO_SHORT_PAT stt) = do
2028 -- Call "initial" only if the stream yields an element, otherwise we
2029 -- may call "initial" but never yield anything. initial may produce a
2030 -- side effect, therefore we will end up doing and discard a side
2031 -- effect.
2033 let idx = 0
2034 let wrd = 0
2035 res <- step (adaptState gst) stt
2036 case res of
2037 Yield x s -> do
2038 acc <- initial
2039 let wrd' = addToWord wrd x
2040 acc' <- if withSep then fstep acc x else return acc
2041 if idx == maxIndex
2042 then do
2043 if wrd' .&. mask == patWord
2044 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
2045 else go0 SPEC (idx + 1) wrd' s acc'
2046 else go0 SPEC (idx + 1) wrd' s acc'
2047 Skip s -> return $ Skip (GO_SHORT_PAT s)
2048 Stop -> return Stop
2050 where
2052 mask :: Word
2053 mask = (1 `shiftL` (elemBits * patLen)) - 1
2055 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
2057 patWord :: Word
2058 patWord = mask .&. A.foldl' addToWord 0 patArr
2060 go0 !_ !idx wrd st !acc = do
2061 res <- step (adaptState gst) st
2062 case res of
2063 Yield x s -> do
2064 let wrd' = addToWord wrd x
2065 acc' <- if withSep then fstep acc x else return acc
2066 if idx == maxIndex
2067 then do
2068 if wrd' .&. mask == patWord
2069 then do
2070 r <- done acc'
2071 return $ Yield r (GO_SHORT_PAT s)
2072 else go1 SPEC wrd' s acc'
2073 else go0 SPEC (idx + 1) wrd' s acc'
2074 Skip s -> go0 SPEC idx wrd s acc
2075 Stop -> do
2076 if (idx == maxIndex) && (wrd .&. mask == patWord)
2077 then return Stop
2078 else do
2079 acc' <- if idx /= 0 && not withSep
2080 then go2 wrd idx acc
2081 else return acc
2082 done acc' >>= \r -> return $ Yield r GO_DONE
2084 {-# INLINE go1 #-}
2085 go1 !_ wrd st !acc = do
2086 res <- step (adaptState gst) st
2087 case res of
2088 Yield x s -> do
2089 let wrd' = addToWord wrd x
2090 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
2091 acc' <- if withSep
2092 then fstep acc x
2093 else fstep acc (toEnum $ fromIntegral old)
2094 if wrd' .&. mask == patWord
2095 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
2096 else go1 SPEC wrd' s acc'
2097 Skip s -> go1 SPEC wrd s acc
2098 Stop ->
2099 -- If the last sequence is a separator do not issue a blank
2100 -- segment.
2101 if wrd .&. mask == patWord
2102 then return Stop
2103 else do
2104 acc' <- if withSep
2105 then return acc
2106 else go2 wrd patLen acc
2107 done acc' >>= \r -> return $ Yield r GO_DONE
2109 go2 !wrd !n !acc | n > 0 = do
2110 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
2111 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
2112 go2 _ _ acc = return acc
2114 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
2115 let idx = 0
2116 res <- step (adaptState gst) stt
2117 case res of
2118 Yield x s -> do
2119 acc <- initial
2120 acc' <- if withSep then fstep acc x else return acc
2121 rh' <- liftIO (RB.unsafeInsert rb rhead x)
2122 if idx == maxIndex
2123 then do
2124 let fold = RB.unsafeFoldRing (RB.ringBound rb)
2125 let !ringHash = fold addCksum 0 rb
2126 if ringHash == patHash
2127 then go2 SPEC ringHash rh' s acc'
2128 else go0 SPEC (idx + 1) rh' s acc'
2129 else go0 SPEC (idx + 1) rh' s acc'
2130 Skip s -> return $ Skip (GO_KARP_RABIN s rb rhead)
2131 Stop -> return Stop
2133 where
2135 k = 2891336453 :: Word32
2136 coeff = k ^ patLen
2137 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
2138 deltaCksum cksum old new =
2139 addCksum cksum new - coeff * fromIntegral (fromEnum old)
2141 -- XXX shall we use a random starting hash or 1 instead of 0?
2142 patHash = A.foldl' addCksum 0 patArr
2144 -- rh == ringHead
2145 go0 !_ !idx !rh st !acc = do
2146 res <- step (adaptState gst) st
2147 case res of
2148 Yield x s -> do
2149 acc' <- if withSep then fstep acc x else return acc
2150 rh' <- liftIO (RB.unsafeInsert rb rh x)
2151 if idx == maxIndex
2152 then do
2153 let fold = RB.unsafeFoldRing (RB.ringBound rb)
2154 let !ringHash = fold addCksum 0 rb
2155 if ringHash == patHash
2156 then go2 SPEC ringHash rh' s acc'
2157 else go1 SPEC ringHash rh' s acc'
2158 else go0 SPEC (idx + 1) rh' s acc'
2159 Skip s -> go0 SPEC idx rh s acc
2160 Stop -> do
2161 -- do not issue a blank segment when we end at pattern
2162 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
2163 then return Stop
2164 else do
2165 !acc' <- if idx /= 0 && not withSep
2166 then RB.unsafeFoldRingM rh fstep acc rb
2167 else return acc
2168 done acc' >>= \r -> return $ Yield r GO_DONE
2170 -- XXX Theoretically this code can do 4 times faster if GHC generates
2171 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
2172 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
2173 -- the generated code changes drastically and becomes 4x slower. Need
2174 -- to investigate what is going on with GHC.
2175 {-# INLINE go1 #-}
2176 go1 !_ !cksum !rh st !acc = do
2177 res <- step (adaptState gst) st
2178 case res of
2179 Yield x s -> do
2180 old <- liftIO $ peek rh
2181 let cksum' = deltaCksum cksum old x
2182 acc' <- if withSep
2183 then fstep acc x
2184 else fstep acc old
2186 if (cksum' == patHash)
2187 then do
2188 rh' <- liftIO (RB.unsafeInsert rb rh x)
2189 go2 SPEC cksum' rh' s acc'
2190 else do
2191 rh' <- liftIO (RB.unsafeInsert rb rh x)
2192 go1 SPEC cksum' rh' s acc'
2193 Skip s -> go1 SPEC cksum rh s acc
2194 Stop -> do
2195 if RB.unsafeEqArray rb rh patArr
2196 then return Stop
2197 else do
2198 acc' <- if withSep
2199 then return acc
2200 else RB.unsafeFoldRingFullM rh fstep acc rb
2201 done acc' >>= \r -> return $ Yield r GO_DONE
2203 go2 !_ !cksum' !rh' s !acc' = do
2204 if RB.unsafeEqArray rb rh' patArr
2205 then do
2206 r <- done acc'
2207 return $ Yield r (GO_KARP_RABIN s rb rhead)
2208 else go1 SPEC cksum' rh' s acc'
2210 stepOuter gst (GO_EMPTY_PAT st) = do
2211 res <- step (adaptState gst) st
2212 case res of
2213 Yield x s -> do
2214 acc <- initial
2215 acc' <- fstep acc x
2216 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
2217 Skip s -> return $ Skip (GO_EMPTY_PAT s)
2218 Stop -> return Stop
2220 stepOuter _ GO_DONE = return Stop
2222data SplitState s arr
2223 = SplitInitial s
2224 | SplitBuffering s arr
2225 | SplitSplitting s arr
2226 | SplitYielding arr (SplitState s arr)
2227 | SplitFinishing
2229-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
2230-- split using a splitBy like combinator. The Fold would consume upto the
2231-- separator and return any leftover which can then be fed to the next fold.
2233-- We can revisit this once we have partial folds/parsers.
2235-- | Performs infix separator style splitting.
2236{-# INLINE_NORMAL splitInnerBy #-}
2237splitInnerBy
2238 :: Monad m
2239 => (f a -> m (f a, Maybe (f a))) -- splitter
2240 -> (f a -> f a -> m (f a)) -- joiner
2241 -> Stream m (f a)
2242 -> Stream m (f a)
2243splitInnerBy splitter joiner (Stream step1 state1) =
2244 (Stream step (SplitInitial state1))
2246 where
2248 {-# INLINE_LATE step #-}
2249 step gst (SplitInitial st) = do
2250 r <- step1 gst st
2251 case r of
2252 Yield x s -> do
2253 (x1, mx2) <- splitter x
2254 return $ case mx2 of
2255 Nothing -> Skip (SplitBuffering s x1)
2256 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2257 Skip s -> return $ Skip (SplitInitial s)
2258 Stop -> return $ Stop
2260 step gst (SplitBuffering st buf) = do
2261 r <- step1 gst st
2262 case r of
2263 Yield x s -> do
2264 (x1, mx2) <- splitter x
2265 buf' <- joiner buf x1
2266 return $ case mx2 of
2267 Nothing -> Skip (SplitBuffering s buf')
2268 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2269 Skip s -> return $ Skip (SplitBuffering s buf)
2270 Stop -> return $ Skip (SplitYielding buf SplitFinishing)
2272 step _ (SplitSplitting st buf) = do
2273 (x1, mx2) <- splitter buf
2274 return $ case mx2 of
2275 Nothing -> Skip $ SplitBuffering st x1
2276 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2278 step _ (SplitYielding x next) = return $ Yield x next
2279 step _ SplitFinishing = return $ Stop
2281-- | Performs infix separator style splitting.
2282{-# INLINE_NORMAL splitInnerBySuffix #-}
2283splitInnerBySuffix
2284 :: (Monad m, Eq (f a), Monoid (f a))
2285 => (f a -> m (f a, Maybe (f a))) -- splitter
2286 -> (f a -> f a -> m (f a)) -- joiner
2287 -> Stream m (f a)
2288 -> Stream m (f a)
2289splitInnerBySuffix splitter joiner (Stream step1 state1) =
2290 (Stream step (SplitInitial state1))
2292 where
2294 {-# INLINE_LATE step #-}
2295 step gst (SplitInitial st) = do
2296 r <- step1 gst st
2297 case r of
2298 Yield x s -> do
2299 (x1, mx2) <- splitter x
2300 return $ case mx2 of
2301 Nothing -> Skip (SplitBuffering s x1)
2302 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2303 Skip s -> return $ Skip (SplitInitial s)
2304 Stop -> return $ Stop
2306 step gst (SplitBuffering st buf) = do
2307 r <- step1 gst st
2308 case r of
2309 Yield x s -> do
2310 (x1, mx2) <- splitter x
2311 buf' <- joiner buf x1
2312 return $ case mx2 of
2313 Nothing -> Skip (SplitBuffering s buf')
2314 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2315 Skip s -> return $ Skip (SplitBuffering s buf)
2316 Stop -> return $
2317 if buf == mempty
2318 then Stop
2319 else Skip (SplitYielding buf SplitFinishing)
2321 step _ (SplitSplitting st buf) = do
2322 (x1, mx2) <- splitter buf
2323 return $ case mx2 of
2324 Nothing -> Skip $ SplitBuffering st x1
2325 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2327 step _ (SplitYielding x next) = return $ Yield x next
2328 step _ SplitFinishing = return $ Stop
2330------------------------------------------------------------------------------
2331-- Substreams
2332------------------------------------------------------------------------------
2334{-# INLINE_NORMAL isPrefixOf #-}
2335isPrefixOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
2336isPrefixOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
2337 where
2338 go (sa, sb, Nothing) = do
2339 r <- stepa defState sa
2340 case r of
2341 Yield x sa' -> go (sa', sb, Just x)
2342 Skip sa' -> go (sa', sb, Nothing)
2343 Stop -> return True
2345 go (sa, sb, Just x) = do
2346 r <- stepb defState sb
2347 case r of
2348 Yield y sb' ->
2349 if x == y
2350 then go (sa, sb', Nothing)
2351 else return False
2352 Skip sb' -> go (sa, sb', Just x)
2353 Stop -> return False
2355{-# INLINE_NORMAL isSubsequenceOf #-}
2356isSubsequenceOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
2357isSubsequenceOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
2358 where
2359 go (sa, sb, Nothing) = do
2360 r <- stepa defState sa
2361 case r of
2362 Yield x sa' -> go (sa', sb, Just x)
2363 Skip sa' -> go (sa', sb, Nothing)
2364 Stop -> return True
2366 go (sa, sb, Just x) = do
2367 r <- stepb defState sb
2368 case r of
2369 Yield y sb' ->
2370 if x == y
2371 then go (sa, sb', Nothing)
2372 else go (sa, sb', Just x)
2373 Skip sb' -> go (sa, sb', Just x)
2374 Stop -> return False
2376{-# INLINE_NORMAL stripPrefix #-}
2377stripPrefix
2378 :: (Eq a, Monad m)
2379 => Stream m a -> Stream m a -> m (Maybe (Stream m a))
2380stripPrefix (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
2381 where
2382 go (sa, sb, Nothing) = do
2383 r <- stepa defState sa
2384 case r of
2385 Yield x sa' -> go (sa', sb, Just x)
2386 Skip sa' -> go (sa', sb, Nothing)
2387 Stop -> return $ Just (Stream stepb sb)
2389 go (sa, sb, Just x) = do
2390 r <- stepb defState sb
2391 case r of
2392 Yield y sb' ->
2393 if x == y
2394 then go (sa, sb', Nothing)
2395 else return Nothing
2396 Skip sb' -> go (sa, sb', Just x)
2397 Stop -> return Nothing
2399------------------------------------------------------------------------------
2400-- Map and Fold
2401------------------------------------------------------------------------------
2403-- | Execute a monadic action for each element of the 'Stream'
2404{-# INLINE_NORMAL mapM_ #-}
2405mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
2406mapM_ m = drain . mapM m
2408-------------------------------------------------------------------------------
2409-- Stream transformations using Unfolds
2410-------------------------------------------------------------------------------
2412-- Define a unique structure to use in inspection testing
2413data ConcatMapUState o i =
2414 ConcatMapUOuter o
2415 | ConcatMapUInner o i
2417-- | @concatMapU unfold stream@ uses @unfold@ to map the input stream elements
2418-- to streams and then flattens the generated streams into a single output
2419-- stream.
2421-- This is like 'concatMap' but uses an unfold with an explicit state to
2422-- generate the stream instead of a 'Stream' type generator. This allows better
2423-- optimization via fusion. This can be many times more efficient than
2424-- 'concatMap'.
2426{-# INLINE_NORMAL concatMapU #-}
2427concatMapU :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2428concatMapU (Unfold istep inject) (Stream ostep ost) =
2429 Stream step (ConcatMapUOuter ost)
2430 where
2431 {-# INLINE_LATE step #-}
2432 step gst (ConcatMapUOuter o) = do
2433 r <- ostep (adaptState gst) o
2434 case r of
2435 Yield a o' -> do
2436 i <- inject a
2437 i `seq` return (Skip (ConcatMapUInner o' i))
2438 Skip o' -> return $ Skip (ConcatMapUOuter o')
2439 Stop -> return $ Stop
2441 step _ (ConcatMapUInner o i) = do
2442 r <- istep i
2443 return $ case r of
2444 Yield x i' -> Yield x (ConcatMapUInner o i')
2445 Skip i' -> Skip (ConcatMapUInner o i')
2446 Stop -> Skip (ConcatMapUOuter o)
2448data ConcatUnfoldInterleaveState o i =
2449 ConcatUnfoldInterleaveOuter o [i]
2450 | ConcatUnfoldInterleaveInner o [i]
2451 | ConcatUnfoldInterleaveInnerL [i] [i]
2452 | ConcatUnfoldInterleaveInnerR [i] [i]
2454-- XXX use arrays to store state instead of lists.
2455-- XXX In general we can use different scheduling strategies e.g. how to
2456-- schedule the outer vs inner loop or assigning weights to different streams
2457-- or outer and inner loops.
2459-- After a yield, switch to the next stream. Do not switch streams on Skip.
2460-- Yield from outer stream switches to the inner stream.
2462-- There are two choices here, (1) exhaust the outer stream first and then
2463-- start yielding from the inner streams, this is much simpler to implement,
2464-- (2) yield at least one element from an inner stream before going back to
2465-- outer stream and opening the next stream from it.
2467-- Ideally, we need some scheduling bias to inner streams vs outer stream.
2468-- Maybe we can configure the behavior.
2470{-# INLINE_NORMAL concatUnfoldInterleave #-}
2471concatUnfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2472concatUnfoldInterleave (Unfold istep inject) (Stream ostep ost) =
2473 Stream step (ConcatUnfoldInterleaveOuter ost [])
2474 where
2475 {-# INLINE_LATE step #-}
2476 step gst (ConcatUnfoldInterleaveOuter o ls) = do
2477 r <- ostep (adaptState gst) o
2478 case r of
2479 Yield a o' -> do
2480 i <- inject a
2481 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
2482 Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
2483 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2485 step _ (ConcatUnfoldInterleaveInner _ []) = undefined
2486 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
2487 r <- istep st
2488 return $ case r of
2489 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
2490 Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
2491 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
2493 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
2494 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
2495 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
2497 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
2498 r <- istep st
2499 return $ case r of
2500 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
2501 Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
2502 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
2504 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
2505 step _ (ConcatUnfoldInterleaveInnerR ls []) =
2506 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2508 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
2509 r <- istep st
2510 return $ case r of
2511 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2512 Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
2513 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
2515-- XXX In general we can use different scheduling strategies e.g. how to
2516-- schedule the outer vs inner loop or assigning weights to different streams
2517-- or outer and inner loops.
2519-- This could be inefficient if the tasks are too small.
2521-- Compared to concatUnfoldInterleave this one switches streams on Skips.
2523{-# INLINE_NORMAL concatUnfoldRoundrobin #-}
2524concatUnfoldRoundrobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2525concatUnfoldRoundrobin (Unfold istep inject) (Stream ostep ost) =
2526 Stream step (ConcatUnfoldInterleaveOuter ost [])
2527 where
2528 {-# INLINE_LATE step #-}
2529 step gst (ConcatUnfoldInterleaveOuter o ls) = do
2530 r <- ostep (adaptState gst) o
2531 case r of
2532 Yield a o' -> do
2533 i <- inject a
2534 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
2535 Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
2536 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2538 step _ (ConcatUnfoldInterleaveInner o []) =
2539 return $ Skip (ConcatUnfoldInterleaveOuter o [])
2541 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
2542 r <- istep st
2543 return $ case r of
2544 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
2545 Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
2546 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
2548 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
2549 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
2550 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
2552 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
2553 r <- istep st
2554 return $ case r of
2555 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
2556 Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
2557 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
2559 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
2560 step _ (ConcatUnfoldInterleaveInnerR ls []) =
2561 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2563 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
2564 r <- istep st
2565 return $ case r of
2566 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2567 Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2568 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
2570data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
2572-- Note that this could be much faster compared to the CPS stream. However, as
2573-- the number of streams being composed increases this may become expensive.
2574-- Need to see where the breaking point is between the two.
2576{-# INLINE_NORMAL append #-}
2577append :: Monad m => Stream m a -> Stream m a -> Stream m a
2578append (Stream step1 state1) (Stream step2 state2) =
2579 Stream step (AppendFirst state1)
2581 where
2583 {-# INLINE_LATE step #-}
2584 step gst (AppendFirst st) = do
2585 r <- step1 gst st
2586 return $ case r of
2587 Yield a s -> Yield a (AppendFirst s)
2588 Skip s -> Skip (AppendFirst s)
2589 Stop -> Skip (AppendSecond state2)
2591 step gst (AppendSecond st) = do
2592 r <- step2 gst st
2593 return $ case r of
2594 Yield a s -> Yield a (AppendSecond s)
2595 Skip s -> Skip (AppendSecond s)
2596 Stop -> Stop
2598data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
2599 | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
2601{-# INLINE_NORMAL interleave #-}
2602interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
2603interleave (Stream step1 state1) (Stream step2 state2) =
2604 Stream step (InterleaveFirst state1 state2)
2606 where
2608 {-# INLINE_LATE step #-}
2609 step gst (InterleaveFirst st1 st2) = do
2610 r <- step1 gst st1
2611 return $ case r of
2612 Yield a s -> Yield a (InterleaveSecond s st2)
2613 Skip s -> Skip (InterleaveFirst s st2)
2614 Stop -> Skip (InterleaveSecondOnly st2)
2616 step gst (InterleaveSecond st1 st2) = do
2617 r <- step2 gst st2
2618 return $ case r of
2619 Yield a s -> Yield a (InterleaveFirst st1 s)
2620 Skip s -> Skip (InterleaveSecond st1 s)
2621 Stop -> Skip (InterleaveFirstOnly st1)
2623 step gst (InterleaveFirstOnly st1) = do
2624 r <- step1 gst st1
2625 return $ case r of
2626 Yield a s -> Yield a (InterleaveFirstOnly s)
2627 Skip s -> Skip (InterleaveFirstOnly s)
2628 Stop -> Stop
2630 step gst (InterleaveSecondOnly st2) = do
2631 r <- step2 gst st2
2632 return $ case r of
2633 Yield a s -> Yield a (InterleaveSecondOnly s)
2634 Skip s -> Skip (InterleaveSecondOnly s)
2635 Stop -> Stop
2637{-# INLINE_NORMAL interleaveMin #-}
2638interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
2639interleaveMin (Stream step1 state1) (Stream step2 state2) =
2640 Stream step (InterleaveFirst state1 state2)
2642 where
2644 {-# INLINE_LATE step #-}
2645 step gst (InterleaveFirst st1 st2) = do
2646 r <- step1 gst st1
2647 return $ case r of
2648 Yield a s -> Yield a (InterleaveSecond s st2)
2649 Skip s -> Skip (InterleaveFirst s st2)
2650 Stop -> Stop
2652 step gst (InterleaveSecond st1 st2) = do
2653 r <- step2 gst st2
2654 return $ case r of
2655 Yield a s -> Yield a (InterleaveFirst st1 s)
2656 Skip s -> Skip (InterleaveSecond st1 s)
2657 Stop -> Stop
2659 step _ (InterleaveFirstOnly _) = undefined
2660 step _ (InterleaveSecondOnly _) = undefined
2662{-# INLINE_NORMAL interleaveSuffix #-}
2663interleaveSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
2664interleaveSuffix (Stream step1 state1) (Stream step2 state2) =
2665 Stream step (InterleaveFirst state1 state2)
2667 where
2669 {-# INLINE_LATE step #-}
2670 step gst (InterleaveFirst st1 st2) = do
2671 r <- step1 gst st1
2672 return $ case r of
2673 Yield a s -> Yield a (InterleaveSecond s st2)
2674 Skip s -> Skip (InterleaveFirst s st2)
2675 Stop -> Stop
2677 step gst (InterleaveSecond st1 st2) = do
2678 r <- step2 gst st2
2679 return $ case r of
2680 Yield a s -> Yield a (InterleaveFirst st1 s)
2681 Skip s -> Skip (InterleaveSecond st1 s)
2682 Stop -> Skip (InterleaveFirstOnly st1)
2684 step gst (InterleaveFirstOnly st1) = do
2685 r <- step1 gst st1
2686 return $ case r of
2687 Yield a s -> Yield a (InterleaveFirstOnly s)
2688 Skip s -> Skip (InterleaveFirstOnly s)
2689 Stop -> Stop
2691 step _ (InterleaveSecondOnly _) = undefined
2693data InterleaveInfixState s1 s2 a
2694 = InterleaveInfixFirst s1 s2
2695 | InterleaveInfixSecondBuf s1 s2
2696 | InterleaveInfixSecondYield s1 s2 a
2697 | InterleaveInfixFirstYield s1 s2 a
2698 | InterleaveInfixFirstOnly s1
2700{-# INLINE_NORMAL interleaveInfix #-}
2701interleaveInfix :: Monad m => Stream m a -> Stream m a -> Stream m a
2702interleaveInfix (Stream step1 state1) (Stream step2 state2) =
2703 Stream step (InterleaveInfixFirst state1 state2)
2705 where
2707 {-# INLINE_LATE step #-}
2708 step gst (InterleaveInfixFirst st1 st2) = do
2709 r <- step1 gst st1
2710 return $ case r of
2711 Yield a s -> Yield a (InterleaveInfixSecondBuf s st2)
2712 Skip s -> Skip (InterleaveInfixFirst s st2)
2713 Stop -> Stop
2715 step gst (InterleaveInfixSecondBuf st1 st2) = do
2716 r <- step2 gst st2
2717 return $ case r of
2718 Yield a s -> Skip (InterleaveInfixSecondYield st1 s a)
2719 Skip s -> Skip (InterleaveInfixSecondBuf st1 s)
2720 Stop -> Skip (InterleaveInfixFirstOnly st1)
2722 step gst (InterleaveInfixSecondYield st1 st2 x) = do
2723 r <- step1 gst st1
2724 return $ case r of
2725 Yield a s -> Yield x (InterleaveInfixFirstYield s st2 a)
2726 Skip s -> Skip (InterleaveInfixSecondYield s st2 x)
2727 Stop -> Stop
2729 step _ (InterleaveInfixFirstYield st1 st2 x) = do
2730 return $ Yield x (InterleaveInfixSecondBuf st1 st2)
2732 step gst (InterleaveInfixFirstOnly st1) = do
2733 r <- step1 gst st1
2734 return $ case r of
2735 Yield a s -> Yield a (InterleaveInfixFirstOnly s)
2736 Skip s -> Skip (InterleaveInfixFirstOnly s)
2737 Stop -> Stop
2739{-# INLINE_NORMAL roundRobin #-}
2740roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
2741roundRobin (Stream step1 state1) (Stream step2 state2) =
2742 Stream step (InterleaveFirst state1 state2)
2744 where
2746 {-# INLINE_LATE step #-}
2747 step gst (InterleaveFirst st1 st2) = do
2748 r <- step1 gst st1
2749 return $ case r of
2750 Yield a s -> Yield a (InterleaveSecond s st2)
2751 Skip s -> Skip (InterleaveSecond s st2)
2752 Stop -> Skip (InterleaveSecondOnly st2)
2754 step gst (InterleaveSecond st1 st2) = do
2755 r <- step2 gst st2
2756 return $ case r of
2757 Yield a s -> Yield a (InterleaveFirst st1 s)
2758 Skip s -> Skip (InterleaveFirst st1 s)
2759 Stop -> Skip (InterleaveFirstOnly st1)
2761 step gst (InterleaveSecondOnly st2) = do
2762 r <- step2 gst st2
2763 return $ case r of
2764 Yield a s -> Yield a (InterleaveSecondOnly s)
2765 Skip s -> Skip (InterleaveSecondOnly s)
2766 Stop -> Stop
2768 step gst (InterleaveFirstOnly st1) = do
2769 r <- step1 gst st1
2770 return $ case r of
2771 Yield a s -> Yield a (InterleaveFirstOnly s)
2772 Skip s -> Skip (InterleaveFirstOnly s)
2773 Stop -> Stop
2775data ICUState s1 s2 i1 i2 =
2776 ICUFirst s1 s2
2777 | ICUSecond s1 s2
2778 | ICUSecondOnly s2
2779 | ICUFirstOnly s1
2780 | ICUFirstInner s1 s2 i1
2781 | ICUSecondInner s1 s2 i2
2782 | ICUFirstOnlyInner s1 i1
2783 | ICUSecondOnlyInner s2 i2
2785-- | Interleave streams (full streams, not the elements) unfolded from two
2786-- input streams and concat. Stop when the first stream stops. If the second
2787-- stream ends before the first one then first stream still keeps running alone
2788-- without any interleaving with the second stream.
2790-- [a1, a2, ... an] [b1, b2 ...]
2791-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
2792-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
2793-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
2795{-# INLINE_NORMAL gintercalateSuffix #-}
2796gintercalateSuffix
2797 :: Monad m
2798 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
2799gintercalateSuffix
2800 (Unfold istep1 inject1) (Stream step1 state1)
2801 (Unfold istep2 inject2) (Stream step2 state2) =
2802 Stream step (ICUFirst state1 state2)
2804 where
2806 {-# INLINE_LATE step #-}
2807 step gst (ICUFirst s1 s2) = do
2808 r <- step1 (adaptState gst) s1
2809 case r of
2810 Yield a s -> do
2811 i <- inject1 a
2812 i `seq` return (Skip (ICUFirstInner s s2 i))
2813 Skip s -> return $ Skip (ICUFirst s s2)
2814 Stop -> return Stop
2816 step gst (ICUFirstOnly s1) = do
2817 r <- step1 (adaptState gst) s1
2818 case r of
2819 Yield a s -> do
2820 i <- inject1 a
2821 i `seq` return (Skip (ICUFirstOnlyInner s i))
2822 Skip s -> return $ Skip (ICUFirstOnly s)
2823 Stop -> return Stop
2825 step _ (ICUFirstInner s1 s2 i1) = do
2826 r <- istep1 i1
2827 return $ case r of
2828 Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
2829 Skip i' -> Skip (ICUFirstInner s1 s2 i')
2830 Stop -> Skip (ICUSecond s1 s2)
2832 step _ (ICUFirstOnlyInner s1 i1) = do
2833 r <- istep1 i1
2834 return $ case r of
2835 Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
2836 Skip i' -> Skip (ICUFirstOnlyInner s1 i')
2837 Stop -> Skip (ICUFirstOnly s1)
2839 step gst (ICUSecond s1 s2) = do
2840 r <- step2 (adaptState gst) s2
2841 case r of
2842 Yield a s -> do
2843 i <- inject2 a
2844 i `seq` return (Skip (ICUSecondInner s1 s i))
2845 Skip s -> return $ Skip (ICUSecond s1 s)
2846 Stop -> return $ Skip (ICUFirstOnly s1)
2848 step _ (ICUSecondInner s1 s2 i2) = do
2849 r <- istep2 i2
2850 return $ case r of
2851 Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
2852 Skip i' -> Skip (ICUSecondInner s1 s2 i')
2853 Stop -> Skip (ICUFirst s1 s2)
2855 step _ (ICUSecondOnly _s2) = undefined
2856 step _ (ICUSecondOnlyInner _s2 _i2) = undefined
2858data InterposeSuffixState s1 i1 =
2859 InterposeSuffixFirst s1
2860 -- | InterposeSuffixFirstYield s1 i1
2861 | InterposeSuffixFirstInner s1 i1
2862 | InterposeSuffixSecond s1
2864-- Note that if an unfolded layer turns out to be nil we still emit the
2865-- separator effect. An alternate behavior could be to emit the separator
2866-- effect only if at least one element has been yielded by the unfolding.
2867-- However, that becomes a bit complicated, so we have chosen the former
2868-- behvaior for now.
2869{-# INLINE_NORMAL interposeSuffix #-}
2870interposeSuffix
2871 :: Monad m
2872 => m c -> Unfold m b c -> Stream m b -> Stream m c
2873interposeSuffix
2874 action
2875 (Unfold istep1 inject1) (Stream step1 state1) =
2876 Stream step (InterposeSuffixFirst state1)
2878 where
2880 {-# INLINE_LATE step #-}
2881 step gst (InterposeSuffixFirst s1) = do
2882 r <- step1 (adaptState gst) s1
2883 case r of
2884 Yield a s -> do
2885 i <- inject1 a
2886 i `seq` return (Skip (InterposeSuffixFirstInner s i))
2887 -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
2888 Skip s -> return $ Skip (InterposeSuffixFirst s)
2889 Stop -> return Stop
2891 {-
2892 step _ (InterposeSuffixFirstYield s1 i1) = do
2893 r <- istep1 i1
2894 return $ case r of
2895 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
2896 Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
2897 Stop -> Skip (InterposeSuffixFirst s1)
2898 -}
2900 step _ (InterposeSuffixFirstInner s1 i1) = do
2901 r <- istep1 i1
2902 return $ case r of
2903 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
2904 Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
2905 Stop -> Skip (InterposeSuffixSecond s1)
2907 step _ (InterposeSuffixSecond s1) = do
2908 r <- action
2909 return $ Yield r (InterposeSuffixFirst s1)
2911data ICALState s1 s2 i1 i2 a =
2912 ICALFirst s1 s2
2913 -- | ICALFirstYield s1 s2 i1
2914 | ICALFirstInner s1 s2 i1
2915 | ICALFirstOnly s1
2916 | ICALFirstOnlyInner s1 i1
2917 | ICALSecondInject s1 s2
2918 | ICALFirstInject s1 s2 i2
2919 -- | ICALFirstBuf s1 s2 i1 i2
2920 | ICALSecondInner s1 s2 i1 i2
2921 -- -- | ICALSecondInner s1 s2 i1 i2 a
2922 -- -- | ICALFirstResume s1 s2 i1 i2 a
2924-- | Interleave streams (full streams, not the elements) unfolded from two
2925-- input streams and concat. Stop when the first stream stops. If the second
2926-- stream ends before the first one then first stream still keeps running alone
2927-- without any interleaving with the second stream.
2929-- [a1, a2, ... an] [b1, b2 ...]
2930-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
2931-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
2932-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
2934{-# INLINE_NORMAL gintercalate #-}
2935gintercalate
2936 :: Monad m
2937 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
2938gintercalate
2939 (Unfold istep1 inject1) (Stream step1 state1)
2940 (Unfold istep2 inject2) (Stream step2 state2) =
2941 Stream step (ICALFirst state1 state2)
2943 where
2945 {-# INLINE_LATE step #-}
2946 step gst (ICALFirst s1 s2) = do
2947 r <- step1 (adaptState gst) s1
2948 case r of
2949 Yield a s -> do
2950 i <- inject1 a
2951 i `seq` return (Skip (ICALFirstInner s s2 i))
2952 -- i `seq` return (Skip (ICALFirstYield s s2 i))
2953 Skip s -> return $ Skip (ICALFirst s s2)
2954 Stop -> return Stop
2956 {-
2957 step _ (ICALFirstYield s1 s2 i1) = do
2958 r <- istep1 i1
2959 return $ case r of
2960 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
2961 Skip i' -> Skip (ICALFirstYield s1 s2 i')
2962 Stop -> Skip (ICALFirst s1 s2)
2963 -}
2965 step _ (ICALFirstInner s1 s2 i1) = do
2966 r <- istep1 i1
2967 return $ case r of
2968 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
2969 Skip i' -> Skip (ICALFirstInner s1 s2 i')
2970 Stop -> Skip (ICALSecondInject s1 s2)
2972 step gst (ICALFirstOnly s1) = do
2973 r <- step1 (adaptState gst) s1
2974 case r of
2975 Yield a s -> do
2976 i <- inject1 a
2977 i `seq` return (Skip (ICALFirstOnlyInner s i))
2978 Skip s -> return $ Skip (ICALFirstOnly s)
2979 Stop -> return Stop
2981 step _ (ICALFirstOnlyInner s1 i1) = do
2982 r <- istep1 i1
2983 return $ case r of
2984 Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
2985 Skip i' -> Skip (ICALFirstOnlyInner s1 i')
2986 Stop -> Skip (ICALFirstOnly s1)
2988 -- We inject the second stream even before checking if the first stream
2989 -- would yield any more elements. There is no clear choice whether we
2990 -- should do this before or after that. Doing it after may make the state
2991 -- machine a bit simpler though.
2992 step gst (ICALSecondInject s1 s2) = do
2993 r <- step2 (adaptState gst) s2
2994 case r of
2995 Yield a s -> do
2996 i <- inject2 a
2997 i `seq` return (Skip (ICALFirstInject s1 s i))
2998 Skip s -> return $ Skip (ICALSecondInject s1 s)
2999 Stop -> return $ Skip (ICALFirstOnly s1)
3001 step gst (ICALFirstInject s1 s2 i2) = do
3002 r <- step1 (adaptState gst) s1
3003 case r of
3004 Yield a s -> do
3005 i <- inject1 a
3006 i `seq` return (Skip (ICALSecondInner s s2 i i2))
3007 -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
3008 Skip s -> return $ Skip (ICALFirstInject s s2 i2)
3009 Stop -> return Stop
3011 {-
3012 step _ (ICALFirstBuf s1 s2 i1 i2) = do
3013 r <- istep1 i1
3014 return $ case r of
3015 Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
3016 Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
3017 Stop -> Stop
3019 step _ (ICALSecondInner s1 s2 i1 i2 v) = do
3020 r <- istep2 i2
3021 return $ case r of
3022 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
3023 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
3024 Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
3025 -}
3027 step _ (ICALSecondInner s1 s2 i1 i2) = do
3028 r <- istep2 i2
3029 return $ case r of
3030 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
3031 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
3032 Stop -> Skip (ICALFirstInner s1 s2 i1)
3033 -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
3035 {-
3036 step _ (ICALFirstResume s1 s2 i1 i2 x) = do
3037 return $ Yield x (ICALFirstInner s1 s2 i1 i2)
3038 -}
3040data InterposeState s1 i1 a =
3041 InterposeFirst s1
3042 -- | InterposeFirstYield s1 i1
3043 | InterposeFirstInner s1 i1
3044 | InterposeFirstInject s1
3045 -- | InterposeFirstBuf s1 i1
3046 | InterposeSecondYield s1 i1
3047 -- -- | InterposeSecondYield s1 i1 a
3048 -- -- | InterposeFirstResume s1 i1 a
3050-- Note that this only interposes the pure values, we may run many effects to
3051-- generate those values as some effects may not generate anything (Skip).
3052{-# INLINE_NORMAL interpose #-}
3053interpose :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
3054interpose
3055 action
3056 (Unfold istep1 inject1) (Stream step1 state1) =
3057 Stream step (InterposeFirst state1)
3059 where
3061 {-# INLINE_LATE step #-}
3062 step gst (InterposeFirst s1) = do
3063 r <- step1 (adaptState gst) s1
3064 case r of
3065 Yield a s -> do
3066 i <- inject1 a
3067 i `seq` return (Skip (InterposeFirstInner s i))
3068 -- i `seq` return (Skip (InterposeFirstYield s i))
3069 Skip s -> return $ Skip (InterposeFirst s)
3070 Stop -> return Stop
3072 {-
3073 step _ (InterposeFirstYield s1 i1) = do
3074 r <- istep1 i1
3075 return $ case r of
3076 Yield x i' -> Yield x (InterposeFirstInner s1 i')
3077 Skip i' -> Skip (InterposeFirstYield s1 i')
3078 Stop -> Skip (InterposeFirst s1)
3079 -}
3081 step _ (InterposeFirstInner s1 i1) = do
3082 r <- istep1 i1
3083 return $ case r of
3084 Yield x i' -> Yield x (InterposeFirstInner s1 i')
3085 Skip i' -> Skip (InterposeFirstInner s1 i')
3086 Stop -> Skip (InterposeFirstInject s1)
3088 step gst (InterposeFirstInject s1) = do
3089 r <- step1 (adaptState gst) s1
3090 case r of
3091 Yield a s -> do
3092 i <- inject1 a
3093 -- i `seq` return (Skip (InterposeFirstBuf s i))
3094 i `seq` return (Skip (InterposeSecondYield s i))
3095 Skip s -> return $ Skip (InterposeFirstInject s)
3096 Stop -> return Stop
3098 {-
3099 step _ (InterposeFirstBuf s1 i1) = do
3100 r <- istep1 i1
3101 return $ case r of
3102 Yield x i' -> Skip (InterposeSecondYield s1 i' x)
3103 Skip i' -> Skip (InterposeFirstBuf s1 i')
3104 Stop -> Stop
3105 -}
3107 {-
3108 step _ (InterposeSecondYield s1 i1 v) = do
3109 r <- action
3110 return $ Yield r (InterposeFirstResume s1 i1 v)
3111 -}
3112 step _ (InterposeSecondYield s1 i1) = do
3113 r <- action
3114 return $ Yield r (InterposeFirstInner s1 i1)
3116 {-
3117 step _ (InterposeFirstResume s1 i1 v) = do
3118 return $ Yield v (InterposeFirstInner s1 i1)
3119 -}
3121------------------------------------------------------------------------------
3122-- Exceptions
3123------------------------------------------------------------------------------
3125data GbracketState s1 s2 v
3126 = GBracketInit
3127 | GBracketNormal s1 v
3128 | GBracketException s2
3130-- | The most general bracketing and exception combinator. All other
3131-- combinators can be expressed in terms of this combinator. This can also be
3132-- used for cases which are not covered by the standard combinators.
3134-- /Internal/
3136{-# INLINE_NORMAL gbracket_ #-}
3137gbracket_
3138 :: Monad m
3139 => m c -- ^ before
3140 -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
3141 -> (c -> m d) -- ^ after, on normal stop
3142 -> (c -> e -> Stream m b -> Stream m b) -- ^ on exception
3143 -> (c -> Stream m b) -- ^ stream generator
3144 -> Stream m b
3145gbracket_ bef exc aft fexc fnormal =
3146 Stream step GBracketInit
3148 where
3150 {-# INLINE_LATE step #-}
3151 step _ GBracketInit = do
3152 r <- bef
3153 return $ Skip $ GBracketNormal (fnormal r) r
3155 step gst (GBracketNormal (UnStream step1 st) v) = do
3156 res <- exc $ step1 gst st
3157 case res of
3158 Right r -> case r of
3159 Yield x s ->
3160 return $ Yield x (GBracketNormal (Stream step1 s) v)
3161 Skip s -> return $ Skip (GBracketNormal (Stream step1 s) v)
3162 Stop -> aft v >> return Stop
3163 Left e ->
3164 return $ Skip (GBracketException (fexc v e (UnStream step1 st)))
3165 step gst (GBracketException (UnStream step1 st)) = do
3166 res <- step1 gst st
3167 case res of
3168 Yield x s -> return $ Yield x (GBracketException (Stream step1 s))
3169 Skip s -> return $ Skip (GBracketException (Stream step1 s))
3170 Stop -> return Stop
3172------------------------------------------------------------------------------
3173-- Finalizers
3174------------------------------------------------------------------------------
3176-- | Make a finalizer from a monadic action @m a@ that can run in IO monad.
3177mkIOFinalizer :: MonadBaseControl IO m => m b -> m (IO ())
3178mkIOFinalizer f = do
3179 mrun <- captureMonadState
3180 return $
3181 void $ do
3182 _ <- runInIO mrun f
3183 return ()
3185-- | Run an IO action stored in a finalized IORef.
3186runIORefFinalizerGC :: IORef (Maybe (IO ())) -> IO ()
3187runIORefFinalizerGC ref = do
3188 res <- readIORef ref
3189 case res of
3190 Nothing -> return ()
3191 Just f -> f
3193-- | Create an IORef holding a finalizer that is called automatically when
3194-- the IORef is garbage collected. The IORef can be written to with a 'Nothing'
3195-- value to deactivate the finalizer.
3197-- Note: The finalizer is always run with the state of the monad captured at
3198-- the time of calling newFinalizedIORef. To run it on garbage collection we
3199-- have no option but to take a snapshot of the monadic state at some point of
3200-- time. For normal case we could run it with the current state of the monad
3201-- but we want to keep both the cases consistent.
3203newFinalizedIORef :: (MonadIO m, MonadBaseControl IO m)
3204 => m a -> m (IORef (Maybe (IO ())))
3205newFinalizedIORef finalizer = do
3206 f <- mkIOFinalizer finalizer
3207 ref <- liftIO $ newIORef $ Just f
3208 _ <- liftIO $ mkWeakIORef ref (runIORefFinalizerGC ref)
3209 return ref
3211-- | Run the finalizer stored in an IORef and deactivate it so that it is run
3212-- only once. Note, the action runs with async exceptions masked.
3214runIORefFinalizer :: MonadIO m => IORef (Maybe (IO ())) -> m ()
3215runIORefFinalizer ref = liftIO $ do
3216 res <- readIORef ref
3217 case res of
3218 Nothing -> return ()
3219 Just action -> do
3220 -- if an async exception comes after writing 'Nothing' then the
3221 -- finalizing action will never be run. We need to do this
3222 -- atomically wrt async exceptions.
3223 mask_ $ do
3224 writeIORef ref Nothing
3225 action
3227-- | Run an action clearing the finalizer IORef atomically wrt async
3228-- exceptions. The action is run with async exceptions masked.
3229withIORefFinalizer :: MonadBaseControl IO m
3230 => IORef (Maybe (IO ())) -> m a -> m a
3231withIORefFinalizer ref action = do
3232 control $ \runinio ->
3233 mask_ $ do
3234 writeIORef ref Nothing
3235 runinio action
3237------------------------------------------------------------------------------
3239data GbracketIOState s1 s2 v wref
3240 = GBracketIOInit
3241 | GBracketIONormal s1 v wref
3242 | GBracketIOException s2
3244-- | The most general bracketing and exception combinator. All other
3245-- combinators can be expressed in terms of this combinator. This can also be
3246-- used for cases which are not covered by the standard combinators.
3248-- | It uses a finalizer to make sure we run the finalizing action
3249-- when the stream is garbage collected.
3251-- /Internal/
3253{-# INLINE_NORMAL gbracket #-}
3254gbracket
3255 :: (MonadIO m, MonadBaseControl IO m)
3256 => m c -- ^ before
3257 -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
3258 -> (c -> m d) -- ^ after, on normal stop or GC
3259 -> (c -> e -> Stream m b -> m (Stream m b)) -- ^ on exception
3260 -> (c -> Stream m b) -- ^ stream generator
3261 -> Stream m b
3262gbracket bef exc aft fexc fnormal =
3263 Stream step GBracketIOInit
3265 where
3267 -- If the stream is never evaluated the "aft" action will never be
3268 -- called. For that to occur we will need the user of this API to pass a
3269 -- weak pointer to us.
3270 {-# INLINE_LATE step #-}
3271 step _ GBracketIOInit = do
3272 -- We mask asynchronous exceptions to make the execution
3273 -- of 'bef' and the registration of 'aft' atomic.
3274 -- A similar thing is done in the resourcet package: https://git.io/JvKV3
3275 -- Tutorial: https://markkarpov.com/tutorial/exceptions.html
3276 (r, ref) <- liftBaseOp_ mask_ $ do
3277 r <- bef
3278 ref <- newFinalizedIORef (aft r)
3279 return (r, ref)
3280 return $ Skip $ GBracketIONormal (fnormal r) r ref
3282 step gst (GBracketIONormal (UnStream step1 st) v ref) = do
3283 res <- exc $ step1 gst st
3284 case res of
3285 Right r -> case r of
3286 Yield x s ->
3287 return $ Yield x (GBracketIONormal (Stream step1 s) v ref)
3288 Skip s ->
3289 return $ Skip (GBracketIONormal (Stream step1 s) v ref)
3290 Stop -> do
3291 runIORefFinalizer ref
3292 return Stop
3293 Left e -> do
3294 -- Clearing of finalizer and running of exception handler must
3295 -- be atomic wrt async exceptions. Otherwise if we have cleared
3296 -- the finalizer and have not run the exception handler then we
3297 -- may leak the resource.
3298 stream <- withIORefFinalizer ref (fexc v e (UnStream step1 st))
3299 return $ Skip (GBracketIOException stream)
3300 step gst (GBracketIOException (UnStream step1 st)) = do
3301 res <- step1 gst st
3302 case res of
3303 Yield x s ->
3304 return $ Yield x (GBracketIOException (Stream step1 s))
3305 Skip s -> return $ Skip (GBracketIOException (Stream step1 s))
3306 Stop -> return Stop
3308-- | Run a side effect before the stream yields its first element.
3309{-# INLINE_NORMAL before #-}
3310before :: Monad m => m b -> Stream m a -> Stream m a
3311before action (Stream step state) = Stream step' Nothing
3313 where
3315 {-# INLINE_LATE step' #-}
3316 step' _ Nothing = action >> return (Skip (Just state))
3318 step' gst (Just st) = do
3319 res <- step gst st
3320 case res of
3321 Yield x s -> return $ Yield x (Just s)
3322 Skip s -> return $ Skip (Just s)
3323 Stop -> return Stop
3325-- | Run a side effect whenever the stream stops normally.
3326{-# INLINE_NORMAL after_ #-}
3327after_ :: Monad m => m b -> Stream m a -> Stream m a
3328after_ action (Stream step state) = Stream step' state
3330 where
3332 {-# INLINE_LATE step' #-}
3333 step' gst st = do
3334 res <- step gst st
3335 case res of
3336 Yield x s -> return $ Yield x s
3337 Skip s -> return $ Skip s
3338 Stop -> action >> return Stop
3340{-# INLINE_NORMAL after #-}
3341after :: (MonadIO m, MonadBaseControl IO m)
3342 => m b -> Stream m a -> Stream m a
3343after action (Stream step state) = Stream step' Nothing
3345 where
3347 {-# INLINE_LATE step' #-}
3348 step' _ Nothing = do
3349 ref <- newFinalizedIORef action
3350 return $ Skip $ Just (state, ref)
3351 step' gst (Just (st, ref)) = do
3352 res <- step gst st
3353 case res of
3354 Yield x s -> return $ Yield x (Just (s, ref))
3355 Skip s -> return $ Skip (Just (s, ref))
3356 Stop -> do
3357 runIORefFinalizer ref
3358 return Stop
3360-- XXX These combinators are expensive due to the call to
3361-- onException/handle/try on each step. Therefore, when possible, they should
3362-- be called in an outer loop where we perform less iterations. For example, we
3363-- cannot call them on each iteration in a char stream, instead we can call
3364-- them when doing an IO on an array.
3366-- XXX For high performance error checks in busy streams we may need another
3367-- Error constructor in step.
3369-- | Run a side effect whenever the stream aborts due to an exception. The
3370-- exception is not caught, simply rethrown.
3371{-# INLINE_NORMAL onException #-}
3372onException :: MonadCatch m => m b -> Stream m a -> Stream m a
3373onException action str =
3374 gbracket_ (return ()) MC.try return
3375 (\_ (e :: MC.SomeException) _ -> nilM (action >> MC.throwM e))
3376 (\_ -> str)
3378{-# INLINE_NORMAL _onException #-}
3379_onException :: MonadCatch m => m b -> Stream m a -> Stream m a
3380_onException action (Stream step state) = Stream step' state
3382 where
3384 {-# INLINE_LATE step' #-}
3385 step' gst st = do
3386 res <- step gst st `MC.onException` action
3387 case res of
3388 Yield x s -> return $ Yield x s
3389 Skip s -> return $ Skip s
3390 Stop -> return Stop
3392-- XXX bracket is like concatMap, it generates a stream and then flattens it.
3393-- Like concatMap it has 10x worse performance compared to linear fused
3394-- compositions.
3396-- | Run the first action before the stream starts and remember its output,
3397-- generate a stream using the output, run the second action providing the
3398-- remembered value as an argument whenever the stream ends normally or due to
3399-- an exception.
3400{-# INLINE_NORMAL bracket_ #-}
3401bracket_ :: MonadCatch m => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
3402bracket_ bef aft bet =
3403 gbracket_ bef MC.try aft
3404 (\a (e :: SomeException) _ -> nilM (aft a >> MC.throwM e)) bet
3406-- | Run the first action before the stream starts and remember its output,
3407-- generate a stream using the output, run the second action providing the
3408-- remembered value as an argument whenever the stream ends normally or due to
3409-- an exception or gets garbage collected.
3411{-# INLINE_NORMAL bracket #-}
3412bracket :: (MonadAsync m, MonadCatch m)
3413 => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
3414bracket bef aft bet =
3415 gbracket bef MC.try aft
3416 (\a (e :: SomeException) _ -> aft a >> return (nilM (MC.throwM e))) bet
3418data BracketState s v = BracketInit | BracketRun s v
3420{-# INLINE_NORMAL _bracket #-}
3421_bracket :: MonadCatch m => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
3422_bracket bef aft bet = Stream step' BracketInit
3424 where
3426 {-# INLINE_LATE step' #-}
3427 step' _ BracketInit = bef >>= \x -> return (Skip (BracketRun (bet x) x))
3429 -- NOTE: It is important to use UnStream instead of the Stream pattern
3430 -- here, otherwise we get huge perf degradation, see note in concatMap.
3431 step' gst (BracketRun (UnStream step state) v) = do
3432 -- res <- step gst state `MC.onException` aft v
3433 res <- MC.try $ step gst state
3434 case res of
3435 Left (e :: SomeException) -> aft v >> MC.throwM e >> return Stop
3436 Right r -> case r of
3437 Yield x s -> return $ Yield x (BracketRun (Stream step s) v)
3438 Skip s -> return $ Skip (BracketRun (Stream step s) v)
3439 Stop -> aft v >> return Stop
3441-- | Run a side effect whenever the stream stops normally or aborts due to an
3442-- exception.
3443{-# INLINE finally_ #-}
3444finally_ :: MonadCatch m => m b -> Stream m a -> Stream m a
3445-- finally action xs = after action $ onException action xs
3446finally_ action xs = bracket_ (return ()) (\_ -> action) (const xs)
3448-- | Run a side effect whenever the stream stops normally or aborts due to an
3449-- exception or gets garbage collected.
3451{-# INLINE finally #-}
3452finally :: (MonadAsync m, MonadCatch m) => m b -> Stream m a -> Stream m a
3453finally action xs = bracket (return ()) (\_ -> action) (const xs)
3455-- | When evaluating a stream if an exception occurs, stream
3456-- evaluation aborts and the specified exception handler is run with
3457-- the exception and the Stream which threw the exception as argument.
3459{-# INLINE_NORMAL ghandle #-}
3460ghandle :: (MonadCatch m, Exception e)
3461 => (e -> Stream m a -> Stream m a) -> Stream m a -> Stream m a
3462ghandle f str =
3463 gbracket_ (return ()) MC.try return (\_ -> f) (\_ -> str)
3465-- | When evaluating a stream if an exception occurs, stream evaluation aborts
3466-- and the specified exception handler is run with the exception as argument.
3467{-# INLINE_NORMAL handle #-}
3468handle :: (MonadCatch m, Exception e)
3469 => (e -> Stream m a) -> Stream m a -> Stream m a
3470handle f str =
3471 gbracket_ (return ()) MC.try return (\_ e _ -> f e) (\_ -> str)
3473{-# INLINE_NORMAL _handle #-}
3474_handle :: (MonadCatch m, Exception e)
3475 => (e -> Stream m a) -> Stream m a -> Stream m a
3476_handle f (Stream step state) = Stream step' (Left state)
3478 where
3480 {-# INLINE_LATE step' #-}
3481 step' gst (Left st) = do
3482 res <- MC.try $ step gst st
3483 case res of
3484 Left e -> return $ Skip $ Right (f e)
3485 Right r -> case r of
3486 Yield x s -> return $ Yield x (Left s)
3487 Skip s -> return $ Skip (Left s)
3488 Stop -> return Stop
3490 step' gst (Right (UnStream step1 st)) = do
3491 res <- step1 gst st
3492 case res of
3493 Yield x s -> return $ Yield x (Right (Stream step1 s))
3494 Skip s -> return $ Skip (Right (Stream step1 s))
3495 Stop -> return Stop
3497-------------------------------------------------------------------------------
3498-- General transformation
3499-------------------------------------------------------------------------------
3501{-# INLINE_NORMAL transform #-}
3502transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
3503transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
3504 Stream step' (Consume pstate, state)
3506 where
3508 {-# INLINE_LATE step' #-}
3510 step' gst (Consume pst, st) = pst `seq` do
3511 r <- step (adaptState gst) st
3512 case r of
3513 Yield x s -> do
3514 res <- pstep1 pst x
3515 case res of
3516 Pipe.Yield b pst' -> return $ Yield b (pst', s)
3517 Pipe.Continue pst' -> return $ Skip (pst', s)
3518 Skip s -> return $ Skip (Consume pst, s)
3519 Stop -> return Stop
3521 step' _ (Produce pst, st) = pst `seq` do
3522 res <- pstep2 pst
3523 case res of
3524 Pipe.Yield b pst' -> return $ Yield b (pst', st)
3525 Pipe.Continue pst' -> return $ Skip (pst', st)
3527------------------------------------------------------------------------------
3528-- Transformation by Folding (Scans)
3529------------------------------------------------------------------------------
3531------------------------------------------------------------------------------
3532-- Prescans
3533------------------------------------------------------------------------------
3535-- XXX Is a prescan useful, discarding the last step does not sound useful? I
3536-- am not sure about the utility of this function, so this is implemented but
3537-- not exposed. We can expose it if someone provides good reasons why this is
3538-- useful.
3540-- XXX We have to execute the stream one step ahead to know that we are at the
3541-- last step. The vector implementation of prescan executes the last fold step
3542-- but does not yield the result. This means we have executed the effect but
3543-- discarded value. This does not sound right. In this implementation we are
3544-- not executing the last fold step.
3545{-# INLINE_NORMAL prescanlM' #-}
3546prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
3547prescanlM' f mz (Stream step state) = Stream step' (state, mz)
3548 where
3549 {-# INLINE_LATE step' #-}
3550 step' gst (st, prev) = do
3551 r <- step (adaptState gst) st
3552 case r of
3553 Yield x s -> do
3554 acc <- prev
3555 return $ Yield acc (s, f acc x)
3556 Skip s -> return $ Skip (s, prev)
3557 Stop -> return Stop
3559{-# INLINE prescanl' #-}
3560prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3561prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
3563------------------------------------------------------------------------------
3564-- Monolithic postscans (postscan followed by a map)
3565------------------------------------------------------------------------------
3567-- The performance of a modular postscan followed by a map seems to be
3568-- equivalent to this monolithic scan followed by map therefore we may not need
3569-- this implementation. We just have it for performance comparison and in case
3570-- modular version does not perform well in some situation.
3572{-# INLINE_NORMAL postscanlMx' #-}
3573postscanlMx' :: Monad m
3574 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
3575postscanlMx' fstep begin done (Stream step state) = do
3576 Stream step' (state, begin)
3577 where
3578 {-# INLINE_LATE step' #-}
3579 step' gst (st, acc) = do
3580 r <- step (adaptState gst) st
3581 case r of
3582 Yield x s -> do
3583 old <- acc
3584 y <- fstep old x
3585 v <- done y
3586 v `seq` y `seq` return (Yield v (s, return y))
3587 Skip s -> return $ Skip (s, acc)
3588 Stop -> return Stop
3590{-# INLINE_NORMAL postscanlx' #-}
3591postscanlx' :: Monad m
3592 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
3593postscanlx' fstep begin done s =
3594 postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
3596-- XXX do we need consM strict to evaluate the begin value?
3597{-# INLINE scanlMx' #-}
3598scanlMx' :: Monad m
3599 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
3600scanlMx' fstep begin done s =
3601 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
3603{-# INLINE scanlx' #-}
3604scanlx' :: Monad m
3605 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
3606scanlx' fstep begin done s =
3607 scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
3609------------------------------------------------------------------------------
3610-- postscans
3611------------------------------------------------------------------------------
3613{-# INLINE_NORMAL postscanlM' #-}
3614postscanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3615postscanlM' fstep begin (Stream step state) =
3616 begin `seq` Stream step' (state, begin)
3617 where
3618 {-# INLINE_LATE step' #-}
3619 step' gst (st, acc) = acc `seq` do
3620 r <- step (adaptState gst) st
3621 case r of
3622 Yield x s -> do
3623 y <- fstep acc x
3624 y `seq` return (Yield y (s, y))
3625 Skip s -> return $ Skip (s, acc)
3626 Stop -> return Stop
3628{-# INLINE_NORMAL postscanl' #-}
3629postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
3630postscanl' f = postscanlM' (\a b -> return (f a b))
3632-- We can possibly have the "done" function as a Maybe to provide an option to
3633-- emit or not emit the accumulator when the stream stops.
3635-- TBD: use a single Yield point
3637{-# INLINE_NORMAL postscanlMAfter' #-}
3638postscanlMAfter' :: Monad m
3639 => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
3640postscanlMAfter' fstep initial done (Stream step1 state1) = do
3641 Stream step (Just (state1, initial))
3643 where
3645 {-# INLINE_LATE step #-}
3646 step gst (Just (st, acc)) = do
3647 r <- step1 (adaptState gst) st
3648 case r of
3649 Yield x s -> do
3650 old <- acc
3651 y <- fstep old x
3652 y `seq` return (Yield y (Just (s, return y)))
3653 Skip s -> return $ Skip $ Just (s, acc)
3654 Stop -> acc >>= done >>= \res -> return (Yield res Nothing)
3655 step _ Nothing = return Stop
3657{-# INLINE_NORMAL postscanlM #-}
3658postscanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3659postscanlM fstep begin (Stream step state) = Stream step' (state, begin)
3660 where
3661 {-# INLINE_LATE step' #-}
3662 step' gst (st, acc) = do
3663 r <- step (adaptState gst) st
3664 case r of
3665 Yield x s -> do
3666 y <- fstep acc x
3667 return (Yield y (s, y))
3668 Skip s -> return $ Skip (s, acc)
3669 Stop -> return Stop
3671{-# INLINE_NORMAL postscanl #-}
3672postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
3673postscanl f = postscanlM (\a b -> return (f a b))
3675{-# INLINE_NORMAL scanlM' #-}
3676scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3677scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
3679{-# INLINE scanlMAfter' #-}
3680scanlMAfter' :: Monad m
3681 => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
3682scanlMAfter' fstep initial done s =
3683 (initial >>= \x -> x `seq` return x) `consM`
3684 postscanlMAfter' fstep initial done s
3686{-# INLINE scanl' #-}
3687scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3688scanl' f = scanlM' (\a b -> return (f a b))
3690{-# INLINE_NORMAL scanlM #-}
3691scanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3692scanlM fstep begin s = begin `cons` postscanlM fstep begin s
3694{-# INLINE scanl #-}
3695scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3696scanl f = scanlM (\a b -> return (f a b))
3698{-# INLINE_NORMAL scanl1M #-}
3699scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
3700scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
3701 where
3702 {-# INLINE_LATE step' #-}
3703 step' gst (st, Nothing) = do
3704 r <- step gst st
3705 case r of
3706 Yield x s -> return $ Yield x (s, Just x)
3707 Skip s -> return $ Skip (s, Nothing)
3708 Stop -> return Stop
3710 step' gst (st, Just acc) = do
3711 r <- step gst st
3712 case r of
3713 Yield y s -> do
3714 z <- fstep acc y
3715 return $ Yield z (s, Just z)
3716 Skip s -> return $ Skip (s, Just acc)
3717 Stop -> return Stop
3719{-# INLINE scanl1 #-}
3720scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
3721scanl1 f = scanl1M (\x y -> return (f x y))
3723{-# INLINE_NORMAL scanl1M' #-}
3724scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
3725scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
3726 where
3727 {-# INLINE_LATE step' #-}
3728 step' gst (st, Nothing) = do
3729 r <- step gst st
3730 case r of
3731 Yield x s -> x `seq` return $ Yield x (s, Just x)
3732 Skip s -> return $ Skip (s, Nothing)
3733 Stop -> return Stop
3735 step' gst (st, Just acc) = acc `seq` do
3736 r <- step gst st
3737 case r of
3738 Yield y s -> do
3739 z <- fstep acc y
3740 z `seq` return $ Yield z (s, Just z)
3741 Skip s -> return $ Skip (s, Just acc)
3742 Stop -> return Stop
3744{-# INLINE scanl1' #-}
3745scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
3746scanl1' f = scanl1M' (\x y -> return (f x y))
3748------------------------------------------------------------------------------
3749-- Stateful map/scan
3750------------------------------------------------------------------------------
3752data RollingMapState s a = RollingMapInit s | RollingMapGo s a
3754{-# INLINE rollingMapM #-}
3755rollingMapM :: Monad m => (a -> a -> m b) -> Stream m a -> Stream m b
3756rollingMapM f (Stream step1 state1) = Stream step (RollingMapInit state1)
3757 where
3758 step gst (RollingMapInit st) = do
3759 r <- step1 (adaptState gst) st
3760 return $ case r of
3761 Yield x s -> Skip $ RollingMapGo s x
3762 Skip s -> Skip $ RollingMapInit s
3763 Stop -> Stop
3765 step gst (RollingMapGo s1 x1) = do
3766 r <- step1 (adaptState gst) s1
3767 case r of
3768 Yield x s -> do
3769 !res <- f x x1
3770 return $ Yield res $ RollingMapGo s x
3771 Skip s -> return $ Skip $ RollingMapGo s x1
3772 Stop -> return $ Stop
3774{-# INLINE rollingMap #-}
3775rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
3776rollingMap f = rollingMapM (\x y -> return $ f x y)
3778------------------------------------------------------------------------------
3779-- Tapping/Distributing
3780------------------------------------------------------------------------------
3782{-# INLINE tap #-}
3783tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
3784tap (Fold fstep initial extract) (Stream step state) = Stream step' Nothing
3786 where
3788 step' _ Nothing = do
3789 r <- initial
3790 return $ Skip (Just (r, state))
3792 step' gst (Just (acc, st)) = acc `seq` do
3793 r <- step gst st
3794 case r of
3795 Yield x s -> do
3796 acc' <- fstep acc x
3797 return $ Yield x (Just (acc', s))
3798 Skip s -> return $ Skip (Just (acc, s))
3799 Stop -> do
3800 void $ extract acc
3801 return $ Stop
3803{-# INLINE_NORMAL tapOffsetEvery #-}
3804tapOffsetEvery :: Monad m
3805 => Int -> Int -> Fold m a b -> Stream m a -> Stream m a
3806tapOffsetEvery offset n (Fold fstep initial extract) (Stream step state) =
3807 Stream step' Nothing
3809 where
3811 {-# INLINE_LATE step' #-}
3812 step' _ Nothing = do
3813 r <- initial
3814 return $ Skip (Just (r, state, offset `mod` n))
3816 step' gst (Just (acc, st, count)) | count <= 0 = do
3817 r <- step gst st
3818 case r of
3819 Yield x s -> do
3820 !acc' <- fstep acc x
3821 return $ Yield x (Just (acc', s, n - 1))
3822 Skip s -> return $ Skip (Just (acc, s, count))
3823 Stop -> do
3824 void $ extract acc
3825 return $ Stop
3827 step' gst (Just (acc, st, count)) = do
3828 r <- step gst st
3829 case r of
3830 Yield x s -> return $ Yield x (Just (acc, s, count - 1))
3831 Skip s -> return $ Skip (Just (acc, s, count))
3832 Stop -> do
3833 void $ extract acc
3834 return $ Stop
3836{-# INLINE_NORMAL pollCounts #-}
3837pollCounts
3838 :: MonadAsync m
3839 => (a -> Bool)
3840 -> (Stream m Int -> Stream m Int)
3841 -> Fold m Int b
3842 -> Stream m a
3843 -> Stream m a
3844pollCounts predicate transf fld (Stream step state) = Stream step' Nothing
3845 where
3847 {-# INLINE_LATE step' #-}
3848 step' _ Nothing = do
3849 -- As long as we are using an "Int" for counts lockfree reads from
3850 -- Var should work correctly on both 32-bit and 64-bit machines.
3851 -- However, an Int on a 32-bit machine may overflow quickly.
3852 countVar <- liftIO $ Prim.newIORef (0 :: Int)
3853 tid <- forkManaged
3854 $ void $ runFold fld
3855 $ transf $ fromPrimIORef countVar
3856 return $ Skip (Just (countVar, tid, state))
3858 step' gst (Just (countVar, tid, st)) = do
3859 r <- step gst st
3860 case r of
3861 Yield x s -> do
3862 when (predicate x) $ liftIO $ Prim.modifyIORef' countVar (+ 1)
3863 return $ Yield x (Just (countVar, tid, s))
3864 Skip s -> return $ Skip (Just (countVar, tid, s))
3865 Stop -> do
3866 liftIO $ killThread tid
3867 return Stop
3869{-# INLINE_NORMAL tapRate #-}
3870tapRate ::
3871 (MonadAsync m, MonadCatch m)
3872 => Double
3873 -> (Int -> m b)
3874 -> Stream m a
3875 -> Stream m a
3876tapRate samplingRate action (Stream step state) = Stream step' Nothing
3877 where
3878 {-# NOINLINE loop #-}
3879 loop countVar prev = do
3880 i <-
3881 MC.catch
3882 (do liftIO $ threadDelay (round $ samplingRate * 1000000)
3883 i <- liftIO $ Prim.readIORef countVar
3884 let !diff = i - prev
3885 void $ action diff
3886 return i)
3887 (\(e :: AsyncException) -> do
3888 i <- liftIO $ Prim.readIORef countVar
3889 let !diff = i - prev
3890 void $ action diff
3891 throwM (MC.toException e))
3892 loop countVar i
3894 {-# INLINE_LATE step' #-}
3895 step' _ Nothing = do
3896 countVar <- liftIO $ Prim.newIORef 0
3897 tid <- fork $ loop countVar 0
3898 ref <- liftIO $ newIORef ()
3899 _ <- liftIO $ mkWeakIORef ref (killThread tid)
3900 return $ Skip (Just (countVar, tid, state, ref))
3902 step' gst (Just (countVar, tid, st, ref)) = do
3903 r <- step gst st
3904 case r of
3905 Yield x s -> do
3906 liftIO $ Prim.modifyIORef' countVar (+ 1)
3907 return $ Yield x (Just (countVar, tid, s, ref))
3908 Skip s -> return $ Skip (Just (countVar, tid, s, ref))
3909 Stop -> do
3910 liftIO $ killThread tid
3911 return Stop
3914-------------------------------------------------------------------------------
3915-- Filtering
3916-------------------------------------------------------------------------------
3918{-# INLINE_NORMAL takeWhileM #-}
3919takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
3920takeWhileM f (Stream step state) = Stream step' state
3921 where
3922 {-# INLINE_LATE step' #-}
3923 step' gst st = do
3924 r <- step gst st
3925 case r of
3926 Yield x s -> do
3927 b <- f x
3928 return $ if b then Yield x s else Stop
3929 Skip s -> return $ Skip s
3930 Stop -> return Stop
3932{-# INLINE takeWhile #-}
3933takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
3934takeWhile f = takeWhileM (return . f)
3936{-# INLINE_NORMAL drop #-}
3937drop :: Monad m => Int -> Stream m a -> Stream m a
3938drop n (Stream step state) = Stream step' (state, Just n)
3939 where
3940 {-# INLINE_LATE step' #-}
3941 step' gst (st, Just i)
3942 | i > 0 = do
3943 r <- step gst st
3944 return $
3945 case r of
3946 Yield _ s -> Skip (s, Just (i - 1))
3947 Skip s -> Skip (s, Just i)
3948 Stop -> Stop
3949 | otherwise = return $ Skip (st, Nothing)
3951 step' gst (st, Nothing) = do
3952 r <- step gst st
3953 return $
3954 case r of
3955 Yield x s -> Yield x (s, Nothing)
3956 Skip s -> Skip (s, Nothing)
3957 Stop -> Stop
3959data DropWhileState s a
3960 = DropWhileDrop s
3961 | DropWhileYield a s
3962 | DropWhileNext s
3964{-# INLINE_NORMAL dropWhileM #-}
3965dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
3966dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
3967 where
3968 {-# INLINE_LATE step' #-}
3969 step' gst (DropWhileDrop st) = do
3970 r <- step gst st
3971 case r of
3972 Yield x s -> do
3973 b <- f x
3974 if b
3975 then return $ Skip (DropWhileDrop s)
3976 else return $ Skip (DropWhileYield x s)
3977 Skip s -> return $ Skip (DropWhileDrop s)
3978 Stop -> return Stop
3980 step' gst (DropWhileNext st) = do
3981 r <- step gst st
3982 case r of
3983 Yield x s -> return $ Skip (DropWhileYield x s)
3984 Skip s -> return $ Skip (DropWhileNext s)
3985 Stop -> return Stop
3987 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
3989{-# INLINE dropWhile #-}
3990dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
3991dropWhile f = dropWhileM (return . f)
3993{-# INLINE_NORMAL filterM #-}
3994filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
3995filterM f (Stream step state) = Stream step' state
3996 where
3997 {-# INLINE_LATE step' #-}
3998 step' gst st = do
3999 r <- step gst st
4000 case r of
4001 Yield x s -> do
4002 b <- f x
4003 return $ if b
4004 then Yield x s
4005 else Skip s
4006 Skip s -> return $ Skip s
4007 Stop -> return Stop
4009{-# INLINE filter #-}
4010filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
4011filter f = filterM (return . f)
4013{-# INLINE_NORMAL uniq #-}
4014uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
4015uniq (Stream step state) = Stream step' (Nothing, state)
4016 where
4017 {-# INLINE_LATE step' #-}
4018 step' gst (Nothing, st) = do
4019 r <- step gst st
4020 case r of
4021 Yield x s -> return $ Yield x (Just x, s)
4022 Skip s -> return $ Skip (Nothing, s)
4023 Stop -> return Stop
4024 step' gst (Just x, st) = do
4025 r <- step gst st
4026 case r of
4027 Yield y s | x == y -> return $ Skip (Just x, s)
4028 | otherwise -> return $ Yield y (Just y, s)
4029 Skip s -> return $ Skip (Just x, s)
4030 Stop -> return Stop
4032------------------------------------------------------------------------------
4033-- Transformation by Mapping
4034------------------------------------------------------------------------------
4036{-# INLINE_NORMAL sequence #-}
4037sequence :: Monad m => Stream m (m a) -> Stream m a
4038sequence (Stream step state) = Stream step' state
4039 where
4040 {-# INLINE_LATE step' #-}
4041 step' gst st = do
4042 r <- step (adaptState gst) st
4043 case r of
4044 Yield x s -> x >>= \a -> return (Yield a s)
4045 Skip s -> return $ Skip s
4046 Stop -> return Stop
4048------------------------------------------------------------------------------
4049-- Inserting
4050------------------------------------------------------------------------------
4052data LoopState x s = FirstYield s
4053 | InterspersingYield s
4054 | YieldAndCarry x s
4056{-# INLINE_NORMAL intersperseM #-}
4057intersperseM :: Monad m => m a -> Stream m a -> Stream m a
4058intersperseM m (Stream step state) = Stream step' (FirstYield state)
4059 where
4060 {-# INLINE_LATE step' #-}
4061 step' gst (FirstYield st) = do
4062 r <- step gst st
4063 return $
4064 case r of
4065 Yield x s -> Skip (YieldAndCarry x s)
4066 Skip s -> Skip (FirstYield s)
4067 Stop -> Stop
4069 step' gst (InterspersingYield st) = do
4070 r <- step gst st
4071 case r of
4072 Yield x s -> do
4073 a <- m
4074 return $ Yield a (YieldAndCarry x s)
4075 Skip s -> return $ Skip $ InterspersingYield s
4076 Stop -> return Stop
4078 step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
4080{-# INLINE_NORMAL intersperseM_ #-}
4081intersperseM_ :: Monad m => m b -> Stream m a -> Stream m a
4082intersperseM_ m (Stream step1 state1) = Stream step (Left (pure (), state1))
4083 where
4084 {-# INLINE_LATE step #-}
4085 step gst (Left (eff, st)) = do
4086 r <- step1 gst st
4087 case r of
4088 Yield x s -> eff >> return (Yield x (Right s))
4089 Skip s -> return $ Skip (Left (eff, s))
4090 Stop -> return Stop
4092 step _ (Right st) = return $ Skip $ Left (void m, st)
4094data SuffixState s a
4095 = SuffixElem s
4096 | SuffixSuffix s
4097 | SuffixYield a (SuffixState s a)
4099{-# INLINE_NORMAL intersperseSuffix #-}
4100intersperseSuffix :: forall m a. Monad m => m a -> Stream m a -> Stream m a
4101intersperseSuffix action (Stream step state) = Stream step' (SuffixElem state)
4102 where
4103 {-# INLINE_LATE step' #-}
4104 step' gst (SuffixElem st) = do
4105 r <- step gst st
4106 return $ case r of
4107 Yield x s -> Skip (SuffixYield x (SuffixSuffix s))
4108 Skip s -> Skip (SuffixElem s)
4109 Stop -> Stop
4111 step' _ (SuffixSuffix st) = do
4112 action >>= \r -> return $ Skip (SuffixYield r (SuffixElem st))
4114 step' _ (SuffixYield x next) = return $ Yield x next
4116{-# INLINE_NORMAL intersperseSuffix_ #-}
4117intersperseSuffix_ :: Monad m => m b -> Stream m a -> Stream m a
4118intersperseSuffix_ m (Stream step1 state1) = Stream step (Left state1)
4119 where
4120 {-# INLINE_LATE step #-}
4121 step gst (Left st) = do
4122 r <- step1 gst st
4123 case r of
4124 Yield x s -> return $ Yield x (Right s)
4125 Skip s -> return $ Skip $ Left s
4126 Stop -> return Stop
4128 step _ (Right st) = m >> return (Skip (Left st))
4130data SuffixSpanState s a
4131 = SuffixSpanElem s Int
4132 | SuffixSpanSuffix s
4133 | SuffixSpanYield a (SuffixSpanState s a)
4134 | SuffixSpanLast
4135 | SuffixSpanStop
4137-- | intersperse after every n items
4138{-# INLINE_NORMAL intersperseSuffixBySpan #-}
4139intersperseSuffixBySpan :: forall m a. Monad m
4140 => Int -> m a -> Stream m a -> Stream m a
4141intersperseSuffixBySpan n action (Stream step state) =
4142 Stream step' (SuffixSpanElem state n)
4143 where
4144 {-# INLINE_LATE step' #-}
4145 step' gst (SuffixSpanElem st i) | i > 0 = do
4146 r <- step gst st
4147 return $ case r of
4148 Yield x s -> Skip (SuffixSpanYield x (SuffixSpanElem s (i - 1)))
4149 Skip s -> Skip (SuffixSpanElem s i)
4150 Stop -> if i == n then Stop else Skip SuffixSpanLast
4151 step' _ (SuffixSpanElem st _) = return $ Skip (SuffixSpanSuffix st)
4153 step' _ (SuffixSpanSuffix st) = do
4154 action >>= \r -> return $ Skip (SuffixSpanYield r (SuffixSpanElem st n))
4156 step' _ (SuffixSpanLast) = do
4157 action >>= \r -> return $ Skip (SuffixSpanYield r SuffixSpanStop)
4159 step' _ (SuffixSpanYield x next) = return $ Yield x next
4161 step' _ (SuffixSpanStop) = return Stop
4163{-# INLINE intersperse #-}
4164intersperse :: Monad m => a -> Stream m a -> Stream m a
4165intersperse a = intersperseM (return a)
4167{-# INLINE_NORMAL insertBy #-}
4168insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
4169insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
4170 where
4171 {-# INLINE_LATE step' #-}
4172 step' gst (st, False, _) = do
4173 r <- step gst st
4174 case r of
4175 Yield x s -> case cmp a x of
4176 GT -> return $ Yield x (s, False, Nothing)
4177 _ -> return $ Yield a (s, True, Just x)
4178 Skip s -> return $ Skip (s, False, Nothing)
4179 Stop -> return $ Yield a (st, True, Nothing)
4181 step' _ (_, True, Nothing) = return Stop
4183 step' gst (st, True, Just prev) = do
4184 r <- step gst st
4185 case r of
4186 Yield x s -> return $ Yield prev (s, True, Just x)
4187 Skip s -> return $ Skip (s, True, Just prev)
4188 Stop -> return $ Yield prev (st, True, Nothing)
4190------------------------------------------------------------------------------
4191-- Deleting
4192------------------------------------------------------------------------------
4194{-# INLINE_NORMAL deleteBy #-}
4195deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
4196deleteBy eq x (Stream step state) = Stream step' (state, False)
4197 where
4198 {-# INLINE_LATE step' #-}
4199 step' gst (st, False) = do
4200 r <- step gst st
4201 case r of
4202 Yield y s -> return $
4203 if eq x y then Skip (s, True) else Yield y (s, False)
4204 Skip s -> return $ Skip (s, False)
4205 Stop -> return Stop
4207 step' gst (st, True) = do
4208 r <- step gst st
4209 case r of
4210 Yield y s -> return $ Yield y (s, True)
4211 Skip s -> return $ Skip (s, True)
4212 Stop -> return Stop
4214------------------------------------------------------------------------------
4215-- Transformation by Map and Filter
4216------------------------------------------------------------------------------
4218-- XXX Will this always fuse properly?
4219{-# INLINE_NORMAL mapMaybe #-}
4220mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
4221mapMaybe f = fmap fromJust . filter isJust . map f
4223{-# INLINE_NORMAL mapMaybeM #-}
4224mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
4225mapMaybeM f = fmap fromJust . filter isJust . mapM f
4227------------------------------------------------------------------------------
4228-- Zipping
4229------------------------------------------------------------------------------
4231{-# INLINE_NORMAL indexed #-}
4232indexed :: Monad m => Stream m a -> Stream m (Int, a)
4233indexed (Stream step state) = Stream step' (state, 0)
4234 where
4235 {-# INLINE_LATE step' #-}
4236 step' gst (st, i) = i `seq` do
4237 r <- step (adaptState gst) st
4238 case r of
4239 Yield x s -> return $ Yield (i, x) (s, i+1)
4240 Skip s -> return $ Skip (s, i)
4241 Stop -> return Stop
4243{-# INLINE_NORMAL indexedR #-}
4244indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
4245indexedR m (Stream step state) = Stream step' (state, m)
4246 where
4247 {-# INLINE_LATE step' #-}
4248 step' gst (st, i) = i `seq` do
4249 r <- step (adaptState gst) st
4250 case r of
4251 Yield x s -> let i' = i - 1
4252 in return $ Yield (i, x) (s, i')
4253 Skip s -> return $ Skip (s, i)
4254 Stop -> return Stop
4256{-# INLINE_NORMAL zipWithM #-}
4257zipWithM :: Monad m
4258 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
4259zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
4260 where
4261 {-# INLINE_LATE step #-}
4262 step gst (sa, sb, Nothing) = do
4263 r <- stepa (adaptState gst) sa
4264 return $
4265 case r of
4266 Yield x sa' -> Skip (sa', sb, Just x)
4267 Skip sa' -> Skip (sa', sb, Nothing)
4268 Stop -> Stop
4270 step gst (sa, sb, Just x) = do
4271 r <- stepb (adaptState gst) sb
4272 case r of
4273 Yield y sb' -> do
4274 z <- f x y
4275 return $ Yield z (sa, sb', Nothing)
4276 Skip sb' -> return $ Skip (sa, sb', Just x)
4277 Stop -> return Stop
4279#if __GLASGOW_HASKELL__ >= 801
4280{-# RULES "zipWithM xs xs"
4281 forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
4282#endif
4284{-# INLINE zipWith #-}
4285zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
4286zipWith f = zipWithM (\a b -> return (f a b))
4288------------------------------------------------------------------------------
4289-- Merging
4290------------------------------------------------------------------------------
4292{-# INLINE_NORMAL mergeByM #-}
4293mergeByM
4294 :: (Monad m)
4295 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
4296mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
4297 Stream step (Just ta, Just tb, Nothing, Nothing)
4298 where
4299 {-# INLINE_LATE step #-}
4301 -- one of the values is missing, and the corresponding stream is running
4302 step gst (Just sa, sb, Nothing, b) = do
4303 r <- stepa gst sa
4304 return $ case r of
4305 Yield a sa' -> Skip (Just sa', sb, Just a, b)
4306 Skip sa' -> Skip (Just sa', sb, Nothing, b)
4307 Stop -> Skip (Nothing, sb, Nothing, b)
4309 step gst (sa, Just sb, a, Nothing) = do
4310 r <- stepb gst sb
4311 return $ case r of
4312 Yield b sb' -> Skip (sa, Just sb', a, Just b)
4313 Skip sb' -> Skip (sa, Just sb', a, Nothing)
4314 Stop -> Skip (sa, Nothing, a, Nothing)
4316 -- both the values are available
4317 step _ (sa, sb, Just a, Just b) = do
4318 res <- cmp a b
4319 return $ case res of
4320 GT -> Yield b (sa, sb, Just a, Nothing)
4321 _ -> Yield a (sa, sb, Nothing, Just b)
4323 -- one of the values is missing, corresponding stream is done
4324 step _ (Nothing, sb, Nothing, Just b) =
4325 return $ Yield b (Nothing, sb, Nothing, Nothing)
4327 step _ (sa, Nothing, Just a, Nothing) =
4328 return $ Yield a (sa, Nothing, Nothing, Nothing)
4330 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
4332{-# INLINE mergeBy #-}
4333mergeBy
4334 :: (Monad m)
4335 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
4336mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
4338------------------------------------------------------------------------------
4339-- Transformation comprehensions
4340------------------------------------------------------------------------------
4342{-# INLINE_NORMAL the #-}
4343the :: (Eq a, Monad m) => Stream m a -> m (Maybe a)
4344the (Stream step state) = go state
4345 where
4346 go st = do
4347 r <- step defState st
4348 case r of
4349 Yield x s -> go' x s
4350 Skip s -> go s
4351 Stop -> return Nothing
4352 go' n st = do
4353 r <- step defState st
4354 case r of
4355 Yield x s | x == n -> go' n s
4356 | otherwise -> return Nothing
4357 Skip s -> go' n s
4358 Stop -> return (Just n)
4360{-# INLINE runFold #-}
4361runFold :: (Monad m) => Fold m a b -> Stream m a -> m b
4362runFold (Fold step begin done) = foldlMx' step begin done
4364-------------------------------------------------------------------------------
4365-- Concurrent application and fold
4366-------------------------------------------------------------------------------
4368-- XXX These functions should be moved to Stream/Parallel.hs
4370-- Using StreamD the worker stream producing code can fuse with the code to
4371-- queue output to the SVar giving some perf boost.
4373-- Note that StreamD can only be used in limited situations, specifically, we
4374-- cannot implement joinStreamVarPar using this.
4376-- XXX make sure that the SVar passed is a Parallel style SVar.
4378-- | Fold the supplied stream to the SVar asynchronously using Parallel
4379-- concurrency style.
4380-- {-# INLINE_NORMAL toSVarParallel #-}
4381{-# INLINE toSVarParallel #-}
4382toSVarParallel :: MonadAsync m
4383 => State t m a -> SVar t m a -> Stream m a -> m ()
4384toSVarParallel st sv xs =
4385 if svarInspectMode sv
4386 then forkWithDiag
4387 else do
4388 tid <-
4389 case getYieldLimit st of
4390 Nothing -> doFork (work Nothing)
4391 (svarMrun sv)
4392 (handleChildException sv)
4393 Just _ -> doFork (workLim Nothing)
4394 (svarMrun sv)
4395 (handleChildException sv)
4396 modifyThread sv tid
4398 where
4400 {-# NOINLINE work #-}
4401 work info = (runFold (FL.toParallelSVar sv info) xs)
4403 {-# NOINLINE workLim #-}
4404 workLim info = runFold (FL.toParallelSVarLimited sv info) xs
4406 {-# NOINLINE forkWithDiag #-}
4407 forkWithDiag = do
4408 -- We do not use workerCount in case of ParallelVar but still there is
4409 -- no harm in maintaining it correctly.
4410 liftIO $ atomicModifyIORefCAS_ (workerCount sv) $ \n -> n + 1
4411 recordMaxWorkers sv
4412 -- This allocation matters when significant number of workers are being
4413 -- sent. We allocate it only when needed. The overhead increases by 4x.
4414 winfo <-
4415 case yieldRateInfo sv of
4416 Nothing -> return Nothing
4417 Just _ -> liftIO $ do
4418 cntRef <- newIORef 0
4419 t <- getTime Monotonic
4420 lat <- newIORef (0, t)
4421 return $ Just WorkerInfo
4422 { workerYieldMax = 0
4423 , workerYieldCount = cntRef
4424 , workerLatencyStart = lat
4426 tid <-
4427 case getYieldLimit st of
4428 Nothing -> doFork (work winfo)
4429 (svarMrun sv)
4430 (handleChildException sv)
4431 Just _ -> doFork (workLim winfo)
4432 (svarMrun sv)
4433 (handleChildException sv)
4434 modifyThread sv tid
4436{-# INLINE_NORMAL mkParallelD #-}
4437mkParallelD :: MonadAsync m => Stream m a -> Stream m a
4438mkParallelD m = Stream step Nothing
4439 where
4441 step gst Nothing = do
4442 sv <- newParallelVar StopNone gst
4443 toSVarParallel gst sv m
4444 -- XXX use unfold instead?
4445 return $ Skip $ Just $ fromSVar sv
4447 step gst (Just (UnStream step1 st)) = do
4448 r <- step1 gst st
4449 return $ case r of
4450 Yield a s -> Yield a (Just $ Stream step1 s)
4451 Skip s -> Skip (Just $ Stream step1 s)
4452 Stop -> Stop
4454-- Compare with mkAsync. mkAsync uses an Async style SVar whereas this uses a
4455-- parallel style SVar for evaluation. Currently, parallel style cannot use
4456-- rate control whereas Async style can use rate control. In async style SVar
4457-- the worker thread terminates when the buffer is full whereas in Parallel
4458-- style it blocks.
4460-- | Make the stream producer and consumer run concurrently by introducing a
4461-- buffer between them. The producer thread evaluates the input stream until
4462-- the buffer fills, it blocks if the buffer is full until there is space in
4463-- the buffer. The consumer consumes the stream lazily from the buffer.
4465-- /Internal/
4467{-# INLINE_NORMAL mkParallel #-}
4468mkParallel :: (K.IsStream t, MonadAsync m) => t m a -> t m a
4469mkParallel = fromStreamD . mkParallelD . toStreamD
4471-- Note: we can use another API with two callbacks stop and yield if we want
4472-- the callback to be able to indicate end of stream.
4474-- | Generates a callback and a stream pair. The callback returned is used to
4475-- queue values to the stream. The stream is infinite, there is no way for the
4476-- callback to indicate that it is done now.
4478-- /Internal/
4480{-# INLINE_NORMAL newCallbackStream #-}
4481newCallbackStream :: (K.IsStream t, MonadAsync m) => m ((a -> m ()), t m a)
4482newCallbackStream = do
4483 sv <- newParallelVar StopNone defState
4485 -- XXX Add our own thread-id to the SVar as we can not know the callback's
4486 -- thread-id and the callback is not run in a managed worker. We need to
4487 -- handle this better.
4488 liftIO myThreadId >>= modifyThread sv
4490 let callback a = liftIO $ void $ send sv (ChildYield a)
4491 -- XXX we can return an SVar and then the consumer can unfold from the
4492 -- SVar?
4493 return (callback, fromStreamD (fromSVar sv))
4495-------------------------------------------------------------------------------
4496-- Concurrent tap
4497-------------------------------------------------------------------------------
4499-- | Create an SVar with a fold consumer that will fold any elements sent to it
4500-- using the supplied fold function.
4501{-# INLINE newFoldSVar #-}
4502newFoldSVar :: MonadAsync m => State t m a -> Fold m a b -> m (SVar t m a)
4503newFoldSVar stt f = do
4504 -- Buffer size for the SVar is derived from the current state
4505 sv <- newParallelVar StopAny (adaptState stt)
4506 -- Add the producer thread-id to the SVar.
4507 liftIO myThreadId >>= modifyThread sv
4508 void $ doFork (work sv) (svarMrun sv) (handleFoldException sv)
4509 return sv
4511 where
4513 {-# NOINLINE work #-}
4514 work sv = void $ runFold f $ fromProducer sv
4516data TapState sv st = TapInit | Tapping sv st | TapDone st
4518{-# INLINE_NORMAL tapAsync #-}
4519tapAsync :: MonadAsync m => Fold m a b -> Stream m a -> Stream m a
4520tapAsync f (Stream step1 state1) = Stream step TapInit
4521 where
4523 drainFold svr = do
4524 -- In general, a Stop event would come equipped with the result
4525 -- of the fold. It is not used here but it would be useful in
4526 -- applicative and distribute.
4527 done <- fromConsumer svr
4528 when (not done) $ do
4529 liftIO $ withDiagMVar svr "teeToSVar: waiting to drain"
4530 $ takeMVar (outputDoorBellFromConsumer svr)
4531 drainFold svr
4533 stopFold svr = do
4534 liftIO $ sendStop svr Nothing
4535 -- drain/wait until a stop event arrives from the fold.
4536 drainFold svr
4538 {-# INLINE_LATE step #-}
4539 step gst TapInit = do
4540 sv <- newFoldSVar gst f
4541 return $ Skip (Tapping sv state1)
4543 step gst (Tapping sv st) = do
4544 r <- step1 gst st
4545 case r of
4546 Yield a s -> do
4547 done <- pushToFold sv a
4548 if done
4549 then do
4550 -- XXX we do not need to wait synchronously here
4551 stopFold sv
4552 return $ Yield a (TapDone s)
4553 else return $ Yield a (Tapping sv s)
4554 Skip s -> return $ Skip (Tapping sv s)
4555 Stop -> do
4556 stopFold sv
4557 return $ Stop
4559 step gst (TapDone st) = do
4560 r <- step1 gst st
4561 return $ case r of
4562 Yield a s -> Yield a (TapDone s)
4563 Skip s -> Skip (TapDone s)
4564 Stop -> Stop
4566-- XXX Exported from Array again as this fold is specific to Array
4567-- | Take last 'n' elements from the stream and discard the rest.
4568{-# INLINE lastN #-}
4569lastN :: (Storable a, MonadIO m) => Int -> Fold m a (Array a)
4570lastN n
4571 | n <= 0 = fmap (const mempty) FL.drain
4572 | otherwise = A.unsafeFreeze <$> Fold step initial done
4573 where
4574 step (Tuple3' rb rh i) a = do
4575 rh1 <- liftIO $ RB.unsafeInsert rb rh a
4576 return $ Tuple3' rb rh1 (i + 1)
4577 initial = fmap (\(a, b) -> Tuple3' a b (0 :: Int)) $ liftIO $ RB.new n
4578 done (Tuple3' rb rh i) = do
4579 arr <- liftIO $ MA.newArray n
4580 foldFunc i rh snoc' arr rb
4581 snoc' b a = liftIO $ MA.unsafeSnoc b a
4582 foldFunc i
4583 | i < n = RB.unsafeFoldRingM
4584 | otherwise = RB.unsafeFoldRingFullM
4586------------------------------------------------------------------------------
4587-- Time related
4588------------------------------------------------------------------------------
4590-- XXX using getTime in the loop can be pretty expensive especially for
4591-- computations where iterations are lightweight. We have the following
4592-- options:
4594-- 1) Run a timeout thread updating a flag asynchronously and check that
4595-- flag here, that way we can have a cheap termination check.
4597-- 2) Use COARSE clock to get time with lower resolution but more efficiently.
4599-- 3) Use rdtscp/rdtsc to get time directly from the processor, compute the
4600-- termination value of rdtsc in the beginning and then in each iteration just
4601-- get rdtsc and check if we should terminate.
4603data TakeByTime st s
4604 = TakeByTimeInit st
4605 | TakeByTimeCheck st s
4606 | TakeByTimeYield st s
4608{-# INLINE_NORMAL takeByTime #-}
4609takeByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
4610takeByTime duration (Stream step1 state1) = Stream step (TakeByTimeInit state1)
4611 where
4613 lim = toRelTime64 duration
4615 {-# INLINE_LATE step #-}
4616 step _ (TakeByTimeInit _) | lim == 0 = return Stop
4617 step _ (TakeByTimeInit st) = do
4618 t0 <- liftIO $ getTime Monotonic
4619 return $ Skip (TakeByTimeYield st t0)
4620 step _ (TakeByTimeCheck st t0) = do
4621 t <- liftIO $ getTime Monotonic
4622 return $
4623 if diffAbsTime64 t t0 > lim
4624 then Stop
4625 else Skip (TakeByTimeYield st t0)
4626 step gst (TakeByTimeYield st t0) = do
4627 r <- step1 gst st
4628 return $ case r of
4629 Yield x s -> Yield x (TakeByTimeCheck s t0)
4630 Skip s -> Skip (TakeByTimeCheck s t0)
4631 Stop -> Stop
4633data DropByTime st s x
4634 = DropByTimeInit st
4635 | DropByTimeGen st s
4636 | DropByTimeCheck st s x
4637 | DropByTimeYield st
4639{-# INLINE_NORMAL dropByTime #-}
4640dropByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
4641dropByTime duration (Stream step1 state1) = Stream step (DropByTimeInit state1)
4642 where
4644 lim = toRelTime64 duration
4646 {-# INLINE_LATE step #-}
4647 step _ (DropByTimeInit st) = do
4648 t0 <- liftIO $ getTime Monotonic
4649 return $ Skip (DropByTimeGen st t0)
4650 step gst (DropByTimeGen st t0) = do
4651 r <- step1 gst st
4652 return $ case r of
4653 Yield x s -> Skip (DropByTimeCheck s t0 x)
4654 Skip s -> Skip (DropByTimeGen s t0)
4655 Stop -> Stop
4656 step _ (DropByTimeCheck st t0 x) = do
4657 t <- liftIO $ getTime Monotonic
4658 if diffAbsTime64 t t0 <= lim
4659 then return $ Skip $ DropByTimeGen st t0
4660 else return $ Yield x $ DropByTimeYield st
4661 step gst (DropByTimeYield st) = do
4662 r <- step1 gst st
4663 return $ case r of
4664 Yield x s -> Yield x (DropByTimeYield s)
4665 Skip s -> Skip (DropByTimeYield s)
4666 Stop -> Stop
4668{-# INLINE updateTimeVar #-}
4669updateTimeVar :: Prim.IORef Int64 -> IO ()
4670updateTimeVar timeVar = do
4671 MicroSecond64 t <- fromAbsTime <$> getTime Monotonic
4672 Prim.modifyIORef' timeVar (const t)
4674{-# INLINE updateWithDelay #-}
4675updateWithDelay :: RealFrac a => a -> Prim.IORef Int64 -> IO ()
4676updateWithDelay precision timeVar = do
4677 threadDelay (delayTime precision)
4678 updateTimeVar timeVar
4680 where
4682 -- Keep the minimum at least a millisecond to avoid high CPU usage
4683 {-# INLINE delayTime #-}
4684 delayTime g
4685 | g' >= fromIntegral (maxBound :: Int) = maxBound
4686 | g' < 1000 = 1000
4687 | otherwise = round g'
4689 where
4691 g' = g * 10 ^ (6 :: Int)
4693-- XXX we should move this to stream generation section of this file. Also, the
4694-- take/drop combinators above should be moved to filtering section.
4696{-# INLINE_NORMAL times #-}
4697times :: MonadAsync m => Double -> Stream m (AbsTime, RelTime64)
4698times g = Stream step Nothing
4700 where
4702 {-# INLINE_LATE step #-}
4703 step _ Nothing = do
4704 -- XXX note that this is safe only on a 64-bit machine. On a 32-bit
4705 -- machine a 64-bit 'Var' cannot be read consistently without a lock
4706 -- while another thread is writing to it.
4707 timeVar <- liftIO $ Prim.newIORef (0 :: Int64)
4708 liftIO $ updateTimeVar timeVar
4709 tid <- forkManaged $ liftIO $ forever (updateWithDelay g timeVar)
4710 a <- liftIO $ Prim.readIORef timeVar
4711 return $ Skip $ Just (timeVar, tid, a)
4713 step _ s@(Just (timeVar, _, t0)) = do
4714 a <- liftIO $ Prim.readIORef timeVar
4715 -- XXX we can perhaps use an AbsTime64 using a 64 bit Int for
4716 -- efficiency. or maybe we can use a representation using Double for
4717 -- floating precision time
4718 return $ Yield (toAbsTime (MicroSecond64 t0),
4719 (toRelTime64 (MicroSecond64 (a - t0)))) s