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.Control.Concurrent (MonadAsync, fork, forkManaged)
137import Streamly.Internal.Data.Fold.Type (Fold(..))
138import Streamly.Internal.Data.Pipe.Type (Pipe(..), PipeState(..))
139import Streamly.Internal.Data.SVar.Type (defState, adaptState)
140import Streamly.Internal.Data.Time.Clock (Clock(Monotonic), getTime)
141import Streamly.Internal.Data.Time.Units
142 (TimeUnit64, toRelTime64, diffAbsTime64)
143import Streamly.Internal.System.IO (defaultChunkSize)
145import qualified Streamly.Internal.Data.Array.Foreign.Type as A
146import qualified Streamly.Internal.Data.Fold.Type as FL
147import qualified Streamly.Internal.Data.IORef.Prim as Prim
148import qualified Streamly.Internal.Data.Pipe.Type as Pipe
149import qualified Streamly.Internal.Data.Stream.StreamK as K
152 ( drop, dropWhile, filter, map, mapM, reverse
153 , scanl, scanl1, sequence, take, takeWhile)
155import Streamly.Internal.Data.Stream.StreamD.Type
157------------------------------------------------------------------------------
159------------------------------------------------------------------------------
161{-# INLINE_NORMAL transform #-}
162transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
163transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
164 Stream step' (Consume pstate, state)
168 {-# INLINE_LATE step' #-}
170 step' gst (Consume pst, st) = pst `seq` do
171 r <- step (adaptState gst) st
176 Pipe.Yield b pst' -> return $ Yield b (pst', s)
177 Pipe.Continue pst' -> return $ Skip (pst', s)
178 Skip s -> return $ Skip (Consume pst, s)
181 step' _ (Produce pst, st) = pst `seq` do
184 Pipe.Yield b pst' -> return $ Yield b (pst', st)
185 Pipe.Continue pst' -> return $ Skip (pst', st)
187------------------------------------------------------------------------------
188-- Transformation Folds
189------------------------------------------------------------------------------
191{-# INLINE_NORMAL foldlT #-}
192foldlT :: (Monad m, Monad (s m), MonadTrans s)
193 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
194foldlT fstep begin (Stream step state) = go SPEC begin state
197 r <- lift $ step defState st
199 Yield x s -> go SPEC (fstep acc x) s
200 Skip s -> go SPEC acc s
203-- Note, this is going to have horrible performance, because of the nature of
204-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
205-- likely be practically unusable.
206{-# INLINE_NORMAL foldlS #-}
208 => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
209foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
211 step' gst (Left (st, acc)) = do
212 r <- step (adaptState gst) st
214 Yield x s -> Skip (Left (s, fstep acc x))
215 Skip s -> Skip (Left (s, acc))
216 Stop -> Skip (Right acc)
218 step' gst (Right (Stream stp stt)) = do
219 r <- stp (adaptState gst) stt
221 Yield x s -> Yield x (Right (Stream stp s))
222 Skip s -> Skip (Right (Stream stp s))
225------------------------------------------------------------------------------
226-- Transformation by Mapping
227------------------------------------------------------------------------------
229{-# INLINE_NORMAL sequence #-}
230sequence :: Monad m => Stream m (m a) -> Stream m a
231sequence (Stream step state) = Stream step' state
233 {-# INLINE_LATE step' #-}
235 r <- step (adaptState gst) st
237 Yield x s -> x >>= \a -> return (Yield a s)
238 Skip s -> return $ Skip s
241------------------------------------------------------------------------------
242-- Mapping side effects
243------------------------------------------------------------------------------
246 = TapInit | Tapping !fs st | TapDone st
248-- XXX Multiple yield points
250tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
251tap (Fold fstep initial extract) (Stream step state) = Stream step' TapInit
260 FL.Partial s -> Tapping s state
261 FL.Done _ -> TapDone state
262 step' gst (Tapping acc st) = do
270 FL.Partial fs -> Tapping fs s
271 FL.Done _ -> TapDone s
272 Skip s -> return $ Skip (Tapping acc s)
276 step' gst (TapDone st) = do
280 Yield x s -> Yield x (TapDone s)
281 Skip s -> Skip (TapDone s)
284data TapOffState fs s a
286 | TapOffTapping !fs s Int
289-- XXX Multiple yield points
290{-# INLINE_NORMAL tapOffsetEvery #-}
291tapOffsetEvery :: Monad m
292 => Int -> Int -> Fold m a b -> Stream m a -> Stream m a
293tapOffsetEvery offset n (Fold fstep initial extract) (Stream step state) =
294 Stream step' TapOffInit
298 {-# INLINE_LATE step' #-}
299 step' _ TapOffInit = do
304 FL.Partial s -> TapOffTapping s state (offset `mod` n)
305 FL.Done _ -> TapOffDone state
306 step' gst (TapOffTapping acc st count) = do
317 TapOffTapping sres s (n - 1)
318 FL.Done _ -> TapOffDone s
319 else return $ TapOffTapping acc s (count - 1)
320 return $ Yield x next
321 Skip s -> return $ Skip (TapOffTapping acc s count)
325 step' gst (TapOffDone st) = do
329 Yield x s -> Yield x (TapOffDone s)
330 Skip s -> Skip (TapOffDone s)
333{-# INLINE_NORMAL pollCounts #-}
337 -> (Stream m Int -> Stream m Int)
341pollCounts predicate transf fld (Stream step state) = Stream step' Nothing
344 {-# INLINE_LATE step' #-}
346 -- As long as we are using an "Int" for counts lockfree reads from
347 -- Var should work correctly on both 32-bit and 64-bit machines.
348 -- However, an Int on a 32-bit machine may overflow quickly.
349 countVar <- liftIO $ Prim.newIORef (0 :: Int)
352 $ transf $ Prim.toStreamD countVar
353 return $ Skip (Just (countVar, tid, state))
355 step' gst (Just (countVar, tid, st)) = do
359 when (predicate x) $ liftIO $ Prim.modifyIORef' countVar (+ 1)
360 return $ Yield x (Just (countVar, tid, s))
361 Skip s -> return $ Skip (Just (countVar, tid, s))
363 liftIO $ killThread tid
366{-# INLINE_NORMAL tapRate #-}
368 (MonadAsync m, MonadCatch m)
373tapRate samplingRate action (Stream step state) = Stream step' Nothing
375 {-# NOINLINE loop #-}
376 loop countVar prev = do
379 (do liftIO $ threadDelay (round $ samplingRate * 1000000)
380 i <- liftIO $ Prim.readIORef countVar
384 (\(e :: AsyncException) -> do
385 i <- liftIO $ Prim.readIORef countVar
388 throwM (MC.toException e))
391 {-# INLINE_LATE step' #-}
393 countVar <- liftIO $ Prim.newIORef 0
394 tid <- fork $ loop countVar 0
395 ref <- liftIO $ newIORef ()
396 _ <- liftIO $ mkWeakIORef ref (killThread tid)
397 return $ Skip (Just (countVar, tid, state, ref))
399 step' gst (Just (countVar, tid, st, ref)) = do
403 liftIO $ Prim.modifyIORef' countVar (+ 1)
404 return $ Yield x (Just (countVar, tid, s, ref))
405 Skip s -> return $ Skip (Just (countVar, tid, s, ref))
407 liftIO $ killThread tid
410------------------------------------------------------------------------------
411-- Scanning with a Fold
412------------------------------------------------------------------------------
414data ScanState s f = ScanInit s | ScanDo s !f | ScanDone
416{-# INLINE_NORMAL postscanOnce #-}
417postscanOnce :: Monad m => FL.Fold m a b -> Stream m a -> Stream m b
418postscanOnce (FL.Fold fstep initial extract) (Stream sstep state) =
419 Stream step (ScanInit state)
423 {-# INLINE_LATE step #-}
424 step _ (ScanInit st) = do
428 FL.Partial fs -> Skip $ ScanDo st fs
429 FL.Done b -> Yield b ScanDone
430 step gst (ScanDo st fs) = do
431 res <- sstep (adaptState gst) st
438 return $ Yield b $ ScanDo s fs1
439 FL.Done b -> return $ Yield b ScanDone
440 Skip s -> return $ Skip $ ScanDo s fs
442 step _ ScanDone = return Stop
444{-# INLINE scanOnce #-}
446 => FL.Fold m a b -> Stream m a -> Stream m b
447scanOnce (FL.Fold fstep initial extract) (Stream sstep state) =
448 Stream step (ScanInit state)
452 {-# INLINE_LATE step #-}
453 step _ (ScanInit st) = do
458 return $ Yield b $ ScanDo st fs
459 FL.Done b -> return $ Yield b ScanDone
460 step gst (ScanDo st fs) = do
461 res <- sstep (adaptState gst) st
468 return $ Yield b $ ScanDo s fs1
469 FL.Done b -> return $ Yield b ScanDone
470 Skip s -> return $ Skip $ ScanDo s fs
472 step _ ScanDone = return Stop
474------------------------------------------------------------------------------
475-- Scanning - Prescans
476------------------------------------------------------------------------------
478-- Adapted from the vector package.
480-- XXX Is a prescan useful, discarding the last step does not sound useful? I
481-- am not sure about the utility of this function, so this is implemented but
482-- not exposed. We can expose it if someone provides good reasons why this is
485-- XXX We have to execute the stream one step ahead to know that we are at the
486-- last step. The vector implementation of prescan executes the last fold step
487-- but does not yield the result. This means we have executed the effect but
488-- discarded value. This does not sound right. In this implementation we are
489-- not executing the last fold step.
490{-# INLINE_NORMAL prescanlM' #-}
491prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
492prescanlM' f mz (Stream step state) = Stream step' (state, mz)
494 {-# INLINE_LATE step' #-}
495 step' gst (st, prev) = do
496 r <- step (adaptState gst) st
500 return $ Yield acc (s, f acc x)
501 Skip s -> return $ Skip (s, prev)
504{-# INLINE prescanl' #-}
505prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
506prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
508------------------------------------------------------------------------------
509-- Monolithic postscans (postscan followed by a map)
510------------------------------------------------------------------------------
512-- The performance of a modular postscan followed by a map seems to be
513-- equivalent to this monolithic scan followed by map therefore we may not need
514-- this implementation. We just have it for performance comparison and in case
515-- modular version does not perform well in some situation.
517{-# INLINE_NORMAL postscanlMx' #-}
518postscanlMx' :: Monad m
519 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
520postscanlMx' fstep begin done (Stream step state) = do
521 Stream step' (state, begin)
523 {-# INLINE_LATE step' #-}
524 step' gst (st, acc) = do
525 r <- step (adaptState gst) st
531 v `seq` y `seq` return (Yield v (s, return y))
532 Skip s -> return $ Skip (s, acc)
535{-# INLINE_NORMAL postscanlx' #-}
536postscanlx' :: Monad m
537 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
538postscanlx' fstep begin done s =
539 postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
541-- XXX do we need consM strict to evaluate the begin value?
542{-# INLINE scanlMx' #-}
544 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
545scanlMx' fstep begin done s =
546 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
548{-# INLINE scanlx' #-}
550 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
551scanlx' fstep begin done s =
552 scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
554------------------------------------------------------------------------------
556------------------------------------------------------------------------------
558-- Adapted from the vector package.
559{-# INLINE_NORMAL postscanlM' #-}
560postscanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
561postscanlM' fstep begin (Stream step state) =
564 {-# INLINE_LATE step' #-}
567 return $ Skip (Just (state, x))
569 step' gst (Just (st, acc)) = do
570 r <- step (adaptState gst) st
574 return $ Yield y (Just (s, y))
575 Skip s -> return $ Skip (Just (s, acc))
578{-# INLINE_NORMAL postscanl' #-}
579postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
580postscanl' f seed = postscanlM' (\a b -> return (f a b)) (return seed)
582-- We can possibly have the "done" function as a Maybe to provide an option to
583-- emit or not emit the accumulator when the stream stops.
585-- TBD: use a single Yield point
587{-# INLINE_NORMAL postscanlMAfter' #-}
588postscanlMAfter' :: Monad m
589 => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
590postscanlMAfter' fstep initial done (Stream step1 state1) = do
591 Stream step (Just (state1, initial))
595 {-# INLINE_LATE step #-}
596 step gst (Just (st, acc)) = do
597 r <- step1 (adaptState gst) st
602 y `seq` return (Yield y (Just (s, return y)))
603 Skip s -> return $ Skip $ Just (s, acc)
604 Stop -> acc >>= done >>= \res -> return (Yield res Nothing)
605 step _ Nothing = return Stop
607{-# INLINE_NORMAL postscanlM #-}
608postscanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
609postscanlM fstep begin (Stream step state) = Stream step' Nothing
611 {-# INLINE_LATE step' #-}
614 return $ Skip (Just (state, r))
616 step' gst (Just (st, acc)) = do
617 r <- step (adaptState gst) st
621 return (Yield y (Just (s, y)))
622 Skip s -> return $ Skip (Just (s, acc))
625{-# INLINE_NORMAL postscanl #-}
626postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
627postscanl f seed = postscanlM (\a b -> return (f a b)) (return seed)
629{-# INLINE_NORMAL scanlM' #-}
630scanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
631scanlM' fstep begin (Stream step state) = Stream step' Nothing
633 {-# INLINE_LATE step' #-}
636 return $ Yield x (Just (state, x))
637 step' gst (Just (st, acc)) = do
638 r <- step (adaptState gst) st
642 return $ Yield y (Just (s, y))
643 Skip s -> return $ Skip (Just (s, acc))
646{-# INLINE scanlMAfter' #-}
647scanlMAfter' :: Monad m
648 => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
649scanlMAfter' fstep initial done s =
650 (initial >>= \x -> x `seq` return x) `consM`
651 postscanlMAfter' fstep initial done s
654scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
655scanl' f seed = scanlM' (\a b -> return (f a b)) (return seed)
657{-# INLINE_NORMAL scanlM #-}
658scanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
659scanlM fstep begin (Stream step state) = Stream step' Nothing
661 {-# INLINE_LATE step' #-}
664 return $ Yield x (Just (state, x))
665 step' gst (Just (st, acc)) = do
666 r <- step (adaptState gst) st
670 return $ Yield y (Just (s, y))
671 Skip s -> return $ Skip (Just (s, acc))
672 Stop -> return $ Stop
675scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
676scanl f seed = scanlM (\a b -> return (f a b)) (return seed)
678-- Adapted from the vector package
679{-# INLINE_NORMAL scanl1M #-}
680scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
681scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
683 {-# INLINE_LATE step' #-}
684 step' gst (st, Nothing) = do
687 Yield x s -> return $ Yield x (s, Just x)
688 Skip s -> return $ Skip (s, Nothing)
691 step' gst (st, Just acc) = do
696 return $ Yield z (s, Just z)
697 Skip s -> return $ Skip (s, Just acc)
701scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
702scanl1 f = scanl1M (\x y -> return (f x y))
704-- Adapted from the vector package
705{-# INLINE_NORMAL scanl1M' #-}
706scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
707scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
709 {-# INLINE_LATE step' #-}
710 step' gst (st, Nothing) = do
713 Yield x s -> x `seq` return $ Yield x (s, Just x)
714 Skip s -> return $ Skip (s, Nothing)
717 step' gst (st, Just acc) = acc `seq` do
722 z `seq` return $ Yield z (s, Just z)
723 Skip s -> return $ Skip (s, Just acc)
726{-# INLINE scanl1' #-}
727scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
728scanl1' f = scanl1M' (\x y -> return (f x y))
730-------------------------------------------------------------------------------
732-------------------------------------------------------------------------------
734-- Adapted from the vector package
735{-# INLINE_NORMAL filterM #-}
736filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
737filterM f (Stream step state) = Stream step' state
739 {-# INLINE_LATE step' #-}
748 Skip s -> return $ Skip s
752filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
753filter f = filterM (return . f)
755-- Adapted from the vector package
756{-# INLINE_NORMAL uniq #-}
757uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
758uniq (Stream step state) = Stream step' (Nothing, state)
760 {-# INLINE_LATE step' #-}
761 step' gst (Nothing, st) = do
764 Yield x s -> return $ Yield x (Just x, s)
765 Skip s -> return $ Skip (Nothing, s)
767 step' gst (Just x, st) = do
770 Yield y s | x == y -> return $ Skip (Just x, s)
771 | otherwise -> return $ Yield y (Just y, s)
772 Skip s -> return $ Skip (Just x, s)
775{-# INLINE_NORMAL deleteBy #-}
776deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
777deleteBy eq x (Stream step state) = Stream step' (state, False)
779 {-# INLINE_LATE step' #-}
780 step' gst (st, False) = do
783 Yield y s -> return $
784 if eq x y then Skip (s, True) else Yield y (s, False)
785 Skip s -> return $ Skip (s, False)
788 step' gst (st, True) = do
791 Yield y s -> return $ Yield y (s, True)
792 Skip s -> return $ Skip (s, True)
795------------------------------------------------------------------------------
797------------------------------------------------------------------------------
799-- XXX using getTime in the loop can be pretty expensive especially for
800-- computations where iterations are lightweight. We have the following
803-- 1) Run a timeout thread updating a flag asynchronously and check that
804-- flag here, that way we can have a cheap termination check.
806-- 2) Use COARSE clock to get time with lower resolution but more efficiently.
808-- 3) Use rdtscp/rdtsc to get time directly from the processor, compute the
809-- termination value of rdtsc in the beginning and then in each iteration just
810-- get rdtsc and check if we should terminate.
814 | TakeByTimeCheck st s
815 | TakeByTimeYield st s
817{-# INLINE_NORMAL takeByTime #-}
818takeByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
819takeByTime duration (Stream step1 state1) = Stream step (TakeByTimeInit state1)
822 lim = toRelTime64 duration
824 {-# INLINE_LATE step #-}
825 step _ (TakeByTimeInit _) | lim == 0 = return Stop
826 step _ (TakeByTimeInit st) = do
827 t0 <- liftIO $ getTime Monotonic
828 return $ Skip (TakeByTimeYield st t0)
829 step _ (TakeByTimeCheck st t0) = do
830 t <- liftIO $ getTime Monotonic
832 if diffAbsTime64 t t0 > lim
834 else Skip (TakeByTimeYield st t0)
835 step gst (TakeByTimeYield st t0) = do
838 Yield x s -> Yield x (TakeByTimeCheck s t0)
839 Skip s -> Skip (TakeByTimeCheck s t0)
842data DropByTime st s x
845 | DropByTimeCheck st s x
848{-# INLINE_NORMAL dropByTime #-}
849dropByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
850dropByTime duration (Stream step1 state1) = Stream step (DropByTimeInit state1)
853 lim = toRelTime64 duration
855 {-# INLINE_LATE step #-}
856 step _ (DropByTimeInit st) = do
857 t0 <- liftIO $ getTime Monotonic
858 return $ Skip (DropByTimeGen st t0)
859 step gst (DropByTimeGen st t0) = do
862 Yield x s -> Skip (DropByTimeCheck s t0 x)
863 Skip s -> Skip (DropByTimeGen s t0)
865 step _ (DropByTimeCheck st t0 x) = do
866 t <- liftIO $ getTime Monotonic
867 if diffAbsTime64 t t0 <= lim
868 then return $ Skip $ DropByTimeGen st t0
869 else return $ Yield x $ DropByTimeYield st
870 step gst (DropByTimeYield st) = do
873 Yield x s -> Yield x (DropByTimeYield s)
874 Skip s -> Skip (DropByTimeYield s)
877-- Adapted from the vector package
878{-# INLINE_NORMAL drop #-}
879drop :: Monad m => Int -> Stream m a -> Stream m a
880drop n (Stream step state) = Stream step' (state, Just n)
882 {-# INLINE_LATE step' #-}
883 step' gst (st, Just i)
888 Yield _ s -> Skip (s, Just (i - 1))
889 Skip s -> Skip (s, Just i)
891 | otherwise = return $ Skip (st, Nothing)
893 step' gst (st, Nothing) = do
897 Yield x s -> Yield x (s, Nothing)
898 Skip s -> Skip (s, Nothing)
901-- Adapted from the vector package
902data DropWhileState s a
907{-# INLINE_NORMAL dropWhileM #-}
908dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
909dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
911 {-# INLINE_LATE step' #-}
912 step' gst (DropWhileDrop st) = do
918 then return $ Skip (DropWhileDrop s)
919 else return $ Skip (DropWhileYield x s)
920 Skip s -> return $ Skip (DropWhileDrop s)
923 step' gst (DropWhileNext st) = do
926 Yield x s -> return $ Skip (DropWhileYield x s)
927 Skip s -> return $ Skip (DropWhileNext s)
930 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
932{-# INLINE dropWhile #-}
933dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
934dropWhile f = dropWhileM (return . f)
936------------------------------------------------------------------------------
938------------------------------------------------------------------------------
940{-# INLINE_NORMAL insertBy #-}
941insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
942insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
944 {-# INLINE_LATE step' #-}
945 step' gst (st, False, _) = do
948 Yield x s -> case cmp a x of
949 GT -> return $ Yield x (s, False, Nothing)
950 _ -> return $ Yield a (s, True, Just x)
951 Skip s -> return $ Skip (s, False, Nothing)
952 Stop -> return $ Yield a (st, True, Nothing)
954 step' _ (_, True, Nothing) = return Stop
956 step' gst (st, True, Just prev) = do
959 Yield x s -> return $ Yield prev (s, True, Just x)
960 Skip s -> return $ Skip (s, True, Just prev)
961 Stop -> return $ Yield prev (st, True, Nothing)
963data LoopState x s = FirstYield s
964 | InterspersingYield s
967{-# INLINE_NORMAL intersperseM #-}
968intersperseM :: Monad m => m a -> Stream m a -> Stream m a
969intersperseM m (Stream step state) = Stream step' (FirstYield state)
971 {-# INLINE_LATE step' #-}
972 step' gst (FirstYield st) = do
976 Yield x s -> Skip (YieldAndCarry x s)
977 Skip s -> Skip (FirstYield s)
980 step' gst (InterspersingYield st) = do
985 return $ Yield a (YieldAndCarry x s)
986 Skip s -> return $ Skip $ InterspersingYield s
989 step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
991{-# INLINE intersperse #-}
992intersperse :: Monad m => a -> Stream m a -> Stream m a
993intersperse a = intersperseM (return a)
995{-# INLINE_NORMAL intersperseM_ #-}
996intersperseM_ :: Monad m => m b -> Stream m a -> Stream m a
997intersperseM_ m (Stream step1 state1) = Stream step (Left (pure (), state1))
999 {-# INLINE_LATE step #-}
1000 step gst (Left (eff, st)) = do
1003 Yield x s -> eff >> return (Yield x (Right s))
1004 Skip s -> return $ Skip (Left (eff, s))
1007 step _ (Right st) = return $ Skip $ Left (void m, st)
1012 | SuffixYield a (SuffixState s a)
1014{-# INLINE_NORMAL intersperseSuffix #-}
1015intersperseSuffix :: forall m a. Monad m => m a -> Stream m a -> Stream m a
1016intersperseSuffix action (Stream step state) = Stream step' (SuffixElem state)
1018 {-# INLINE_LATE step' #-}
1019 step' gst (SuffixElem st) = do
1022 Yield x s -> Skip (SuffixYield x (SuffixSuffix s))
1023 Skip s -> Skip (SuffixElem s)
1026 step' _ (SuffixSuffix st) = do
1027 action >>= \r -> return $ Skip (SuffixYield r (SuffixElem st))
1029 step' _ (SuffixYield x next) = return $ Yield x next
1031{-# INLINE_NORMAL intersperseSuffix_ #-}
1032intersperseSuffix_ :: Monad m => m b -> Stream m a -> Stream m a
1033intersperseSuffix_ m (Stream step1 state1) = Stream step (Left state1)
1035 {-# INLINE_LATE step #-}
1036 step gst (Left st) = do
1039 Yield x s -> return $ Yield x (Right s)
1040 Skip s -> return $ Skip $ Left s
1043 step _ (Right st) = m >> return (Skip (Left st))
1045data SuffixSpanState s a
1046 = SuffixSpanElem s Int
1047 | SuffixSpanSuffix s
1048 | SuffixSpanYield a (SuffixSpanState s a)
1052-- | intersperse after every n items
1053{-# INLINE_NORMAL intersperseSuffixBySpan #-}
1054intersperseSuffixBySpan :: forall m a. Monad m
1055 => Int -> m a -> Stream m a -> Stream m a
1056intersperseSuffixBySpan n action (Stream step state) =
1057 Stream step' (SuffixSpanElem state n)
1059 {-# INLINE_LATE step' #-}
1060 step' gst (SuffixSpanElem st i) | i > 0 = do
1063 Yield x s -> Skip (SuffixSpanYield x (SuffixSpanElem s (i - 1)))
1064 Skip s -> Skip (SuffixSpanElem s i)
1065 Stop -> if i == n then Stop else Skip SuffixSpanLast
1066 step' _ (SuffixSpanElem st _) = return $ Skip (SuffixSpanSuffix st)
1068 step' _ (SuffixSpanSuffix st) = do
1069 action >>= \r -> return $ Skip (SuffixSpanYield r (SuffixSpanElem st n))
1071 step' _ (SuffixSpanLast) = do
1072 action >>= \r -> return $ Skip (SuffixSpanYield r SuffixSpanStop)
1074 step' _ (SuffixSpanYield x next) = return $ Yield x next
1076 step' _ (SuffixSpanStop) = return Stop
1078------------------------------------------------------------------------------
1080------------------------------------------------------------------------------
1082-- We can implement reverse as:
1084-- > reverse = foldlS (flip cons) nil
1086-- However, this implementation is unusable because of the horrible performance
1087-- of cons. So we just convert it to a list first and then stream from the
1090-- XXX Maybe we can use an Array instead of a list here?
1091{-# INLINE_NORMAL reverse #-}
1092reverse :: Monad m => Stream m a -> Stream m a
1093reverse m = Stream step Nothing
1095 {-# INLINE_LATE step #-}
1097 xs <- foldl' (flip (:)) [] m
1098 return $ Skip (Just xs)
1099 step _ (Just (x:xs)) = return $ Yield x (Just xs)
1100 step _ (Just []) = return Stop
1102-- Much faster reverse for Storables
1103{-# INLINE_NORMAL reverse' #-}
1104reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
1106-- This commented implementation copies the whole stream into one single array
1107-- and then streams from that array, this has exactly the same performance as
1108-- the chunked code that follows. Though this could be problematic due to
1109-- unbounded large allocations. However, if we use an idiomatic implementation
1110-- of arraysOf instead of the custom implementation then the chunked code
1111-- becomes worse by 6 times. Need to investigate if that can be improved.
1112import Foreign.ForeignPtr (touchForeignPtr)
1113import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
1114import Foreign.Ptr (Ptr, plusPtr)
1115reverse' m = Stream step Nothing
1117 {-# INLINE_LATE step #-}
1119 arr <- A.fromStreamD m
1120 let p = A.aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
1121 return $ Skip $ Just (A.aStart arr, p)
1123 step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
1125 step _ (Just (start, p)) = do
1126 let !x = A.unsafeInlineIO $ do
1128 touchForeignPtr start
1130 next = p `plusPtr` negate (sizeOf (undefined :: a))
1131 return $ Yield x (Just (start, next))
1134 A.flattenArraysRev -- unfoldMany A.readRev
1138 . A.arraysOf defaultChunkSize
1140------------------------------------------------------------------------------
1142------------------------------------------------------------------------------
1144-- Adapted from the vector package
1145{-# INLINE_NORMAL indexed #-}
1146indexed :: Monad m => Stream m a -> Stream m (Int, a)
1147indexed (Stream step state) = Stream step' (state, 0)
1149 {-# INLINE_LATE step' #-}
1150 step' gst (st, i) = i `seq` do
1151 r <- step (adaptState gst) st
1153 Yield x s -> return $ Yield (i, x) (s, i+1)
1154 Skip s -> return $ Skip (s, i)
1157-- Adapted from the vector package
1158{-# INLINE_NORMAL indexedR #-}
1159indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
1160indexedR m (Stream step state) = Stream step' (state, m)
1162 {-# INLINE_LATE step' #-}
1163 step' gst (st, i) = i `seq` do
1164 r <- step (adaptState gst) st
1166 Yield x s -> let i' = i - 1
1167 in return $ Yield (i, x) (s, i')
1168 Skip s -> return $ Skip (s, i)
1171------------------------------------------------------------------------------
1173------------------------------------------------------------------------------
1175{-# INLINE_NORMAL findIndices #-}
1176findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
1177findIndices p (Stream step state) = Stream step' (state, 0)
1179 {-# INLINE_LATE step' #-}
1180 step' gst (st, i) = i `seq` do
1181 r <- step (adaptState gst) st
1183 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
1184 Skip s -> Skip (s, i)
1187------------------------------------------------------------------------------
1189------------------------------------------------------------------------------
1191data RollingMapState s a = RollingMapInit s | RollingMapGo s a
1193{-# INLINE rollingMapM #-}
1194rollingMapM :: Monad m => (a -> a -> m b) -> Stream m a -> Stream m b
1195rollingMapM f (Stream step1 state1) = Stream step (RollingMapInit state1)
1197 step gst (RollingMapInit st) = do
1198 r <- step1 (adaptState gst) st
1200 Yield x s -> Skip $ RollingMapGo s x
1201 Skip s -> Skip $ RollingMapInit s
1204 step gst (RollingMapGo s1 x1) = do
1205 r <- step1 (adaptState gst) s1
1209 return $ Yield res $ RollingMapGo s x
1210 Skip s -> return $ Skip $ RollingMapGo s x1
1211 Stop -> return $ Stop
1213{-# INLINE rollingMap #-}
1214rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
1215rollingMap f = rollingMapM (\x y -> return $ f x y)
1217------------------------------------------------------------------------------
1219------------------------------------------------------------------------------
1221-- XXX Will this always fuse properly?
1222{-# INLINE_NORMAL mapMaybe #-}
1223mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
1224mapMaybe f = fmap fromJust . filter isJust . map f
1226{-# INLINE_NORMAL mapMaybeM #-}
1227mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
1228mapMaybeM 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