on d7d42be help sign in
4254 lines 148 kB history raw
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE CPP #-}
3{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE ExistentialQuantification #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE PatternSynonyms #-}
9{-# LANGUAGE RecordWildCards #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE ViewPatterns #-}
12{-# LANGUAGE RankNTypes #-}
13{-# LANGUAGE MagicHash #-}
15#if __GLASGOW_HASKELL__ >= 801
16{-# LANGUAGE TypeApplications #-}
17#endif
19#include "inline.hs"
21-- |
22-- Module : Streamly.Internal.Data.Stream.StreamD
23-- Copyright : (c) 2018 Harendra Kumar
24-- (c) Roman Leshchinskiy 2008-2010
25-- (c) The University of Glasgow, 2009
26--
27-- License : BSD3
28-- Maintainer : streamly@composewell.com
29-- Stability : experimental
30-- Portability : GHC
31--
32-- Direct style re-implementation of CPS style stream in StreamK module. The
33-- symbol or suffix 'D' in this module denotes the "Direct" style. GHC is able
34-- to INLINE and fuse direct style better, providing better performance than
35-- CPS implementation.
36--
37-- @
38-- import qualified Streamly.Internal.Data.Stream.StreamD as D
39-- @
41-- Some of the functions in this file have been adapted from the vector
42-- library, https://hackage.haskell.org/package/vector.
44module Streamly.Internal.Data.Stream.StreamD
45 (
46 -- * The stream type
47 Step (..)
49#if __GLASGOW_HASKELL__ >= 800
50 , Stream (Stream, UnStream)
51#else
52 , Stream (UnStream)
53 , pattern Stream
54#endif
56 -- * Construction
57 , nil
58 , nilM
59 , cons
61 -- * Deconstruction
62 , uncons
64 -- * Generation
65 -- ** Unfolds
66 , unfoldr
67 , unfoldrM
68 , unfold
70 -- ** Specialized Generation
71 -- | Generate a monadic stream from a seed.
72 , repeat
73 , repeatM
74 , replicate
75 , replicateM
76 , fromIndices
77 , fromIndicesM
78 , generate
79 , generateM
80 , iterate
81 , iterateM
83 -- ** Enumerations
84 , enumerateFromStepIntegral
85 , enumerateFromIntegral
86 , enumerateFromThenIntegral
87 , enumerateFromToIntegral
88 , enumerateFromThenToIntegral
90 , enumerateFromStepNum
91 , numFrom
92 , numFromThen
93 , enumerateFromToFractional
94 , enumerateFromThenToFractional
96 -- ** Time
97 , currentTime
99 -- ** Conversions
100 -- | Transform an input structure into a stream.
101 -- | Direct style stream does not support @fromFoldable@.
102 , yield
103 , yieldM
104 , fromList
105 , fromListM
106 , fromStreamK
107 , fromStreamD
108 , fromPrimVar
109 , fromSVar
111 -- * Elimination
112 -- ** General Folds
113 , foldrS
114 , foldrT
115 , foldrM
116 , foldrMx
117 , foldr
118 , foldr1
120 , foldl'
121 , foldlM'
122 , foldlS
123 , foldlT
124 , reverse
125 , reverse'
127 , foldlx'
128 , foldlMx'
129 , runFold
131 -- ** Specialized Folds
132 , tap
133 , tapOffsetEvery
134 , tapAsync
135 , tapRate
136 , pollCounts
137 , drain
138 , null
139 , head
140 , headElse
141 , tail
142 , last
143 , elem
144 , notElem
145 , all
146 , any
147 , maximum
148 , maximumBy
149 , minimum
150 , minimumBy
151 , findIndices
152 , lookup
153 , findM
154 , find
155 , (!!)
156 , toSVarParallel
158 -- ** Flattening nested streams
159 , concatMapM
160 , concatMap
161 , ConcatMapUState (..)
162 , concatMapU
163 , ConcatUnfoldInterleaveState (..)
164 , concatUnfoldInterleave
165 , concatUnfoldRoundrobin
166 , AppendState(..)
167 , append
168 , InterleaveState(..)
169 , interleave
170 , interleaveMin
171 , interleaveSuffix
172 , interleaveInfix
173 , roundRobin -- interleaveFair?/ParallelFair
174 , gintercalateSuffix
175 , interposeSuffix
176 , gintercalate
177 , interpose
179 -- ** Grouping
180 , groupsOf
181 , groupsOf2
182 , groupsBy
183 , groupsRollingBy
185 -- ** Splitting
186 , splitBy
187 , splitSuffixBy
188 , wordsBy
189 , splitSuffixBy'
191 , splitOn
192 , splitSuffixOn
194 , splitInnerBy
195 , splitInnerBySuffix
197 -- ** Substreams
198 , isPrefixOf
199 , isSubsequenceOf
200 , stripPrefix
202 -- ** Map and Fold
203 , mapM_
205 -- ** Conversions
206 -- | Transform a stream into another type.
207 , toList
208 , toListRev
209 , toStreamK
210 , toStreamD
212 , hoist
213 , generally
215 , liftInner
216 , runReaderT
217 , evalStateT
218 , runStateT
220 -- * Transformation
221 , transform
223 -- ** By folding (scans)
224 , scanlM'
225 , scanl'
226 , scanlM
227 , scanl
228 , scanl1M'
229 , scanl1'
230 , scanl1M
231 , scanl1
233 , prescanl'
234 , prescanlM'
236 , postscanl
237 , postscanlM
238 , postscanl'
239 , postscanlM'
241 , postscanlx'
242 , postscanlMx'
243 , scanlMx'
244 , scanlx'
246 -- * Filtering
247 , filter
248 , filterM
249 , uniq
250 , take
251 , takeByTime
252 , takeWhile
253 , takeWhileM
254 , drop
255 , dropByTime
256 , dropWhile
257 , dropWhileM
259 -- * Mapping
260 , map
261 , mapM
262 , sequence
263 , rollingMap
264 , rollingMapM
266 -- * Inserting
267 , intersperseM
268 , intersperse
269 , intersperseSuffix
270 , intersperseSuffixBySpan
271 , insertBy
273 -- * Deleting
274 , deleteBy
276 -- ** Map and Filter
277 , mapMaybe
278 , mapMaybeM
280 -- * Zipping
281 , indexed
282 , indexedR
283 , zipWith
284 , zipWithM
286 -- * Comparisons
287 , eqBy
288 , cmpBy
290 -- * Merging
291 , mergeBy
292 , mergeByM
294 -- * Transformation comprehensions
295 , the
297 -- * Exceptions
298 , newFinalizedIORef
299 , gbracket
300 , before
301 , after
302 , afterIO
303 , bracket
304 , bracketIO
305 , onException
306 , finally
307 , finallyIO
308 , handle
310 -- * Concurrent Application
311 , mkParallel
312 , mkParallelD
314 , lastN
315 )
316where
318import Control.Concurrent (killThread, myThreadId, takeMVar, threadDelay)
319import Control.Exception
320 (Exception, SomeException, AsyncException, fromException)
321import Control.Monad (void, when, forever)
322import Control.Monad.Catch (MonadCatch, throwM)
323import Control.Monad.IO.Class (MonadIO(..))
324import Control.Monad.Reader (ReaderT)
325import Control.Monad.State.Strict (StateT)
326import Control.Monad.Trans (MonadTrans(lift))
327import Control.Monad.Trans.Control (MonadBaseControl)
328import Data.Bits (shiftR, shiftL, (.|.), (.&.))
329import Data.Functor.Identity (Identity(..))
330import Data.Int (Int64)
331import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef, IORef)
332import Data.Maybe (fromJust, isJust, isNothing)
333import Data.Word (Word32)
334import Foreign.Ptr (Ptr)
335import Foreign.Storable (Storable(..))
336import GHC.Types (SPEC(..))
337import System.Mem (performMajorGC)
338import Prelude
339 hiding (map, mapM, mapM_, repeat, foldr, last, take, filter,
340 takeWhile, drop, dropWhile, all, any, maximum, minimum, elem,
341 notElem, null, head, tail, zipWith, lookup, foldr1, sequence,
342 (!!), scanl, scanl1, concatMap, replicate, enumFromTo, concat,
343 reverse, iterate)
345import qualified Control.Monad.Catch as MC
346import qualified Control.Monad.Reader as Reader
347import qualified Control.Monad.State.Strict as State
348import qualified Prelude
350import Streamly.Internal.Mutable.Prim.Var
351 (Prim, Var, readVar, newVar, modifyVar')
352import Streamly.Internal.Data.Time.Units
353 (TimeUnit64, toRelTime64, diffAbsTime64)
355import Streamly.Internal.Data.Atomics (atomicModifyIORefCAS_)
356import Streamly.Internal.Memory.Array.Types (Array(..))
357import Streamly.Internal.Data.Fold.Types (Fold(..))
358import Streamly.Internal.Data.Pipe.Types (Pipe(..), PipeState(..))
359import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
360import Streamly.Internal.Data.Time.Units
361 (MicroSecond64(..), fromAbsTime, toAbsTime, AbsTime)
362import Streamly.Internal.Data.Unfold.Types (Unfold(..))
363import Streamly.Internal.Data.Strict (Tuple3'(..))
365import Streamly.Internal.Data.Stream.StreamD.Type
366import Streamly.Internal.Data.SVar
367import Streamly.Internal.Data.Stream.SVar (fromConsumer, pushToFold)
369import qualified Streamly.Internal.Data.Pipe.Types as Pipe
370import qualified Streamly.Internal.Memory.Array.Types as A
371import qualified Streamly.Internal.Data.Fold as FL
372import qualified Streamly.Memory.Ring as RB
373import qualified Streamly.Internal.Data.Stream.StreamK as K
375------------------------------------------------------------------------------
376-- Construction
377------------------------------------------------------------------------------
379-- | An empty 'Stream'.
380{-# INLINE_NORMAL nil #-}
381nil :: Monad m => Stream m a
382nil = Stream (\_ _ -> return Stop) ()
384-- | An empty 'Stream' with a side effect.
385{-# INLINE_NORMAL nilM #-}
386nilM :: Monad m => m b -> Stream m a
387nilM m = Stream (\_ _ -> m >> return Stop) ()
389{-# INLINE_NORMAL consM #-}
390consM :: Monad m => m a -> Stream m a -> Stream m a
391consM m (Stream step state) = Stream step1 Nothing
392 where
393 {-# INLINE_LATE step1 #-}
394 step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
395 step1 gst (Just st) = do
396 r <- step gst st
397 return $
398 case r of
399 Yield a s -> Yield a (Just s)
400 Skip s -> Skip (Just s)
401 Stop -> Stop
403-- XXX implement in terms of consM?
404-- cons x = consM (return x)
405--
406-- | Can fuse but has O(n^2) complexity.
407{-# INLINE_NORMAL cons #-}
408cons :: Monad m => a -> Stream m a -> Stream m a
409cons x (Stream step state) = Stream step1 Nothing
410 where
411 {-# INLINE_LATE step1 #-}
412 step1 _ Nothing = return $ Yield x (Just state)
413 step1 gst (Just st) = do
414 r <- step gst st
415 return $
416 case r of
417 Yield a s -> Yield a (Just s)
418 Skip s -> Skip (Just s)
419 Stop -> Stop
421-------------------------------------------------------------------------------
422-- Deconstruction
423-------------------------------------------------------------------------------
425-- Does not fuse, has the same performance as the StreamK version.
426{-# INLINE_NORMAL uncons #-}
427uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
428uncons (UnStream step state) = go state
429 where
430 go st = do
431 r <- step defState st
432 case r of
433 Yield x s -> return $ Just (x, Stream step s)
434 Skip s -> go s
435 Stop -> return Nothing
437------------------------------------------------------------------------------
438-- Generation by unfold
439------------------------------------------------------------------------------
441{-# INLINE_NORMAL unfoldrM #-}
442unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
443unfoldrM next state = Stream step state
444 where
445 {-# INLINE_LATE step #-}
446 step _ st = do
447 r <- next st
448 return $ case r of
449 Just (x, s) -> Yield x s
450 Nothing -> Stop
452{-# INLINE_LATE unfoldr #-}
453unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
454unfoldr f = unfoldrM (return . f)
456-- | Convert an 'Unfold' into a 'Stream' by supplying it a seed.
457--
458{-# INLINE_NORMAL unfold #-}
459unfold :: Monad m => Unfold m a b -> a -> Stream m b
460unfold (Unfold ustep inject) seed = Stream step Nothing
461 where
462 {-# INLINE_LATE step #-}
463 step _ Nothing = inject seed >>= return . Skip . Just
464 step _ (Just st) = do
465 r <- ustep st
466 return $ case r of
467 Yield x s -> Yield x (Just s)
468 Skip s -> Skip (Just s)
469 Stop -> Stop
471------------------------------------------------------------------------------
472-- Specialized Generation
473------------------------------------------------------------------------------
475{-# INLINE_NORMAL repeatM #-}
476repeatM :: Monad m => m a -> Stream m a
477repeatM x = Stream (\_ _ -> x >>= \r -> return $ Yield r ()) ()
479{-# INLINE_NORMAL repeat #-}
480repeat :: Monad m => a -> Stream m a
481repeat x = Stream (\_ _ -> return $ Yield x ()) ()
483{-# INLINE_NORMAL iterateM #-}
484iterateM :: Monad m => (a -> m a) -> m a -> Stream m a
485iterateM step = Stream (\_ st -> st >>= \x -> return $ Yield x (step x))
487{-# INLINE_NORMAL iterate #-}
488iterate :: Monad m => (a -> a) -> a -> Stream m a
489iterate step st = iterateM (return . step) (return st)
491{-# INLINE_NORMAL replicateM #-}
492replicateM :: forall m a. Monad m => Int -> m a -> Stream m a
493replicateM n p = Stream step n
494 where
495 {-# INLINE_LATE step #-}
496 step _ (i :: Int)
497 | i <= 0 = return Stop
498 | otherwise = do
499 x <- p
500 return $ Yield x (i - 1)
502{-# INLINE_NORMAL replicate #-}
503replicate :: Monad m => Int -> a -> Stream m a
504replicate n x = replicateM n (return x)
506-- This would not work properly for floats, therefore we put an Integral
507-- constraint.
508-- | Can be used to enumerate unbounded integrals. This does not check for
509-- overflow or underflow for bounded integrals.
510{-# INLINE_NORMAL enumerateFromStepIntegral #-}
511enumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
512enumerateFromStepIntegral from stride =
513 from `seq` stride `seq` Stream step from
514 where
515 {-# INLINE_LATE step #-}
516 step _ !x = return $ Yield x $! (x + stride)
518-- We are assuming that "to" is constrained by the type to be within
519-- max/min bounds.
520{-# INLINE enumerateFromToIntegral #-}
521enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
522enumerateFromToIntegral from to =
523 takeWhile (<= to) $ enumerateFromStepIntegral from 1
525{-# INLINE enumerateFromIntegral #-}
526enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
527enumerateFromIntegral from = enumerateFromToIntegral from maxBound
529data EnumState a = EnumInit | EnumYield a a a | EnumStop
531{-# INLINE_NORMAL enumerateFromThenToIntegralUp #-}
532enumerateFromThenToIntegralUp
533 :: (Monad m, Integral a)
534 => a -> a -> a -> Stream m a
535enumerateFromThenToIntegralUp from next to = Stream step EnumInit
536 where
537 {-# INLINE_LATE step #-}
538 step _ EnumInit =
539 return $
540 if to < next
541 then if to < from
542 then Stop
543 else Yield from EnumStop
544 else -- from <= next <= to
545 let stride = next - from
546 in Skip $ EnumYield from stride (to - stride)
548 step _ (EnumYield x stride toMinus) =
549 return $
550 if x > toMinus
551 then Yield x EnumStop
552 else Yield x $ EnumYield (x + stride) stride toMinus
554 step _ EnumStop = return Stop
556{-# INLINE_NORMAL enumerateFromThenToIntegralDn #-}
557enumerateFromThenToIntegralDn
558 :: (Monad m, Integral a)
559 => a -> a -> a -> Stream m a
560enumerateFromThenToIntegralDn from next to = Stream step EnumInit
561 where
562 {-# INLINE_LATE step #-}
563 step _ EnumInit =
564 return $ if to > next
565 then if to > from
566 then Stop
567 else Yield from EnumStop
568 else -- from >= next >= to
569 let stride = next - from
570 in Skip $ EnumYield from stride (to - stride)
572 step _ (EnumYield x stride toMinus) =
573 return $
574 if x < toMinus
575 then Yield x EnumStop
576 else Yield x $ EnumYield (x + stride) stride toMinus
578 step _ EnumStop = return Stop
580{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
581enumerateFromThenToIntegral
582 :: (Monad m, Integral a)
583 => a -> a -> a -> Stream m a
584enumerateFromThenToIntegral from next to
585 | next >= from = enumerateFromThenToIntegralUp from next to
586 | otherwise = enumerateFromThenToIntegralDn from next to
588{-# INLINE_NORMAL enumerateFromThenIntegral #-}
589enumerateFromThenIntegral
590 :: (Monad m, Integral a, Bounded a)
591 => a -> a -> Stream m a
592enumerateFromThenIntegral from next =
593 if next > from
594 then enumerateFromThenToIntegralUp from next maxBound
595 else enumerateFromThenToIntegralDn from next minBound
597-- For floating point numbers if the increment is less than the precision then
598-- it just gets lost. Therefore we cannot always increment it correctly by just
599-- repeated addition.
600-- 9007199254740992 + 1 + 1 :: Double => 9.007199254740992e15
601-- 9007199254740992 + 2 :: Double => 9.007199254740994e15
603-- Instead we accumulate the increment counter and compute the increment
604-- every time before adding it to the starting number.
605--
606-- This works for Integrals as well as floating point numbers, but
607-- enumerateFromStepIntegral is faster for integrals.
608{-# INLINE_NORMAL enumerateFromStepNum #-}
609enumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
610enumerateFromStepNum from stride = Stream step 0
611 where
612 {-# INLINE_LATE step #-}
613 step _ !i = return $ (Yield $! (from + i * stride)) $! (i + 1)
615{-# INLINE_NORMAL numFrom #-}
616numFrom :: (Monad m, Num a) => a -> Stream m a
617numFrom from = enumerateFromStepNum from 1
619{-# INLINE_NORMAL numFromThen #-}
620numFromThen :: (Monad m, Num a) => a -> a -> Stream m a
621numFromThen from next = enumerateFromStepNum from (next - from)
623-- We cannot write a general function for Num. The only way to write code
624-- portable between the two is to use a 'Real' constraint and convert between
625-- Fractional and Integral using fromRational which is horribly slow.
626{-# INLINE_NORMAL enumerateFromToFractional #-}
627enumerateFromToFractional
628 :: (Monad m, Fractional a, Ord a)
629 => a -> a -> Stream m a
630enumerateFromToFractional from to =
631 takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
633{-# INLINE_NORMAL enumerateFromThenToFractional #-}
634enumerateFromThenToFractional
635 :: (Monad m, Fractional a, Ord a)
636 => a -> a -> a -> Stream m a
637enumerateFromThenToFractional from next to =
638 takeWhile predicate $ numFromThen from next
639 where
640 mid = (next - from) / 2
641 predicate | next >= from = (<= to + mid)
642 | otherwise = (>= to + mid)
644-------------------------------------------------------------------------------
645-- Generation by Conversion
646-------------------------------------------------------------------------------
648{-# INLINE_NORMAL fromIndicesM #-}
649fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
650fromIndicesM gen = Stream step 0
651 where
652 {-# INLINE_LATE step #-}
653 step _ i = do
654 x <- gen i
655 return $ Yield x (i + 1)
657{-# INLINE fromIndices #-}
658fromIndices :: Monad m => (Int -> a) -> Stream m a
659fromIndices gen = fromIndicesM (return . gen)
661{-# INLINE_NORMAL generateM #-}
662generateM :: Monad m => Int -> (Int -> m a) -> Stream m a
663generateM n gen = n `seq` Stream step 0
664 where
665 {-# INLINE_LATE step #-}
666 step _ i | i < n = do
667 x <- gen i
668 return $ Yield x (i + 1)
669 | otherwise = return Stop
671{-# INLINE generate #-}
672generate :: Monad m => Int -> (Int -> a) -> Stream m a
673generate n gen = generateM n (return . gen)
675-- XXX we need the MonadAsync constraint because of a rewrite rule.
676-- | Convert a list of monadic actions to a 'Stream'
677{-# INLINE_LATE fromListM #-}
678fromListM :: MonadAsync m => [m a] -> Stream m a
679fromListM = Stream step
680 where
681 {-# INLINE_LATE step #-}
682 step _ (m:ms) = m >>= \x -> return $ Yield x ms
683 step _ [] = return Stop
685{-# INLINE toStreamD #-}
686toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
687toStreamD = fromStreamK . K.toStream
689{-# INLINE_NORMAL fromPrimVar #-}
690fromPrimVar :: (MonadIO m, Prim a) => Var IO a -> Stream m a
691fromPrimVar var = Stream step ()
692 where
693 {-# INLINE_LATE step #-}
694 step _ () = liftIO (readVar var) >>= \x -> return $ Yield x ()
696-------------------------------------------------------------------------------
697-- Generation from SVar
698-------------------------------------------------------------------------------
700data FromSVarState t m a =
701 FromSVarInit
702 | FromSVarRead (SVar t m a)
703 | FromSVarLoop (SVar t m a) [ChildEvent a]
704 | FromSVarDone (SVar t m a)
706{-# INLINE_NORMAL fromSVar #-}
707fromSVar :: (MonadAsync m) => SVar t m a -> Stream m a
708fromSVar svar = Stream step FromSVarInit
709 where
711 {-# INLINE_LATE step #-}
712 step _ FromSVarInit = do
713 ref <- liftIO $ newIORef ()
714 _ <- liftIO $ mkWeakIORef ref hook
715 -- when this copy of svar gets garbage collected "ref" will get
716 -- garbage collected and our GC hook will be called.
717 let sv = svar{svarRef = Just ref}
718 return $ Skip (FromSVarRead sv)
720 where
722 {-# NOINLINE hook #-}
723 hook = do
724 when (svarInspectMode svar) $ do
725 r <- liftIO $ readIORef (svarStopTime (svarStats svar))
726 when (isNothing r) $
727 printSVar svar "SVar Garbage Collected"
728 cleanupSVar svar
729 -- If there are any SVars referenced by this SVar a GC will prompt
730 -- them to be cleaned up quickly.
731 when (svarInspectMode svar) performMajorGC
733 step _ (FromSVarRead sv) = do
734 list <- readOutputQ sv
735 -- Reversing the output is important to guarantee that we process the
736 -- outputs in the same order as they were generated by the constituent
737 -- streams.
738 return $ Skip $ FromSVarLoop sv (Prelude.reverse list)
740 step _ (FromSVarLoop sv []) = do
741 done <- postProcess sv
742 return $ Skip $ if done
743 then (FromSVarDone sv)
744 else (FromSVarRead sv)
746 step _ (FromSVarLoop sv (ev : es)) = do
747 case ev of
748 ChildYield a -> return $ Yield a (FromSVarLoop sv es)
749 ChildStop tid e -> do
750 accountThread sv tid
751 case e of
752 Nothing -> do
753 stop <- shouldStop tid
754 if stop
755 then do
756 liftIO (cleanupSVar sv)
757 return $ Skip (FromSVarDone sv)
758 else return $ Skip (FromSVarLoop sv es)
759 Just ex ->
760 case fromException ex of
761 Just ThreadAbort ->
762 return $ Skip (FromSVarLoop sv es)
763 Nothing -> liftIO (cleanupSVar sv) >> throwM ex
764 where
766 shouldStop tid =
767 case svarStopStyle sv of
768 StopNone -> return False
769 StopAny -> return True
770 StopBy -> do
771 sid <- liftIO $ readIORef (svarStopBy sv)
772 return $ if tid == sid then True else False
774 step _ (FromSVarDone sv) = do
775 when (svarInspectMode sv) $ do
776 t <- liftIO $ getTime Monotonic
777 liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
778 liftIO $ printSVar sv "SVar Done"
779 return Stop
781-------------------------------------------------------------------------------
782-- Process events received by a fold consumer from a stream producer
783-------------------------------------------------------------------------------
785{-# INLINE_NORMAL fromProducer #-}
786fromProducer :: (MonadAsync m) => SVar t m a -> Stream m a
787fromProducer svar = Stream step (FromSVarRead svar)
788 where
790 {-# INLINE_LATE step #-}
791 step _ (FromSVarRead sv) = do
792 list <- readOutputQ sv
793 -- Reversing the output is important to guarantee that we process the
794 -- outputs in the same order as they were generated by the constituent
795 -- streams.
796 return $ Skip $ FromSVarLoop sv (Prelude.reverse list)
798 step _ (FromSVarLoop sv []) = return $ Skip $ FromSVarRead sv
799 step _ (FromSVarLoop sv (ev : es)) = do
800 case ev of
801 ChildYield a -> return $ Yield a (FromSVarLoop sv es)
802 ChildStop tid e -> do
803 accountThread sv tid
804 case e of
805 Nothing -> do
806 sendStopToProducer sv
807 return $ Skip (FromSVarDone sv)
808 Just _ -> error "Bug: fromProducer: received exception"
810 step _ (FromSVarDone sv) = do
811 when (svarInspectMode sv) $ do
812 t <- liftIO $ getTime Monotonic
813 liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
814 liftIO $ printSVar sv "SVar Done"
815 return Stop
817 step _ FromSVarInit = undefined
819-------------------------------------------------------------------------------
820-- Hoisting the inner monad
821-------------------------------------------------------------------------------
823{-# INLINE_NORMAL hoist #-}
824hoist :: Monad n => (forall x. m x -> n x) -> Stream m a -> Stream n a
825hoist f (Stream step state) = (Stream step' state)
826 where
827 {-# INLINE_LATE step' #-}
828 step' gst st = do
829 r <- f $ step (adaptState gst) st
830 return $ case r of
831 Yield x s -> Yield x s
832 Skip s -> Skip s
833 Stop -> Stop
835{-# INLINE generally #-}
836generally :: Monad m => Stream Identity a -> Stream m a
837generally = hoist (return . runIdentity)
839{-# INLINE_NORMAL liftInner #-}
840liftInner :: (Monad m, MonadTrans t, Monad (t m))
841 => Stream m a -> Stream (t m) a
842liftInner (Stream step state) = Stream step' state
843 where
844 {-# INLINE_LATE step' #-}
845 step' gst st = do
846 r <- lift $ step (adaptState gst) st
847 return $ case r of
848 Yield x s -> Yield x s
849 Skip s -> Skip s
850 Stop -> Stop
852{-# INLINE_NORMAL runReaderT #-}
853runReaderT :: Monad m => s -> Stream (ReaderT s m) a -> Stream m a
854runReaderT sval (Stream step state) = Stream step' state
855 where
856 {-# INLINE_LATE step' #-}
857 step' gst st = do
858 r <- Reader.runReaderT (step (adaptState gst) st) sval
859 return $ case r of
860 Yield x s -> Yield x s
861 Skip s -> Skip s
862 Stop -> Stop
864{-# INLINE_NORMAL evalStateT #-}
865evalStateT :: Monad m => s -> Stream (StateT s m) a -> Stream m a
866evalStateT sval (Stream step state) = Stream step' (state, sval)
867 where
868 {-# INLINE_LATE step' #-}
869 step' gst (st, sv) = do
870 (r, sv') <- State.runStateT (step (adaptState gst) st) sv
871 return $ case r of
872 Yield x s -> Yield x (s, sv')
873 Skip s -> Skip (s, sv')
874 Stop -> Stop
876{-# INLINE_NORMAL runStateT #-}
877runStateT :: Monad m => s -> Stream (StateT s m) a -> Stream m (s, a)
878runStateT sval (Stream step state) = Stream step' (state, sval)
879 where
880 {-# INLINE_LATE step' #-}
881 step' gst (st, sv) = do
882 (r, sv') <- State.runStateT (step (adaptState gst) st) sv
883 return $ case r of
884 Yield x s -> Yield (sv', x) (s, sv')
885 Skip s -> Skip (s, sv')
886 Stop -> Stop
888------------------------------------------------------------------------------
889-- Elimination by Folds
890------------------------------------------------------------------------------
892------------------------------------------------------------------------------
893-- Right Folds
894------------------------------------------------------------------------------
896{-# INLINE_NORMAL foldr1 #-}
897foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
898foldr1 f m = do
899 r <- uncons m
900 case r of
901 Nothing -> return Nothing
902 Just (h, t) -> fmap Just (foldr f h t)
904------------------------------------------------------------------------------
905-- Left Folds
906------------------------------------------------------------------------------
908{-# INLINE_NORMAL foldlT #-}
909foldlT :: (Monad m, Monad (s m), MonadTrans s)
910 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
911foldlT fstep begin (Stream step state) = go SPEC begin state
912 where
913 go !_ acc st = do
914 r <- lift $ step defState st
915 case r of
916 Yield x s -> go SPEC (fstep acc x) s
917 Skip s -> go SPEC acc s
918 Stop -> acc
920-- Note, this is going to have horrible performance, because of the nature of
921-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
922-- likely be practically unusable.
923{-# INLINE_NORMAL foldlS #-}
924foldlS :: Monad m
925 => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
926foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
927 where
928 step' gst (Left (st, acc)) = do
929 r <- step (adaptState gst) st
930 return $ case r of
931 Yield x s -> Skip (Left (s, fstep acc x))
932 Skip s -> Skip (Left (s, acc))
933 Stop -> Skip (Right acc)
935 step' gst (Right (Stream stp stt)) = do
936 r <- stp (adaptState gst) stt
937 return $ case r of
938 Yield x s -> Yield x (Right (Stream stp s))
939 Skip s -> Skip (Right (Stream stp s))
940 Stop -> Stop
942------------------------------------------------------------------------------
943-- Specialized Folds
944------------------------------------------------------------------------------
946-- | Run a streaming composition, discard the results.
947{-# INLINE_LATE drain #-}
948drain :: Monad m => Stream m a -> m ()
949-- drain = foldrM (\_ xs -> xs) (return ())
950drain (Stream step state) = go SPEC state
951 where
952 go !_ st = do
953 r <- step defState st
954 case r of
955 Yield _ s -> go SPEC s
956 Skip s -> go SPEC s
957 Stop -> return ()
959{-# INLINE_NORMAL null #-}
960null :: Monad m => Stream m a -> m Bool
961null m = foldrM (\_ _ -> return False) (return True) m
963{-# INLINE_NORMAL head #-}
964head :: Monad m => Stream m a -> m (Maybe a)
965head m = foldrM (\x _ -> return (Just x)) (return Nothing) m
967{-# INLINE_NORMAL headElse #-}
968headElse :: Monad m => a -> Stream m a -> m a
969headElse a m = foldrM (\x _ -> return x) (return a) m
971-- Does not fuse, has the same performance as the StreamK version.
972{-# INLINE_NORMAL tail #-}
973tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
974tail (UnStream step state) = go state
975 where
976 go st = do
977 r <- step defState st
978 case r of
979 Yield _ s -> return (Just $ Stream step s)
980 Skip s -> go s
981 Stop -> return Nothing
983-- XXX will it fuse? need custom impl?
984{-# INLINE_NORMAL last #-}
985last :: Monad m => Stream m a -> m (Maybe a)
986last = foldl' (\_ y -> Just y) Nothing
988{-# INLINE_NORMAL elem #-}
989elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
990-- elem e m = foldrM (\x xs -> if x == e then return True else xs) (return False) m
991elem e (Stream step state) = go state
992 where
993 go st = do
994 r <- step defState st
995 case r of
996 Yield x s
997 | x == e -> return True
998 | otherwise -> go s
999 Skip s -> go s
1000 Stop -> return False
1002{-# INLINE_NORMAL notElem #-}
1003notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
1004notElem e s = fmap not (elem e s)
1006{-# INLINE_NORMAL all #-}
1007all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
1008-- all p m = foldrM (\x xs -> if p x then xs else return False) (return True) m
1009all p (Stream step state) = go state
1010 where
1011 go st = do
1012 r <- step defState st
1013 case r of
1014 Yield x s
1015 | p x -> go s
1016 | otherwise -> return False
1017 Skip s -> go s
1018 Stop -> return True
1020{-# INLINE_NORMAL any #-}
1021any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
1022-- any p m = foldrM (\x xs -> if p x then return True else xs) (return False) m
1023any p (Stream step state) = go state
1024 where
1025 go st = do
1026 r <- step defState st
1027 case r of
1028 Yield x s
1029 | p x -> return True
1030 | otherwise -> go s
1031 Skip s -> go s
1032 Stop -> return False
1034{-# INLINE_NORMAL maximum #-}
1035maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
1036maximum (Stream step state) = go Nothing state
1037 where
1038 go Nothing st = do
1039 r <- step defState st
1040 case r of
1041 Yield x s -> go (Just x) s
1042 Skip s -> go Nothing s
1043 Stop -> return Nothing
1044 go (Just acc) st = do
1045 r <- step defState st
1046 case r of
1047 Yield x s
1048 | acc <= x -> go (Just x) s
1049 | otherwise -> go (Just acc) s
1050 Skip s -> go (Just acc) s
1051 Stop -> return (Just acc)
1053{-# INLINE_NORMAL maximumBy #-}
1054maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
1055maximumBy cmp (Stream step state) = go Nothing state
1056 where
1057 go Nothing st = do
1058 r <- step defState st
1059 case r of
1060 Yield x s -> go (Just x) s
1061 Skip s -> go Nothing s
1062 Stop -> return Nothing
1063 go (Just acc) st = do
1064 r <- step defState st
1065 case r of
1066 Yield x s -> case cmp acc x of
1067 GT -> go (Just acc) s
1068 _ -> go (Just x) s
1069 Skip s -> go (Just acc) s
1070 Stop -> return (Just acc)
1072{-# INLINE_NORMAL minimum #-}
1073minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
1074minimum (Stream step state) = go Nothing state
1075 where
1076 go Nothing st = do
1077 r <- step defState st
1078 case r of
1079 Yield x s -> go (Just x) s
1080 Skip s -> go Nothing s
1081 Stop -> return Nothing
1082 go (Just acc) st = do
1083 r <- step defState st
1084 case r of
1085 Yield x s
1086 | acc <= x -> go (Just acc) s
1087 | otherwise -> go (Just x) s
1088 Skip s -> go (Just acc) s
1089 Stop -> return (Just acc)
1091{-# INLINE_NORMAL minimumBy #-}
1092minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
1093minimumBy cmp (Stream step state) = go Nothing state
1094 where
1095 go Nothing st = do
1096 r <- step defState st
1097 case r of
1098 Yield x s -> go (Just x) s
1099 Skip s -> go Nothing s
1100 Stop -> return Nothing
1101 go (Just acc) st = do
1102 r <- step defState st
1103 case r of
1104 Yield x s -> case cmp acc x of
1105 GT -> go (Just x) s
1106 _ -> go (Just acc) s
1107 Skip s -> go (Just acc) s
1108 Stop -> return (Just acc)
1110{-# INLINE_NORMAL (!!) #-}
1111(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
1112(Stream step state) !! i = go i state
1113 where
1114 go n st = do
1115 r <- step defState st
1116 case r of
1117 Yield x s | n < 0 -> return Nothing
1118 | n == 0 -> return $ Just x
1119 | otherwise -> go (n - 1) s
1120 Skip s -> go n s
1121 Stop -> return Nothing
1123{-# INLINE_NORMAL lookup #-}
1124lookup :: (Monad m, Eq a) => a -> Stream m (a, b) -> m (Maybe b)
1125lookup e m = foldrM (\(a, b) xs -> if e == a then return (Just b) else xs)
1126 (return Nothing) m
1128{-# INLINE_NORMAL findM #-}
1129findM :: Monad m => (a -> m Bool) -> Stream m a -> m (Maybe a)
1130findM p m = foldrM (\x xs -> p x >>= \r -> if r then return (Just x) else xs)
1131 (return Nothing) m
1133{-# INLINE find #-}
1134find :: Monad m => (a -> Bool) -> Stream m a -> m (Maybe a)
1135find p = findM (return . p)
1137{-# INLINE_NORMAL findIndices #-}
1138findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
1139findIndices p (Stream step state) = Stream step' (state, 0)
1140 where
1141 {-# INLINE_LATE step' #-}
1142 step' gst (st, i) = i `seq` do
1143 r <- step (adaptState gst) st
1144 return $ case r of
1145 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
1146 Skip s -> Skip (s, i)
1147 Stop -> Stop
1149{-# INLINE toListRev #-}
1150toListRev :: Monad m => Stream m a -> m [a]
1151toListRev = foldl' (flip (:)) []
1153-- We can implement reverse as:
1155-- > reverse = foldlS (flip cons) nil
1157-- However, this implementation is unusable because of the horrible performance
1158-- of cons. So we just convert it to a list first and then stream from the
1159-- list.
1161-- XXX Maybe we can use an Array instead of a list here?
1162{-# INLINE_NORMAL reverse #-}
1163reverse :: Monad m => Stream m a -> Stream m a
1164reverse m = Stream step Nothing
1165 where
1166 {-# INLINE_LATE step #-}
1167 step _ Nothing = do
1168 xs <- toListRev m
1169 return $ Skip (Just xs)
1170 step _ (Just (x:xs)) = return $ Yield x (Just xs)
1171 step _ (Just []) = return Stop
1173-- Much faster reverse for Storables
1174{-# INLINE_NORMAL reverse' #-}
1175reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
1177-- This commented implementation copies the whole stream into one single array
1178-- and then streams from that array, this is 3-4x faster than the chunked code
1179-- that follows. Though this could be problematic due to unbounded large
1180-- allocations. We need to figure out why the chunked code is slower and if we
1181-- can optimize the chunked code to work as fast as this one. It may be a
1182-- fusion issue?
1183import Foreign.ForeignPtr (touchForeignPtr)
1184import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
1185import Foreign.Ptr (Ptr, plusPtr)
1186reverse' m = Stream step Nothing
1187 where
1188 {-# INLINE_LATE step #-}
1189 step _ Nothing = do
1190 arr <- A.fromStreamD m
1191 let p = aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
1192 return $ Skip $ Just (aStart arr, p)
1194 step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
1196 step _ (Just (start, p)) = do
1197 let !x = A.unsafeInlineIO $ do
1198 r <- peek p
1199 touchForeignPtr start
1200 return r
1201 next = p `plusPtr` negate (sizeOf (undefined :: a))
1202 return $ Yield x (Just (start, next))
1204reverse' m =
1205 A.flattenArraysRev
1206 $ fromStreamK
1207 $ K.reverse
1208 $ toStreamK
1209 $ A.fromStreamDArraysOf A.defaultChunkSize m
1212------------------------------------------------------------------------------
1213-- Grouping/Splitting
1214------------------------------------------------------------------------------
1216{-# INLINE_NORMAL splitSuffixBy' #-}
1217splitSuffixBy' :: Monad m
1218 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1219splitSuffixBy' predicate f (Stream step state) =
1220 Stream (stepOuter f) (Just state)
1222 where
1224 {-# INLINE_LATE stepOuter #-}
1225 stepOuter (Fold fstep initial done) gst (Just st) = do
1226 res <- step (adaptState gst) st
1227 case res of
1228 Yield x s -> do
1229 acc <- initial
1230 acc' <- fstep acc x
1231 if (predicate x)
1232 then done acc' >>= \val -> return $ Yield val (Just s)
1233 else go SPEC s acc'
1235 Skip s -> return $ Skip $ Just s
1236 Stop -> return Stop
1238 where
1240 go !_ stt !acc = do
1241 res <- step (adaptState gst) stt
1242 case res of
1243 Yield x s -> do
1244 acc' <- fstep acc x
1245 if (predicate x)
1246 then done acc' >>= \val -> return $ Yield val (Just s)
1247 else go SPEC s acc'
1248 Skip s -> go SPEC s acc
1249 Stop -> done acc >>= \val -> return $ Yield val Nothing
1251 stepOuter _ _ Nothing = return Stop
1253{-# INLINE_NORMAL groupsBy #-}
1254groupsBy :: Monad m
1255 => (a -> a -> Bool)
1256 -> Fold m a b
1257 -> Stream m a
1258 -> Stream m b
1259groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
1261 where
1263 {-# INLINE_LATE stepOuter #-}
1264 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1265 res <- step (adaptState gst) st
1266 case res of
1267 Yield x s -> do
1268 acc <- initial
1269 acc' <- fstep acc x
1270 go SPEC x s acc'
1272 Skip s -> return $ Skip $ (Just s, Nothing)
1273 Stop -> return Stop
1275 where
1277 go !_ prev stt !acc = do
1278 res <- step (adaptState gst) stt
1279 case res of
1280 Yield x s -> do
1281 if cmp x prev
1282 then do
1283 acc' <- fstep acc x
1284 go SPEC prev s acc'
1285 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1286 Skip s -> go SPEC prev s acc
1287 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1289 stepOuter (Fold fstep initial done) gst (Just st, Just prev) = do
1290 acc <- initial
1291 acc' <- fstep acc prev
1292 go SPEC st acc'
1294 where
1296 -- XXX code duplicated from the previous equation
1297 go !_ stt !acc = do
1298 res <- step (adaptState gst) stt
1299 case res of
1300 Yield x s -> do
1301 if cmp x prev
1302 then do
1303 acc' <- fstep acc x
1304 go SPEC s acc'
1305 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1306 Skip s -> go SPEC s acc
1307 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1309 stepOuter _ _ (Nothing,_) = return Stop
1311{-# INLINE_NORMAL groupsRollingBy #-}
1312groupsRollingBy :: Monad m
1313 => (a -> a -> Bool)
1314 -> Fold m a b
1315 -> Stream m a
1316 -> Stream m b
1317groupsRollingBy cmp f (Stream step state) =
1318 Stream (stepOuter f) (Just state, Nothing)
1319 where
1321 {-# INLINE_LATE stepOuter #-}
1322 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
1323 res <- step (adaptState gst) st
1324 case res of
1325 Yield x s -> do
1326 acc <- initial
1327 acc' <- fstep acc x
1328 go SPEC x s acc'
1330 Skip s -> return $ Skip $ (Just s, Nothing)
1331 Stop -> return Stop
1333 where
1334 go !_ prev stt !acc = do
1335 res <- step (adaptState gst) stt
1336 case res of
1337 Yield x s -> do
1338 if cmp prev x
1339 then do
1340 acc' <- fstep acc x
1341 go SPEC x s acc'
1342 else
1343 done acc >>= \r -> return $ Yield r (Just s, Just x)
1344 Skip s -> go SPEC prev s acc
1345 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1347 stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1348 acc <- initial
1349 acc' <- fstep acc prev'
1350 go SPEC prev' st acc'
1352 where
1353 go !_ prevv stt !acc = do
1354 res <- step (adaptState gst) stt
1355 case res of
1356 Yield x s -> do
1357 if cmp prevv x
1358 then do
1359 acc' <- fstep acc x
1360 go SPEC x s acc'
1361 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1362 Skip s -> go SPEC prevv s acc
1363 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1365 stepOuter _ _ (Nothing, _) = return Stop
1367{-# INLINE_NORMAL splitBy #-}
1368splitBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1369splitBy predicate f (Stream step state) = Stream (step' f) (Just state)
1371 where
1373 {-# INLINE_LATE step' #-}
1374 step' (Fold fstep initial done) gst (Just st) = initial >>= go SPEC st
1376 where
1378 go !_ stt !acc = do
1379 res <- step (adaptState gst) stt
1380 case res of
1381 Yield x s -> do
1382 if predicate x
1383 then done acc >>= \r -> return $ Yield r (Just s)
1384 else do
1385 acc' <- fstep acc x
1386 go SPEC s acc'
1387 Skip s -> go SPEC s acc
1388 Stop -> done acc >>= \r -> return $ Yield r Nothing
1390 step' _ _ Nothing = return Stop
1392-- XXX requires -funfolding-use-threshold=150 in lines-unlines benchmark
1393{-# INLINE_NORMAL splitSuffixBy #-}
1394splitSuffixBy :: Monad m
1395 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1396splitSuffixBy predicate f (Stream step state) = Stream (step' f) (Just state)
1398 where
1400 {-# INLINE_LATE step' #-}
1401 step' (Fold fstep initial done) gst (Just st) = do
1402 res <- step (adaptState gst) st
1403 case res of
1404 Yield x s -> do
1405 acc <- initial
1406 if predicate x
1407 then done acc >>= \val -> return $ Yield val (Just s)
1408 else do
1409 acc' <- fstep acc x
1410 go SPEC s acc'
1412 Skip s -> return $ Skip $ Just s
1413 Stop -> return Stop
1415 where
1417 go !_ stt !acc = do
1418 res <- step (adaptState gst) stt
1419 case res of
1420 Yield x s -> do
1421 if predicate x
1422 then done acc >>= \r -> return $ Yield r (Just s)
1423 else do
1424 acc' <- fstep acc x
1425 go SPEC s acc'
1426 Skip s -> go SPEC s acc
1427 Stop -> done acc >>= \r -> return $ Yield r Nothing
1429 step' _ _ Nothing = return Stop
1431{-# INLINE_NORMAL wordsBy #-}
1432wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1433wordsBy predicate f (Stream step state) = Stream (stepOuter f) (Just state)
1435 where
1437 {-# INLINE_LATE stepOuter #-}
1438 stepOuter (Fold fstep initial done) gst (Just st) = do
1439 res <- step (adaptState gst) st
1440 case res of
1441 Yield x s -> do
1442 if predicate x
1443 then return $ Skip (Just s)
1444 else do
1445 acc <- initial
1446 acc' <- fstep acc x
1447 go SPEC s acc'
1449 Skip s -> return $ Skip $ Just s
1450 Stop -> return Stop
1452 where
1454 go !_ stt !acc = do
1455 res <- step (adaptState gst) stt
1456 case res of
1457 Yield x s -> do
1458 if predicate x
1459 then done acc >>= \r -> return $ Yield r (Just s)
1460 else do
1461 acc' <- fstep acc x
1462 go SPEC s acc'
1463 Skip s -> go SPEC s acc
1464 Stop -> done acc >>= \r -> return $ Yield r Nothing
1466 stepOuter _ _ Nothing = return Stop
1468-- String search algorithms:
1469-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1472-- TODO can we unify the splitting operations using a splitting configuration
1473-- like in the split package.
1475data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1477data SplitOptions = SplitOptions
1478 { style :: SplitStyle
1479 , withSep :: Bool -- ^ keep the separators in output
1480 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1481 -- , trimHead :: Bool -- ^ drop blank at head
1482 -- , trimTail :: Bool -- ^ drop blank at tail
1486data SplitOnState s a =
1487 GO_START
1488 | GO_EMPTY_PAT s
1489 | GO_SINGLE_PAT s a
1490 | GO_SHORT_PAT s
1491 | GO_KARP_RABIN s !(RB.Ring a) !(Ptr a)
1492 | GO_DONE
1494{-# INLINE_NORMAL splitOn #-}
1495splitOn
1496 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1497 => Array a
1498 -> Fold m a b
1499 -> Stream m a
1500 -> Stream m b
1501splitOn patArr@Array{..} (Fold fstep initial done) (Stream step state) =
1502 Stream stepOuter GO_START
1504 where
1506 patLen = A.length patArr
1507 maxIndex = patLen - 1
1508 elemBits = sizeOf (undefined :: a) * 8
1510 {-# INLINE_LATE stepOuter #-}
1511 stepOuter _ GO_START =
1512 if patLen == 0
1513 then return $ Skip $ GO_EMPTY_PAT state
1514 else if patLen == 1
1515 then do
1516 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1517 return $ Skip $ GO_SINGLE_PAT state r
1518 else if sizeOf (undefined :: a) * patLen
1519 <= sizeOf (undefined :: Word)
1520 then return $ Skip $ GO_SHORT_PAT state
1521 else do
1522 (rb, rhead) <- liftIO $ RB.new patLen
1523 return $ Skip $ GO_KARP_RABIN state rb rhead
1525 stepOuter gst (GO_SINGLE_PAT stt pat) = initial >>= go SPEC stt
1527 where
1529 go !_ st !acc = do
1530 res <- step (adaptState gst) st
1531 case res of
1532 Yield x s -> do
1533 if pat == x
1534 then do
1535 r <- done acc
1536 return $ Yield r (GO_SINGLE_PAT s pat)
1537 else fstep acc x >>= go SPEC s
1538 Skip s -> go SPEC s acc
1539 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1541 stepOuter gst (GO_SHORT_PAT stt) = initial >>= go0 SPEC 0 (0 :: Word) stt
1543 where
1545 mask :: Word
1546 mask = (1 `shiftL` (elemBits * patLen)) - 1
1548 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1550 patWord :: Word
1551 patWord = mask .&. A.foldl' addToWord 0 patArr
1553 go0 !_ !idx wrd st !acc = do
1554 res <- step (adaptState gst) st
1555 case res of
1556 Yield x s -> do
1557 let wrd' = addToWord wrd x
1558 if idx == maxIndex
1559 then do
1560 if wrd' .&. mask == patWord
1561 then do
1562 r <- done acc
1563 return $ Yield r (GO_SHORT_PAT s)
1564 else go1 SPEC wrd' s acc
1565 else go0 SPEC (idx + 1) wrd' s acc
1566 Skip s -> go0 SPEC idx wrd s acc
1567 Stop -> do
1568 acc' <- if idx /= 0
1569 then go2 wrd idx acc
1570 else return acc
1571 done acc' >>= \r -> return $ Yield r GO_DONE
1573 {-# INLINE go1 #-}
1574 go1 !_ wrd st !acc = do
1575 res <- step (adaptState gst) st
1576 case res of
1577 Yield x s -> do
1578 let wrd' = addToWord wrd x
1579 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1580 acc' <- fstep acc (toEnum $ fromIntegral old)
1581 if wrd' .&. mask == patWord
1582 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1583 else go1 SPEC wrd' s acc'
1584 Skip s -> go1 SPEC wrd s acc
1585 Stop -> do
1586 acc' <- go2 wrd patLen acc
1587 done acc' >>= \r -> return $ Yield r GO_DONE
1589 go2 !wrd !n !acc | n > 0 = do
1590 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1591 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1592 go2 _ _ acc = return acc
1594 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1595 initial >>= go0 SPEC 0 rhead stt
1597 where
1599 k = 2891336453 :: Word32
1600 coeff = k ^ patLen
1601 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1602 deltaCksum cksum old new =
1603 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1605 -- XXX shall we use a random starting hash or 1 instead of 0?
1606 patHash = A.foldl' addCksum 0 patArr
1608 -- rh == ringHead
1609 go0 !_ !idx !rh st !acc = do
1610 res <- step (adaptState gst) st
1611 case res of
1612 Yield x s -> do
1613 rh' <- liftIO $ RB.unsafeInsert rb rh x
1614 if idx == maxIndex
1615 then do
1616 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1617 let !ringHash = fold addCksum 0 rb
1618 if ringHash == patHash
1619 then go2 SPEC ringHash rh' s acc
1620 else go1 SPEC ringHash rh' s acc
1621 else go0 SPEC (idx + 1) rh' s acc
1622 Skip s -> go0 SPEC idx rh s acc
1623 Stop -> do
1624 !acc' <- if idx /= 0
1625 then RB.unsafeFoldRingM rh fstep acc rb
1626 else return acc
1627 done acc' >>= \r -> return $ Yield r GO_DONE
1629 -- XXX Theoretically this code can do 4 times faster if GHC generates
1630 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1631 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1632 -- the generated code changes drastically and becomes 4x slower. Need
1633 -- to investigate what is going on with GHC.
1634 {-# INLINE go1 #-}
1635 go1 !_ !cksum !rh st !acc = do
1636 res <- step (adaptState gst) st
1637 case res of
1638 Yield x s -> do
1639 old <- liftIO $ peek rh
1640 let cksum' = deltaCksum cksum old x
1641 acc' <- fstep acc old
1643 if (cksum' == patHash)
1644 then do
1645 rh' <- liftIO (RB.unsafeInsert rb rh x)
1646 go2 SPEC cksum' rh' s acc'
1647 else do
1648 rh' <- liftIO (RB.unsafeInsert rb rh x)
1649 go1 SPEC cksum' rh' s acc'
1650 Skip s -> go1 SPEC cksum rh s acc
1651 Stop -> do
1652 acc' <- RB.unsafeFoldRingFullM rh fstep acc rb
1653 done acc' >>= \r -> return $ Yield r GO_DONE
1655 go2 !_ !cksum' !rh' s !acc' = do
1656 if RB.unsafeEqArray rb rh' patArr
1657 then do
1658 r <- done acc'
1659 return $ Yield r (GO_KARP_RABIN s rb rhead)
1660 else go1 SPEC cksum' rh' s acc'
1662 stepOuter gst (GO_EMPTY_PAT st) = do
1663 res <- step (adaptState gst) st
1664 case res of
1665 Yield x s -> do
1666 acc <- initial
1667 acc' <- fstep acc x
1668 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1669 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1670 Stop -> return Stop
1672 stepOuter _ GO_DONE = return Stop
1674{-# INLINE_NORMAL splitSuffixOn #-}
1675splitSuffixOn
1676 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1677 => Bool
1678 -> Array a
1679 -> Fold m a b
1680 -> Stream m a
1681 -> Stream m b
1682splitSuffixOn withSep patArr@Array{..} (Fold fstep initial done)
1683 (Stream step state) =
1684 Stream stepOuter GO_START
1686 where
1688 patLen = A.length patArr
1689 maxIndex = patLen - 1
1690 elemBits = sizeOf (undefined :: a) * 8
1692 {-# INLINE_LATE stepOuter #-}
1693 stepOuter _ GO_START =
1694 if patLen == 0
1695 then return $ Skip $ GO_EMPTY_PAT state
1696 else if patLen == 1
1697 then do
1698 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1699 return $ Skip $ GO_SINGLE_PAT state r
1700 else if sizeOf (undefined :: a) * patLen
1701 <= sizeOf (undefined :: Word)
1702 then return $ Skip $ GO_SHORT_PAT state
1703 else do
1704 (rb, rhead) <- liftIO $ RB.new patLen
1705 return $ Skip $ GO_KARP_RABIN state rb rhead
1707 stepOuter gst (GO_SINGLE_PAT stt pat) = do
1708 -- This first part is the only difference between splitOn and
1709 -- splitSuffixOn.
1710 -- If the last element is a separator do not issue a blank segment.
1711 res <- step (adaptState gst) stt
1712 case res of
1713 Yield x s -> do
1714 acc <- initial
1715 if pat == x
1716 then do
1717 acc' <- if withSep then fstep acc x else return acc
1718 done acc' >>= \r -> return $ Yield r (GO_SINGLE_PAT s pat)
1719 else fstep acc x >>= go SPEC s
1720 Skip s -> return $ Skip $ (GO_SINGLE_PAT s pat)
1721 Stop -> return Stop
1723 where
1725 -- This is identical for splitOn and splitSuffixOn
1726 go !_ st !acc = do
1727 res <- step (adaptState gst) st
1728 case res of
1729 Yield x s -> do
1730 if pat == x
1731 then do
1732 acc' <- if withSep then fstep acc x else return acc
1733 r <- done acc'
1734 return $ Yield r (GO_SINGLE_PAT s pat)
1735 else fstep acc x >>= go SPEC s
1736 Skip s -> go SPEC s acc
1737 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1739 stepOuter gst (GO_SHORT_PAT stt) = do
1741 -- Call "initial" only if the stream yields an element, otherwise we
1742 -- may call "initial" but never yield anything. initial may produce a
1743 -- side effect, therefore we will end up doing and discard a side
1744 -- effect.
1746 let idx = 0
1747 let wrd = 0
1748 res <- step (adaptState gst) stt
1749 case res of
1750 Yield x s -> do
1751 acc <- initial
1752 let wrd' = addToWord wrd x
1753 acc' <- if withSep then fstep acc x else return acc
1754 if idx == maxIndex
1755 then do
1756 if wrd' .&. mask == patWord
1757 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1758 else go0 SPEC (idx + 1) wrd' s acc'
1759 else go0 SPEC (idx + 1) wrd' s acc'
1760 Skip s -> return $ Skip (GO_SHORT_PAT s)
1761 Stop -> return Stop
1763 where
1765 mask :: Word
1766 mask = (1 `shiftL` (elemBits * patLen)) - 1
1768 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1770 patWord :: Word
1771 patWord = mask .&. A.foldl' addToWord 0 patArr
1773 go0 !_ !idx wrd st !acc = do
1774 res <- step (adaptState gst) st
1775 case res of
1776 Yield x s -> do
1777 let wrd' = addToWord wrd x
1778 acc' <- if withSep then fstep acc x else return acc
1779 if idx == maxIndex
1780 then do
1781 if wrd' .&. mask == patWord
1782 then do
1783 r <- done acc'
1784 return $ Yield r (GO_SHORT_PAT s)
1785 else go1 SPEC wrd' s acc'
1786 else go0 SPEC (idx + 1) wrd' s acc'
1787 Skip s -> go0 SPEC idx wrd s acc
1788 Stop -> do
1789 if (idx == maxIndex) && (wrd .&. mask == patWord)
1790 then return Stop
1791 else do
1792 acc' <- if idx /= 0 && not withSep
1793 then go2 wrd idx acc
1794 else return acc
1795 done acc' >>= \r -> return $ Yield r GO_DONE
1797 {-# INLINE go1 #-}
1798 go1 !_ wrd st !acc = do
1799 res <- step (adaptState gst) st
1800 case res of
1801 Yield x s -> do
1802 let wrd' = addToWord wrd x
1803 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1804 acc' <- if withSep
1805 then fstep acc x
1806 else fstep acc (toEnum $ fromIntegral old)
1807 if wrd' .&. mask == patWord
1808 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1809 else go1 SPEC wrd' s acc'
1810 Skip s -> go1 SPEC wrd s acc
1811 Stop ->
1812 -- If the last sequence is a separator do not issue a blank
1813 -- segment.
1814 if wrd .&. mask == patWord
1815 then return Stop
1816 else do
1817 acc' <- if withSep
1818 then return acc
1819 else go2 wrd patLen acc
1820 done acc' >>= \r -> return $ Yield r GO_DONE
1822 go2 !wrd !n !acc | n > 0 = do
1823 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1824 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1825 go2 _ _ acc = return acc
1827 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1828 let idx = 0
1829 res <- step (adaptState gst) stt
1830 case res of
1831 Yield x s -> do
1832 acc <- initial
1833 acc' <- if withSep then fstep acc x else return acc
1834 rh' <- liftIO (RB.unsafeInsert rb rhead x)
1835 if idx == maxIndex
1836 then do
1837 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1838 let !ringHash = fold addCksum 0 rb
1839 if ringHash == patHash
1840 then go2 SPEC ringHash rh' s acc'
1841 else go0 SPEC (idx + 1) rh' s acc'
1842 else go0 SPEC (idx + 1) rh' s acc'
1843 Skip s -> return $ Skip (GO_KARP_RABIN s rb rhead)
1844 Stop -> return Stop
1846 where
1848 k = 2891336453 :: Word32
1849 coeff = k ^ patLen
1850 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1851 deltaCksum cksum old new =
1852 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1854 -- XXX shall we use a random starting hash or 1 instead of 0?
1855 patHash = A.foldl' addCksum 0 patArr
1857 -- rh == ringHead
1858 go0 !_ !idx !rh st !acc = do
1859 res <- step (adaptState gst) st
1860 case res of
1861 Yield x s -> do
1862 acc' <- if withSep then fstep acc x else return acc
1863 rh' <- liftIO (RB.unsafeInsert rb rh x)
1864 if idx == maxIndex
1865 then do
1866 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1867 let !ringHash = fold addCksum 0 rb
1868 if ringHash == patHash
1869 then go2 SPEC ringHash rh' s acc'
1870 else go1 SPEC ringHash rh' s acc'
1871 else go0 SPEC (idx + 1) rh' s acc'
1872 Skip s -> go0 SPEC idx rh s acc
1873 Stop -> do
1874 -- do not issue a blank segment when we end at pattern
1875 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
1876 then return Stop
1877 else do
1878 !acc' <- if idx /= 0 && not withSep
1879 then RB.unsafeFoldRingM rh fstep acc rb
1880 else return acc
1881 done acc' >>= \r -> return $ Yield r GO_DONE
1883 -- XXX Theoretically this code can do 4 times faster if GHC generates
1884 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1885 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1886 -- the generated code changes drastically and becomes 4x slower. Need
1887 -- to investigate what is going on with GHC.
1888 {-# INLINE go1 #-}
1889 go1 !_ !cksum !rh st !acc = do
1890 res <- step (adaptState gst) st
1891 case res of
1892 Yield x s -> do
1893 old <- liftIO $ peek rh
1894 let cksum' = deltaCksum cksum old x
1895 acc' <- if withSep
1896 then fstep acc x
1897 else fstep acc old
1899 if (cksum' == patHash)
1900 then do
1901 rh' <- liftIO (RB.unsafeInsert rb rh x)
1902 go2 SPEC cksum' rh' s acc'
1903 else do
1904 rh' <- liftIO (RB.unsafeInsert rb rh x)
1905 go1 SPEC cksum' rh' s acc'
1906 Skip s -> go1 SPEC cksum rh s acc
1907 Stop -> do
1908 if RB.unsafeEqArray rb rh patArr
1909 then return Stop
1910 else do
1911 acc' <- if withSep
1912 then return acc
1913 else RB.unsafeFoldRingFullM rh fstep acc rb
1914 done acc' >>= \r -> return $ Yield r GO_DONE
1916 go2 !_ !cksum' !rh' s !acc' = do
1917 if RB.unsafeEqArray rb rh' patArr
1918 then do
1919 r <- done acc'
1920 return $ Yield r (GO_KARP_RABIN s rb rhead)
1921 else go1 SPEC cksum' rh' s acc'
1923 stepOuter gst (GO_EMPTY_PAT st) = do
1924 res <- step (adaptState gst) st
1925 case res of
1926 Yield x s -> do
1927 acc <- initial
1928 acc' <- fstep acc x
1929 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1930 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1931 Stop -> return Stop
1933 stepOuter _ GO_DONE = return Stop
1935data SplitState s arr
1936 = SplitInitial s
1937 | SplitBuffering s arr
1938 | SplitSplitting s arr
1939 | SplitYielding arr (SplitState s arr)
1940 | SplitFinishing
1942-- XXX An alternative approach would be to use a partial fold (Fold m a b) to
1943-- split using a splitBy like combinator. The Fold would consume upto the
1944-- separator and return any leftover which can then be fed to the next fold.
1946-- We can revisit this once we have partial folds/parsers.
1948-- | Performs infix separator style splitting.
1949{-# INLINE_NORMAL splitInnerBy #-}
1950splitInnerBy
1951 :: Monad m
1952 => (f a -> m (f a, Maybe (f a))) -- splitter
1953 -> (f a -> f a -> m (f a)) -- joiner
1954 -> Stream m (f a)
1955 -> Stream m (f a)
1956splitInnerBy splitter joiner (Stream step1 state1) =
1957 (Stream step (SplitInitial state1))
1959 where
1961 {-# INLINE_LATE step #-}
1962 step gst (SplitInitial st) = do
1963 r <- step1 gst st
1964 case r of
1965 Yield x s -> do
1966 (x1, mx2) <- splitter x
1967 return $ case mx2 of
1968 Nothing -> Skip (SplitBuffering s x1)
1969 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
1970 Skip s -> return $ Skip (SplitInitial s)
1971 Stop -> return $ Stop
1973 step gst (SplitBuffering st buf) = do
1974 r <- step1 gst st
1975 case r of
1976 Yield x s -> do
1977 (x1, mx2) <- splitter x
1978 buf' <- joiner buf x1
1979 return $ case mx2 of
1980 Nothing -> Skip (SplitBuffering s buf')
1981 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
1982 Skip s -> return $ Skip (SplitBuffering s buf)
1983 Stop -> return $ Skip (SplitYielding buf SplitFinishing)
1985 step _ (SplitSplitting st buf) = do
1986 (x1, mx2) <- splitter buf
1987 return $ case mx2 of
1988 Nothing -> Skip $ SplitBuffering st x1
1989 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
1991 step _ (SplitYielding x next) = return $ Yield x next
1992 step _ SplitFinishing = return $ Stop
1994-- | Performs infix separator style splitting.
1995{-# INLINE_NORMAL splitInnerBySuffix #-}
1996splitInnerBySuffix
1997 :: (Monad m, Eq (f a), Monoid (f a))
1998 => (f a -> m (f a, Maybe (f a))) -- splitter
1999 -> (f a -> f a -> m (f a)) -- joiner
2000 -> Stream m (f a)
2001 -> Stream m (f a)
2002splitInnerBySuffix splitter joiner (Stream step1 state1) =
2003 (Stream step (SplitInitial state1))
2005 where
2007 {-# INLINE_LATE step #-}
2008 step gst (SplitInitial st) = do
2009 r <- step1 gst st
2010 case r of
2011 Yield x s -> do
2012 (x1, mx2) <- splitter x
2013 return $ case mx2 of
2014 Nothing -> Skip (SplitBuffering s x1)
2015 Just x2 -> Skip (SplitYielding x1 (SplitSplitting s x2))
2016 Skip s -> return $ Skip (SplitInitial s)
2017 Stop -> return $ Stop
2019 step gst (SplitBuffering st buf) = do
2020 r <- step1 gst st
2021 case r of
2022 Yield x s -> do
2023 (x1, mx2) <- splitter x
2024 buf' <- joiner buf x1
2025 return $ case mx2 of
2026 Nothing -> Skip (SplitBuffering s buf')
2027 Just x2 -> Skip (SplitYielding buf' (SplitSplitting s x2))
2028 Skip s -> return $ Skip (SplitBuffering s buf)
2029 Stop -> return $
2030 if buf == mempty
2031 then Stop
2032 else Skip (SplitYielding buf SplitFinishing)
2034 step _ (SplitSplitting st buf) = do
2035 (x1, mx2) <- splitter buf
2036 return $ case mx2 of
2037 Nothing -> Skip $ SplitBuffering st x1
2038 Just x2 -> Skip $ SplitYielding x1 (SplitSplitting st x2)
2040 step _ (SplitYielding x next) = return $ Yield x next
2041 step _ SplitFinishing = return $ Stop
2043------------------------------------------------------------------------------
2044-- Substreams
2045------------------------------------------------------------------------------
2047{-# INLINE_NORMAL isPrefixOf #-}
2048isPrefixOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
2049isPrefixOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
2050 where
2051 go (sa, sb, Nothing) = do
2052 r <- stepa defState sa
2053 case r of
2054 Yield x sa' -> go (sa', sb, Just x)
2055 Skip sa' -> go (sa', sb, Nothing)
2056 Stop -> return True
2058 go (sa, sb, Just x) = do
2059 r <- stepb defState sb
2060 case r of
2061 Yield y sb' ->
2062 if x == y
2063 then go (sa, sb', Nothing)
2064 else return False
2065 Skip sb' -> go (sa, sb', Just x)
2066 Stop -> return False
2068{-# INLINE_NORMAL isSubsequenceOf #-}
2069isSubsequenceOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
2070isSubsequenceOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
2071 where
2072 go (sa, sb, Nothing) = do
2073 r <- stepa defState sa
2074 case r of
2075 Yield x sa' -> go (sa', sb, Just x)
2076 Skip sa' -> go (sa', sb, Nothing)
2077 Stop -> return True
2079 go (sa, sb, Just x) = do
2080 r <- stepb defState sb
2081 case r of
2082 Yield y sb' ->
2083 if x == y
2084 then go (sa, sb', Nothing)
2085 else go (sa, sb', Just x)
2086 Skip sb' -> go (sa, sb', Just x)
2087 Stop -> return False
2089{-# INLINE_NORMAL stripPrefix #-}
2090stripPrefix
2091 :: (Eq a, Monad m)
2092 => Stream m a -> Stream m a -> m (Maybe (Stream m a))
2093stripPrefix (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
2094 where
2095 go (sa, sb, Nothing) = do
2096 r <- stepa defState sa
2097 case r of
2098 Yield x sa' -> go (sa', sb, Just x)
2099 Skip sa' -> go (sa', sb, Nothing)
2100 Stop -> return $ Just (Stream stepb sb)
2102 go (sa, sb, Just x) = do
2103 r <- stepb defState sb
2104 case r of
2105 Yield y sb' ->
2106 if x == y
2107 then go (sa, sb', Nothing)
2108 else return Nothing
2109 Skip sb' -> go (sa, sb', Just x)
2110 Stop -> return Nothing
2112------------------------------------------------------------------------------
2113-- Map and Fold
2114------------------------------------------------------------------------------
2116-- | Execute a monadic action for each element of the 'Stream'
2117{-# INLINE_NORMAL mapM_ #-}
2118mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
2119mapM_ m = drain . mapM m
2121-------------------------------------------------------------------------------
2122-- Stream transformations using Unfolds
2123-------------------------------------------------------------------------------
2125-- Define a unique structure to use in inspection testing
2126data ConcatMapUState o i =
2127 ConcatMapUOuter o
2128 | ConcatMapUInner o i
2130-- | @concatMapU unfold stream@ uses @unfold@ to map the input stream elements
2131-- to streams and then flattens the generated streams into a single output
2132-- stream.
2134-- This is like 'concatMap' but uses an unfold with an explicit state to
2135-- generate the stream instead of a 'Stream' type generator. This allows better
2136-- optimization via fusion. This can be many times more efficient than
2137-- 'concatMap'.
2139{-# INLINE_NORMAL concatMapU #-}
2140concatMapU :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2141concatMapU (Unfold istep inject) (Stream ostep ost) =
2142 Stream step (ConcatMapUOuter ost)
2143 where
2144 {-# INLINE_LATE step #-}
2145 step gst (ConcatMapUOuter o) = do
2146 r <- ostep (adaptState gst) o
2147 case r of
2148 Yield a o' -> do
2149 i <- inject a
2150 i `seq` return (Skip (ConcatMapUInner o' i))
2151 Skip o' -> return $ Skip (ConcatMapUOuter o')
2152 Stop -> return $ Stop
2154 step _ (ConcatMapUInner o i) = do
2155 r <- istep i
2156 return $ case r of
2157 Yield x i' -> Yield x (ConcatMapUInner o i')
2158 Skip i' -> Skip (ConcatMapUInner o i')
2159 Stop -> Skip (ConcatMapUOuter o)
2161data ConcatUnfoldInterleaveState o i =
2162 ConcatUnfoldInterleaveOuter o [i]
2163 | ConcatUnfoldInterleaveInner o [i]
2164 | ConcatUnfoldInterleaveInnerL [i] [i]
2165 | ConcatUnfoldInterleaveInnerR [i] [i]
2167-- XXX use arrays to store state instead of lists.
2168-- XXX In general we can use different scheduling strategies e.g. how to
2169-- schedule the outer vs inner loop or assigning weights to different streams
2170-- or outer and inner loops.
2172-- After a yield, switch to the next stream. Do not switch streams on Skip.
2173-- Yield from outer stream switches to the inner stream.
2175-- There are two choices here, (1) exhaust the outer stream first and then
2176-- start yielding from the inner streams, this is much simpler to implement,
2177-- (2) yield at least one element from an inner stream before going back to
2178-- outer stream and opening the next stream from it.
2180-- Ideally, we need some scheduling bias to inner streams vs outer stream.
2181-- Maybe we can configure the behavior.
2183{-# INLINE_NORMAL concatUnfoldInterleave #-}
2184concatUnfoldInterleave :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2185concatUnfoldInterleave (Unfold istep inject) (Stream ostep ost) =
2186 Stream step (ConcatUnfoldInterleaveOuter ost [])
2187 where
2188 {-# INLINE_LATE step #-}
2189 step gst (ConcatUnfoldInterleaveOuter o ls) = do
2190 r <- ostep (adaptState gst) o
2191 case r of
2192 Yield a o' -> do
2193 i <- inject a
2194 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
2195 Skip o' -> return $ Skip (ConcatUnfoldInterleaveOuter o' ls)
2196 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2198 step _ (ConcatUnfoldInterleaveInner _ []) = undefined
2199 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
2200 r <- istep st
2201 return $ case r of
2202 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
2203 Skip s -> Skip (ConcatUnfoldInterleaveInner o (s:ls))
2204 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
2206 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
2207 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
2208 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
2210 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
2211 r <- istep st
2212 return $ case r of
2213 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
2214 Skip s -> Skip (ConcatUnfoldInterleaveInnerL (s:ls) rs)
2215 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
2217 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
2218 step _ (ConcatUnfoldInterleaveInnerR ls []) =
2219 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2221 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
2222 r <- istep st
2223 return $ case r of
2224 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2225 Skip s -> Skip (ConcatUnfoldInterleaveInnerR ls (s:rs))
2226 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
2228-- XXX In general we can use different scheduling strategies e.g. how to
2229-- schedule the outer vs inner loop or assigning weights to different streams
2230-- or outer and inner loops.
2232-- This could be inefficient if the tasks are too small.
2234-- Compared to concatUnfoldInterleave this one switches streams on Skips.
2236{-# INLINE_NORMAL concatUnfoldRoundrobin #-}
2237concatUnfoldRoundrobin :: Monad m => Unfold m a b -> Stream m a -> Stream m b
2238concatUnfoldRoundrobin (Unfold istep inject) (Stream ostep ost) =
2239 Stream step (ConcatUnfoldInterleaveOuter ost [])
2240 where
2241 {-# INLINE_LATE step #-}
2242 step gst (ConcatUnfoldInterleaveOuter o ls) = do
2243 r <- ostep (adaptState gst) o
2244 case r of
2245 Yield a o' -> do
2246 i <- inject a
2247 i `seq` return (Skip (ConcatUnfoldInterleaveInner o' (i : ls)))
2248 Skip o' -> return $ Skip (ConcatUnfoldInterleaveInner o' ls)
2249 Stop -> return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2251 step _ (ConcatUnfoldInterleaveInner o []) =
2252 return $ Skip (ConcatUnfoldInterleaveOuter o [])
2254 step _ (ConcatUnfoldInterleaveInner o (st:ls)) = do
2255 r <- istep st
2256 return $ case r of
2257 Yield x s -> Yield x (ConcatUnfoldInterleaveOuter o (s:ls))
2258 Skip s -> Skip (ConcatUnfoldInterleaveOuter o (s:ls))
2259 Stop -> Skip (ConcatUnfoldInterleaveOuter o ls)
2261 step _ (ConcatUnfoldInterleaveInnerL [] []) = return Stop
2262 step _ (ConcatUnfoldInterleaveInnerL [] rs) =
2263 return $ Skip (ConcatUnfoldInterleaveInnerR [] rs)
2265 step _ (ConcatUnfoldInterleaveInnerL (st:ls) rs) = do
2266 r <- istep st
2267 return $ case r of
2268 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerL ls (s:rs))
2269 Skip s -> Skip (ConcatUnfoldInterleaveInnerL ls (s:rs))
2270 Stop -> Skip (ConcatUnfoldInterleaveInnerL ls rs)
2272 step _ (ConcatUnfoldInterleaveInnerR [] []) = return Stop
2273 step _ (ConcatUnfoldInterleaveInnerR ls []) =
2274 return $ Skip (ConcatUnfoldInterleaveInnerL ls [])
2276 step _ (ConcatUnfoldInterleaveInnerR ls (st:rs)) = do
2277 r <- istep st
2278 return $ case r of
2279 Yield x s -> Yield x (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2280 Skip s -> Skip (ConcatUnfoldInterleaveInnerR (s:ls) rs)
2281 Stop -> Skip (ConcatUnfoldInterleaveInnerR ls rs)
2283data AppendState s1 s2 = AppendFirst s1 | AppendSecond s2
2285-- Note that this could be much faster compared to the CPS stream. However, as
2286-- the number of streams being composed increases this may become expensive.
2287-- Need to see where the breaking point is between the two.
2289{-# INLINE_NORMAL append #-}
2290append :: Monad m => Stream m a -> Stream m a -> Stream m a
2291append (Stream step1 state1) (Stream step2 state2) =
2292 Stream step (AppendFirst state1)
2294 where
2296 {-# INLINE_LATE step #-}
2297 step gst (AppendFirst st) = do
2298 r <- step1 gst st
2299 return $ case r of
2300 Yield a s -> Yield a (AppendFirst s)
2301 Skip s -> Skip (AppendFirst s)
2302 Stop -> Skip (AppendSecond state2)
2304 step gst (AppendSecond st) = do
2305 r <- step2 gst st
2306 return $ case r of
2307 Yield a s -> Yield a (AppendSecond s)
2308 Skip s -> Skip (AppendSecond s)
2309 Stop -> Stop
2311data InterleaveState s1 s2 = InterleaveFirst s1 s2 | InterleaveSecond s1 s2
2312 | InterleaveSecondOnly s2 | InterleaveFirstOnly s1
2314{-# INLINE_NORMAL interleave #-}
2315interleave :: Monad m => Stream m a -> Stream m a -> Stream m a
2316interleave (Stream step1 state1) (Stream step2 state2) =
2317 Stream step (InterleaveFirst state1 state2)
2319 where
2321 {-# INLINE_LATE step #-}
2322 step gst (InterleaveFirst st1 st2) = do
2323 r <- step1 gst st1
2324 return $ case r of
2325 Yield a s -> Yield a (InterleaveSecond s st2)
2326 Skip s -> Skip (InterleaveFirst s st2)
2327 Stop -> Skip (InterleaveSecondOnly st2)
2329 step gst (InterleaveSecond st1 st2) = do
2330 r <- step2 gst st2
2331 return $ case r of
2332 Yield a s -> Yield a (InterleaveFirst st1 s)
2333 Skip s -> Skip (InterleaveSecond st1 s)
2334 Stop -> Skip (InterleaveFirstOnly st1)
2336 step gst (InterleaveFirstOnly st1) = do
2337 r <- step1 gst st1
2338 return $ case r of
2339 Yield a s -> Yield a (InterleaveFirstOnly s)
2340 Skip s -> Skip (InterleaveFirstOnly s)
2341 Stop -> Stop
2343 step gst (InterleaveSecondOnly st2) = do
2344 r <- step2 gst st2
2345 return $ case r of
2346 Yield a s -> Yield a (InterleaveSecondOnly s)
2347 Skip s -> Skip (InterleaveSecondOnly s)
2348 Stop -> Stop
2350{-# INLINE_NORMAL interleaveMin #-}
2351interleaveMin :: Monad m => Stream m a -> Stream m a -> Stream m a
2352interleaveMin (Stream step1 state1) (Stream step2 state2) =
2353 Stream step (InterleaveFirst state1 state2)
2355 where
2357 {-# INLINE_LATE step #-}
2358 step gst (InterleaveFirst st1 st2) = do
2359 r <- step1 gst st1
2360 return $ case r of
2361 Yield a s -> Yield a (InterleaveSecond s st2)
2362 Skip s -> Skip (InterleaveFirst s st2)
2363 Stop -> Stop
2365 step gst (InterleaveSecond st1 st2) = do
2366 r <- step2 gst st2
2367 return $ case r of
2368 Yield a s -> Yield a (InterleaveFirst st1 s)
2369 Skip s -> Skip (InterleaveSecond st1 s)
2370 Stop -> Stop
2372 step _ (InterleaveFirstOnly _) = undefined
2373 step _ (InterleaveSecondOnly _) = undefined
2375{-# INLINE_NORMAL interleaveSuffix #-}
2376interleaveSuffix :: Monad m => Stream m a -> Stream m a -> Stream m a
2377interleaveSuffix (Stream step1 state1) (Stream step2 state2) =
2378 Stream step (InterleaveFirst state1 state2)
2380 where
2382 {-# INLINE_LATE step #-}
2383 step gst (InterleaveFirst st1 st2) = do
2384 r <- step1 gst st1
2385 return $ case r of
2386 Yield a s -> Yield a (InterleaveSecond s st2)
2387 Skip s -> Skip (InterleaveFirst s st2)
2388 Stop -> Stop
2390 step gst (InterleaveSecond st1 st2) = do
2391 r <- step2 gst st2
2392 return $ case r of
2393 Yield a s -> Yield a (InterleaveFirst st1 s)
2394 Skip s -> Skip (InterleaveSecond st1 s)
2395 Stop -> Skip (InterleaveFirstOnly st1)
2397 step gst (InterleaveFirstOnly st1) = do
2398 r <- step1 gst st1
2399 return $ case r of
2400 Yield a s -> Yield a (InterleaveFirstOnly s)
2401 Skip s -> Skip (InterleaveFirstOnly s)
2402 Stop -> Stop
2404 step _ (InterleaveSecondOnly _) = undefined
2406data InterleaveInfixState s1 s2 a
2407 = InterleaveInfixFirst s1 s2
2408 | InterleaveInfixSecondBuf s1 s2
2409 | InterleaveInfixSecondYield s1 s2 a
2410 | InterleaveInfixFirstYield s1 s2 a
2411 | InterleaveInfixFirstOnly s1
2413{-# INLINE_NORMAL interleaveInfix #-}
2414interleaveInfix :: Monad m => Stream m a -> Stream m a -> Stream m a
2415interleaveInfix (Stream step1 state1) (Stream step2 state2) =
2416 Stream step (InterleaveInfixFirst state1 state2)
2418 where
2420 {-# INLINE_LATE step #-}
2421 step gst (InterleaveInfixFirst st1 st2) = do
2422 r <- step1 gst st1
2423 return $ case r of
2424 Yield a s -> Yield a (InterleaveInfixSecondBuf s st2)
2425 Skip s -> Skip (InterleaveInfixFirst s st2)
2426 Stop -> Stop
2428 step gst (InterleaveInfixSecondBuf st1 st2) = do
2429 r <- step2 gst st2
2430 return $ case r of
2431 Yield a s -> Skip (InterleaveInfixSecondYield st1 s a)
2432 Skip s -> Skip (InterleaveInfixSecondBuf st1 s)
2433 Stop -> Skip (InterleaveInfixFirstOnly st1)
2435 step gst (InterleaveInfixSecondYield st1 st2 x) = do
2436 r <- step1 gst st1
2437 return $ case r of
2438 Yield a s -> Yield x (InterleaveInfixFirstYield s st2 a)
2439 Skip s -> Skip (InterleaveInfixSecondYield s st2 x)
2440 Stop -> Stop
2442 step _ (InterleaveInfixFirstYield st1 st2 x) = do
2443 return $ Yield x (InterleaveInfixSecondBuf st1 st2)
2445 step gst (InterleaveInfixFirstOnly st1) = do
2446 r <- step1 gst st1
2447 return $ case r of
2448 Yield a s -> Yield a (InterleaveInfixFirstOnly s)
2449 Skip s -> Skip (InterleaveInfixFirstOnly s)
2450 Stop -> Stop
2452{-# INLINE_NORMAL roundRobin #-}
2453roundRobin :: Monad m => Stream m a -> Stream m a -> Stream m a
2454roundRobin (Stream step1 state1) (Stream step2 state2) =
2455 Stream step (InterleaveFirst state1 state2)
2457 where
2459 {-# INLINE_LATE step #-}
2460 step gst (InterleaveFirst st1 st2) = do
2461 r <- step1 gst st1
2462 return $ case r of
2463 Yield a s -> Yield a (InterleaveSecond s st2)
2464 Skip s -> Skip (InterleaveSecond s st2)
2465 Stop -> Skip (InterleaveSecondOnly st2)
2467 step gst (InterleaveSecond st1 st2) = do
2468 r <- step2 gst st2
2469 return $ case r of
2470 Yield a s -> Yield a (InterleaveFirst st1 s)
2471 Skip s -> Skip (InterleaveFirst st1 s)
2472 Stop -> Skip (InterleaveFirstOnly st1)
2474 step gst (InterleaveSecondOnly st2) = do
2475 r <- step2 gst st2
2476 return $ case r of
2477 Yield a s -> Yield a (InterleaveSecondOnly s)
2478 Skip s -> Skip (InterleaveSecondOnly s)
2479 Stop -> Stop
2481 step gst (InterleaveFirstOnly st1) = do
2482 r <- step1 gst st1
2483 return $ case r of
2484 Yield a s -> Yield a (InterleaveFirstOnly s)
2485 Skip s -> Skip (InterleaveFirstOnly s)
2486 Stop -> Stop
2488data ICUState s1 s2 i1 i2 =
2489 ICUFirst s1 s2
2490 | ICUSecond s1 s2
2491 | ICUSecondOnly s2
2492 | ICUFirstOnly s1
2493 | ICUFirstInner s1 s2 i1
2494 | ICUSecondInner s1 s2 i2
2495 | ICUFirstOnlyInner s1 i1
2496 | ICUSecondOnlyInner s2 i2
2498-- | Interleave streams (full streams, not the elements) unfolded from two
2499-- input streams and concat. Stop when the first stream stops. If the second
2500-- stream ends before the first one then first stream still keeps running alone
2501-- without any interleaving with the second stream.
2503-- [a1, a2, ... an] [b1, b2 ...]
2504-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
2505-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
2506-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
2508{-# INLINE_NORMAL gintercalateSuffix #-}
2509gintercalateSuffix
2510 :: Monad m
2511 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
2512gintercalateSuffix
2513 (Unfold istep1 inject1) (Stream step1 state1)
2514 (Unfold istep2 inject2) (Stream step2 state2) =
2515 Stream step (ICUFirst state1 state2)
2517 where
2519 {-# INLINE_LATE step #-}
2520 step gst (ICUFirst s1 s2) = do
2521 r <- step1 (adaptState gst) s1
2522 case r of
2523 Yield a s -> do
2524 i <- inject1 a
2525 i `seq` return (Skip (ICUFirstInner s s2 i))
2526 Skip s -> return $ Skip (ICUFirst s s2)
2527 Stop -> return Stop
2529 step gst (ICUFirstOnly s1) = do
2530 r <- step1 (adaptState gst) s1
2531 case r of
2532 Yield a s -> do
2533 i <- inject1 a
2534 i `seq` return (Skip (ICUFirstOnlyInner s i))
2535 Skip s -> return $ Skip (ICUFirstOnly s)
2536 Stop -> return Stop
2538 step _ (ICUFirstInner s1 s2 i1) = do
2539 r <- istep1 i1
2540 return $ case r of
2541 Yield x i' -> Yield x (ICUFirstInner s1 s2 i')
2542 Skip i' -> Skip (ICUFirstInner s1 s2 i')
2543 Stop -> Skip (ICUSecond s1 s2)
2545 step _ (ICUFirstOnlyInner s1 i1) = do
2546 r <- istep1 i1
2547 return $ case r of
2548 Yield x i' -> Yield x (ICUFirstOnlyInner s1 i')
2549 Skip i' -> Skip (ICUFirstOnlyInner s1 i')
2550 Stop -> Skip (ICUFirstOnly s1)
2552 step gst (ICUSecond s1 s2) = do
2553 r <- step2 (adaptState gst) s2
2554 case r of
2555 Yield a s -> do
2556 i <- inject2 a
2557 i `seq` return (Skip (ICUSecondInner s1 s i))
2558 Skip s -> return $ Skip (ICUSecond s1 s)
2559 Stop -> return $ Skip (ICUFirstOnly s1)
2561 step _ (ICUSecondInner s1 s2 i2) = do
2562 r <- istep2 i2
2563 return $ case r of
2564 Yield x i' -> Yield x (ICUSecondInner s1 s2 i')
2565 Skip i' -> Skip (ICUSecondInner s1 s2 i')
2566 Stop -> Skip (ICUFirst s1 s2)
2568 step _ (ICUSecondOnly _s2) = undefined
2569 step _ (ICUSecondOnlyInner _s2 _i2) = undefined
2571data InterposeSuffixState s1 i1 =
2572 InterposeSuffixFirst s1
2573 -- | InterposeSuffixFirstYield s1 i1
2574 | InterposeSuffixFirstInner s1 i1
2575 | InterposeSuffixSecond s1
2577-- Note that if an unfolded layer turns out to be nil we still emit the
2578-- separator effect. An alternate behavior could be to emit the separator
2579-- effect only if at least one element has been yielded by the unfolding.
2580-- However, that becomes a bit complicated, so we have chosen the former
2581-- behvaior for now.
2582{-# INLINE_NORMAL interposeSuffix #-}
2583interposeSuffix
2584 :: Monad m
2585 => m c -> Unfold m b c -> Stream m b -> Stream m c
2586interposeSuffix
2587 action
2588 (Unfold istep1 inject1) (Stream step1 state1) =
2589 Stream step (InterposeSuffixFirst state1)
2591 where
2593 {-# INLINE_LATE step #-}
2594 step gst (InterposeSuffixFirst s1) = do
2595 r <- step1 (adaptState gst) s1
2596 case r of
2597 Yield a s -> do
2598 i <- inject1 a
2599 i `seq` return (Skip (InterposeSuffixFirstInner s i))
2600 -- i `seq` return (Skip (InterposeSuffixFirstYield s i))
2601 Skip s -> return $ Skip (InterposeSuffixFirst s)
2602 Stop -> return Stop
2604 {-
2605 step _ (InterposeSuffixFirstYield s1 i1) = do
2606 r <- istep1 i1
2607 return $ case r of
2608 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
2609 Skip i' -> Skip (InterposeSuffixFirstYield s1 i')
2610 Stop -> Skip (InterposeSuffixFirst s1)
2611 -}
2613 step _ (InterposeSuffixFirstInner s1 i1) = do
2614 r <- istep1 i1
2615 return $ case r of
2616 Yield x i' -> Yield x (InterposeSuffixFirstInner s1 i')
2617 Skip i' -> Skip (InterposeSuffixFirstInner s1 i')
2618 Stop -> Skip (InterposeSuffixSecond s1)
2620 step _ (InterposeSuffixSecond s1) = do
2621 r <- action
2622 return $ Yield r (InterposeSuffixFirst s1)
2624data ICALState s1 s2 i1 i2 a =
2625 ICALFirst s1 s2
2626 -- | ICALFirstYield s1 s2 i1
2627 | ICALFirstInner s1 s2 i1
2628 | ICALFirstOnly s1
2629 | ICALFirstOnlyInner s1 i1
2630 | ICALSecondInject s1 s2
2631 | ICALFirstInject s1 s2 i2
2632 -- | ICALFirstBuf s1 s2 i1 i2
2633 | ICALSecondInner s1 s2 i1 i2
2634 -- -- | ICALSecondInner s1 s2 i1 i2 a
2635 -- -- | ICALFirstResume s1 s2 i1 i2 a
2637-- | Interleave streams (full streams, not the elements) unfolded from two
2638-- input streams and concat. Stop when the first stream stops. If the second
2639-- stream ends before the first one then first stream still keeps running alone
2640-- without any interleaving with the second stream.
2642-- [a1, a2, ... an] [b1, b2 ...]
2643-- => [streamA1, streamA2, ... streamAn] [streamB1, streamB2, ...]
2644-- => [streamA1, streamB1, streamA2...StreamAn, streamBn]
2645-- => [a11, a12, ...a1j, b11, b12, ...b1k, a21, a22, ...]
2647{-# INLINE_NORMAL gintercalate #-}
2648gintercalate
2649 :: Monad m
2650 => Unfold m a c -> Stream m a -> Unfold m b c -> Stream m b -> Stream m c
2651gintercalate
2652 (Unfold istep1 inject1) (Stream step1 state1)
2653 (Unfold istep2 inject2) (Stream step2 state2) =
2654 Stream step (ICALFirst state1 state2)
2656 where
2658 {-# INLINE_LATE step #-}
2659 step gst (ICALFirst s1 s2) = do
2660 r <- step1 (adaptState gst) s1
2661 case r of
2662 Yield a s -> do
2663 i <- inject1 a
2664 i `seq` return (Skip (ICALFirstInner s s2 i))
2665 -- i `seq` return (Skip (ICALFirstYield s s2 i))
2666 Skip s -> return $ Skip (ICALFirst s s2)
2667 Stop -> return Stop
2669 {-
2670 step _ (ICALFirstYield s1 s2 i1) = do
2671 r <- istep1 i1
2672 return $ case r of
2673 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
2674 Skip i' -> Skip (ICALFirstYield s1 s2 i')
2675 Stop -> Skip (ICALFirst s1 s2)
2676 -}
2678 step _ (ICALFirstInner s1 s2 i1) = do
2679 r <- istep1 i1
2680 return $ case r of
2681 Yield x i' -> Yield x (ICALFirstInner s1 s2 i')
2682 Skip i' -> Skip (ICALFirstInner s1 s2 i')
2683 Stop -> Skip (ICALSecondInject s1 s2)
2685 step gst (ICALFirstOnly s1) = do
2686 r <- step1 (adaptState gst) s1
2687 case r of
2688 Yield a s -> do
2689 i <- inject1 a
2690 i `seq` return (Skip (ICALFirstOnlyInner s i))
2691 Skip s -> return $ Skip (ICALFirstOnly s)
2692 Stop -> return Stop
2694 step _ (ICALFirstOnlyInner s1 i1) = do
2695 r <- istep1 i1
2696 return $ case r of
2697 Yield x i' -> Yield x (ICALFirstOnlyInner s1 i')
2698 Skip i' -> Skip (ICALFirstOnlyInner s1 i')
2699 Stop -> Skip (ICALFirstOnly s1)
2701 -- We inject the second stream even before checking if the first stream
2702 -- would yield any more elements. There is no clear choice whether we
2703 -- should do this before or after that. Doing it after may make the state
2704 -- machine a bit simpler though.
2705 step gst (ICALSecondInject s1 s2) = do
2706 r <- step2 (adaptState gst) s2
2707 case r of
2708 Yield a s -> do
2709 i <- inject2 a
2710 i `seq` return (Skip (ICALFirstInject s1 s i))
2711 Skip s -> return $ Skip (ICALSecondInject s1 s)
2712 Stop -> return $ Skip (ICALFirstOnly s1)
2714 step gst (ICALFirstInject s1 s2 i2) = do
2715 r <- step1 (adaptState gst) s1
2716 case r of
2717 Yield a s -> do
2718 i <- inject1 a
2719 i `seq` return (Skip (ICALSecondInner s s2 i i2))
2720 -- i `seq` return (Skip (ICALFirstBuf s s2 i i2))
2721 Skip s -> return $ Skip (ICALFirstInject s s2 i2)
2722 Stop -> return Stop
2724 {-
2725 step _ (ICALFirstBuf s1 s2 i1 i2) = do
2726 r <- istep1 i1
2727 return $ case r of
2728 Yield x i' -> Skip (ICALSecondInner s1 s2 i' i2 x)
2729 Skip i' -> Skip (ICALFirstBuf s1 s2 i' i2)
2730 Stop -> Stop
2732 step _ (ICALSecondInner s1 s2 i1 i2 v) = do
2733 r <- istep2 i2
2734 return $ case r of
2735 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i' v)
2736 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i' v)
2737 Stop -> Skip (ICALFirstResume s1 s2 i1 i2 v)
2738 -}
2740 step _ (ICALSecondInner s1 s2 i1 i2) = do
2741 r <- istep2 i2
2742 return $ case r of
2743 Yield x i' -> Yield x (ICALSecondInner s1 s2 i1 i')
2744 Skip i' -> Skip (ICALSecondInner s1 s2 i1 i')
2745 Stop -> Skip (ICALFirstInner s1 s2 i1)
2746 -- Stop -> Skip (ICALFirstResume s1 s2 i1 i2)
2748 {-
2749 step _ (ICALFirstResume s1 s2 i1 i2 x) = do
2750 return $ Yield x (ICALFirstInner s1 s2 i1 i2)
2751 -}
2753data InterposeState s1 i1 a =
2754 InterposeFirst s1
2755 -- | InterposeFirstYield s1 i1
2756 | InterposeFirstInner s1 i1
2757 | InterposeFirstInject s1
2758 -- | InterposeFirstBuf s1 i1
2759 | InterposeSecondYield s1 i1
2760 -- -- | InterposeSecondYield s1 i1 a
2761 -- -- | InterposeFirstResume s1 i1 a
2763-- Note that this only interposes the pure values, we may run many effects to
2764-- generate those values as some effects may not generate anything (Skip).
2765{-# INLINE_NORMAL interpose #-}
2766interpose :: Monad m => m c -> Unfold m b c -> Stream m b -> Stream m c
2767interpose
2768 action
2769 (Unfold istep1 inject1) (Stream step1 state1) =
2770 Stream step (InterposeFirst state1)
2772 where
2774 {-# INLINE_LATE step #-}
2775 step gst (InterposeFirst s1) = do
2776 r <- step1 (adaptState gst) s1
2777 case r of
2778 Yield a s -> do
2779 i <- inject1 a
2780 i `seq` return (Skip (InterposeFirstInner s i))
2781 -- i `seq` return (Skip (InterposeFirstYield s i))
2782 Skip s -> return $ Skip (InterposeFirst s)
2783 Stop -> return Stop
2785 {-
2786 step _ (InterposeFirstYield s1 i1) = do
2787 r <- istep1 i1
2788 return $ case r of
2789 Yield x i' -> Yield x (InterposeFirstInner s1 i')
2790 Skip i' -> Skip (InterposeFirstYield s1 i')
2791 Stop -> Skip (InterposeFirst s1)
2792 -}
2794 step _ (InterposeFirstInner s1 i1) = do
2795 r <- istep1 i1
2796 return $ case r of
2797 Yield x i' -> Yield x (InterposeFirstInner s1 i')
2798 Skip i' -> Skip (InterposeFirstInner s1 i')
2799 Stop -> Skip (InterposeFirstInject s1)
2801 step gst (InterposeFirstInject s1) = do
2802 r <- step1 (adaptState gst) s1
2803 case r of
2804 Yield a s -> do
2805 i <- inject1 a
2806 -- i `seq` return (Skip (InterposeFirstBuf s i))
2807 i `seq` return (Skip (InterposeSecondYield s i))
2808 Skip s -> return $ Skip (InterposeFirstInject s)
2809 Stop -> return Stop
2811 {-
2812 step _ (InterposeFirstBuf s1 i1) = do
2813 r <- istep1 i1
2814 return $ case r of
2815 Yield x i' -> Skip (InterposeSecondYield s1 i' x)
2816 Skip i' -> Skip (InterposeFirstBuf s1 i')
2817 Stop -> Stop
2818 -}
2820 {-
2821 step _ (InterposeSecondYield s1 i1 v) = do
2822 r <- action
2823 return $ Yield r (InterposeFirstResume s1 i1 v)
2824 -}
2825 step _ (InterposeSecondYield s1 i1) = do
2826 r <- action
2827 return $ Yield r (InterposeFirstInner s1 i1)
2829 {-
2830 step _ (InterposeFirstResume s1 i1 v) = do
2831 return $ Yield v (InterposeFirstInner s1 i1)
2832 -}
2834------------------------------------------------------------------------------
2835-- Exceptions
2836------------------------------------------------------------------------------
2838data GbracketState s1 s2 v
2839 = GBracketInit
2840 | GBracketNormal s1 v
2841 | GBracketException s2
2843-- | The most general bracketing and exception combinator. All other
2844-- combinators can be expressed in terms of this combinator. This can also be
2845-- used for cases which are not covered by the standard combinators.
2847-- /Internal/
2849{-# INLINE_NORMAL gbracket #-}
2850gbracket
2851 :: Monad m
2852 => m c -- ^ before
2853 -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
2854 -> (c -> m d) -- ^ after, on normal stop
2855 -> (c -> e -> Stream m b) -- ^ on exception
2856 -> (c -> Stream m b) -- ^ stream generator
2857 -> Stream m b
2858gbracket bef exc aft fexc fnormal =
2859 Stream step GBracketInit
2861 where
2863 {-# INLINE_LATE step #-}
2864 step _ GBracketInit = do
2865 r <- bef
2866 return $ Skip $ GBracketNormal (fnormal r) r
2868 step gst (GBracketNormal (UnStream step1 st) v) = do
2869 res <- exc $ step1 gst st
2870 case res of
2871 Right r -> case r of
2872 Yield x s ->
2873 return $ Yield x (GBracketNormal (Stream step1 s) v)
2874 Skip s -> return $ Skip (GBracketNormal (Stream step1 s) v)
2875 Stop -> aft v >> return Stop
2876 Left e -> return $ Skip (GBracketException (fexc v e))
2877 step gst (GBracketException (UnStream step1 st)) = do
2878 res <- step1 gst st
2879 case res of
2880 Yield x s -> return $ Yield x (GBracketException (Stream step1 s))
2881 Skip s -> return $ Skip (GBracketException (Stream step1 s))
2882 Stop -> return Stop
2884-- | Create an IORef holding a finalizer that is called automatically when the
2885-- IORef is garbage collected. The IORef can be written to with a 'Nothing'
2886-- value to deactivate the finalizer.
2887newFinalizedIORef :: (MonadIO m, MonadBaseControl IO m)
2888 => m a -> m (IORef (Maybe (IO ())))
2889newFinalizedIORef finalizer = do
2890 mrun <- captureMonadState
2891 ref <- liftIO $ newIORef $ Just $ liftIO $ void $ do
2892 _ <- runInIO mrun finalizer
2893 return ()
2894 let finalizer1 = do
2895 res <- readIORef ref
2896 case res of
2897 Nothing -> return ()
2898 Just f -> f
2899 _ <- liftIO $ mkWeakIORef ref finalizer1
2900 return ref
2902data GbracketIOState s1 s2 v wref
2903 = GBracketIOInit
2904 | GBracketIONormal s1 v wref
2905 | GBracketIOException s2
2907-- | Like gbracket but also uses a finalizer to make sure when the stream is
2908-- garbage collected we run the finalizing action. This requires a MonadIO and
2909-- MonadBaseControl IO constraint.
2911-- | The most general bracketing and exception combinator. All other
2912-- combinators can be expressed in terms of this combinator. This can also be
2913-- used for cases which are not covered by the standard combinators.
2915-- /Internal/
2917{-# INLINE_NORMAL gbracketIO #-}
2918gbracketIO
2919 :: (MonadIO m, MonadBaseControl IO m)
2920 => m c -- ^ before
2921 -> (forall s. m s -> m (Either e s)) -- ^ try (exception handling)
2922 -> (c -> m d) -- ^ after, on normal stop or GC
2923 -> (c -> e -> Stream m b) -- ^ on exception
2924 -> (c -> Stream m b) -- ^ stream generator
2925 -> Stream m b
2926gbracketIO bef exc aft fexc fnormal =
2927 Stream step GBracketIOInit
2929 where
2931 -- If the stream is never evaluated the "aft" action will never be
2932 -- called. For that to occur we will need the user of this API to pass a
2933 -- weak pointer to us.
2934 {-# INLINE_LATE step #-}
2935 step _ GBracketIOInit = do
2936 r <- bef
2937 ref <- newFinalizedIORef (aft r)
2938 return $ Skip $ GBracketIONormal (fnormal r) r ref
2940 step gst (GBracketIONormal (UnStream step1 st) v ref) = do
2941 res <- exc $ step1 gst st
2942 case res of
2943 Right r -> case r of
2944 Yield x s ->
2945 return $ Yield x (GBracketIONormal (Stream step1 s) v ref)
2946 Skip s ->
2947 return $ Skip (GBracketIONormal (Stream step1 s) v ref)
2948 Stop -> do
2949 liftIO (writeIORef ref Nothing)
2950 aft v >> return Stop
2951 Left e -> do
2952 liftIO (writeIORef ref Nothing)
2953 return $ Skip (GBracketIOException (fexc v e))
2954 step gst (GBracketIOException (UnStream step1 st)) = do
2955 res <- step1 gst st
2956 case res of
2957 Yield x s ->
2958 return $ Yield x (GBracketIOException (Stream step1 s))
2959 Skip s -> return $ Skip (GBracketIOException (Stream step1 s))
2960 Stop -> return Stop
2962-- | Run a side effect before the stream yields its first element.
2963{-# INLINE_NORMAL before #-}
2964before :: Monad m => m b -> Stream m a -> Stream m a
2965before action (Stream step state) = Stream step' Nothing
2967 where
2969 {-# INLINE_LATE step' #-}
2970 step' _ Nothing = action >> return (Skip (Just state))
2972 step' gst (Just st) = do
2973 res <- step gst st
2974 case res of
2975 Yield x s -> return $ Yield x (Just s)
2976 Skip s -> return $ Skip (Just s)
2977 Stop -> return Stop
2979-- | Run a side effect whenever the stream stops normally.
2980{-# INLINE_NORMAL after #-}
2981after :: Monad m => m b -> Stream m a -> Stream m a
2982after action (Stream step state) = Stream step' state
2984 where
2986 {-# INLINE_LATE step' #-}
2987 step' gst st = do
2988 res <- step gst st
2989 case res of
2990 Yield x s -> return $ Yield x s
2991 Skip s -> return $ Skip s
2992 Stop -> action >> return Stop
2994{-# INLINE_NORMAL afterIO #-}
2995afterIO :: (MonadIO m, MonadBaseControl IO m)
2996 => m b -> Stream m a -> Stream m a
2997afterIO action (Stream step state) = Stream step' Nothing
2999 where
3001 {-# INLINE_LATE step' #-}
3002 step' _ Nothing = do
3003 ref <- newFinalizedIORef action
3004 return $ Skip $ Just (state, ref)
3005 step' gst (Just (st, ref)) = do
3006 res <- step gst st
3007 case res of
3008 Yield x s -> return $ Yield x (Just (s, ref))
3009 Skip s -> return $ Skip (Just (s, ref))
3010 Stop -> liftIO $ do
3011 Just f <- readIORef ref
3012 writeIORef ref Nothing
3013 f >> return Stop
3015-- XXX These combinators are expensive due to the call to
3016-- onException/handle/try on each step. Therefore, when possible, they should
3017-- be called in an outer loop where we perform less iterations. For example, we
3018-- cannot call them on each iteration in a char stream, instead we can call
3019-- them when doing an IO on an array.
3021-- XXX For high performance error checks in busy streams we may need another
3022-- Error constructor in step.
3024-- | Run a side effect whenever the stream aborts due to an exception. The
3025-- exception is not caught, simply rethrown.
3026{-# INLINE_NORMAL onException #-}
3027onException :: MonadCatch m => m b -> Stream m a -> Stream m a
3028onException action str =
3029 gbracket (return ()) MC.try return
3030 (\_ (e :: MC.SomeException) -> nilM (action >> MC.throwM e))
3031 (\_ -> str)
3033{-# INLINE_NORMAL _onException #-}
3034_onException :: MonadCatch m => m b -> Stream m a -> Stream m a
3035_onException action (Stream step state) = Stream step' state
3037 where
3039 {-# INLINE_LATE step' #-}
3040 step' gst st = do
3041 res <- step gst st `MC.onException` action
3042 case res of
3043 Yield x s -> return $ Yield x s
3044 Skip s -> return $ Skip s
3045 Stop -> return Stop
3047-- XXX bracket is like concatMap, it generates a stream and then flattens it.
3048-- Like concatMap it has 10x worse performance compared to linear fused
3049-- compositions.
3051-- | Run the first action before the stream starts and remember its output,
3052-- generate a stream using the output, run the second action providing the
3053-- remembered value as an argument whenever the stream ends normally or due to
3054-- an exception.
3055{-# INLINE_NORMAL bracket #-}
3056bracket :: MonadCatch m => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
3057bracket bef aft bet =
3058 gbracket bef MC.try aft
3059 (\a (e :: SomeException) -> nilM (aft a >> MC.throwM e)) bet
3061{-# INLINE_NORMAL bracketIO #-}
3062bracketIO :: (MonadAsync m, MonadCatch m)
3063 => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
3064bracketIO bef aft bet =
3065 gbracketIO bef MC.try aft
3066 (\a (e :: SomeException) -> nilM (aft a >> MC.throwM e)) bet
3068data BracketState s v = BracketInit | BracketRun s v
3070{-# INLINE_NORMAL _bracket #-}
3071_bracket :: MonadCatch m => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
3072_bracket bef aft bet = Stream step' BracketInit
3074 where
3076 {-# INLINE_LATE step' #-}
3077 step' _ BracketInit = bef >>= \x -> return (Skip (BracketRun (bet x) x))
3079 -- NOTE: It is important to use UnStream instead of the Stream pattern
3080 -- here, otherwise we get huge perf degradation, see note in concatMap.
3081 step' gst (BracketRun (UnStream step state) v) = do
3082 -- res <- step gst state `MC.onException` aft v
3083 res <- MC.try $ step gst state
3084 case res of
3085 Left (e :: SomeException) -> aft v >> MC.throwM e >> return Stop
3086 Right r -> case r of
3087 Yield x s -> return $ Yield x (BracketRun (Stream step s) v)
3088 Skip s -> return $ Skip (BracketRun (Stream step s) v)
3089 Stop -> aft v >> return Stop
3091-- | Run a side effect whenever the stream stops normally or aborts due to an
3092-- exception.
3093{-# INLINE finally #-}
3094finally :: MonadCatch m => m b -> Stream m a -> Stream m a
3095-- finally action xs = after action $ onException action xs
3096finally action xs = bracket (return ()) (\_ -> action) (const xs)
3098{-# INLINE finallyIO #-}
3099finallyIO :: (MonadAsync m, MonadCatch m) => m b -> Stream m a -> Stream m a
3100finallyIO action xs = bracketIO (return ()) (\_ -> action) (const xs)
3102-- | When evaluating a stream if an exception occurs, stream evaluation aborts
3103-- and the specified exception handler is run with the exception as argument.
3104{-# INLINE_NORMAL handle #-}
3105handle :: (MonadCatch m, Exception e)
3106 => (e -> Stream m a) -> Stream m a -> Stream m a
3107handle f str =
3108 gbracket (return ()) MC.try return (\_ e -> f e) (\_ -> str)
3110{-# INLINE_NORMAL _handle #-}
3111_handle :: (MonadCatch m, Exception e)
3112 => (e -> Stream m a) -> Stream m a -> Stream m a
3113_handle f (Stream step state) = Stream step' (Left state)
3115 where
3117 {-# INLINE_LATE step' #-}
3118 step' gst (Left st) = do
3119 res <- MC.try $ step gst st
3120 case res of
3121 Left e -> return $ Skip $ Right (f e)
3122 Right r -> case r of
3123 Yield x s -> return $ Yield x (Left s)
3124 Skip s -> return $ Skip (Left s)
3125 Stop -> return Stop
3127 step' gst (Right (UnStream step1 st)) = do
3128 res <- step1 gst st
3129 case res of
3130 Yield x s -> return $ Yield x (Right (Stream step1 s))
3131 Skip s -> return $ Skip (Right (Stream step1 s))
3132 Stop -> return Stop
3134-------------------------------------------------------------------------------
3135-- General transformation
3136-------------------------------------------------------------------------------
3138{-# INLINE_NORMAL transform #-}
3139transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
3140transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
3141 Stream step' (Consume pstate, state)
3143 where
3145 {-# INLINE_LATE step' #-}
3147 step' gst (Consume pst, st) = pst `seq` do
3148 r <- step (adaptState gst) st
3149 case r of
3150 Yield x s -> do
3151 res <- pstep1 pst x
3152 case res of
3153 Pipe.Yield b pst' -> return $ Yield b (pst', s)
3154 Pipe.Continue pst' -> return $ Skip (pst', s)
3155 Skip s -> return $ Skip (Consume pst, s)
3156 Stop -> return Stop
3158 step' _ (Produce pst, st) = pst `seq` do
3159 res <- pstep2 pst
3160 case res of
3161 Pipe.Yield b pst' -> return $ Yield b (pst', st)
3162 Pipe.Continue pst' -> return $ Skip (pst', st)
3164------------------------------------------------------------------------------
3165-- Transformation by Folding (Scans)
3166------------------------------------------------------------------------------
3168------------------------------------------------------------------------------
3169-- Prescans
3170------------------------------------------------------------------------------
3172-- XXX Is a prescan useful, discarding the last step does not sound useful? I
3173-- am not sure about the utility of this function, so this is implemented but
3174-- not exposed. We can expose it if someone provides good reasons why this is
3175-- useful.
3177-- XXX We have to execute the stream one step ahead to know that we are at the
3178-- last step. The vector implementation of prescan executes the last fold step
3179-- but does not yield the result. This means we have executed the effect but
3180-- discarded value. This does not sound right. In this implementation we are
3181-- not executing the last fold step.
3182{-# INLINE_NORMAL prescanlM' #-}
3183prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
3184prescanlM' f mz (Stream step state) = Stream step' (state, mz)
3185 where
3186 {-# INLINE_LATE step' #-}
3187 step' gst (st, prev) = do
3188 r <- step (adaptState gst) st
3189 case r of
3190 Yield x s -> do
3191 acc <- prev
3192 return $ Yield acc (s, f acc x)
3193 Skip s -> return $ Skip (s, prev)
3194 Stop -> return Stop
3196{-# INLINE prescanl' #-}
3197prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3198prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
3200------------------------------------------------------------------------------
3201-- Monolithic postscans (postscan followed by a map)
3202------------------------------------------------------------------------------
3204-- The performance of a modular postscan followed by a map seems to be
3205-- equivalent to this monolithic scan followed by map therefore we may not need
3206-- this implementation. We just have it for performance comparison and in case
3207-- modular version does not perform well in some situation.
3209{-# INLINE_NORMAL postscanlMx' #-}
3210postscanlMx' :: Monad m
3211 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
3212postscanlMx' fstep begin done (Stream step state) = do
3213 Stream step' (state, begin)
3214 where
3215 {-# INLINE_LATE step' #-}
3216 step' gst (st, acc) = do
3217 r <- step (adaptState gst) st
3218 case r of
3219 Yield x s -> do
3220 old <- acc
3221 y <- fstep old x
3222 v <- done y
3223 v `seq` y `seq` return (Yield v (s, return y))
3224 Skip s -> return $ Skip (s, acc)
3225 Stop -> return Stop
3227{-# INLINE_NORMAL postscanlx' #-}
3228postscanlx' :: Monad m
3229 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
3230postscanlx' fstep begin done s =
3231 postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
3233-- XXX do we need consM strict to evaluate the begin value?
3234{-# INLINE scanlMx' #-}
3235scanlMx' :: Monad m
3236 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
3237scanlMx' fstep begin done s =
3238 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
3240{-# INLINE scanlx' #-}
3241scanlx' :: Monad m
3242 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
3243scanlx' fstep begin done s =
3244 scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
3246------------------------------------------------------------------------------
3247-- postscans
3248------------------------------------------------------------------------------
3250{-# INLINE_NORMAL postscanlM' #-}
3251postscanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3252postscanlM' fstep begin (Stream step state) =
3253 begin `seq` Stream step' (state, begin)
3254 where
3255 {-# INLINE_LATE step' #-}
3256 step' gst (st, acc) = acc `seq` do
3257 r <- step (adaptState gst) st
3258 case r of
3259 Yield x s -> do
3260 y <- fstep acc x
3261 y `seq` return (Yield y (s, y))
3262 Skip s -> return $ Skip (s, acc)
3263 Stop -> return Stop
3265{-# INLINE_NORMAL postscanl' #-}
3266postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
3267postscanl' f = postscanlM' (\a b -> return (f a b))
3269{-# INLINE_NORMAL postscanlM #-}
3270postscanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3271postscanlM fstep begin (Stream step state) = Stream step' (state, begin)
3272 where
3273 {-# INLINE_LATE step' #-}
3274 step' gst (st, acc) = do
3275 r <- step (adaptState gst) st
3276 case r of
3277 Yield x s -> do
3278 y <- fstep acc x
3279 return (Yield y (s, y))
3280 Skip s -> return $ Skip (s, acc)
3281 Stop -> return Stop
3283{-# INLINE_NORMAL postscanl #-}
3284postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
3285postscanl f = postscanlM (\a b -> return (f a b))
3287{-# INLINE_NORMAL scanlM' #-}
3288scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3289scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
3291{-# INLINE scanl' #-}
3292scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3293scanl' f = scanlM' (\a b -> return (f a b))
3295{-# INLINE_NORMAL scanlM #-}
3296scanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
3297scanlM fstep begin s = begin `cons` postscanlM fstep begin s
3299{-# INLINE scanl #-}
3300scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
3301scanl f = scanlM (\a b -> return (f a b))
3303{-# INLINE_NORMAL scanl1M #-}
3304scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
3305scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
3306 where
3307 {-# INLINE_LATE step' #-}
3308 step' gst (st, Nothing) = do
3309 r <- step gst st
3310 case r of
3311 Yield x s -> return $ Yield x (s, Just x)
3312 Skip s -> return $ Skip (s, Nothing)
3313 Stop -> return Stop
3315 step' gst (st, Just acc) = do
3316 r <- step gst st
3317 case r of
3318 Yield y s -> do
3319 z <- fstep acc y
3320 return $ Yield z (s, Just z)
3321 Skip s -> return $ Skip (s, Just acc)
3322 Stop -> return Stop
3324{-# INLINE scanl1 #-}
3325scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
3326scanl1 f = scanl1M (\x y -> return (f x y))
3328{-# INLINE_NORMAL scanl1M' #-}
3329scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
3330scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
3331 where
3332 {-# INLINE_LATE step' #-}
3333 step' gst (st, Nothing) = do
3334 r <- step gst st
3335 case r of
3336 Yield x s -> x `seq` return $ Yield x (s, Just x)
3337 Skip s -> return $ Skip (s, Nothing)
3338 Stop -> return Stop
3340 step' gst (st, Just acc) = acc `seq` do
3341 r <- step gst st
3342 case r of
3343 Yield y s -> do
3344 z <- fstep acc y
3345 z `seq` return $ Yield z (s, Just z)
3346 Skip s -> return $ Skip (s, Just acc)
3347 Stop -> return Stop
3349{-# INLINE scanl1' #-}
3350scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
3351scanl1' f = scanl1M' (\x y -> return (f x y))
3353------------------------------------------------------------------------------
3354-- Stateful map/scan
3355------------------------------------------------------------------------------
3357data RollingMapState s a = RollingMapInit s | RollingMapGo s a
3359{-# INLINE rollingMapM #-}
3360rollingMapM :: Monad m => (a -> a -> m b) -> Stream m a -> Stream m b
3361rollingMapM f (Stream step1 state1) = Stream step (RollingMapInit state1)
3362 where
3363 step gst (RollingMapInit st) = do
3364 r <- step1 (adaptState gst) st
3365 return $ case r of
3366 Yield x s -> Skip $ RollingMapGo s x
3367 Skip s -> Skip $ RollingMapInit s
3368 Stop -> Stop
3370 step gst (RollingMapGo s1 x1) = do
3371 r <- step1 (adaptState gst) s1
3372 case r of
3373 Yield x s -> do
3374 !res <- f x x1
3375 return $ Yield res $ RollingMapGo s x
3376 Skip s -> return $ Skip $ RollingMapGo s x1
3377 Stop -> return $ Stop
3379{-# INLINE rollingMap #-}
3380rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
3381rollingMap f = rollingMapM (\x y -> return $ f x y)
3383------------------------------------------------------------------------------
3384-- Tapping/Distributing
3385------------------------------------------------------------------------------
3387{-# INLINE tap #-}
3388tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
3389tap (Fold fstep initial extract) (Stream step state) = Stream step' Nothing
3391 where
3393 step' _ Nothing = do
3394 r <- initial
3395 return $ Skip (Just (r, state))
3397 step' gst (Just (acc, st)) = acc `seq` do
3398 r <- step gst st
3399 case r of
3400 Yield x s -> do
3401 acc' <- fstep acc x
3402 return $ Yield x (Just (acc', s))
3403 Skip s -> return $ Skip (Just (acc, s))
3404 Stop -> do
3405 void $ extract acc
3406 return $ Stop
3408{-# INLINE_NORMAL tapOffsetEvery #-}
3409tapOffsetEvery :: Monad m
3410 => Int -> Int -> Fold m a b -> Stream m a -> Stream m a
3411tapOffsetEvery offset n (Fold fstep initial extract) (Stream step state) =
3412 Stream step' Nothing
3414 where
3416 {-# INLINE_LATE step' #-}
3417 step' _ Nothing = do
3418 r <- initial
3419 return $ Skip (Just (r, state, offset `mod` n))
3421 step' gst (Just (acc, st, count)) | count <= 0 = do
3422 r <- step gst st
3423 case r of
3424 Yield x s -> do
3425 !acc' <- fstep acc x
3426 return $ Yield x (Just (acc', s, n - 1))
3427 Skip s -> return $ Skip (Just (acc, s, count))
3428 Stop -> do
3429 void $ extract acc
3430 return $ Stop
3432 step' gst (Just (acc, st, count)) = do
3433 r <- step gst st
3434 case r of
3435 Yield x s -> return $ Yield x (Just (acc, s, count - 1))
3436 Skip s -> return $ Skip (Just (acc, s, count))
3437 Stop -> do
3438 void $ extract acc
3439 return $ Stop
3441{-# INLINE_NORMAL pollCounts #-}
3442pollCounts
3443 :: MonadAsync m
3444 => (Stream m Int -> Stream m Int)
3445 -> Fold m Int b
3446 -> Stream m a
3447 -> Stream m a
3448pollCounts transf fld (Stream step state) = Stream step' Nothing
3449 where
3451 {-# INLINE_LATE step' #-}
3452 step' _ Nothing = do
3453 -- As long as we are using an "Int" for counts lockfree reads from
3454 -- Var should work correctly on both 32-bit and 64-bit machines.
3455 -- However, an Int on a 32-bit machine may overflow quickly.
3456 countVar <- liftIO $ newVar (0 :: Int)
3457 tid <- forkManaged
3458 $ void $ runFold fld
3459 $ transf $ fromPrimVar countVar
3460 return $ Skip (Just (countVar, tid, state))
3462 step' gst (Just (countVar, tid, st)) = do
3463 r <- step gst st
3464 case r of
3465 Yield x s -> do
3466 liftIO $ modifyVar' countVar (+ 1)
3467 return $ Yield x (Just (countVar, tid, s))
3468 Skip s -> return $ Skip (Just (countVar, tid, s))
3469 Stop -> do
3470 liftIO $ killThread tid
3471 return Stop
3473{-# INLINE_NORMAL tapRate #-}
3474tapRate ::
3475 (MonadAsync m, MonadCatch m)
3476 => Double
3477 -> (Int -> m b)
3478 -> Stream m a
3479 -> Stream m a
3480tapRate samplingRate action (Stream step state) = Stream step' Nothing
3481 where
3482 {-# NOINLINE loop #-}
3483 loop countVar prev = do
3484 i <-
3485 MC.catch
3486 (do liftIO $ threadDelay (round $ samplingRate * 1000000)
3487 i <- liftIO $ readVar countVar
3488 let !diff = i - prev
3489 void $ action diff
3490 return i)
3491 (\(e :: AsyncException) -> do
3492 i <- liftIO $ readVar countVar
3493 let !diff = i - prev
3494 void $ action diff
3495 throwM (MC.toException e))
3496 loop countVar i
3498 {-# INLINE_LATE step' #-}
3499 step' _ Nothing = do
3500 countVar <- liftIO $ newVar 0
3501 tid <- fork $ loop countVar 0
3502 ref <- liftIO $ newIORef ()
3503 _ <- liftIO $ mkWeakIORef ref (killThread tid)
3504 return $ Skip (Just (countVar, tid, state, ref))
3506 step' gst (Just (countVar, tid, st, ref)) = do
3507 r <- step gst st
3508 case r of
3509 Yield x s -> do
3510 liftIO $ modifyVar' countVar (+ 1)
3511 return $ Yield x (Just (countVar, tid, s, ref))
3512 Skip s -> return $ Skip (Just (countVar, tid, s, ref))
3513 Stop -> do
3514 liftIO $ killThread tid
3515 return Stop
3518-------------------------------------------------------------------------------
3519-- Filtering
3520-------------------------------------------------------------------------------
3522{-# INLINE_NORMAL takeWhileM #-}
3523takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
3524takeWhileM f (Stream step state) = Stream step' state
3525 where
3526 {-# INLINE_LATE step' #-}
3527 step' gst st = do
3528 r <- step gst st
3529 case r of
3530 Yield x s -> do
3531 b <- f x
3532 return $ if b then Yield x s else Stop
3533 Skip s -> return $ Skip s
3534 Stop -> return Stop
3536{-# INLINE takeWhile #-}
3537takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
3538takeWhile f = takeWhileM (return . f)
3540{-# INLINE_NORMAL drop #-}
3541drop :: Monad m => Int -> Stream m a -> Stream m a
3542drop n (Stream step state) = Stream step' (state, Just n)
3543 where
3544 {-# INLINE_LATE step' #-}
3545 step' gst (st, Just i)
3546 | i > 0 = do
3547 r <- step gst st
3548 return $
3549 case r of
3550 Yield _ s -> Skip (s, Just (i - 1))
3551 Skip s -> Skip (s, Just i)
3552 Stop -> Stop
3553 | otherwise = return $ Skip (st, Nothing)
3555 step' gst (st, Nothing) = do
3556 r <- step gst st
3557 return $
3558 case r of
3559 Yield x s -> Yield x (s, Nothing)
3560 Skip s -> Skip (s, Nothing)
3561 Stop -> Stop
3563data DropWhileState s a
3564 = DropWhileDrop s
3565 | DropWhileYield a s
3566 | DropWhileNext s
3568{-# INLINE_NORMAL dropWhileM #-}
3569dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
3570dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
3571 where
3572 {-# INLINE_LATE step' #-}
3573 step' gst (DropWhileDrop st) = do
3574 r <- step gst st
3575 case r of
3576 Yield x s -> do
3577 b <- f x
3578 if b
3579 then return $ Skip (DropWhileDrop s)
3580 else return $ Skip (DropWhileYield x s)
3581 Skip s -> return $ Skip (DropWhileDrop s)
3582 Stop -> return Stop
3584 step' gst (DropWhileNext st) = do
3585 r <- step gst st
3586 case r of
3587 Yield x s -> return $ Skip (DropWhileYield x s)
3588 Skip s -> return $ Skip (DropWhileNext s)
3589 Stop -> return Stop
3591 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
3593{-# INLINE dropWhile #-}
3594dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
3595dropWhile f = dropWhileM (return . f)
3597{-# INLINE_NORMAL filterM #-}
3598filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
3599filterM f (Stream step state) = Stream step' state
3600 where
3601 {-# INLINE_LATE step' #-}
3602 step' gst st = do
3603 r <- step gst st
3604 case r of
3605 Yield x s -> do
3606 b <- f x
3607 return $ if b
3608 then Yield x s
3609 else Skip s
3610 Skip s -> return $ Skip s
3611 Stop -> return Stop
3613{-# INLINE filter #-}
3614filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
3615filter f = filterM (return . f)
3617{-# INLINE_NORMAL uniq #-}
3618uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
3619uniq (Stream step state) = Stream step' (Nothing, state)
3620 where
3621 {-# INLINE_LATE step' #-}
3622 step' gst (Nothing, st) = do
3623 r <- step gst st
3624 case r of
3625 Yield x s -> return $ Yield x (Just x, s)
3626 Skip s -> return $ Skip (Nothing, s)
3627 Stop -> return Stop
3628 step' gst (Just x, st) = do
3629 r <- step gst st
3630 case r of
3631 Yield y s | x == y -> return $ Skip (Just x, s)
3632 | otherwise -> return $ Yield y (Just y, s)
3633 Skip s -> return $ Skip (Just x, s)
3634 Stop -> return Stop
3636------------------------------------------------------------------------------
3637-- Transformation by Mapping
3638------------------------------------------------------------------------------
3640{-# INLINE_NORMAL sequence #-}
3641sequence :: Monad m => Stream m (m a) -> Stream m a
3642sequence (Stream step state) = Stream step' state
3643 where
3644 {-# INLINE_LATE step' #-}
3645 step' gst st = do
3646 r <- step (adaptState gst) st
3647 case r of
3648 Yield x s -> x >>= \a -> return (Yield a s)
3649 Skip s -> return $ Skip s
3650 Stop -> return Stop
3652------------------------------------------------------------------------------
3653-- Inserting
3654------------------------------------------------------------------------------
3656data LoopState x s = FirstYield s
3657 | InterspersingYield s
3658 | YieldAndCarry x s
3660{-# INLINE_NORMAL intersperseM #-}
3661intersperseM :: Monad m => m a -> Stream m a -> Stream m a
3662intersperseM m (Stream step state) = Stream step' (FirstYield state)
3663 where
3664 {-# INLINE_LATE step' #-}
3665 step' gst (FirstYield st) = do
3666 r <- step gst st
3667 return $
3668 case r of
3669 Yield x s -> Skip (YieldAndCarry x s)
3670 Skip s -> Skip (FirstYield s)
3671 Stop -> Stop
3673 step' gst (InterspersingYield st) = do
3674 r <- step gst st
3675 case r of
3676 Yield x s -> do
3677 a <- m
3678 return $ Yield a (YieldAndCarry x s)
3679 Skip s -> return $ Skip $ InterspersingYield s
3680 Stop -> return Stop
3682 step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
3684data SuffixState s a
3685 = SuffixElem s
3686 | SuffixSuffix s
3687 | SuffixYield a (SuffixState s a)
3689{-# INLINE_NORMAL intersperseSuffix #-}
3690intersperseSuffix :: forall m a. Monad m => m a -> Stream m a -> Stream m a
3691intersperseSuffix action (Stream step state) = Stream step' (SuffixElem state)
3692 where
3693 {-# INLINE_LATE step' #-}
3694 step' gst (SuffixElem st) = do
3695 r <- step gst st
3696 return $ case r of
3697 Yield x s -> Skip (SuffixYield x (SuffixSuffix s))
3698 Skip s -> Skip (SuffixElem s)
3699 Stop -> Stop
3701 step' _ (SuffixSuffix st) = do
3702 action >>= \r -> return $ Skip (SuffixYield r (SuffixElem st))
3704 step' _ (SuffixYield x next) = return $ Yield x next
3706data SuffixSpanState s a
3707 = SuffixSpanElem s Int
3708 | SuffixSpanSuffix s
3709 | SuffixSpanYield a (SuffixSpanState s a)
3710 | SuffixSpanLast
3711 | SuffixSpanStop
3713-- | intersperse after every n items
3714{-# INLINE_NORMAL intersperseSuffixBySpan #-}
3715intersperseSuffixBySpan :: forall m a. Monad m
3716 => Int -> m a -> Stream m a -> Stream m a
3717intersperseSuffixBySpan n action (Stream step state) =
3718 Stream step' (SuffixSpanElem state n)
3719 where
3720 {-# INLINE_LATE step' #-}
3721 step' gst (SuffixSpanElem st i) | i > 0 = do
3722 r <- step gst st
3723 return $ case r of
3724 Yield x s -> Skip (SuffixSpanYield x (SuffixSpanElem s (i - 1)))
3725 Skip s -> Skip (SuffixSpanElem s i)
3726 Stop -> if i == n then Stop else Skip SuffixSpanLast
3727 step' _ (SuffixSpanElem st _) = return $ Skip (SuffixSpanSuffix st)
3729 step' _ (SuffixSpanSuffix st) = do
3730 action >>= \r -> return $ Skip (SuffixSpanYield r (SuffixSpanElem st n))
3732 step' _ (SuffixSpanLast) = do
3733 action >>= \r -> return $ Skip (SuffixSpanYield r SuffixSpanStop)
3735 step' _ (SuffixSpanYield x next) = return $ Yield x next
3737 step' _ (SuffixSpanStop) = return Stop
3739{-# INLINE intersperse #-}
3740intersperse :: Monad m => a -> Stream m a -> Stream m a
3741intersperse a = intersperseM (return a)
3743{-# INLINE_NORMAL insertBy #-}
3744insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
3745insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
3746 where
3747 {-# INLINE_LATE step' #-}
3748 step' gst (st, False, _) = do
3749 r <- step gst st
3750 case r of
3751 Yield x s -> case cmp a x of
3752 GT -> return $ Yield x (s, False, Nothing)
3753 _ -> return $ Yield a (s, True, Just x)
3754 Skip s -> return $ Skip (s, False, Nothing)
3755 Stop -> return $ Yield a (st, True, Nothing)
3757 step' _ (_, True, Nothing) = return Stop
3759 step' gst (st, True, Just prev) = do
3760 r <- step gst st
3761 case r of
3762 Yield x s -> return $ Yield prev (s, True, Just x)
3763 Skip s -> return $ Skip (s, True, Just prev)
3764 Stop -> return $ Yield prev (st, True, Nothing)
3766------------------------------------------------------------------------------
3767-- Deleting
3768------------------------------------------------------------------------------
3770{-# INLINE_NORMAL deleteBy #-}
3771deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
3772deleteBy eq x (Stream step state) = Stream step' (state, False)
3773 where
3774 {-# INLINE_LATE step' #-}
3775 step' gst (st, False) = do
3776 r <- step gst st
3777 case r of
3778 Yield y s -> return $
3779 if eq x y then Skip (s, True) else Yield y (s, False)
3780 Skip s -> return $ Skip (s, False)
3781 Stop -> return Stop
3783 step' gst (st, True) = do
3784 r <- step gst st
3785 case r of
3786 Yield y s -> return $ Yield y (s, True)
3787 Skip s -> return $ Skip (s, True)
3788 Stop -> return Stop
3790------------------------------------------------------------------------------
3791-- Transformation by Map and Filter
3792------------------------------------------------------------------------------
3794-- XXX Will this always fuse properly?
3795{-# INLINE_NORMAL mapMaybe #-}
3796mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
3797mapMaybe f = fmap fromJust . filter isJust . map f
3799{-# INLINE_NORMAL mapMaybeM #-}
3800mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
3801mapMaybeM f = fmap fromJust . filter isJust . mapM f
3803------------------------------------------------------------------------------
3804-- Zipping
3805------------------------------------------------------------------------------
3807{-# INLINE_NORMAL indexed #-}
3808indexed :: Monad m => Stream m a -> Stream m (Int, a)
3809indexed (Stream step state) = Stream step' (state, 0)
3810 where
3811 {-# INLINE_LATE step' #-}
3812 step' gst (st, i) = i `seq` do
3813 r <- step (adaptState gst) st
3814 case r of
3815 Yield x s -> return $ Yield (i, x) (s, i+1)
3816 Skip s -> return $ Skip (s, i)
3817 Stop -> return Stop
3819{-# INLINE_NORMAL indexedR #-}
3820indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
3821indexedR m (Stream step state) = Stream step' (state, m)
3822 where
3823 {-# INLINE_LATE step' #-}
3824 step' gst (st, i) = i `seq` do
3825 r <- step (adaptState gst) st
3826 case r of
3827 Yield x s -> let i' = i - 1
3828 in return $ Yield (i, x) (s, i')
3829 Skip s -> return $ Skip (s, i)
3830 Stop -> return Stop
3832{-# INLINE_NORMAL zipWithM #-}
3833zipWithM :: Monad m
3834 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
3835zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
3836 where
3837 {-# INLINE_LATE step #-}
3838 step gst (sa, sb, Nothing) = do
3839 r <- stepa (adaptState gst) sa
3840 return $
3841 case r of
3842 Yield x sa' -> Skip (sa', sb, Just x)
3843 Skip sa' -> Skip (sa', sb, Nothing)
3844 Stop -> Stop
3846 step gst (sa, sb, Just x) = do
3847 r <- stepb (adaptState gst) sb
3848 case r of
3849 Yield y sb' -> do
3850 z <- f x y
3851 return $ Yield z (sa, sb', Nothing)
3852 Skip sb' -> return $ Skip (sa, sb', Just x)
3853 Stop -> return Stop
3855#if __GLASGOW_HASKELL__ >= 801
3856{-# RULES "zipWithM xs xs"
3857 forall f xs. zipWithM @Identity f xs xs = mapM (\x -> f x x) xs #-}
3858#endif
3860{-# INLINE zipWith #-}
3861zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
3862zipWith f = zipWithM (\a b -> return (f a b))
3864------------------------------------------------------------------------------
3865-- Merging
3866------------------------------------------------------------------------------
3868{-# INLINE_NORMAL mergeByM #-}
3869mergeByM
3870 :: (Monad m)
3871 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
3872mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
3873 Stream step (Just ta, Just tb, Nothing, Nothing)
3874 where
3875 {-# INLINE_LATE step #-}
3877 -- one of the values is missing, and the corresponding stream is running
3878 step gst (Just sa, sb, Nothing, b) = do
3879 r <- stepa gst sa
3880 return $ case r of
3881 Yield a sa' -> Skip (Just sa', sb, Just a, b)
3882 Skip sa' -> Skip (Just sa', sb, Nothing, b)
3883 Stop -> Skip (Nothing, sb, Nothing, b)
3885 step gst (sa, Just sb, a, Nothing) = do
3886 r <- stepb gst sb
3887 return $ case r of
3888 Yield b sb' -> Skip (sa, Just sb', a, Just b)
3889 Skip sb' -> Skip (sa, Just sb', a, Nothing)
3890 Stop -> Skip (sa, Nothing, a, Nothing)
3892 -- both the values are available
3893 step _ (sa, sb, Just a, Just b) = do
3894 res <- cmp a b
3895 return $ case res of
3896 GT -> Yield b (sa, sb, Just a, Nothing)
3897 _ -> Yield a (sa, sb, Nothing, Just b)
3899 -- one of the values is missing, corresponding stream is done
3900 step _ (Nothing, sb, Nothing, Just b) =
3901 return $ Yield b (Nothing, sb, Nothing, Nothing)
3903 step _ (sa, Nothing, Just a, Nothing) =
3904 return $ Yield a (sa, Nothing, Nothing, Nothing)
3906 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
3908{-# INLINE mergeBy #-}
3909mergeBy
3910 :: (Monad m)
3911 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
3912mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
3914------------------------------------------------------------------------------
3915-- Transformation comprehensions
3916------------------------------------------------------------------------------
3918{-# INLINE_NORMAL the #-}
3919the :: (Eq a, Monad m) => Stream m a -> m (Maybe a)
3920the (Stream step state) = go state
3921 where
3922 go st = do
3923 r <- step defState st
3924 case r of
3925 Yield x s -> go' x s
3926 Skip s -> go s
3927 Stop -> return Nothing
3928 go' n st = do
3929 r <- step defState st
3930 case r of
3931 Yield x s | x == n -> go' n s
3932 | otherwise -> return Nothing
3933 Skip s -> go' n s
3934 Stop -> return (Just n)
3936{-# INLINE runFold #-}
3937runFold :: (Monad m) => Fold m a b -> Stream m a -> m b
3938runFold (Fold step begin done) = foldlMx' step begin done
3940-------------------------------------------------------------------------------
3941-- Concurrent application and fold
3942-------------------------------------------------------------------------------
3944-- XXX These functions should be moved to Stream/Parallel.hs
3946-- Using StreamD the worker stream producing code can fuse with the code to
3947-- queue output to the SVar giving some perf boost.
3949-- Note that StreamD can only be used in limited situations, specifically, we
3950-- cannot implement joinStreamVarPar using this.
3952-- XXX make sure that the SVar passed is a Parallel style SVar.
3954-- | Fold the supplied stream to the SVar asynchronously using Parallel
3955-- concurrency style.
3956-- {-# INLINE_NORMAL toSVarParallel #-}
3957{-# INLINE toSVarParallel #-}
3958toSVarParallel :: MonadAsync m
3959 => State t m a -> SVar t m a -> Stream m a -> m ()
3960toSVarParallel st sv xs =
3961 if svarInspectMode sv
3962 then forkWithDiag
3963 else do
3964 tid <-
3965 case getYieldLimit st of
3966 Nothing -> doFork (work Nothing)
3967 (svarMrun sv)
3968 (handleChildException sv)
3969 Just _ -> doFork (workLim Nothing)
3970 (svarMrun sv)
3971 (handleChildException sv)
3972 modifyThread sv tid
3974 where
3976 {-# NOINLINE work #-}
3977 work info = (runFold (FL.toParallelSVar sv info) xs)
3979 {-# NOINLINE workLim #-}
3980 workLim info = runFold (FL.toParallelSVarLimited sv info) xs
3982 {-# NOINLINE forkWithDiag #-}
3983 forkWithDiag = do
3984 -- We do not use workerCount in case of ParallelVar but still there is
3985 -- no harm in maintaining it correctly.
3986 liftIO $ atomicModifyIORefCAS_ (workerCount sv) $ \n -> n + 1
3987 recordMaxWorkers sv
3988 -- This allocation matters when significant number of workers are being
3989 -- sent. We allocate it only when needed. The overhead increases by 4x.
3990 winfo <-
3991 case yieldRateInfo sv of
3992 Nothing -> return Nothing
3993 Just _ -> liftIO $ do
3994 cntRef <- newIORef 0
3995 t <- getTime Monotonic
3996 lat <- newIORef (0, t)
3997 return $ Just WorkerInfo
3998 { workerYieldMax = 0
3999 , workerYieldCount = cntRef
4000 , workerLatencyStart = lat
4002 tid <-
4003 case getYieldLimit st of
4004 Nothing -> doFork (work winfo)
4005 (svarMrun sv)
4006 (handleChildException sv)
4007 Just _ -> doFork (workLim winfo)
4008 (svarMrun sv)
4009 (handleChildException sv)
4010 modifyThread sv tid
4012{-# INLINE_NORMAL mkParallelD #-}
4013mkParallelD :: MonadAsync m => Stream m a -> Stream m a
4014mkParallelD m = Stream step Nothing
4015 where
4017 step gst Nothing = do
4018 sv <- newParallelVar StopNone gst
4019 toSVarParallel gst sv m
4020 -- XXX use unfold instead?
4021 return $ Skip $ Just $ fromSVar sv
4023 step gst (Just (UnStream step1 st)) = do
4024 r <- step1 gst st
4025 return $ case r of
4026 Yield a s -> Yield a (Just $ Stream step1 s)
4027 Skip s -> Skip (Just $ Stream step1 s)
4028 Stop -> Stop
4030-- Compare with mkAsync. mkAsync uses an Async style SVar whereas this uses a
4031-- parallel style SVar for evaluation. Currently, parallel style cannot use
4032-- rate control whereas Async style can use rate control. In async style SVar
4033-- the worker thread terminates when the buffer is full whereas in Parallel
4034-- style it blocks.
4036-- | Make the stream producer and consumer run concurrently by introducing a
4037-- buffer between them. The producer thread evaluates the input stream until
4038-- the buffer fills, it blocks if the buffer is full until there is space in
4039-- the buffer. The consumer consumes the stream lazily from the buffer.
4041-- /Internal/
4043{-# INLINE_NORMAL mkParallel #-}
4044mkParallel :: (K.IsStream t, MonadAsync m) => t m a -> t m a
4045mkParallel = fromStreamD . mkParallelD . toStreamD
4047-------------------------------------------------------------------------------
4048-- Concurrent tap
4049-------------------------------------------------------------------------------
4051-- | Create an SVar with a fold consumer that will fold any elements sent to it
4052-- using the supplied fold function.
4053{-# INLINE newFoldSVar #-}
4054newFoldSVar :: MonadAsync m => State t m a -> Fold m a b -> m (SVar t m a)
4055newFoldSVar stt f = do
4056 -- Buffer size for the SVar is derived from the current state
4057 sv <- newParallelVar StopAny (adaptState stt)
4058 -- Add the producer thread-id to the SVar.
4059 liftIO myThreadId >>= modifyThread sv
4060 void $ doFork (work sv) (svarMrun sv) (handleFoldException sv)
4061 return sv
4063 where
4065 {-# NOINLINE work #-}
4066 work sv = void $ runFold f $ fromProducer sv
4068data TapState sv st = TapInit | Tapping sv st | TapDone st
4070{-# INLINE_NORMAL tapAsync #-}
4071tapAsync :: MonadAsync m => Fold m a b -> Stream m a -> Stream m a
4072tapAsync f (Stream step1 state1) = Stream step TapInit
4073 where
4075 drainFold svr = do
4076 -- In general, a Stop event would come equipped with the result
4077 -- of the fold. It is not used here but it would be useful in
4078 -- applicative and distribute.
4079 done <- fromConsumer svr
4080 when (not done) $ do
4081 liftIO $ withDiagMVar svr "teeToSVar: waiting to drain"
4082 $ takeMVar (outputDoorBellFromConsumer svr)
4083 drainFold svr
4085 stopFold svr = do
4086 liftIO $ sendStop svr Nothing
4087 -- drain/wait until a stop event arrives from the fold.
4088 drainFold svr
4090 {-# INLINE_LATE step #-}
4091 step gst TapInit = do
4092 sv <- newFoldSVar gst f
4093 return $ Skip (Tapping sv state1)
4095 step gst (Tapping sv st) = do
4096 r <- step1 gst st
4097 case r of
4098 Yield a s -> do
4099 done <- pushToFold sv a
4100 if done
4101 then do
4102 -- XXX we do not need to wait synchronously here
4103 stopFold sv
4104 return $ Yield a (TapDone s)
4105 else return $ Yield a (Tapping sv s)
4106 Skip s -> return $ Skip (Tapping sv s)
4107 Stop -> do
4108 stopFold sv
4109 return $ Stop
4111 step gst (TapDone st) = do
4112 r <- step1 gst st
4113 return $ case r of
4114 Yield a s -> Yield a (TapDone s)
4115 Skip s -> Skip (TapDone s)
4116 Stop -> Stop
4118-- XXX Exported from Array again as this fold is specific to Array
4119-- | Take last 'n' elements from the stream and discard the rest.
4120{-# INLINE lastN #-}
4121lastN :: (Storable a, MonadIO m) => Int -> Fold m a (Array a)
4122lastN n = Fold step initial done
4123 where
4124 step (Tuple3' rb rh i) a = do
4125 rh1 <- liftIO $ RB.unsafeInsert rb rh a
4126 return $ Tuple3' rb rh1 (i + 1)
4127 initial = fmap (\(a, b) -> Tuple3' a b (0 :: Int)) $ liftIO $ RB.new n
4128 done (Tuple3' rb rh i) = do
4129 arr <- liftIO $ A.newArray n
4130 foldFunc i rh snoc' arr rb
4131 snoc' b a = liftIO $ A.unsafeSnoc b a
4132 foldFunc i
4133 | i < n = RB.unsafeFoldRingM
4134 | otherwise = RB.unsafeFoldRingFullM
4136------------------------------------------------------------------------------
4137-- Time related
4138------------------------------------------------------------------------------
4140-- XXX using getTime in the loop can be pretty expensive especially for
4141-- computations where iterations are lightweight. We have the following
4142-- options:
4144-- 1) Run a timeout thread updating a flag asynchronously and check that
4145-- flag here, that way we can have a cheap termination check.
4147-- 2) Use COARSE clock to get time with lower resolution but more efficiently.
4149-- 3) Use rdtscp/rdtsc to get time directly from the processor, compute the
4150-- termination value of rdtsc in the beginning and then in each iteration just
4151-- get rdtsc and check if we should terminate.
4153data TakeByTime st s
4154 = TakeByTimeInit st
4155 | TakeByTimeCheck st s
4156 | TakeByTimeYield st s
4158{-# INLINE_NORMAL takeByTime #-}
4159takeByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
4160takeByTime duration (Stream step1 state1) = Stream step (TakeByTimeInit state1)
4161 where
4163 lim = toRelTime64 duration
4165 {-# INLINE_LATE step #-}
4166 step _ (TakeByTimeInit _) | lim == 0 = return Stop
4167 step _ (TakeByTimeInit st) = do
4168 t0 <- liftIO $ getTime Monotonic
4169 return $ Skip (TakeByTimeYield st t0)
4170 step _ (TakeByTimeCheck st t0) = do
4171 t <- liftIO $ getTime Monotonic
4172 return $
4173 if diffAbsTime64 t t0 > lim
4174 then Stop
4175 else Skip (TakeByTimeYield st t0)
4176 step gst (TakeByTimeYield st t0) = do
4177 r <- step1 gst st
4178 return $ case r of
4179 Yield x s -> Yield x (TakeByTimeCheck s t0)
4180 Skip s -> Skip (TakeByTimeCheck s t0)
4181 Stop -> Stop
4183data DropByTime st s x
4184 = DropByTimeInit st
4185 | DropByTimeGen st s
4186 | DropByTimeCheck st s x
4187 | DropByTimeYield st
4189{-# INLINE_NORMAL dropByTime #-}
4190dropByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
4191dropByTime duration (Stream step1 state1) = Stream step (DropByTimeInit state1)
4192 where
4194 lim = toRelTime64 duration
4196 {-# INLINE_LATE step #-}
4197 step _ (DropByTimeInit st) = do
4198 t0 <- liftIO $ getTime Monotonic
4199 return $ Skip (DropByTimeGen st t0)
4200 step gst (DropByTimeGen st t0) = do
4201 r <- step1 gst st
4202 return $ case r of
4203 Yield x s -> Skip (DropByTimeCheck s t0 x)
4204 Skip s -> Skip (DropByTimeGen s t0)
4205 Stop -> Stop
4206 step _ (DropByTimeCheck st t0 x) = do
4207 t <- liftIO $ getTime Monotonic
4208 if diffAbsTime64 t t0 <= lim
4209 then return $ Skip $ DropByTimeGen st t0
4210 else return $ Yield x $ DropByTimeYield st
4211 step gst (DropByTimeYield st) = do
4212 r <- step1 gst st
4213 return $ case r of
4214 Yield x s -> Yield x (DropByTimeYield s)
4215 Skip s -> Skip (DropByTimeYield s)
4216 Stop -> Stop
4218-- XXX we should move this to stream generation section of this file. Also, the
4219-- take/drop combinators above should be moved to filtering section.
4220{-# INLINE_NORMAL currentTime #-}
4221currentTime :: MonadAsync m => Double -> Stream m AbsTime
4222currentTime g = Stream step Nothing
4224 where
4226 g' = g * 10 ^ (6 :: Int)
4228 -- XXX should have a minimum granularity to avoid high CPU usage?
4229 {-# INLINE delayTime #-}
4230 delayTime =
4231 if g' >= fromIntegral (maxBound :: Int)
4232 then maxBound
4233 else round g'
4235 updateTimeVar timeVar = do
4236 threadDelay $ delayTime
4237 MicroSecond64 t <- fromAbsTime <$> getTime Monotonic
4238 modifyVar' timeVar (const t)
4240 {-# INLINE_LATE step #-}
4241 step _ Nothing = do
4242 -- XXX note that this is safe only on a 64-bit machine. On a 32-bit
4243 -- machine a 64-bit 'Var' cannot be read consistently without a lock
4244 -- while another thread is writing to it.
4245 timeVar <- liftIO $ newVar (0 :: Int64)
4246 tid <- forkManaged $ liftIO $ forever (updateTimeVar timeVar)
4247 return $ Skip $ Just (timeVar, tid)
4249 step _ s@(Just (timeVar, _)) = do
4250 a <- liftIO $ readVar timeVar
4251 -- XXX we can perhaps use an AbsTime64 using a 64 bit Int for
4252 -- efficiency. or maybe we can use a representation using Double for
4253 -- floating precision time
4254 return $ Yield (toAbsTime (MicroSecond64 a)) s