2-- Module : Streamly.Internal.Data.Stream.StreamD.Transform
3-- Copyright : (c) 2018 Composewell Technologies
4-- (c) Roman Leshchinskiy 2008-2010
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
10-- "Streamly.Internal.Data.Pipe" might ultimately replace this module.
12-- A few functions in this module have been adapted from the vector package
13-- (c) Roman Leshchinskiy. See the notes in specific combinators.
15module Streamly.Internal.Data.Stream.StreamD.Transform
18 -- | Pass through a 'Pipe'.
22 -- | Stateless one-to-one maps.
39 -- * Scanning By 'Fold'
40 , postscanOnce -- XXX rename to postscan
41 , scanOnce -- XXX rename to scan
44 -- | Left scans. Stateful, mostly one-to-one maps.
70 -- | Produce a subset of the stream.
77 -- | Produce a subset of the stream trimmed at ends.
87 -- * Inserting Elements
88 -- | Produce a superset of the stream.
93 , intersperseSuffixBySpan
95 -- * Inserting Side Effects
100 -- | Produce strictly the same set but reordered.
104 -- * Position Indexing
112 -- | Map using the previous element.
124import Control.Concurrent (killThread, threadDelay)
125import Control.Exception (AsyncException)
126import Control.Monad (void, when)
127import Control.Monad.Catch (MonadCatch, throwM)
128import Control.Monad.IO.Class (MonadIO(..))
129import Control.Monad.Trans.Class (MonadTrans(lift))
130import Data.IORef (newIORef, mkWeakIORef)
131import Data.Maybe (fromJust, isJust)
132import Foreign.Storable (Storable(..))
133import GHC.Types (SPEC(..))
134import qualified Control.Monad.Catch as MC
136import Streamly.Internal.Data.Fold.Type (Fold(..))
137import Streamly.Internal.Data.Pipe.Type (Pipe(..), PipeState(..))
138import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
139import Streamly.Internal.Data.Time.Units
140 (TimeUnit64, toRelTime64, diffAbsTime64)
141import Streamly.Internal.System.IO (defaultChunkSize)
143import qualified Streamly.Internal.Data.Array.Foreign.Type as A
144import qualified Streamly.Internal.Data.Fold.Type as FL
145import qualified Streamly.Internal.Data.IORef.Prim as Prim
146import qualified Streamly.Internal.Data.Pipe.Type as Pipe
147import qualified Streamly.Internal.Data.Stream.StreamK as K
150 ( drop, dropWhile, filter, map, mapM, reverse
151 , scanl, scanl1, sequence, take, takeWhile)
153import Streamly.Internal.Data.Stream.StreamD.Type
154import Streamly.Internal.Data.SVar
156------------------------------------------------------------------------------
158------------------------------------------------------------------------------
160{-# INLINE_NORMAL transform #-}
161transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
162transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
163 Stream step' (Consume pstate, state)
167 {-# INLINE_LATE step' #-}
169 step' gst (Consume pst, st) = pst `seq` do
170 r <- step (adaptState gst) st
175 Pipe.Yield b pst' -> return $ Yield b (pst', s)
176 Pipe.Continue pst' -> return $ Skip (pst', s)
177 Skip s -> return $ Skip (Consume pst, s)
180 step' _ (Produce pst, st) = pst `seq` do
183 Pipe.Yield b pst' -> return $ Yield b (pst', st)
184 Pipe.Continue pst' -> return $ Skip (pst', st)
186------------------------------------------------------------------------------
187-- Transformation Folds
188------------------------------------------------------------------------------
190{-# INLINE_NORMAL foldlT #-}
191foldlT :: (Monad m, Monad (s m), MonadTrans s)
192 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
193foldlT fstep begin (Stream step state) = go SPEC begin state
196 r <- lift $ step defState st
198 Yield x s -> go SPEC (fstep acc x) s
199 Skip s -> go SPEC acc s
202-- Note, this is going to have horrible performance, because of the nature of
203-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
204-- likely be practically unusable.
205{-# INLINE_NORMAL foldlS #-}
207 => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
208foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
210 step' gst (Left (st, acc)) = do
211 r <- step (adaptState gst) st
213 Yield x s -> Skip (Left (s, fstep acc x))
214 Skip s -> Skip (Left (s, acc))
215 Stop -> Skip (Right acc)
217 step' gst (Right (Stream stp stt)) = do
218 r <- stp (adaptState gst) stt
220 Yield x s -> Yield x (Right (Stream stp s))
221 Skip s -> Skip (Right (Stream stp s))
224------------------------------------------------------------------------------
225-- Transformation by Mapping
226------------------------------------------------------------------------------
228{-# INLINE_NORMAL sequence #-}
229sequence :: Monad m => Stream m (m a) -> Stream m a
230sequence (Stream step state) = Stream step' state
232 {-# INLINE_LATE step' #-}
234 r <- step (adaptState gst) st
236 Yield x s -> x >>= \a -> return (Yield a s)
237 Skip s -> return $ Skip s
240------------------------------------------------------------------------------
241-- Mapping side effects
242------------------------------------------------------------------------------
245 = TapInit | Tapping !fs st | TapDone st
247-- XXX Multiple yield points
249tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
250tap (Fold fstep initial extract) (Stream step state) = Stream step' TapInit
259 FL.Partial s -> Tapping s state
260 FL.Done _ -> TapDone state
261 step' gst (Tapping acc st) = do
269 FL.Partial fs -> Tapping fs s
270 FL.Done _ -> TapDone s
271 Skip s -> return $ Skip (Tapping acc s)
275 step' gst (TapDone st) = do
279 Yield x s -> Yield x (TapDone s)
280 Skip s -> Skip (TapDone s)
283data TapOffState fs s a
285 | TapOffTapping !fs s Int
288-- XXX Multiple yield points
289{-# INLINE_NORMAL tapOffsetEvery #-}
290tapOffsetEvery :: Monad m
291 => Int -> Int -> Fold m a b -> Stream m a -> Stream m a
292tapOffsetEvery offset n (Fold fstep initial extract) (Stream step state) =
293 Stream step' TapOffInit
297 {-# INLINE_LATE step' #-}
298 step' _ TapOffInit = do
303 FL.Partial s -> TapOffTapping s state (offset `mod` n)
304 FL.Done _ -> TapOffDone state
305 step' gst (TapOffTapping acc st count) = do
316 TapOffTapping sres s (n - 1)
317 FL.Done _ -> TapOffDone s
318 else return $ TapOffTapping acc s (count - 1)
319 return $ Yield x next
320 Skip s -> return $ Skip (TapOffTapping acc s count)
324 step' gst (TapOffDone st) = do
328 Yield x s -> Yield x (TapOffDone s)
329 Skip s -> Skip (TapOffDone s)
332{-# INLINE_NORMAL pollCounts #-}
336 -> (Stream m Int -> Stream m Int)
340pollCounts predicate transf fld (Stream step state) = Stream step' Nothing
343 {-# INLINE_LATE step' #-}
345 -- As long as we are using an "Int" for counts lockfree reads from
346 -- Var should work correctly on both 32-bit and 64-bit machines.
347 -- However, an Int on a 32-bit machine may overflow quickly.
348 countVar <- liftIO $ Prim.newIORef (0 :: Int)
351 $ transf $ Prim.toStreamD countVar
352 return $ Skip (Just (countVar, tid, state))
354 step' gst (Just (countVar, tid, st)) = do
358 when (predicate x) $ liftIO $ Prim.modifyIORef' countVar (+ 1)
359 return $ Yield x (Just (countVar, tid, s))
360 Skip s -> return $ Skip (Just (countVar, tid, s))
362 liftIO $ killThread tid
365{-# INLINE_NORMAL tapRate #-}
367 (MonadAsync m, MonadCatch m)
372tapRate samplingRate action (Stream step state) = Stream step' Nothing
374 {-# NOINLINE loop #-}
375 loop countVar prev = do
378 (do liftIO $ threadDelay (round $ samplingRate * 1000000)
379 i <- liftIO $ Prim.readIORef countVar
383 (\(e :: AsyncException) -> do
384 i <- liftIO $ Prim.readIORef countVar
387 throwM (MC.toException e))
390 {-# INLINE_LATE step' #-}
392 countVar <- liftIO $ Prim.newIORef 0
393 tid <- fork $ loop countVar 0
394 ref <- liftIO $ newIORef ()
395 _ <- liftIO $ mkWeakIORef ref (killThread tid)
396 return $ Skip (Just (countVar, tid, state, ref))
398 step' gst (Just (countVar, tid, st, ref)) = do
402 liftIO $ Prim.modifyIORef' countVar (+ 1)
403 return $ Yield x (Just (countVar, tid, s, ref))
404 Skip s -> return $ Skip (Just (countVar, tid, s, ref))
406 liftIO $ killThread tid
409------------------------------------------------------------------------------
410-- Scanning with a Fold
411------------------------------------------------------------------------------
413data ScanState s f = ScanInit s | ScanDo s !f | ScanDone
415{-# INLINE_NORMAL postscanOnce #-}
416postscanOnce :: Monad m => FL.Fold m a b -> Stream m a -> Stream m b
417postscanOnce (FL.Fold fstep initial extract) (Stream sstep state) =
418 Stream step (ScanInit state)
422 {-# INLINE_LATE step #-}
423 step _ (ScanInit st) = do
427 FL.Partial fs -> Skip $ ScanDo st fs
428 FL.Done b -> Yield b ScanDone
429 step gst (ScanDo st fs) = do
430 res <- sstep (adaptState gst) st
437 return $ Yield b $ ScanDo s fs1
438 FL.Done b -> return $ Yield b ScanDone
439 Skip s -> return $ Skip $ ScanDo s fs
441 step _ ScanDone = return Stop
443{-# INLINE scanOnce #-}
445 => FL.Fold m a b -> Stream m a -> Stream m b
446scanOnce (FL.Fold fstep initial extract) (Stream sstep state) =
447 Stream step (ScanInit state)
451 {-# INLINE_LATE step #-}
452 step _ (ScanInit st) = do
457 return $ Yield b $ ScanDo st fs
458 FL.Done b -> return $ Yield b ScanDone
459 step gst (ScanDo st fs) = do
460 res <- sstep (adaptState gst) st
467 return $ Yield b $ ScanDo s fs1
468 FL.Done b -> return $ Yield b ScanDone
469 Skip s -> return $ Skip $ ScanDo s fs
471 step _ ScanDone = return Stop
473------------------------------------------------------------------------------
474-- Scanning - Prescans
475------------------------------------------------------------------------------
477-- Adapted from the vector package.
479-- XXX Is a prescan useful, discarding the last step does not sound useful? I
480-- am not sure about the utility of this function, so this is implemented but
481-- not exposed. We can expose it if someone provides good reasons why this is
484-- XXX We have to execute the stream one step ahead to know that we are at the
485-- last step. The vector implementation of prescan executes the last fold step
486-- but does not yield the result. This means we have executed the effect but
487-- discarded value. This does not sound right. In this implementation we are
488-- not executing the last fold step.
489{-# INLINE_NORMAL prescanlM' #-}
490prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
491prescanlM' f mz (Stream step state) = Stream step' (state, mz)
493 {-# INLINE_LATE step' #-}
494 step' gst (st, prev) = do
495 r <- step (adaptState gst) st
499 return $ Yield acc (s, f acc x)
500 Skip s -> return $ Skip (s, prev)
503{-# INLINE prescanl' #-}
504prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
505prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
507------------------------------------------------------------------------------
508-- Monolithic postscans (postscan followed by a map)
509------------------------------------------------------------------------------
511-- The performance of a modular postscan followed by a map seems to be
512-- equivalent to this monolithic scan followed by map therefore we may not need
513-- this implementation. We just have it for performance comparison and in case
514-- modular version does not perform well in some situation.
516{-# INLINE_NORMAL postscanlMx' #-}
517postscanlMx' :: Monad m
518 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
519postscanlMx' fstep begin done (Stream step state) = do
520 Stream step' (state, begin)
522 {-# INLINE_LATE step' #-}
523 step' gst (st, acc) = do
524 r <- step (adaptState gst) st
530 v `seq` y `seq` return (Yield v (s, return y))
531 Skip s -> return $ Skip (s, acc)
534{-# INLINE_NORMAL postscanlx' #-}
535postscanlx' :: Monad m
536 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
537postscanlx' fstep begin done s =
538 postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
540-- XXX do we need consM strict to evaluate the begin value?
541{-# INLINE scanlMx' #-}
543 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
544scanlMx' fstep begin done s =
545 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
547{-# INLINE scanlx' #-}
549 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
550scanlx' fstep begin done s =
551 scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
553------------------------------------------------------------------------------
555------------------------------------------------------------------------------
557-- Adapted from the vector package.
558{-# INLINE_NORMAL postscanlM' #-}
559postscanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
560postscanlM' fstep begin (Stream step state) =
563 {-# INLINE_LATE step' #-}
566 return $ Skip (Just (state, x))
568 step' gst (Just (st, acc)) = do
569 r <- step (adaptState gst) st
573 return $ Yield y (Just (s, y))
574 Skip s -> return $ Skip (Just (s, acc))
577{-# INLINE_NORMAL postscanl' #-}
578postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
579postscanl' f seed = postscanlM' (\a b -> return (f a b)) (return seed)
581-- We can possibly have the "done" function as a Maybe to provide an option to
582-- emit or not emit the accumulator when the stream stops.
584-- TBD: use a single Yield point
586{-# INLINE_NORMAL postscanlMAfter' #-}
587postscanlMAfter' :: Monad m
588 => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
589postscanlMAfter' fstep initial done (Stream step1 state1) = do
590 Stream step (Just (state1, initial))
594 {-# INLINE_LATE step #-}
595 step gst (Just (st, acc)) = do
596 r <- step1 (adaptState gst) st
601 y `seq` return (Yield y (Just (s, return y)))
602 Skip s -> return $ Skip $ Just (s, acc)
603 Stop -> acc >>= done >>= \res -> return (Yield res Nothing)
604 step _ Nothing = return Stop
606{-# INLINE_NORMAL postscanlM #-}
607postscanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
608postscanlM fstep begin (Stream step state) = Stream step' Nothing
610 {-# INLINE_LATE step' #-}
613 return $ Skip (Just (state, r))
615 step' gst (Just (st, acc)) = do
616 r <- step (adaptState gst) st
620 return (Yield y (Just (s, y)))
621 Skip s -> return $ Skip (Just (s, acc))
624{-# INLINE_NORMAL postscanl #-}
625postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
626postscanl f seed = postscanlM (\a b -> return (f a b)) (return seed)
628{-# INLINE_NORMAL scanlM' #-}
629scanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
630scanlM' fstep begin (Stream step state) = Stream step' Nothing
632 {-# INLINE_LATE step' #-}
635 return $ Yield x (Just (state, x))
636 step' gst (Just (st, acc)) = do
637 r <- step (adaptState gst) st
641 return $ Yield y (Just (s, y))
642 Skip s -> return $ Skip (Just (s, acc))
645{-# INLINE scanlMAfter' #-}
646scanlMAfter' :: Monad m
647 => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
648scanlMAfter' fstep initial done s =
649 (initial >>= \x -> x `seq` return x) `consM`
650 postscanlMAfter' fstep initial done s
653scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
654scanl' f seed = scanlM' (\a b -> return (f a b)) (return seed)
656{-# INLINE_NORMAL scanlM #-}
657scanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
658scanlM fstep begin (Stream step state) = Stream step' Nothing
660 {-# INLINE_LATE step' #-}
663 return $ Yield x (Just (state, x))
664 step' gst (Just (st, acc)) = do
665 r <- step (adaptState gst) st
669 return $ Yield y (Just (s, y))
670 Skip s -> return $ Skip (Just (s, acc))
671 Stop -> return $ Stop
674scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
675scanl f seed = scanlM (\a b -> return (f a b)) (return seed)
677-- Adapted from the vector package
678{-# INLINE_NORMAL scanl1M #-}
679scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
680scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
682 {-# INLINE_LATE step' #-}
683 step' gst (st, Nothing) = do
686 Yield x s -> return $ Yield x (s, Just x)
687 Skip s -> return $ Skip (s, Nothing)
690 step' gst (st, Just acc) = do
695 return $ Yield z (s, Just z)
696 Skip s -> return $ Skip (s, Just acc)
700scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
701scanl1 f = scanl1M (\x y -> return (f x y))
703-- Adapted from the vector package
704{-# INLINE_NORMAL scanl1M' #-}
705scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
706scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
708 {-# INLINE_LATE step' #-}
709 step' gst (st, Nothing) = do
712 Yield x s -> x `seq` return $ Yield x (s, Just x)
713 Skip s -> return $ Skip (s, Nothing)
716 step' gst (st, Just acc) = acc `seq` do
721 z `seq` return $ Yield z (s, Just z)
722 Skip s -> return $ Skip (s, Just acc)
725{-# INLINE scanl1' #-}
726scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
727scanl1' f = scanl1M' (\x y -> return (f x y))
729-------------------------------------------------------------------------------
731-------------------------------------------------------------------------------
733-- Adapted from the vector package
734{-# INLINE_NORMAL filterM #-}
735filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
736filterM f (Stream step state) = Stream step' state
738 {-# INLINE_LATE step' #-}
747 Skip s -> return $ Skip s
751filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
752filter f = filterM (return . f)
754-- Adapted from the vector package
755{-# INLINE_NORMAL uniq #-}
756uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
757uniq (Stream step state) = Stream step' (Nothing, state)
759 {-# INLINE_LATE step' #-}
760 step' gst (Nothing, st) = do
763 Yield x s -> return $ Yield x (Just x, s)
764 Skip s -> return $ Skip (Nothing, s)
766 step' gst (Just x, st) = do
769 Yield y s | x == y -> return $ Skip (Just x, s)
770 | otherwise -> return $ Yield y (Just y, s)
771 Skip s -> return $ Skip (Just x, s)
774{-# INLINE_NORMAL deleteBy #-}
775deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
776deleteBy eq x (Stream step state) = Stream step' (state, False)
778 {-# INLINE_LATE step' #-}
779 step' gst (st, False) = do
782 Yield y s -> return $
783 if eq x y then Skip (s, True) else Yield y (s, False)
784 Skip s -> return $ Skip (s, False)
787 step' gst (st, True) = do
790 Yield y s -> return $ Yield y (s, True)
791 Skip s -> return $ Skip (s, True)
794------------------------------------------------------------------------------
796------------------------------------------------------------------------------
798-- XXX using getTime in the loop can be pretty expensive especially for
799-- computations where iterations are lightweight. We have the following
802-- 1) Run a timeout thread updating a flag asynchronously and check that
803-- flag here, that way we can have a cheap termination check.
805-- 2) Use COARSE clock to get time with lower resolution but more efficiently.
807-- 3) Use rdtscp/rdtsc to get time directly from the processor, compute the
808-- termination value of rdtsc in the beginning and then in each iteration just
809-- get rdtsc and check if we should terminate.
813 | TakeByTimeCheck st s
814 | TakeByTimeYield st s
816{-# INLINE_NORMAL takeByTime #-}
817takeByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
818takeByTime duration (Stream step1 state1) = Stream step (TakeByTimeInit state1)
821 lim = toRelTime64 duration
823 {-# INLINE_LATE step #-}
824 step _ (TakeByTimeInit _) | lim == 0 = return Stop
825 step _ (TakeByTimeInit st) = do
826 t0 <- liftIO $ getTime Monotonic
827 return $ Skip (TakeByTimeYield st t0)
828 step _ (TakeByTimeCheck st t0) = do
829 t <- liftIO $ getTime Monotonic
831 if diffAbsTime64 t t0 > lim
833 else Skip (TakeByTimeYield st t0)
834 step gst (TakeByTimeYield st t0) = do
837 Yield x s -> Yield x (TakeByTimeCheck s t0)
838 Skip s -> Skip (TakeByTimeCheck s t0)
841data DropByTime st s x
844 | DropByTimeCheck st s x
847{-# INLINE_NORMAL dropByTime #-}
848dropByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
849dropByTime duration (Stream step1 state1) = Stream step (DropByTimeInit state1)
852 lim = toRelTime64 duration
854 {-# INLINE_LATE step #-}
855 step _ (DropByTimeInit st) = do
856 t0 <- liftIO $ getTime Monotonic
857 return $ Skip (DropByTimeGen st t0)
858 step gst (DropByTimeGen st t0) = do
861 Yield x s -> Skip (DropByTimeCheck s t0 x)
862 Skip s -> Skip (DropByTimeGen s t0)
864 step _ (DropByTimeCheck st t0 x) = do
865 t <- liftIO $ getTime Monotonic
866 if diffAbsTime64 t t0 <= lim
867 then return $ Skip $ DropByTimeGen st t0
868 else return $ Yield x $ DropByTimeYield st
869 step gst (DropByTimeYield st) = do
872 Yield x s -> Yield x (DropByTimeYield s)
873 Skip s -> Skip (DropByTimeYield s)
876-- Adapted from the vector package
877{-# INLINE_NORMAL drop #-}
878drop :: Monad m => Int -> Stream m a -> Stream m a
879drop n (Stream step state) = Stream step' (state, Just n)
881 {-# INLINE_LATE step' #-}
882 step' gst (st, Just i)
887 Yield _ s -> Skip (s, Just (i - 1))
888 Skip s -> Skip (s, Just i)
890 | otherwise = return $ Skip (st, Nothing)
892 step' gst (st, Nothing) = do
896 Yield x s -> Yield x (s, Nothing)
897 Skip s -> Skip (s, Nothing)
900-- Adapted from the vector package
901data DropWhileState s a
906{-# INLINE_NORMAL dropWhileM #-}
907dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
908dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
910 {-# INLINE_LATE step' #-}
911 step' gst (DropWhileDrop st) = do
917 then return $ Skip (DropWhileDrop s)
918 else return $ Skip (DropWhileYield x s)
919 Skip s -> return $ Skip (DropWhileDrop s)
922 step' gst (DropWhileNext st) = do
925 Yield x s -> return $ Skip (DropWhileYield x s)
926 Skip s -> return $ Skip (DropWhileNext s)
929 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
931{-# INLINE dropWhile #-}
932dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
933dropWhile f = dropWhileM (return . f)
935------------------------------------------------------------------------------
937------------------------------------------------------------------------------
939{-# INLINE_NORMAL insertBy #-}
940insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
941insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
943 {-# INLINE_LATE step' #-}
944 step' gst (st, False, _) = do
947 Yield x s -> case cmp a x of
948 GT -> return $ Yield x (s, False, Nothing)
949 _ -> return $ Yield a (s, True, Just x)
950 Skip s -> return $ Skip (s, False, Nothing)
951 Stop -> return $ Yield a (st, True, Nothing)
953 step' _ (_, True, Nothing) = return Stop
955 step' gst (st, True, Just prev) = do
958 Yield x s -> return $ Yield prev (s, True, Just x)
959 Skip s -> return $ Skip (s, True, Just prev)
960 Stop -> return $ Yield prev (st, True, Nothing)
962data LoopState x s = FirstYield s
963 | InterspersingYield s
966{-# INLINE_NORMAL intersperseM #-}
967intersperseM :: Monad m => m a -> Stream m a -> Stream m a
968intersperseM m (Stream step state) = Stream step' (FirstYield state)
970 {-# INLINE_LATE step' #-}
971 step' gst (FirstYield st) = do
975 Yield x s -> Skip (YieldAndCarry x s)
976 Skip s -> Skip (FirstYield s)
979 step' gst (InterspersingYield st) = do
984 return $ Yield a (YieldAndCarry x s)
985 Skip s -> return $ Skip $ InterspersingYield s
988 step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
990{-# INLINE intersperse #-}
991intersperse :: Monad m => a -> Stream m a -> Stream m a
992intersperse a = intersperseM (return a)
994{-# INLINE_NORMAL intersperseM_ #-}
995intersperseM_ :: Monad m => m b -> Stream m a -> Stream m a
996intersperseM_ m (Stream step1 state1) = Stream step (Left (pure (), state1))
998 {-# INLINE_LATE step #-}
999 step gst (Left (eff, st)) = do
1002 Yield x s -> eff >> return (Yield x (Right s))
1003 Skip s -> return $ Skip (Left (eff, s))
1006 step _ (Right st) = return $ Skip $ Left (void m, st)
1011 | SuffixYield a (SuffixState s a)
1013{-# INLINE_NORMAL intersperseSuffix #-}
1014intersperseSuffix :: forall m a. Monad m => m a -> Stream m a -> Stream m a
1015intersperseSuffix action (Stream step state) = Stream step' (SuffixElem state)
1017 {-# INLINE_LATE step' #-}
1018 step' gst (SuffixElem st) = do
1021 Yield x s -> Skip (SuffixYield x (SuffixSuffix s))
1022 Skip s -> Skip (SuffixElem s)
1025 step' _ (SuffixSuffix st) = do
1026 action >>= \r -> return $ Skip (SuffixYield r (SuffixElem st))
1028 step' _ (SuffixYield x next) = return $ Yield x next
1030{-# INLINE_NORMAL intersperseSuffix_ #-}
1031intersperseSuffix_ :: Monad m => m b -> Stream m a -> Stream m a
1032intersperseSuffix_ m (Stream step1 state1) = Stream step (Left state1)
1034 {-# INLINE_LATE step #-}
1035 step gst (Left st) = do
1038 Yield x s -> return $ Yield x (Right s)
1039 Skip s -> return $ Skip $ Left s
1042 step _ (Right st) = m >> return (Skip (Left st))
1044data SuffixSpanState s a
1045 = SuffixSpanElem s Int
1046 | SuffixSpanSuffix s
1047 | SuffixSpanYield a (SuffixSpanState s a)
1051-- | intersperse after every n items
1052{-# INLINE_NORMAL intersperseSuffixBySpan #-}
1053intersperseSuffixBySpan :: forall m a. Monad m
1054 => Int -> m a -> Stream m a -> Stream m a
1055intersperseSuffixBySpan n action (Stream step state) =
1056 Stream step' (SuffixSpanElem state n)
1058 {-# INLINE_LATE step' #-}
1059 step' gst (SuffixSpanElem st i) | i > 0 = do
1062 Yield x s -> Skip (SuffixSpanYield x (SuffixSpanElem s (i - 1)))
1063 Skip s -> Skip (SuffixSpanElem s i)
1064 Stop -> if i == n then Stop else Skip SuffixSpanLast
1065 step' _ (SuffixSpanElem st _) = return $ Skip (SuffixSpanSuffix st)
1067 step' _ (SuffixSpanSuffix st) = do
1068 action >>= \r -> return $ Skip (SuffixSpanYield r (SuffixSpanElem st n))
1070 step' _ (SuffixSpanLast) = do
1071 action >>= \r -> return $ Skip (SuffixSpanYield r SuffixSpanStop)
1073 step' _ (SuffixSpanYield x next) = return $ Yield x next
1075 step' _ (SuffixSpanStop) = return Stop
1077------------------------------------------------------------------------------
1079------------------------------------------------------------------------------
1081-- We can implement reverse as:
1083-- > reverse = foldlS (flip cons) nil
1085-- However, this implementation is unusable because of the horrible performance
1086-- of cons. So we just convert it to a list first and then stream from the
1089-- XXX Maybe we can use an Array instead of a list here?
1090{-# INLINE_NORMAL reverse #-}
1091reverse :: Monad m => Stream m a -> Stream m a
1092reverse m = Stream step Nothing
1094 {-# INLINE_LATE step #-}
1096 xs <- foldl' (flip (:)) [] m
1097 return $ Skip (Just xs)
1098 step _ (Just (x:xs)) = return $ Yield x (Just xs)
1099 step _ (Just []) = return Stop
1101-- Much faster reverse for Storables
1102{-# INLINE_NORMAL reverse' #-}
1103reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
1105-- This commented implementation copies the whole stream into one single array
1106-- and then streams from that array, this has exactly the same performance as
1107-- the chunked code that follows. Though this could be problematic due to
1108-- unbounded large allocations. However, if we use an idiomatic implementation
1109-- of arraysOf instead of the custom implementation then the chunked code
1110-- becomes worse by 6 times. Need to investigate if that can be improved.
1111import Foreign.ForeignPtr (touchForeignPtr)
1112import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
1113import Foreign.Ptr (Ptr, plusPtr)
1114reverse' m = Stream step Nothing
1116 {-# INLINE_LATE step #-}
1118 arr <- A.fromStreamD m
1119 let p = A.aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
1120 return $ Skip $ Just (A.aStart arr, p)
1122 step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
1124 step _ (Just (start, p)) = do
1125 let !x = A.unsafeInlineIO $ do
1127 touchForeignPtr start
1129 next = p `plusPtr` negate (sizeOf (undefined :: a))
1130 return $ Yield x (Just (start, next))
1133 A.flattenArraysRev -- unfoldMany A.readRev
1137 . A.arraysOf defaultChunkSize
1139------------------------------------------------------------------------------
1141------------------------------------------------------------------------------
1143-- Adapted from the vector package
1144{-# INLINE_NORMAL indexed #-}
1145indexed :: Monad m => Stream m a -> Stream m (Int, a)
1146indexed (Stream step state) = Stream step' (state, 0)
1148 {-# INLINE_LATE step' #-}
1149 step' gst (st, i) = i `seq` do
1150 r <- step (adaptState gst) st
1152 Yield x s -> return $ Yield (i, x) (s, i+1)
1153 Skip s -> return $ Skip (s, i)
1156-- Adapted from the vector package
1157{-# INLINE_NORMAL indexedR #-}
1158indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
1159indexedR m (Stream step state) = Stream step' (state, m)
1161 {-# INLINE_LATE step' #-}
1162 step' gst (st, i) = i `seq` do
1163 r <- step (adaptState gst) st
1165 Yield x s -> let i' = i - 1
1166 in return $ Yield (i, x) (s, i')
1167 Skip s -> return $ Skip (s, i)
1170------------------------------------------------------------------------------
1172------------------------------------------------------------------------------
1174{-# INLINE_NORMAL findIndices #-}
1175findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
1176findIndices p (Stream step state) = Stream step' (state, 0)
1178 {-# INLINE_LATE step' #-}
1179 step' gst (st, i) = i `seq` do
1180 r <- step (adaptState gst) st
1182 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
1183 Skip s -> Skip (s, i)
1186------------------------------------------------------------------------------
1188------------------------------------------------------------------------------
1190data RollingMapState s a = RollingMapInit s | RollingMapGo s a
1192{-# INLINE rollingMapM #-}
1193rollingMapM :: Monad m => (a -> a -> m b) -> Stream m a -> Stream m b
1194rollingMapM f (Stream step1 state1) = Stream step (RollingMapInit state1)
1196 step gst (RollingMapInit st) = do
1197 r <- step1 (adaptState gst) st
1199 Yield x s -> Skip $ RollingMapGo s x
1200 Skip s -> Skip $ RollingMapInit s
1203 step gst (RollingMapGo s1 x1) = do
1204 r <- step1 (adaptState gst) s1
1208 return $ Yield res $ RollingMapGo s x
1209 Skip s -> return $ Skip $ RollingMapGo s x1
1210 Stop -> return $ Stop
1212{-# INLINE rollingMap #-}
1213rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
1214rollingMap f = rollingMapM (\x y -> return $ f x y)
1216------------------------------------------------------------------------------
1218------------------------------------------------------------------------------
1220-- XXX Will this always fuse properly?
1221{-# INLINE_NORMAL mapMaybe #-}
1222mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
1223mapMaybe f = fmap fromJust . filter isJust . map f
1225{-# INLINE_NORMAL mapMaybeM #-}
1226mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
1227mapMaybeM f = fmap fromJust . filter isJust . mapM f
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list