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)
142import qualified Streamly.Internal.Data.Array.Foreign.Type as A
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
146import qualified Streamly.Internal.Data.Stream.StreamK as K
149 ( drop, dropWhile, filter, map, mapM, reverse
150 , scanl, scanl1, sequence, take, takeWhile)
152import Streamly.Internal.Data.Stream.StreamD.Type
153import Streamly.Internal.Data.SVar
155------------------------------------------------------------------------------
157------------------------------------------------------------------------------
159{-# INLINE_NORMAL transform #-}
160transform :: Monad m => Pipe m a b -> Stream m a -> Stream m b
161transform (Pipe pstep1 pstep2 pstate) (Stream step state) =
162 Stream step' (Consume pstate, state)
166 {-# INLINE_LATE step' #-}
168 step' gst (Consume pst, st) = pst `seq` do
169 r <- step (adaptState gst) st
174 Pipe.Yield b pst' -> return $ Yield b (pst', s)
175 Pipe.Continue pst' -> return $ Skip (pst', s)
176 Skip s -> return $ Skip (Consume pst, s)
179 step' _ (Produce pst, st) = pst `seq` do
182 Pipe.Yield b pst' -> return $ Yield b (pst', st)
183 Pipe.Continue pst' -> return $ Skip (pst', st)
185------------------------------------------------------------------------------
186-- Transformation Folds
187------------------------------------------------------------------------------
189{-# INLINE_NORMAL foldlT #-}
190foldlT :: (Monad m, Monad (s m), MonadTrans s)
191 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
192foldlT fstep begin (Stream step state) = go SPEC begin state
195 r <- lift $ step defState st
197 Yield x s -> go SPEC (fstep acc x) s
198 Skip s -> go SPEC acc s
201-- Note, this is going to have horrible performance, because of the nature of
202-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
203-- likely be practically unusable.
204{-# INLINE_NORMAL foldlS #-}
206 => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
207foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
209 step' gst (Left (st, acc)) = do
210 r <- step (adaptState gst) st
212 Yield x s -> Skip (Left (s, fstep acc x))
213 Skip s -> Skip (Left (s, acc))
214 Stop -> Skip (Right acc)
216 step' gst (Right (Stream stp stt)) = do
217 r <- stp (adaptState gst) stt
219 Yield x s -> Yield x (Right (Stream stp s))
220 Skip s -> Skip (Right (Stream stp s))
223------------------------------------------------------------------------------
224-- Transformation by Mapping
225------------------------------------------------------------------------------
227{-# INLINE_NORMAL sequence #-}
228sequence :: Monad m => Stream m (m a) -> Stream m a
229sequence (Stream step state) = Stream step' state
231 {-# INLINE_LATE step' #-}
233 r <- step (adaptState gst) st
235 Yield x s -> x >>= \a -> return (Yield a s)
236 Skip s -> return $ Skip s
239------------------------------------------------------------------------------
240-- Mapping side effects
241------------------------------------------------------------------------------
244 = TapInit | Tapping !fs st | TapDone st
246-- XXX Multiple yield points
248tap :: Monad m => Fold m a b -> Stream m a -> Stream m a
249tap (Fold fstep initial extract) (Stream step state) = Stream step' TapInit
258 FL.Partial s -> Tapping s state
259 FL.Done _ -> TapDone state
260 step' gst (Tapping acc st) = do
268 FL.Partial fs -> Tapping fs s
269 FL.Done _ -> TapDone s
270 Skip s -> return $ Skip (Tapping acc s)
274 step' gst (TapDone st) = do
278 Yield x s -> Yield x (TapDone s)
279 Skip s -> Skip (TapDone s)
282data TapOffState fs s a
284 | TapOffTapping !fs s Int
287-- XXX Multiple yield points
288{-# INLINE_NORMAL tapOffsetEvery #-}
289tapOffsetEvery :: Monad m
290 => Int -> Int -> Fold m a b -> Stream m a -> Stream m a
291tapOffsetEvery offset n (Fold fstep initial extract) (Stream step state) =
292 Stream step' TapOffInit
296 {-# INLINE_LATE step' #-}
297 step' _ TapOffInit = do
302 FL.Partial s -> TapOffTapping s state (offset `mod` n)
303 FL.Done _ -> TapOffDone state
304 step' gst (TapOffTapping acc st count) = do
315 TapOffTapping sres s (n - 1)
316 FL.Done _ -> TapOffDone s
317 else return $ TapOffTapping acc s (count - 1)
318 return $ Yield x next
319 Skip s -> return $ Skip (TapOffTapping acc s count)
323 step' gst (TapOffDone st) = do
327 Yield x s -> Yield x (TapOffDone s)
328 Skip s -> Skip (TapOffDone s)
331{-# INLINE_NORMAL pollCounts #-}
335 -> (Stream m Int -> Stream m Int)
339pollCounts predicate transf fld (Stream step state) = Stream step' Nothing
342 {-# INLINE_LATE step' #-}
344 -- As long as we are using an "Int" for counts lockfree reads from
345 -- Var should work correctly on both 32-bit and 64-bit machines.
346 -- However, an Int on a 32-bit machine may overflow quickly.
347 countVar <- liftIO $ Prim.newIORef (0 :: Int)
350 $ transf $ Prim.toStreamD countVar
351 return $ Skip (Just (countVar, tid, state))
353 step' gst (Just (countVar, tid, st)) = do
357 when (predicate x) $ liftIO $ Prim.modifyIORef' countVar (+ 1)
358 return $ Yield x (Just (countVar, tid, s))
359 Skip s -> return $ Skip (Just (countVar, tid, s))
361 liftIO $ killThread tid
364{-# INLINE_NORMAL tapRate #-}
366 (MonadAsync m, MonadCatch m)
371tapRate samplingRate action (Stream step state) = Stream step' Nothing
373 {-# NOINLINE loop #-}
374 loop countVar prev = do
377 (do liftIO $ threadDelay (round $ samplingRate * 1000000)
378 i <- liftIO $ Prim.readIORef countVar
382 (\(e :: AsyncException) -> do
383 i <- liftIO $ Prim.readIORef countVar
386 throwM (MC.toException e))
389 {-# INLINE_LATE step' #-}
391 countVar <- liftIO $ Prim.newIORef 0
392 tid <- fork $ loop countVar 0
393 ref <- liftIO $ newIORef ()
394 _ <- liftIO $ mkWeakIORef ref (killThread tid)
395 return $ Skip (Just (countVar, tid, state, ref))
397 step' gst (Just (countVar, tid, st, ref)) = do
401 liftIO $ Prim.modifyIORef' countVar (+ 1)
402 return $ Yield x (Just (countVar, tid, s, ref))
403 Skip s -> return $ Skip (Just (countVar, tid, s, ref))
405 liftIO $ killThread tid
408------------------------------------------------------------------------------
409-- Scanning with a Fold
410------------------------------------------------------------------------------
412data ScanState s f = ScanInit s | ScanDo s !f | ScanDone
414{-# INLINE_NORMAL postscanOnce #-}
415postscanOnce :: Monad m => FL.Fold m a b -> Stream m a -> Stream m b
416postscanOnce (FL.Fold fstep initial extract) (Stream sstep state) =
417 Stream step (ScanInit state)
421 {-# INLINE_LATE step #-}
422 step _ (ScanInit st) = do
426 FL.Partial fs -> Skip $ ScanDo st fs
427 FL.Done b -> Yield b ScanDone
428 step gst (ScanDo st fs) = do
429 res <- sstep (adaptState gst) st
436 return $ Yield b $ ScanDo s fs1
437 FL.Done b -> return $ Yield b ScanDone
438 Skip s -> return $ Skip $ ScanDo s fs
440 step _ ScanDone = return Stop
442{-# INLINE scanOnce #-}
444 => FL.Fold m a b -> Stream m a -> Stream m b
445scanOnce (FL.Fold fstep initial extract) (Stream sstep state) =
446 Stream step (ScanInit state)
450 {-# INLINE_LATE step #-}
451 step _ (ScanInit st) = do
456 return $ Yield b $ ScanDo st fs
457 FL.Done b -> return $ Yield b ScanDone
458 step gst (ScanDo st fs) = do
459 res <- sstep (adaptState gst) st
466 return $ Yield b $ ScanDo s fs1
467 FL.Done b -> return $ Yield b ScanDone
468 Skip s -> return $ Skip $ ScanDo s fs
470 step _ ScanDone = return Stop
472------------------------------------------------------------------------------
473-- Scanning - Prescans
474------------------------------------------------------------------------------
476-- Adapted from the vector package.
478-- XXX Is a prescan useful, discarding the last step does not sound useful? I
479-- am not sure about the utility of this function, so this is implemented but
480-- not exposed. We can expose it if someone provides good reasons why this is
483-- XXX We have to execute the stream one step ahead to know that we are at the
484-- last step. The vector implementation of prescan executes the last fold step
485-- but does not yield the result. This means we have executed the effect but
486-- discarded value. This does not sound right. In this implementation we are
487-- not executing the last fold step.
488{-# INLINE_NORMAL prescanlM' #-}
489prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
490prescanlM' f mz (Stream step state) = Stream step' (state, mz)
492 {-# INLINE_LATE step' #-}
493 step' gst (st, prev) = do
494 r <- step (adaptState gst) st
498 return $ Yield acc (s, f acc x)
499 Skip s -> return $ Skip (s, prev)
502{-# INLINE prescanl' #-}
503prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
504prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
506------------------------------------------------------------------------------
507-- Monolithic postscans (postscan followed by a map)
508------------------------------------------------------------------------------
510-- The performance of a modular postscan followed by a map seems to be
511-- equivalent to this monolithic scan followed by map therefore we may not need
512-- this implementation. We just have it for performance comparison and in case
513-- modular version does not perform well in some situation.
515{-# INLINE_NORMAL postscanlMx' #-}
516postscanlMx' :: Monad m
517 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
518postscanlMx' fstep begin done (Stream step state) = do
519 Stream step' (state, begin)
521 {-# INLINE_LATE step' #-}
522 step' gst (st, acc) = do
523 r <- step (adaptState gst) st
529 v `seq` y `seq` return (Yield v (s, return y))
530 Skip s -> return $ Skip (s, acc)
533{-# INLINE_NORMAL postscanlx' #-}
534postscanlx' :: Monad m
535 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
536postscanlx' fstep begin done s =
537 postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
539-- XXX do we need consM strict to evaluate the begin value?
540{-# INLINE scanlMx' #-}
542 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
543scanlMx' fstep begin done s =
544 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
546{-# INLINE scanlx' #-}
548 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
549scanlx' fstep begin done s =
550 scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
552------------------------------------------------------------------------------
554------------------------------------------------------------------------------
556-- Adapted from the vector package.
557{-# INLINE_NORMAL postscanlM' #-}
558postscanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
559postscanlM' fstep begin (Stream step state) =
562 {-# INLINE_LATE step' #-}
565 return $ Skip (Just (state, x))
567 step' gst (Just (st, acc)) = do
568 r <- step (adaptState gst) st
572 return $ Yield y (Just (s, y))
573 Skip s -> return $ Skip (Just (s, acc))
576{-# INLINE_NORMAL postscanl' #-}
577postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
578postscanl' f seed = postscanlM' (\a b -> return (f a b)) (return seed)
580-- We can possibly have the "done" function as a Maybe to provide an option to
581-- emit or not emit the accumulator when the stream stops.
583-- TBD: use a single Yield point
585{-# INLINE_NORMAL postscanlMAfter' #-}
586postscanlMAfter' :: Monad m
587 => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
588postscanlMAfter' fstep initial done (Stream step1 state1) = do
589 Stream step (Just (state1, initial))
593 {-# INLINE_LATE step #-}
594 step gst (Just (st, acc)) = do
595 r <- step1 (adaptState gst) st
600 y `seq` return (Yield y (Just (s, return y)))
601 Skip s -> return $ Skip $ Just (s, acc)
602 Stop -> acc >>= done >>= \res -> return (Yield res Nothing)
603 step _ Nothing = return Stop
605{-# INLINE_NORMAL postscanlM #-}
606postscanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
607postscanlM fstep begin (Stream step state) = Stream step' Nothing
609 {-# INLINE_LATE step' #-}
612 return $ Skip (Just (state, r))
614 step' gst (Just (st, acc)) = do
615 r <- step (adaptState gst) st
619 return (Yield y (Just (s, y)))
620 Skip s -> return $ Skip (Just (s, acc))
623{-# INLINE_NORMAL postscanl #-}
624postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
625postscanl f seed = postscanlM (\a b -> return (f a b)) (return seed)
627{-# INLINE_NORMAL scanlM' #-}
628scanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
629scanlM' fstep begin (Stream step state) = Stream step' Nothing
631 {-# INLINE_LATE step' #-}
634 return $ Yield x (Just (state, x))
635 step' gst (Just (st, acc)) = do
636 r <- step (adaptState gst) st
640 return $ Yield y (Just (s, y))
641 Skip s -> return $ Skip (Just (s, acc))
644{-# INLINE scanlMAfter' #-}
645scanlMAfter' :: Monad m
646 => (b -> a -> m b) -> m b -> (b -> m b) -> Stream m a -> Stream m b
647scanlMAfter' fstep initial done s =
648 (initial >>= \x -> x `seq` return x) `consM`
649 postscanlMAfter' fstep initial done s
652scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
653scanl' f seed = scanlM' (\a b -> return (f a b)) (return seed)
655{-# INLINE_NORMAL scanlM #-}
656scanlM :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
657scanlM fstep begin (Stream step state) = Stream step' Nothing
659 {-# INLINE_LATE step' #-}
662 return $ Yield x (Just (state, x))
663 step' gst (Just (st, acc)) = do
664 r <- step (adaptState gst) st
668 return $ Yield y (Just (s, y))
669 Skip s -> return $ Skip (Just (s, acc))
670 Stop -> return $ Stop
673scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
674scanl f seed = scanlM (\a b -> return (f a b)) (return seed)
676-- Adapted from the vector package
677{-# INLINE_NORMAL scanl1M #-}
678scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
679scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
681 {-# INLINE_LATE step' #-}
682 step' gst (st, Nothing) = do
685 Yield x s -> return $ Yield x (s, Just x)
686 Skip s -> return $ Skip (s, Nothing)
689 step' gst (st, Just acc) = do
694 return $ Yield z (s, Just z)
695 Skip s -> return $ Skip (s, Just acc)
699scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
700scanl1 f = scanl1M (\x y -> return (f x y))
702-- Adapted from the vector package
703{-# INLINE_NORMAL scanl1M' #-}
704scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
705scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
707 {-# INLINE_LATE step' #-}
708 step' gst (st, Nothing) = do
711 Yield x s -> x `seq` return $ Yield x (s, Just x)
712 Skip s -> return $ Skip (s, Nothing)
715 step' gst (st, Just acc) = acc `seq` do
720 z `seq` return $ Yield z (s, Just z)
721 Skip s -> return $ Skip (s, Just acc)
724{-# INLINE scanl1' #-}
725scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
726scanl1' f = scanl1M' (\x y -> return (f x y))
728-------------------------------------------------------------------------------
730-------------------------------------------------------------------------------
732-- Adapted from the vector package
733{-# INLINE_NORMAL filterM #-}
734filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
735filterM f (Stream step state) = Stream step' state
737 {-# INLINE_LATE step' #-}
746 Skip s -> return $ Skip s
750filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
751filter f = filterM (return . f)
753-- Adapted from the vector package
754{-# INLINE_NORMAL uniq #-}
755uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
756uniq (Stream step state) = Stream step' (Nothing, state)
758 {-# INLINE_LATE step' #-}
759 step' gst (Nothing, st) = do
762 Yield x s -> return $ Yield x (Just x, s)
763 Skip s -> return $ Skip (Nothing, s)
765 step' gst (Just x, st) = do
768 Yield y s | x == y -> return $ Skip (Just x, s)
769 | otherwise -> return $ Yield y (Just y, s)
770 Skip s -> return $ Skip (Just x, s)
773{-# INLINE_NORMAL deleteBy #-}
774deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
775deleteBy eq x (Stream step state) = Stream step' (state, False)
777 {-# INLINE_LATE step' #-}
778 step' gst (st, False) = do
781 Yield y s -> return $
782 if eq x y then Skip (s, True) else Yield y (s, False)
783 Skip s -> return $ Skip (s, False)
786 step' gst (st, True) = do
789 Yield y s -> return $ Yield y (s, True)
790 Skip s -> return $ Skip (s, True)
793------------------------------------------------------------------------------
795------------------------------------------------------------------------------
797-- XXX using getTime in the loop can be pretty expensive especially for
798-- computations where iterations are lightweight. We have the following
801-- 1) Run a timeout thread updating a flag asynchronously and check that
802-- flag here, that way we can have a cheap termination check.
804-- 2) Use COARSE clock to get time with lower resolution but more efficiently.
806-- 3) Use rdtscp/rdtsc to get time directly from the processor, compute the
807-- termination value of rdtsc in the beginning and then in each iteration just
808-- get rdtsc and check if we should terminate.
812 | TakeByTimeCheck st s
813 | TakeByTimeYield st s
815{-# INLINE_NORMAL takeByTime #-}
816takeByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
817takeByTime duration (Stream step1 state1) = Stream step (TakeByTimeInit state1)
820 lim = toRelTime64 duration
822 {-# INLINE_LATE step #-}
823 step _ (TakeByTimeInit _) | lim == 0 = return Stop
824 step _ (TakeByTimeInit st) = do
825 t0 <- liftIO $ getTime Monotonic
826 return $ Skip (TakeByTimeYield st t0)
827 step _ (TakeByTimeCheck st t0) = do
828 t <- liftIO $ getTime Monotonic
830 if diffAbsTime64 t t0 > lim
832 else Skip (TakeByTimeYield st t0)
833 step gst (TakeByTimeYield st t0) = do
836 Yield x s -> Yield x (TakeByTimeCheck s t0)
837 Skip s -> Skip (TakeByTimeCheck s t0)
840data DropByTime st s x
843 | DropByTimeCheck st s x
846{-# INLINE_NORMAL dropByTime #-}
847dropByTime :: (MonadIO m, TimeUnit64 t) => t -> Stream m a -> Stream m a
848dropByTime duration (Stream step1 state1) = Stream step (DropByTimeInit state1)
851 lim = toRelTime64 duration
853 {-# INLINE_LATE step #-}
854 step _ (DropByTimeInit st) = do
855 t0 <- liftIO $ getTime Monotonic
856 return $ Skip (DropByTimeGen st t0)
857 step gst (DropByTimeGen st t0) = do
860 Yield x s -> Skip (DropByTimeCheck s t0 x)
861 Skip s -> Skip (DropByTimeGen s t0)
863 step _ (DropByTimeCheck st t0 x) = do
864 t <- liftIO $ getTime Monotonic
865 if diffAbsTime64 t t0 <= lim
866 then return $ Skip $ DropByTimeGen st t0
867 else return $ Yield x $ DropByTimeYield st
868 step gst (DropByTimeYield st) = do
871 Yield x s -> Yield x (DropByTimeYield s)
872 Skip s -> Skip (DropByTimeYield s)
875-- Adapted from the vector package
876{-# INLINE_NORMAL drop #-}
877drop :: Monad m => Int -> Stream m a -> Stream m a
878drop n (Stream step state) = Stream step' (state, Just n)
880 {-# INLINE_LATE step' #-}
881 step' gst (st, Just i)
886 Yield _ s -> Skip (s, Just (i - 1))
887 Skip s -> Skip (s, Just i)
889 | otherwise = return $ Skip (st, Nothing)
891 step' gst (st, Nothing) = do
895 Yield x s -> Yield x (s, Nothing)
896 Skip s -> Skip (s, Nothing)
899-- Adapted from the vector package
900data DropWhileState s a
905{-# INLINE_NORMAL dropWhileM #-}
906dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
907dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
909 {-# INLINE_LATE step' #-}
910 step' gst (DropWhileDrop st) = do
916 then return $ Skip (DropWhileDrop s)
917 else return $ Skip (DropWhileYield x s)
918 Skip s -> return $ Skip (DropWhileDrop s)
921 step' gst (DropWhileNext st) = do
924 Yield x s -> return $ Skip (DropWhileYield x s)
925 Skip s -> return $ Skip (DropWhileNext s)
928 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
930{-# INLINE dropWhile #-}
931dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
932dropWhile f = dropWhileM (return . f)
934------------------------------------------------------------------------------
936------------------------------------------------------------------------------
938{-# INLINE_NORMAL insertBy #-}
939insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
940insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
942 {-# INLINE_LATE step' #-}
943 step' gst (st, False, _) = do
946 Yield x s -> case cmp a x of
947 GT -> return $ Yield x (s, False, Nothing)
948 _ -> return $ Yield a (s, True, Just x)
949 Skip s -> return $ Skip (s, False, Nothing)
950 Stop -> return $ Yield a (st, True, Nothing)
952 step' _ (_, True, Nothing) = return Stop
954 step' gst (st, True, Just prev) = do
957 Yield x s -> return $ Yield prev (s, True, Just x)
958 Skip s -> return $ Skip (s, True, Just prev)
959 Stop -> return $ Yield prev (st, True, Nothing)
961data LoopState x s = FirstYield s
962 | InterspersingYield s
965{-# INLINE_NORMAL intersperseM #-}
966intersperseM :: Monad m => m a -> Stream m a -> Stream m a
967intersperseM m (Stream step state) = Stream step' (FirstYield state)
969 {-# INLINE_LATE step' #-}
970 step' gst (FirstYield st) = do
974 Yield x s -> Skip (YieldAndCarry x s)
975 Skip s -> Skip (FirstYield s)
978 step' gst (InterspersingYield st) = do
983 return $ Yield a (YieldAndCarry x s)
984 Skip s -> return $ Skip $ InterspersingYield s
987 step' _ (YieldAndCarry x st) = return $ Yield x (InterspersingYield st)
989{-# INLINE intersperse #-}
990intersperse :: Monad m => a -> Stream m a -> Stream m a
991intersperse a = intersperseM (return a)
993{-# INLINE_NORMAL intersperseM_ #-}
994intersperseM_ :: Monad m => m b -> Stream m a -> Stream m a
995intersperseM_ m (Stream step1 state1) = Stream step (Left (pure (), state1))
997 {-# INLINE_LATE step #-}
998 step gst (Left (eff, st)) = do
1001 Yield x s -> eff >> return (Yield x (Right s))
1002 Skip s -> return $ Skip (Left (eff, s))
1005 step _ (Right st) = return $ Skip $ Left (void m, st)
1010 | SuffixYield a (SuffixState s a)
1012{-# INLINE_NORMAL intersperseSuffix #-}
1013intersperseSuffix :: forall m a. Monad m => m a -> Stream m a -> Stream m a
1014intersperseSuffix action (Stream step state) = Stream step' (SuffixElem state)
1016 {-# INLINE_LATE step' #-}
1017 step' gst (SuffixElem st) = do
1020 Yield x s -> Skip (SuffixYield x (SuffixSuffix s))
1021 Skip s -> Skip (SuffixElem s)
1024 step' _ (SuffixSuffix st) = do
1025 action >>= \r -> return $ Skip (SuffixYield r (SuffixElem st))
1027 step' _ (SuffixYield x next) = return $ Yield x next
1029{-# INLINE_NORMAL intersperseSuffix_ #-}
1030intersperseSuffix_ :: Monad m => m b -> Stream m a -> Stream m a
1031intersperseSuffix_ m (Stream step1 state1) = Stream step (Left state1)
1033 {-# INLINE_LATE step #-}
1034 step gst (Left st) = do
1037 Yield x s -> return $ Yield x (Right s)
1038 Skip s -> return $ Skip $ Left s
1041 step _ (Right st) = m >> return (Skip (Left st))
1043data SuffixSpanState s a
1044 = SuffixSpanElem s Int
1045 | SuffixSpanSuffix s
1046 | SuffixSpanYield a (SuffixSpanState s a)
1050-- | intersperse after every n items
1051{-# INLINE_NORMAL intersperseSuffixBySpan #-}
1052intersperseSuffixBySpan :: forall m a. Monad m
1053 => Int -> m a -> Stream m a -> Stream m a
1054intersperseSuffixBySpan n action (Stream step state) =
1055 Stream step' (SuffixSpanElem state n)
1057 {-# INLINE_LATE step' #-}
1058 step' gst (SuffixSpanElem st i) | i > 0 = do
1061 Yield x s -> Skip (SuffixSpanYield x (SuffixSpanElem s (i - 1)))
1062 Skip s -> Skip (SuffixSpanElem s i)
1063 Stop -> if i == n then Stop else Skip SuffixSpanLast
1064 step' _ (SuffixSpanElem st _) = return $ Skip (SuffixSpanSuffix st)
1066 step' _ (SuffixSpanSuffix st) = do
1067 action >>= \r -> return $ Skip (SuffixSpanYield r (SuffixSpanElem st n))
1069 step' _ (SuffixSpanLast) = do
1070 action >>= \r -> return $ Skip (SuffixSpanYield r SuffixSpanStop)
1072 step' _ (SuffixSpanYield x next) = return $ Yield x next
1074 step' _ (SuffixSpanStop) = return Stop
1076------------------------------------------------------------------------------
1078------------------------------------------------------------------------------
1080-- We can implement reverse as:
1082-- > reverse = foldlS (flip cons) nil
1084-- However, this implementation is unusable because of the horrible performance
1085-- of cons. So we just convert it to a list first and then stream from the
1088-- XXX Maybe we can use an Array instead of a list here?
1089{-# INLINE_NORMAL reverse #-}
1090reverse :: Monad m => Stream m a -> Stream m a
1091reverse m = Stream step Nothing
1093 {-# INLINE_LATE step #-}
1095 xs <- foldl' (flip (:)) [] m
1096 return $ Skip (Just xs)
1097 step _ (Just (x:xs)) = return $ Yield x (Just xs)
1098 step _ (Just []) = return Stop
1100-- Much faster reverse for Storables
1101{-# INLINE_NORMAL reverse' #-}
1102reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
1104-- This commented implementation copies the whole stream into one single array
1105-- and then streams from that array, this has exactly the same performance as
1106-- the chunked code that follows. Though this could be problematic due to
1107-- unbounded large allocations. However, if we use an idiomatic implementation
1108-- of arraysOf instead of the custom implementation then the chunked code
1109-- becomes worse by 6 times. Need to investigate if that can be improved.
1110import Foreign.ForeignPtr (touchForeignPtr)
1111import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
1112import Foreign.Ptr (Ptr, plusPtr)
1113reverse' m = Stream step Nothing
1115 {-# INLINE_LATE step #-}
1117 arr <- A.fromStreamD m
1118 let p = A.aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
1119 return $ Skip $ Just (A.aStart arr, p)
1121 step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
1123 step _ (Just (start, p)) = do
1124 let !x = A.unsafeInlineIO $ do
1126 touchForeignPtr start
1128 next = p `plusPtr` negate (sizeOf (undefined :: a))
1129 return $ Yield x (Just (start, next))
1132 A.flattenArraysRev -- unfoldMany A.readRev
1136 . A.arraysOf A.defaultChunkSize
1138------------------------------------------------------------------------------
1140------------------------------------------------------------------------------
1142-- Adapted from the vector package
1143{-# INLINE_NORMAL indexed #-}
1144indexed :: Monad m => Stream m a -> Stream m (Int, a)
1145indexed (Stream step state) = Stream step' (state, 0)
1147 {-# INLINE_LATE step' #-}
1148 step' gst (st, i) = i `seq` do
1149 r <- step (adaptState gst) st
1151 Yield x s -> return $ Yield (i, x) (s, i+1)
1152 Skip s -> return $ Skip (s, i)
1155-- Adapted from the vector package
1156{-# INLINE_NORMAL indexedR #-}
1157indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
1158indexedR m (Stream step state) = Stream step' (state, m)
1160 {-# INLINE_LATE step' #-}
1161 step' gst (st, i) = i `seq` do
1162 r <- step (adaptState gst) st
1164 Yield x s -> let i' = i - 1
1165 in return $ Yield (i, x) (s, i')
1166 Skip s -> return $ Skip (s, i)
1169------------------------------------------------------------------------------
1171------------------------------------------------------------------------------
1173{-# INLINE_NORMAL findIndices #-}
1174findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
1175findIndices p (Stream step state) = Stream step' (state, 0)
1177 {-# INLINE_LATE step' #-}
1178 step' gst (st, i) = i `seq` do
1179 r <- step (adaptState gst) st
1181 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
1182 Skip s -> Skip (s, i)
1185------------------------------------------------------------------------------
1187------------------------------------------------------------------------------
1189data RollingMapState s a = RollingMapInit s | RollingMapGo s a
1191{-# INLINE rollingMapM #-}
1192rollingMapM :: Monad m => (a -> a -> m b) -> Stream m a -> Stream m b
1193rollingMapM f (Stream step1 state1) = Stream step (RollingMapInit state1)
1195 step gst (RollingMapInit st) = do
1196 r <- step1 (adaptState gst) st
1198 Yield x s -> Skip $ RollingMapGo s x
1199 Skip s -> Skip $ RollingMapInit s
1202 step gst (RollingMapGo s1 x1) = do
1203 r <- step1 (adaptState gst) s1
1207 return $ Yield res $ RollingMapGo s x
1208 Skip s -> return $ Skip $ RollingMapGo s x1
1209 Stop -> return $ Stop
1211{-# INLINE rollingMap #-}
1212rollingMap :: Monad m => (a -> a -> b) -> Stream m a -> Stream m b
1213rollingMap f = rollingMapM (\x y -> return $ f x y)
1215------------------------------------------------------------------------------
1217------------------------------------------------------------------------------
1219-- XXX Will this always fuse properly?
1220{-# INLINE_NORMAL mapMaybe #-}
1221mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
1222mapMaybe f = fmap fromJust . filter isJust . map f
1224{-# INLINE_NORMAL mapMaybeM #-}
1225mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
1226mapMaybeM 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