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 GHC.Types (SPEC(..))
133import qualified Control.Monad.Catch as MC
135import Streamly.Internal.Control.Concurrent (MonadAsync, fork, forkManaged)
136import Streamly.Internal.Data.Fold.Type (Fold(..))
137import Streamly.Internal.Data.Pipe.Type (Pipe(..), PipeState(..))
138import Streamly.Internal.Data.SVar.Type (defState, adaptState)
139import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
140import Streamly.Internal.Data.Time.Units
141 (TimeUnit64, toRelTime64, diffAbsTime64)
143import qualified Streamly.Internal.Data.Fold.Type as FL
144import qualified Streamly.Internal.Data.IORef.Prim as Prim
145import qualified Streamly.Internal.Data.Pipe.Type as Pipe
148 ( drop, dropWhile, filter, map, mapM, reverse
149 , scanl, scanl1, sequence, take, takeWhile)
151import Streamly.Internal.Data.Stream.StreamD.Type
153------------------------------------------------------------------------------
155------------------------------------------------------------------------------
157{-# INLINE_NORMAL transform #-}
158transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
159transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
160 Stream step' (Consume pstate, state)
164 {-# INLINE_LATE step' #-}
166 step' gst (Consume pst, st) = pst `seq` do
167 r <- step (adaptState gst) st
172 Pipe.Yield b pst' -> return $ Yield b (pst', s)
173 Pipe.Continue pst' -> return $ Skip (pst', s)
174 Skip s -> return $ Skip (Consume pst, s)
177 step' _ (Produce pst, st) = pst `seq` do
180 Pipe.Yield b pst' -> return $ Yield b (pst', st)
181 Pipe.Continue pst' -> return $ Skip (pst', st)
183------------------------------------------------------------------------------
184-- Transformation Folds
185------------------------------------------------------------------------------
187{-# INLINE_NORMAL foldlT #-}
188foldlT :: (Monad m, Monad (s m), MonadTrans s)
189 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
190foldlT fstep begin (Stream step state) = go SPEC begin state
193 r <- lift $ step defState st
195 Yield x s -> go SPEC (fstep acc x) s
196 Skip s -> go SPEC acc s
199-- Note, this is going to have horrible performance, because of the nature of
200-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
201-- likely be practically unusable.
202{-# INLINE_NORMAL foldlS #-}
204 => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
205foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
207 step' gst (Left (st, acc)) = do
208 r <- step (adaptState gst) st
210 Yield x s -> Skip (Left (s, fstep acc x))
211 Skip s -> Skip (Left (s, acc))
212 Stop -> Skip (Right acc)
214 step' gst (Right (Stream stp stt)) = do
215 r <- stp (adaptState gst) stt
217 Yield x s -> Yield x (Right (Stream stp s))
218 Skip s -> Skip (Right (Stream stp s))
221------------------------------------------------------------------------------
222-- Transformation by Mapping
223------------------------------------------------------------------------------
225{-# INLINE_NORMAL sequence #-}
226sequence :: Monad m => Stream m (m a) -> Stream m a
227sequence (Stream step state) = Stream step' state
229 {-# INLINE_LATE step' #-}
231 r <- step (adaptState gst) st
233 Yield x s -> x >>= \a -> return (Yield a s)
234 Skip s -> return $ Skip s
237------------------------------------------------------------------------------
238-- Mapping side effects
239------------------------------------------------------------------------------
242 = TapInit | Tapping !fs st | TapDone st
244-- XXX Multiple yield points
246tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
247tap (Fold fstep initial extract) (Stream step state) = Stream step' TapInit
256 FL.Partial s -> Tapping s state
257 FL.Done _ -> TapDone state
258 step' gst (Tapping acc st) = do
266 FL.Partial fs -> Tapping fs s
267 FL.Done _ -> TapDone s
268 Skip s -> return $ Skip (Tapping acc s)
272 step' gst (TapDone st) = do
276 Yield x s -> Yield x (TapDone s)
277 Skip s -> Skip (TapDone s)
280data TapOffState fs s a
282 | TapOffTapping !fs s Int
285-- XXX Multiple yield points
286{-# INLINE_NORMAL tapOffsetEvery #-}
287tapOffsetEvery :: Monad m
288 => Int -> Int -> Fold m a b -> Stream m a -> Stream m a
289tapOffsetEvery offset n (Fold fstep initial extract) (Stream step state) =
290 Stream step' TapOffInit
294 {-# INLINE_LATE step' #-}
295 step' _ TapOffInit = do
300 FL.Partial s -> TapOffTapping s state (offset `mod` n)
301 FL.Done _ -> TapOffDone state
302 step' gst (TapOffTapping acc st count) = do
313 TapOffTapping sres s (n - 1)
314 FL.Done _ -> TapOffDone s
315 else return $ TapOffTapping acc s (count - 1)
316 return $ Yield x next
317 Skip s -> return $ Skip (TapOffTapping acc s count)
321 step' gst (TapOffDone st) = do
325 Yield x s -> Yield x (TapOffDone s)
326 Skip s -> Skip (TapOffDone s)
329{-# INLINE_NORMAL pollCounts #-}
333 -> (Stream m Int -> Stream m Int)
337pollCounts predicate transf fld (Stream step state) = Stream step' Nothing
340 {-# INLINE_LATE step' #-}
342 -- As long as we are using an "Int" for counts lockfree reads from
343 -- Var should work correctly on both 32-bit and 64-bit machines.
344 -- However, an Int on a 32-bit machine may overflow quickly.
345 countVar <- liftIO $ Prim.newIORef (0 :: Int)
348 $ transf $ Prim.toStreamD countVar
349 return $ Skip (Just (countVar, tid, state))
351 step' gst (Just (countVar, tid, st)) = do
355 when (predicate x) $ liftIO $ Prim.modifyIORef' countVar (+ 1)
356 return $ Yield x (Just (countVar, tid, s))
357 Skip s -> return $ Skip (Just (countVar, tid, s))
359 liftIO $ killThread tid
362{-# INLINE_NORMAL tapRate #-}
364 (MonadAsync m, MonadCatch m)
369tapRate samplingRate action (Stream step state) = Stream step' Nothing
371 {-# NOINLINE loop #-}
372 loop countVar prev = do
375 (do liftIO $ threadDelay (round $ samplingRate * 1000000)
376 i <- liftIO $ Prim.readIORef countVar
380 (\(e :: AsyncException) -> do
381 i <- liftIO $ Prim.readIORef countVar
384 throwM (MC.toException e))
387 {-# INLINE_LATE step' #-}
389 countVar <- liftIO $ Prim.newIORef 0
390 tid <- fork $ loop countVar 0
391 ref <- liftIO $ newIORef ()
392 _ <- liftIO $ mkWeakIORef ref (killThread tid)
393 return $ Skip (Just (countVar, tid, state, ref))
395 step' gst (Just (countVar, tid, st, ref)) = do
399 liftIO $ Prim.modifyIORef' countVar (+ 1)
400 return $ Yield x (Just (countVar, tid, s, ref))
401 Skip s -> return $ Skip (Just (countVar, tid, s, ref))
403 liftIO $ killThread tid
406------------------------------------------------------------------------------
407-- Scanning with a Fold
408------------------------------------------------------------------------------
410data ScanState s f = ScanInit s | ScanDo s !f | ScanDone
412{-# INLINE_NORMAL postscanOnce #-}
413postscanOnce :: Monad m => FL.Fold m a b -> Stream m a -> Stream m b
414postscanOnce (FL.Fold fstep initial extract) (Stream sstep state) =
415 Stream step (ScanInit state)
419 {-# INLINE_LATE step #-}
420 step _ (ScanInit st) = do
424 FL.Partial fs -> Skip $ ScanDo st fs
425 FL.Done b -> Yield b ScanDone
426 step gst (ScanDo st fs) = do
427 res <- sstep (adaptState gst) st
434 return $ Yield b $ ScanDo s fs1
435 FL.Done b -> return $ Yield b ScanDone
436 Skip s -> return $ Skip $ ScanDo s fs
438 step _ ScanDone = return Stop
440{-# INLINE scanOnce #-}
442 => FL.Fold m a b -> Stream m a -> Stream m b
443scanOnce (FL.Fold fstep initial extract) (Stream sstep state) =
444 Stream step (ScanInit state)
448 {-# INLINE_LATE step #-}
449 step _ (ScanInit st) = do
454 return $ Yield b $ ScanDo st fs
455 FL.Done b -> return $ Yield b ScanDone
456 step gst (ScanDo st fs) = do
457 res <- sstep (adaptState gst) st
464 return $ Yield b $ ScanDo s fs1
465 FL.Done b -> return $ Yield b ScanDone
466 Skip s -> return $ Skip $ ScanDo s fs
468 step _ ScanDone = return Stop
470------------------------------------------------------------------------------
471-- Scanning - Prescans
472------------------------------------------------------------------------------
474-- Adapted from the vector package.
476-- XXX Is a prescan useful, discarding the last step does not sound useful? I
477-- am not sure about the utility of this function, so this is implemented but
478-- not exposed. We can expose it if someone provides good reasons why this is
481-- XXX We have to execute the stream one step ahead to know that we are at the
482-- last step. The vector implementation of prescan executes the last fold step
483-- but does not yield the result. This means we have executed the effect but
484-- discarded value. This does not sound right. In this implementation we are
485-- not executing the last fold step.
486{-# INLINE_NORMAL prescanlM' #-}
487prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
488prescanlM' f mz (Stream step state) = Stream step' (state, mz)
490 {-# INLINE_LATE step' #-}
491 step' gst (st, prev) = do
492 r <- step (adaptState gst) st
496 return $ Yield acc (s, f acc x)
497 Skip s -> return $ Skip (s, prev)
500{-# INLINE prescanl' #-}
501prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
502prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
504------------------------------------------------------------------------------
505-- Monolithic postscans (postscan followed by a map)
506------------------------------------------------------------------------------
508-- The performance of a modular postscan followed by a map seems to be
509-- equivalent to this monolithic scan followed by map therefore we may not need
510-- this implementation. We just have it for performance comparison and in case
511-- modular version does not perform well in some situation.
513{-# INLINE_NORMAL postscanlMx' #-}
514postscanlMx' :: Monad m
515 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
516postscanlMx' fstep begin done (Stream step state) = do
517 Stream step' (state, begin)
519 {-# INLINE_LATE step' #-}
520 step' gst (st, acc) = do
521 r <- step (adaptState gst) st
527 v `seq` y `seq` return (Yield v (s, return y))
528 Skip s -> return $ Skip (s, acc)
531{-# INLINE_NORMAL postscanlx' #-}
532postscanlx' :: Monad m
533 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
534postscanlx' fstep begin done =
535 postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done)
537-- XXX do we need consM strict to evaluate the begin value?
538{-# INLINE scanlMx' #-}
540 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
541scanlMx' fstep begin done s =
542 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
544{-# INLINE scanlx' #-}
546 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
547scanlx' fstep begin done =
548 scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done)
550------------------------------------------------------------------------------
552------------------------------------------------------------------------------
554-- Adapted from the vector package.
555{-# INLINE_NORMAL postscanlM' #-}
556postscanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
557postscanlM' fstep begin (Stream step state) =
560 {-# INLINE_LATE step' #-}
563 return $ Skip (Just (state, x))
565 step' gst (Just (st, acc)) = do
566 r <- step (adaptState gst) st
570 return $ Yield y (Just (s, y))
571 Skip s -> return $ Skip (Just (s, acc))
574{-# INLINE_NORMAL postscanl' #-}
575postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
576postscanl' f seed = postscanlM' (\a b -> return (f a b)) (return seed)
578-- We can possibly have the "done" function as a Maybe to provide an option to
579-- emit or not emit the accumulator when the stream stops.
581-- TBD: use a single Yield point
583{-# INLINE_NORMAL postscanlMAfter' #-}
584postscanlMAfter' :: Monad m
585 => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
586postscanlMAfter' fstep initial done (Stream step1 state1) = do
587 Stream step (Just (state1, initial))
591 {-# INLINE_LATE step #-}
592 step gst (Just (st, acc)) = do
593 r <- step1 (adaptState gst) st
598 y `seq` return (Yield y (Just (s, return y)))
599 Skip s -> return $ Skip $ Just (s, acc)
600 Stop -> acc >>= done >>= \res -> return (Yield res Nothing)
601 step _ Nothing = return Stop
603{-# INLINE_NORMAL postscanlM #-}
604postscanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
605postscanlM fstep begin (Stream step state) = Stream step' Nothing
607 {-# INLINE_LATE step' #-}
610 return $ Skip (Just (state, r))
612 step' gst (Just (st, acc)) = do
613 r <- step (adaptState gst) st
617 return (Yield y (Just (s, y)))
618 Skip s -> return $ Skip (Just (s, acc))
621{-# INLINE_NORMAL postscanl #-}
622postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
623postscanl f seed = postscanlM (\a b -> return (f a b)) (return seed)
625{-# INLINE_NORMAL scanlM' #-}
626scanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
627scanlM' fstep begin (Stream step state) = Stream step' Nothing
629 {-# INLINE_LATE step' #-}
632 return $ Yield x (Just (state, x))
633 step' gst (Just (st, acc)) = do
634 r <- step (adaptState gst) st
638 return $ Yield y (Just (s, y))
639 Skip s -> return $ Skip (Just (s, acc))
642{-# INLINE scanlMAfter' #-}
643scanlMAfter' :: Monad m
644 => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
645scanlMAfter' fstep initial done s =
646 (initial >>= \x -> x `seq` return x) `consM`
647 postscanlMAfter' fstep initial done s
650scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
651scanl' f seed = scanlM' (\a b -> return (f a b)) (return seed)
653{-# INLINE_NORMAL scanlM #-}
654scanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
655scanlM fstep begin (Stream step state) = Stream step' Nothing
657 {-# INLINE_LATE step' #-}
660 return $ Yield x (Just (state, x))
661 step' gst (Just (st, acc)) = do
662 r <- step (adaptState gst) st
666 return $ Yield y (Just (s, y))
667 Skip s -> return $ Skip (Just (s, acc))
671scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
672scanl f seed = scanlM (\a b -> return (f a b)) (return seed)
674-- Adapted from the vector package
675{-# INLINE_NORMAL scanl1M #-}
676scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
677scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
679 {-# INLINE_LATE step' #-}
680 step' gst (st, Nothing) = do
683 Yield x s -> return $ Yield x (s, Just x)
684 Skip s -> return $ Skip (s, Nothing)
687 step' gst (st, Just acc) = do
692 return $ Yield z (s, Just z)
693 Skip s -> return $ Skip (s, Just acc)
697scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
698scanl1 f = scanl1M (\x y -> return (f x y))
700-- Adapted from the vector package
701{-# INLINE_NORMAL scanl1M' #-}
702scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
703scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
705 {-# INLINE_LATE step' #-}
706 step' gst (st, Nothing) = do
709 Yield x s -> x `seq` return $ Yield x (s, Just x)
710 Skip s -> return $ Skip (s, Nothing)
713 step' gst (st, Just acc) = acc `seq` do
718 z `seq` return $ Yield z (s, Just z)
719 Skip s -> return $ Skip (s, Just acc)
722{-# INLINE scanl1' #-}
723scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
724scanl1' f = scanl1M' (\x y -> return (f x y))
726-------------------------------------------------------------------------------
728-------------------------------------------------------------------------------
730-- Adapted from the vector package
731{-# INLINE_NORMAL filterM #-}
732filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
733filterM f (Stream step state) = Stream step' state
735 {-# INLINE_LATE step' #-}
744 Skip s -> return $ Skip s
748filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
749filter f = filterM (return . f)
751-- Adapted from the vector package
752{-# INLINE_NORMAL uniq #-}
753uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
754uniq (Stream step state) = Stream step' (Nothing, state)
756 {-# INLINE_LATE step' #-}
757 step' gst (Nothing, st) = do
760 Yield x s -> return $ Yield x (Just x, s)
761 Skip s -> return $ Skip (Nothing, s)
763 step' gst (Just x, st) = do
766 Yield y s | x == y -> return $ Skip (Just x, s)
767 | otherwise -> return $ Yield y (Just y, s)
768 Skip s -> return $ Skip (Just x, s)
771{-# INLINE_NORMAL deleteBy #-}
772deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
773deleteBy eq x (Stream step state) = Stream step' (state, False)
775 {-# INLINE_LATE step' #-}
776 step' gst (st, False) = do
779 Yield y s -> return $
780 if eq x y then Skip (s, True) else Yield y (s, False)
781 Skip s -> return $ Skip (s, False)
784 step' gst (st, True) = do
787 Yield y s -> return $ Yield y (s, True)
788 Skip s -> return $ Skip (s, True)
791------------------------------------------------------------------------------
793------------------------------------------------------------------------------
795-- XXX using getTime in the loop can be pretty expensive especially for
796-- computations where iterations are lightweight. We have the following
799-- 1) Run a timeout thread updating a flag asynchronously and check that
800-- flag here, that way we can have a cheap termination check.
802-- 2) Use COARSE clock to get time with lower resolution but more efficiently.
804-- 3) Use rdtscp/rdtsc to get time directly from the processor, compute the
805-- termination value of rdtsc in the beginning and then in each iteration just
806-- get rdtsc and check if we should terminate.
810 | TakeByTimeCheck st s
811 | TakeByTimeYield st s
813{-# INLINE_NORMAL takeByTime #-}
814takeByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
815takeByTime duration (Stream step1 state1) = Stream step (TakeByTimeInit state1)
818 lim = toRelTime64 duration
820 {-# INLINE_LATE step #-}
821 step _ (TakeByTimeInit _) | lim == 0 = return Stop
822 step _ (TakeByTimeInit st) = do
823 t0 <- liftIO $ getTime Monotonic
824 return $ Skip (TakeByTimeYield st t0)
825 step _ (TakeByTimeCheck st t0) = do
826 t <- liftIO $ getTime Monotonic
828 if diffAbsTime64 t t0 > lim
830 else Skip (TakeByTimeYield st t0)
831 step gst (TakeByTimeYield st t0) = do
834 Yield x s -> Yield x (TakeByTimeCheck s t0)
835 Skip s -> Skip (TakeByTimeCheck s t0)
838data DropByTime st s x
841 | DropByTimeCheck st s x
844{-# INLINE_NORMAL dropByTime #-}
845dropByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
846dropByTime duration (Stream step1 state1) = Stream step (DropByTimeInit state1)
849 lim = toRelTime64 duration
851 {-# INLINE_LATE step #-}
852 step _ (DropByTimeInit st) = do
853 t0 <- liftIO $ getTime Monotonic
854 return $ Skip (DropByTimeGen st t0)
855 step gst (DropByTimeGen st t0) = do
858 Yield x s -> Skip (DropByTimeCheck s t0 x)
859 Skip s -> Skip (DropByTimeGen s t0)
861 step _ (DropByTimeCheck st t0 x) = do
862 t <- liftIO $ getTime Monotonic
863 if diffAbsTime64 t t0 <= lim
864 then return $ Skip $ DropByTimeGen st t0
865 else return $ Yield x $ DropByTimeYield st
866 step gst (DropByTimeYield st) = do
869 Yield x s -> Yield x (DropByTimeYield s)
870 Skip s -> Skip (DropByTimeYield s)
873-- Adapted from the vector package
874{-# INLINE_NORMAL drop #-}
875drop :: Monad m => Int -> Stream m a -> Stream m a
876drop n (Stream step state) = Stream step' (state, Just n)
878 {-# INLINE_LATE step' #-}
879 step' gst (st, Just i)
884 Yield _ s -> Skip (s, Just (i - 1))
885 Skip s -> Skip (s, Just i)
887 | otherwise = return $ Skip (st, Nothing)
889 step' gst (st, Nothing) = do
893 Yield x s -> Yield x (s, Nothing)
894 Skip s -> Skip (s, Nothing)
897-- Adapted from the vector package
898data DropWhileState s a
903{-# INLINE_NORMAL dropWhileM #-}
904dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
905dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
907 {-# INLINE_LATE step' #-}
908 step' gst (DropWhileDrop st) = do
914 then return $ Skip (DropWhileDrop s)
915 else return $ Skip (DropWhileYield x s)
916 Skip s -> return $ Skip (DropWhileDrop s)
919 step' gst (DropWhileNext st) = do
922 Yield x s -> return $ Skip (DropWhileYield x s)
923 Skip s -> return $ Skip (DropWhileNext s)
926 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
928{-# INLINE dropWhile #-}
929dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
930dropWhile f = dropWhileM (return . f)
932------------------------------------------------------------------------------
934------------------------------------------------------------------------------
936{-# INLINE_NORMAL insertBy #-}
937insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
938insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
940 {-# INLINE_LATE step' #-}
941 step' gst (st, False, _) = do
944 Yield x s -> case cmp a x of
945 GT -> return $ Yield x (s, False, Nothing)
946 _ -> return $ Yield a (s, True, Just x)
947 Skip s -> return $ Skip (s, False, Nothing)
948 Stop -> return $ Yield a (st, True, Nothing)
950 step' _ (_, True, Nothing) = return Stop
952 step' gst (st, True, Just prev) = do
955 Yield x s -> return $ Yield prev (s, True, Just x)
956 Skip s -> return $ Skip (s, True, Just prev)
957 Stop -> return $ Yield prev (st, True, Nothing)
959data LoopState x s = FirstYield s
960 | InterspersingYield s
963{-# INLINE_NORMAL intersperseM #-}
964intersperseM :: Monad m => m a -> Stream m a -> Stream m a
965intersperseM m (Stream step state) = Stream step' (FirstYield state)
967 {-# INLINE_LATE step' #-}
968 step' gst (FirstYield st) = do
972 Yield x s -> Skip (YieldAndCarry x s)
973 Skip s -> Skip (FirstYield s)
976 step' gst (InterspersingYield st) = do
981 return $ Yield a (YieldAndCarry x s)
982 Skip s -> return $ Skip $ InterspersingYield s
985 step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
987{-# INLINE intersperse #-}
988intersperse :: Monad m => a -> Stream m a -> Stream m a
989intersperse a = intersperseM (return a)
991{-# INLINE_NORMAL intersperseM_ #-}
992intersperseM_ :: Monad m => m b -> Stream m a -> Stream m a
993intersperseM_ m (Stream step1 state1) = Stream step (Left (pure (), state1))
995 {-# INLINE_LATE step #-}
996 step gst (Left (eff, st)) = do
999 Yield x s -> eff >> return (Yield x (Right s))
1000 Skip s -> return $ Skip (Left (eff, s))
1003 step _ (Right st) = return $ Skip $ Left (void m, st)
1008 | SuffixYield a (SuffixState s a)
1010{-# INLINE_NORMAL intersperseSuffix #-}
1011intersperseSuffix :: forall m a. Monad m => m a -> Stream m a -> Stream m a
1012intersperseSuffix action (Stream step state) = Stream step' (SuffixElem state)
1014 {-# INLINE_LATE step' #-}
1015 step' gst (SuffixElem st) = do
1018 Yield x s -> Skip (SuffixYield x (SuffixSuffix s))
1019 Skip s -> Skip (SuffixElem s)
1022 step' _ (SuffixSuffix st) = do
1023 action >>= \r -> return $ Skip (SuffixYield r (SuffixElem st))
1025 step' _ (SuffixYield x next) = return $ Yield x next
1027{-# INLINE_NORMAL intersperseSuffix_ #-}
1028intersperseSuffix_ :: Monad m => m b -> Stream m a -> Stream m a
1029intersperseSuffix_ m (Stream step1 state1) = Stream step (Left state1)
1031 {-# INLINE_LATE step #-}
1032 step gst (Left st) = do
1035 Yield x s -> return $ Yield x (Right s)
1036 Skip s -> return $ Skip $ Left s
1039 step _ (Right st) = m >> return (Skip (Left st))
1041data SuffixSpanState s a
1042 = SuffixSpanElem s Int
1043 | SuffixSpanSuffix s
1044 | SuffixSpanYield a (SuffixSpanState s a)
1048-- | intersperse after every n items
1049{-# INLINE_NORMAL intersperseSuffixBySpan #-}
1050intersperseSuffixBySpan :: forall m a. Monad m
1051 => Int -> m a -> Stream m a -> Stream m a
1052intersperseSuffixBySpan n action (Stream step state) =
1053 Stream step' (SuffixSpanElem state n)
1055 {-# INLINE_LATE step' #-}
1056 step' gst (SuffixSpanElem st i) | i > 0 = do
1059 Yield x s -> Skip (SuffixSpanYield x (SuffixSpanElem s (i - 1)))
1060 Skip s -> Skip (SuffixSpanElem s i)
1061 Stop -> if i == n then Stop else Skip SuffixSpanLast
1062 step' _ (SuffixSpanElem st _) = return $ Skip (SuffixSpanSuffix st)
1064 step' _ (SuffixSpanSuffix st) = do
1065 action >>= \r -> return $ Skip (SuffixSpanYield r (SuffixSpanElem st n))
1067 step' _ SuffixSpanLast = do
1068 action >>= \r -> return $ Skip (SuffixSpanYield r SuffixSpanStop)
1070 step' _ (SuffixSpanYield x next) = return $ Yield x next
1072 step' _ SuffixSpanStop = return Stop
1074------------------------------------------------------------------------------
1076------------------------------------------------------------------------------
1078-- We can implement reverse as:
1080-- > reverse = foldlS (flip cons) nil
1082-- However, this implementation is unusable because of the horrible performance
1083-- of cons. So we just convert it to a list first and then stream from the
1086-- XXX Maybe we can use an Array instead of a list here?
1087{-# INLINE_NORMAL reverse #-}
1088reverse :: Monad m => Stream m a -> Stream m a
1089reverse m = Stream step Nothing
1091 {-# INLINE_LATE step #-}
1093 xs <- foldl' (flip (:)) [] m
1094 return $ Skip (Just xs)
1095 step _ (Just (x:xs)) = return $ Yield x (Just xs)
1096 step _ (Just []) = return Stop
1098-- Much faster reverse for Storables
1100{-# INLINE_NORMAL reverse' #-}
1101reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
1102-- This commented implementation copies the whole stream into one single array
1103-- and then streams from that array, this has exactly the same performance as
1104-- the chunked code in IsStream.Common.reverse' . Though this could be problematic due to
1105-- unbounded large allocations. However, if we use an idiomatic implementation
1106-- of arraysOf instead of the custom implementation then the chunked code
1107-- becomes worse by 6 times. Need to investigate if that can be improved.
1108import Foreign.ForeignPtr (touchForeignPtr)
1109import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
1110import Foreign.Ptr (Ptr, plusPtr)
1111reverse' m = Stream step Nothing
1113 {-# INLINE_LATE step #-}
1115 arr <- A.fromStreamD m
1116 let p = A.aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
1117 return $ Skip $ Just (A.aStart arr, p)
1119 step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
1121 step _ (Just (start, p)) = do
1122 let !x = A.unsafeInlineIO $ do
1124 touchForeignPtr start
1126 next = p `plusPtr` negate (sizeOf (undefined :: a))
1127 return $ Yield x (Just (start, next))
1130------------------------------------------------------------------------------
1132------------------------------------------------------------------------------
1134-- Adapted from the vector package
1135{-# INLINE_NORMAL indexed #-}
1136indexed :: Monad m => Stream m a -> Stream m (Int, a)
1137indexed (Stream step state) = Stream step' (state, 0)
1139 {-# INLINE_LATE step' #-}
1140 step' gst (st, i) = i `seq` do
1141 r <- step (adaptState gst) st
1143 Yield x s -> return $ Yield (i, x) (s, i+1)
1144 Skip s -> return $ Skip (s, i)
1147-- Adapted from the vector package
1148{-# INLINE_NORMAL indexedR #-}
1149indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
1150indexedR m (Stream step state) = Stream step' (state, m)
1152 {-# INLINE_LATE step' #-}
1153 step' gst (st, i) = i `seq` do
1154 r <- step (adaptState gst) st
1156 Yield x s -> let i' = i - 1
1157 in return $ Yield (i, x) (s, i')
1158 Skip s -> return $ Skip (s, i)
1161------------------------------------------------------------------------------
1163------------------------------------------------------------------------------
1165{-# INLINE_NORMAL findIndices #-}
1166findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
1167findIndices p (Stream step state) = Stream step' (state, 0)
1169 {-# INLINE_LATE step' #-}
1170 step' gst (st, i) = i `seq` do
1171 r <- step (adaptState gst) st
1173 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
1174 Skip s -> Skip (s, i)
1177------------------------------------------------------------------------------
1179------------------------------------------------------------------------------
1181data RollingMapState s a = RollingMapInit s | RollingMapGo s a
1183{-# INLINE rollingMapM #-}
1184rollingMapM :: Monad m => (a -> a -> m b) -> Stream m a -> Stream m b
1185rollingMapM f (Stream step1 state1) = Stream step (RollingMapInit state1)
1187 step gst (RollingMapInit st) = do
1188 r <- step1 (adaptState gst) st
1190 Yield x s -> Skip $ RollingMapGo s x
1191 Skip s -> Skip $ RollingMapInit s
1194 step gst (RollingMapGo s1 x1) = do
1195 r <- step1 (adaptState gst) s1
1199 return $ Yield res $ RollingMapGo s x
1200 Skip s -> return $ Skip $ RollingMapGo s x1
1203{-# INLINE rollingMap #-}
1204rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
1205rollingMap f = rollingMapM (\x y -> return $ f x y)
1207------------------------------------------------------------------------------
1209------------------------------------------------------------------------------
1211-- XXX Will this always fuse properly?
1212{-# INLINE_NORMAL mapMaybe #-}
1213mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
1214mapMaybe f = fmap fromJust . filter isJust . map f
1216{-# INLINE_NORMAL mapMaybeM #-}
1217mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
1218mapMaybeM 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