1{-# LANGUAGE BangPatterns #-}
3{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE ExistentialQuantification #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE PatternSynonyms #-}
9{-# LANGUAGE RecordWildCards #-}
10{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE ViewPatterns #-}
12{-# LANGUAGE RankNTypes #-}
17-- Module : Streamly.Streams.StreamD
18-- Copyright : (c) 2018 Harendra Kumar
19-- Copyright : (c) Roman Leshchinskiy 2008-2010
22-- Maintainer : harendra.kumar@gmail.com
23-- Stability : experimental
26-- Direct style re-implementation of CPS style stream in StreamK module. The
27-- symbol or suffix 'D' in this module denotes the "Direct" style. GHC is able
28-- to INLINE and fuse direct style better, providing better performance than
32-- import qualified Streamly.Streams.StreamD as D
35-- Some of the functions in this file have been adapted from the vector
36-- library, https://hackage.haskell.org/package/vector.
38module Streamly.Streams.StreamD
56 -- ** Specialized Generation
57 -- | Generate a monadic stream from a seed.
67 , enumerateFromStepIntegral
68 , enumerateFromIntegral
69 , enumerateFromThenIntegral
70 , enumerateFromToIntegral
71 , enumerateFromThenToIntegral
73 , enumerateFromStepNum
76 , enumerateFromToFractional
77 , enumerateFromThenToFractional
80 -- | Transform an input structure into a stream.
81 -- | Direct style stream does not support @fromFoldable@.
108 -- ** Specialized Folds
129 -- ** Flattening nested streams
156 -- | Transform a stream into another type.
163 -- ** By folding (scans)
226 -- * Transformation comprehensions
239import Control.Exception (Exception)
240import Control.Monad.Catch (MonadCatch)
241import Control.Monad.IO.Class (MonadIO(..))
242import Control.Monad.Trans (MonadTrans(lift))
243import Data.Word (Word32)
244import Data.Bits (shiftR, shiftL, (.|.), (.&.))
245import Data.Maybe (fromJust, isJust)
246import Foreign.Ptr (Ptr)
247import Foreign.Storable (Storable(..))
248import GHC.Types (SPEC(..))
250 hiding (map, mapM, mapM_, repeat, foldr, last, take, filter,
251 takeWhile, drop, dropWhile, all, any, maximum, minimum, elem,
252 notElem, null, head, tail, zipWith, lookup, foldr1, sequence,
253 (!!), scanl, scanl1, concatMap, replicate, enumFromTo, concat,
256import qualified Control.Monad.Catch as MC
258import Streamly.Mem.Array.Types (Array(..))
259import Streamly.Fold.Types (Fold(..))
260import Streamly.SVar (MonadAsync, defState, adaptState)
261import Streamly.Sink.Types (Sink(..))
263import Streamly.Streams.StreamD.Type
265import qualified Streamly.Mem.Array.Types as A
266import qualified Streamly.Mem.Ring as RB
267import qualified Streamly.Streams.StreamK as K
269------------------------------------------------------------------------------
271------------------------------------------------------------------------------
273-- | An empty 'Stream'.
274{-# INLINE_NORMAL nil #-}
275nil :: Monad m => Stream m a
276nil = Stream (\_ _ -> return Stop) ()
278{-# INLINE_NORMAL consM #-}
279consM :: Monad m => m a -> Stream m a -> Stream m a
280consM m (Stream step state) = Stream step1 Nothing
282 {-# INLINE_LATE step1 #-}
283 step1 _ Nothing = m >>= \x -> return $ Yield x (Just state)
284 step1 gst (Just st) = do
288 Yield a s -> Yield a (Just s)
289 Skip s -> Skip (Just s)
292-- XXX implement in terms of consM?
293-- cons x = consM (return x)
295-- | Can fuse but has O(n^2) complexity.
296{-# INLINE_NORMAL cons #-}
297cons :: Monad m => a -> Stream m a -> Stream m a
298cons x (Stream step state) = Stream step1 Nothing
300 {-# INLINE_LATE step1 #-}
301 step1 _ Nothing = return $ Yield x (Just state)
302 step1 gst (Just st) = do
306 Yield a s -> Yield a (Just s)
307 Skip s -> Skip (Just s)
310-------------------------------------------------------------------------------
312-------------------------------------------------------------------------------
314-- Does not fuse, has the same performance as the StreamK version.
315{-# INLINE_NORMAL uncons #-}
316uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
317uncons (UnStream step state) = go state
320 r <- step defState st
322 Yield x s -> return $ Just (x, Stream step s)
324 Stop -> return Nothing
326------------------------------------------------------------------------------
327-- Generation by unfold
328------------------------------------------------------------------------------
330{-# INLINE_NORMAL unfoldrM #-}
331unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
332unfoldrM next state = Stream step state
334 {-# INLINE_LATE step #-}
338 Just (x, s) -> Yield x s
341{-# INLINE_LATE unfoldr #-}
342unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
343unfoldr f = unfoldrM (return . f)
345------------------------------------------------------------------------------
346-- Specialized Generation
347------------------------------------------------------------------------------
349repeat :: Monad m => a -> Stream m a
350repeat x = Stream (\_ _ -> return $ Yield x ()) ()
352{-# INLINE_NORMAL replicateM #-}
353replicateM :: Monad m => Int -> m a -> Stream m a
354replicateM n p = Stream step n
356 {-# INLINE_LATE step #-}
357 step _ i | i <= 0 = return Stop
360 return $ Yield x (i - 1)
362{-# INLINE_NORMAL replicate #-}
363replicate :: Monad m => Int -> a -> Stream m a
364replicate n x = replicateM n (return x)
366-- This would not work properly for floats, therefore we put an Integral
368-- | Can be used to enumerate unbounded integrals. This does not check for
369-- overflow or underflow for bounded integrals.
370{-# INLINE_NORMAL enumerateFromStepIntegral #-}
371enumerateFromStepIntegral :: (Integral a, Monad m) => a -> a -> Stream m a
372enumerateFromStepIntegral from stride =
373 from `seq` stride `seq` Stream step from
375 {-# INLINE_LATE step #-}
376 step _ !x = return $ Yield x $! (x + stride)
378-- We are assuming that "to" is constrained by the type to be within
380{-# INLINE enumerateFromToIntegral #-}
381enumerateFromToIntegral :: (Monad m, Integral a) => a -> a -> Stream m a
382enumerateFromToIntegral from to =
383 takeWhile (<= to) $ enumerateFromStepIntegral from 1
385{-# INLINE enumerateFromIntegral #-}
386enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => a -> Stream m a
387enumerateFromIntegral from = enumerateFromToIntegral from maxBound
389data EnumState a = EnumInit | EnumYield a a a | EnumStop
391{-# INLINE_NORMAL enumerateFromThenToIntegralUp #-}
392enumerateFromThenToIntegralUp
393 :: (Monad m, Integral a)
394 => a -> a -> a -> Stream m a
395enumerateFromThenToIntegralUp from next to = Stream step EnumInit
397 {-# INLINE_LATE step #-}
403 else Yield from EnumStop
404 else -- from <= next <= to
405 let stride = next - from
406 in Skip $ EnumYield from stride (to - stride)
408 step _ (EnumYield x stride toMinus) =
411 then Yield x EnumStop
412 else Yield x $ EnumYield (x + stride) stride toMinus
414 step _ EnumStop = return Stop
416{-# INLINE_NORMAL enumerateFromThenToIntegralDn #-}
417enumerateFromThenToIntegralDn
418 :: (Monad m, Integral a)
419 => a -> a -> a -> Stream m a
420enumerateFromThenToIntegralDn from next to = Stream step EnumInit
422 {-# INLINE_LATE step #-}
424 return $ if to > next
427 else Yield from EnumStop
428 else -- from >= next >= to
429 let stride = next - from
430 in Skip $ EnumYield from stride (to - stride)
432 step _ (EnumYield x stride toMinus) =
435 then Yield x EnumStop
436 else Yield x $ EnumYield (x + stride) stride toMinus
438 step _ EnumStop = return Stop
440{-# INLINE_NORMAL enumerateFromThenToIntegral #-}
441enumerateFromThenToIntegral
442 :: (Monad m, Integral a)
443 => a -> a -> a -> Stream m a
444enumerateFromThenToIntegral from next to
445 | next >= from = enumerateFromThenToIntegralUp from next to
446 | otherwise = enumerateFromThenToIntegralDn from next to
448{-# INLINE_NORMAL enumerateFromThenIntegral #-}
449enumerateFromThenIntegral
450 :: (Monad m, Integral a, Bounded a)
451 => a -> a -> Stream m a
452enumerateFromThenIntegral from next =
454 then enumerateFromThenToIntegralUp from next maxBound
455 else enumerateFromThenToIntegralDn from next minBound
457-- For floating point numbers if the increment is less than the precision then
458-- it just gets lost. Therefore we cannot always increment it correctly by just
460-- 9007199254740992 + 1 + 1 :: Double => 9.007199254740992e15
461-- 9007199254740992 + 2 :: Double => 9.007199254740994e15
463-- Instead we accumulate the increment counter and compute the increment
464-- everytime before adding it to the starting number.
466-- This works for Integrals as well as floating point numbers, but
467-- enumerateFromStepIntegral is faster for integrals.
468{-# INLINE_NORMAL enumerateFromStepNum #-}
469enumerateFromStepNum :: (Monad m, Num a) => a -> a -> Stream m a
470enumerateFromStepNum from stride = Stream step 0
472 {-# INLINE_LATE step #-}
473 step _ !i = return $ (Yield $! (from + i * stride)) $! (i + 1)
475{-# INLINE_NORMAL numFrom #-}
476numFrom :: (Monad m, Num a) => a -> Stream m a
477numFrom from = enumerateFromStepNum from 1
479{-# INLINE_NORMAL numFromThen #-}
480numFromThen :: (Monad m, Num a) => a -> a -> Stream m a
481numFromThen from next = enumerateFromStepNum from (next - from)
483-- We cannot write a general function for Num. The only way to write code
484-- portable between the two is to use a 'Real' constraint and convert between
485-- Fractional and Integral using fromRational which is horribly slow.
486{-# INLINE_NORMAL enumerateFromToFractional #-}
487enumerateFromToFractional
488 :: (Monad m, Fractional a, Ord a)
489 => a -> a -> Stream m a
490enumerateFromToFractional from to =
491 takeWhile (<= to + 1 / 2) $ enumerateFromStepNum from 1
493{-# INLINE_NORMAL enumerateFromThenToFractional #-}
494enumerateFromThenToFractional
495 :: (Monad m, Fractional a, Ord a)
496 => a -> a -> a -> Stream m a
497enumerateFromThenToFractional from next to =
498 takeWhile predicate $ numFromThen from next
500 mid = (next - from) / 2
501 predicate | next >= from = (<= to + mid)
502 | otherwise = (>= to + mid)
504-------------------------------------------------------------------------------
505-- Generation by Conversion
506-------------------------------------------------------------------------------
508{-# INLINE_NORMAL fromIndicesM #-}
509fromIndicesM :: Monad m => (Int -> m a) -> Stream m a
510fromIndicesM gen = Stream step 0
512 {-# INLINE_LATE step #-}
515 return $ Yield x (i + 1)
517{-# INLINE fromIndices #-}
518fromIndices :: Monad m => (Int -> a) -> Stream m a
519fromIndices gen = fromIndicesM (return . gen)
521{-# INLINE_NORMAL generateM #-}
522generateM :: Monad m => Int -> (Int -> m a) -> Stream m a
523generateM n gen = n `seq` Stream step 0
525 {-# INLINE_LATE step #-}
526 step _ i | i < n = do
528 return $ Yield x (i + 1)
529 | otherwise = return Stop
531{-# INLINE generate #-}
532generate :: Monad m => Int -> (Int -> a) -> Stream m a
533generate n gen = generateM n (return . gen)
535-- XXX we need the MonadAsync constraint because of a rewrite rule.
536-- | Convert a list of monadic actions to a 'Stream'
537{-# INLINE_LATE fromListM #-}
538fromListM :: MonadAsync m => [m a] -> Stream m a
539fromListM = Stream step
541 {-# INLINE_LATE step #-}
542 step _ (m:ms) = m >>= \x -> return $ Yield x ms
543 step _ [] = return Stop
545{-# INLINE toStreamD #-}
546toStreamD :: (K.IsStream t, Monad m) => t m a -> Stream m a
547toStreamD = fromStreamK . K.toStream
549------------------------------------------------------------------------------
550-- Elimination by Folds
551------------------------------------------------------------------------------
553------------------------------------------------------------------------------
555------------------------------------------------------------------------------
557{-# INLINE_NORMAL foldr1 #-}
558foldr1 :: Monad m => (a -> a -> a) -> Stream m a -> m (Maybe a)
562 Nothing -> return Nothing
563 Just (h, t) -> fmap Just (foldr f h t)
565------------------------------------------------------------------------------
567------------------------------------------------------------------------------
569{-# INLINE_NORMAL foldlT #-}
570foldlT :: (Monad m, Monad (s m), MonadTrans s)
571 => (s m b -> a -> s m b) -> s m b -> Stream m a -> s m b
572foldlT fstep begin (Stream step state) = go SPEC begin state
575 r <- lift $ step defState st
577 Yield x s -> go SPEC (fstep acc x) s
578 Skip s -> go SPEC acc s
581-- Note, this is going to have horrible performance, because of the nature of
582-- the stream type (i.e. direct stream vs CPS). Its only for reference, it is
583-- likely be practically unusable.
584{-# INLINE_NORMAL foldlS #-}
586 => (Stream m b -> a -> Stream m b) -> Stream m b -> Stream m a -> Stream m b
587foldlS fstep begin (Stream step state) = Stream step' (Left (state, begin))
589 step' gst (Left (st, acc)) = do
590 r <- step (adaptState gst) st
592 Yield x s -> Skip (Left (s, fstep acc x))
593 Skip s -> Skip (Left (s, acc))
594 Stop -> Skip (Right acc)
596 step' gst (Right (Stream stp stt)) = do
597 r <- stp (adaptState gst) stt
599 Yield x s -> Yield x (Right (Stream stp s))
600 Skip s -> Skip (Right (Stream stp s))
603------------------------------------------------------------------------------
605------------------------------------------------------------------------------
607-- | Run a streaming composition, discard the results.
608{-# INLINE_LATE drain #-}
609drain :: Monad m => Stream m a -> m ()
610-- drain m = foldrM (\x xs -> x `seq` xs) (return ()) m
611drain (Stream step state) = go SPEC state
614 r <- step defState st
616 Yield _ s -> go SPEC s
620{-# INLINE_NORMAL null #-}
621null :: Monad m => Stream m a -> m Bool
622null m = foldrM (\_ _ -> return False) (return True) m
625{-# INLINE_NORMAL head #-}
626head :: Monad m => Stream m a -> m (Maybe a)
627head m = foldrM (\x _ -> return (Just x)) (return Nothing) m
629-- Does not fuse, has the same performance as the StreamK version.
630{-# INLINE_NORMAL tail #-}
631tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
632tail (UnStream step state) = go state
635 r <- step defState st
637 Yield _ s -> return (Just $ Stream step s)
639 Stop -> return Nothing
641-- XXX will it fuse? need custom impl?
642{-# INLINE_NORMAL last #-}
643last :: Monad m => Stream m a -> m (Maybe a)
644last = foldl' (\_ y -> Just y) Nothing
646{-# INLINE_NORMAL elem #-}
647elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
648-- elem e m = foldrM (\x xs -> if x == e then return True else xs) (return False) m
649elem e (Stream step state) = go state
652 r <- step defState st
655 | x == e -> return True
660{-# INLINE_NORMAL notElem #-}
661notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
662notElem e s = fmap not (elem e s)
664{-# INLINE_NORMAL all #-}
665all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
666-- all p m = foldrM (\x xs -> if p x then xs else return False) (return True) m
667all p (Stream step state) = go state
670 r <- step defState st
674 | otherwise -> return False
678{-# INLINE_NORMAL any #-}
679any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
680-- any p m = foldrM (\x xs -> if p x then return True else xs) (return False) m
681any p (Stream step state) = go state
684 r <- step defState st
692{-# INLINE_NORMAL maximum #-}
693maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
694maximum (Stream step state) = go Nothing state
697 r <- step defState st
699 Yield x s -> go (Just x) s
700 Skip s -> go Nothing s
701 Stop -> return Nothing
702 go (Just acc) st = do
703 r <- step defState st
706 | acc <= x -> go (Just x) s
707 | otherwise -> go (Just acc) s
708 Skip s -> go (Just acc) s
709 Stop -> return (Just acc)
711{-# INLINE_NORMAL maximumBy #-}
712maximumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
713maximumBy cmp (Stream step state) = go Nothing state
716 r <- step defState st
718 Yield x s -> go (Just x) s
719 Skip s -> go Nothing s
720 Stop -> return Nothing
721 go (Just acc) st = do
722 r <- step defState st
724 Yield x s -> case cmp acc x of
725 GT -> go (Just acc) s
727 Skip s -> go (Just acc) s
728 Stop -> return (Just acc)
730{-# INLINE_NORMAL minimum #-}
731minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
732minimum (Stream step state) = go Nothing state
735 r <- step defState st
737 Yield x s -> go (Just x) s
738 Skip s -> go Nothing s
739 Stop -> return Nothing
740 go (Just acc) st = do
741 r <- step defState st
744 | acc <= x -> go (Just acc) s
745 | otherwise -> go (Just x) s
746 Skip s -> go (Just acc) s
747 Stop -> return (Just acc)
749{-# INLINE_NORMAL minimumBy #-}
750minimumBy :: Monad m => (a -> a -> Ordering) -> Stream m a -> m (Maybe a)
751minimumBy cmp (Stream step state) = go Nothing state
754 r <- step defState st
756 Yield x s -> go (Just x) s
757 Skip s -> go Nothing s
758 Stop -> return Nothing
759 go (Just acc) st = do
760 r <- step defState st
762 Yield x s -> case cmp acc x of
765 Skip s -> go (Just acc) s
766 Stop -> return (Just acc)
768{-# INLINE_NORMAL (!!) #-}
769(!!) :: (Monad m) => Stream m a -> Int -> m (Maybe a)
770(Stream step state) !! i = go i state
773 r <- step defState st
775 Yield x s | n < 0 -> return Nothing
776 | n == 0 -> return $ Just x
777 | otherwise -> go (n - 1) s
779 Stop -> return Nothing
781{-# INLINE_NORMAL lookup #-}
782lookup :: (Monad m, Eq a) => a -> Stream m (a, b) -> m (Maybe b)
783lookup e m = foldrM (\(a, b) xs -> if e == a then return (Just b) else xs)
786{-# INLINE_NORMAL findM #-}
787findM :: Monad m => (a -> m Bool) -> Stream m a -> m (Maybe a)
788findM p m = foldrM (\x xs -> p x >>= \r -> if r then return (Just x) else xs)
792find :: Monad m => (a -> Bool) -> Stream m a -> m (Maybe a)
793find p = findM (return . p)
795{-# INLINE_NORMAL findIndices #-}
796findIndices :: Monad m => (a -> Bool) -> Stream m a -> Stream m Int
797findIndices p (Stream step state) = Stream step' (state, 0)
799 {-# INLINE_LATE step' #-}
800 step' gst (st, i) = do
801 r <- step (adaptState gst) st
803 Yield x s -> if p x then Yield i (s, i+1) else Skip (s, i+1)
804 Skip s -> Skip (s, i+1)
807{-# INLINE toListRev #-}
808toListRev :: Monad m => Stream m a -> m [a]
809toListRev = foldl' (flip (:)) []
811-- We can implement reverse as:
813-- > reverse = foldlS (flip cons) nil
815-- However, this implementation is unusable because of the horrible performance
816-- of cons. So we just convert it to a list first and then stream from the
819-- XXX Maybe we can use an Array instead of a list here?
820{-# INLINE_NORMAL reverse #-}
821reverse :: Monad m => Stream m a -> Stream m a
822reverse m = Stream step Nothing
824 {-# INLINE_LATE step #-}
827 return $ Skip (Just xs)
828 step _ (Just (x:xs)) = return $ Yield x (Just xs)
829 step _ (Just []) = return Stop
831-- Much faster reverse for Storables
832{-# INLINE_NORMAL reverse' #-}
833reverse' :: forall m a. (MonadIO m, Storable a) => Stream m a -> Stream m a
835-- This commented implementation copies the whole stream into one single array
836-- and then streams from that array, this is 3-4x faster than the chunked code
837-- that follows. Though this could be problematic due to unbounded large
838-- allocations. We need to figure out why the chunked code is slower and if we
839-- can optimize the chunked code to work as fast as this one. It may be a
841import Foreign.ForeignPtr (touchForeignPtr)
842import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
843import Foreign.Ptr (Ptr, plusPtr)
844reverse' m = Stream step Nothing
846 {-# INLINE_LATE step #-}
848 arr <- A.fromStreamD m
849 let p = aEnd arr `plusPtr` negate (sizeOf (undefined :: a))
850 return $ Skip $ Just (aStart arr, p)
852 step _ (Just (start, p)) | p < unsafeForeignPtrToPtr start = return Stop
854 step _ (Just (start, p)) = do
855 let !x = A.unsafeInlineIO $ do
857 touchForeignPtr start
859 next = p `plusPtr` negate (sizeOf (undefined :: a))
860 return $ Yield x (Just (start, next))
867 $ A.fromStreamDArraysOf A.defaultChunkSize m
870------------------------------------------------------------------------------
872------------------------------------------------------------------------------
874{-# INLINE_NORMAL splitSuffixBy' #-}
875splitSuffixBy' :: Monad m
876 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
877splitSuffixBy' predicate f (Stream step state) =
878 Stream (stepOuter f) (Just state)
882 {-# INLINE_LATE stepOuter #-}
883 stepOuter (Fold fstep initial done) gst (Just st) = do
884 res <- step (adaptState gst) st
890 then done acc' >>= \val -> return $ Yield val (Just s)
893 Skip s -> return $ Skip $ Just s
899 res <- step (adaptState gst) stt
904 then done acc' >>= \val -> return $ Yield val (Just s)
906 Skip s -> go SPEC s acc
907 Stop -> done acc >>= \val -> return $ Yield val Nothing
909 stepOuter _ _ Nothing = return Stop
911{-# INLINE_NORMAL groupsBy #-}
917groupsBy cmp f (Stream step state) = Stream (stepOuter f) (Just state, Nothing)
921 {-# INLINE_LATE stepOuter #-}
922 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
923 res <- step (adaptState gst) st
930 Skip s -> return $ Skip $ (Just s, Nothing)
935 go !_ prev stt !acc = do
936 res <- step (adaptState gst) stt
943 else done acc >>= \r -> return $ Yield r (Just s, Just x)
944 Skip s -> go SPEC prev s acc
945 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
947 stepOuter (Fold fstep initial done) gst (Just st, Just prev) = do
949 acc' <- fstep acc prev
954 -- XXX code duplicated from the previous equation
956 res <- step (adaptState gst) stt
963 else done acc >>= \r -> return $ Yield r (Just s, Just x)
964 Skip s -> go SPEC s acc
965 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
967 stepOuter _ _ (Nothing,_) = return Stop
969{-# INLINE_NORMAL groupsRollingBy #-}
970groupsRollingBy :: Monad m
975groupsRollingBy cmp f (Stream step state) =
976 Stream (stepOuter f) (Just state, Nothing)
979 {-# INLINE_LATE stepOuter #-}
980 stepOuter (Fold fstep initial done) gst (Just st, Nothing) = do
981 res <- step (adaptState gst) st
988 Skip s -> return $ Skip $ (Just s, Nothing)
992 go !_ prev stt !acc = do
993 res <- step (adaptState gst) stt
1001 done acc >>= \r -> return $ Yield r (Just s, Just x)
1002 Skip s -> go SPEC prev s acc
1003 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1005 stepOuter (Fold fstep initial done) gst (Just st, Just prev') = do
1007 acc' <- fstep acc prev'
1008 go SPEC prev' st acc'
1011 go !_ prevv stt !acc = do
1012 res <- step (adaptState gst) stt
1019 else done acc >>= \r -> return $ Yield r (Just s, Just x)
1020 Skip s -> go SPEC prevv s acc
1021 Stop -> done acc >>= \r -> return $ Yield r (Nothing, Nothing)
1023 stepOuter _ _ (Nothing, _) = return Stop
1025{-# INLINE_NORMAL splitBy #-}
1026splitBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1027splitBy predicate f (Stream step state) = Stream (step' f) (Just state)
1031 {-# INLINE_LATE step' #-}
1032 step' (Fold fstep initial done) gst (Just st) = initial >>= go SPEC st
1037 res <- step (adaptState gst) stt
1041 then done acc >>= \r -> return $ Yield r (Just s)
1045 Skip s -> go SPEC s acc
1046 Stop -> done acc >>= \r -> return $ Yield r Nothing
1048 step' _ _ Nothing = return Stop
1050{-# INLINE_NORMAL splitSuffixBy #-}
1051splitSuffixBy :: Monad m
1052 => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1053splitSuffixBy predicate f (Stream step state) = Stream (step' f) (Just state)
1057 {-# INLINE_LATE step' #-}
1058 step' (Fold fstep initial done) gst (Just st) = do
1059 res <- step (adaptState gst) st
1064 then done acc >>= \val -> return $ Yield val (Just s)
1069 Skip s -> return $ Skip $ Just s
1075 res <- step (adaptState gst) stt
1079 then done acc >>= \r -> return $ Yield r (Just s)
1083 Skip s -> go SPEC s acc
1084 Stop -> done acc >>= \r -> return $ Yield r Nothing
1086 step' _ _ Nothing = return Stop
1088{-# INLINE_NORMAL wordsBy #-}
1089wordsBy :: Monad m => (a -> Bool) -> Fold m a b -> Stream m a -> Stream m b
1090wordsBy predicate f (Stream step state) = Stream (stepOuter f) (Just state)
1094 {-# INLINE_LATE stepOuter #-}
1095 stepOuter (Fold fstep initial done) gst (Just st) = do
1096 res <- step (adaptState gst) st
1100 then return $ Skip (Just s)
1106 Skip s -> return $ Skip $ Just s
1112 res <- step (adaptState gst) stt
1116 then done acc >>= \r -> return $ Yield r (Just s)
1120 Skip s -> go SPEC s acc
1121 Stop -> done acc >>= \r -> return $ Yield r Nothing
1123 stepOuter _ _ Nothing = return Stop
1125-- String search algorithms:
1126-- http://www-igm.univ-mlv.fr/~lecroq/string/index.html
1129-- TODO can we unify the splitting operations using a splitting configuration
1130-- like in the split package.
1132data SplitStyle = Infix | Suffix | Prefix deriving (Eq, Show)
1134data SplitOptions = SplitOptions
1135 { style :: SplitStyle
1136 , withSep :: Bool -- ^ keep the separators in output
1137 -- , compact :: Bool -- ^ treat multiple consecutive separators as one
1138 -- , trimHead :: Bool -- ^ drop blank at head
1139 -- , trimTail :: Bool -- ^ drop blank at tail
1143data SplitOnState s a =
1148 | GO_KARP_RABIN s !(RB.Ring a) !(Ptr a)
1151{-# INLINE_NORMAL splitOn #-}
1153 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1158splitOn patArr@Array{..} (Fold fstep initial done) (Stream step state) =
1159 Stream stepOuter GO_START
1163 patLen = A.length patArr
1164 maxIndex = patLen - 1
1165 elemBits = sizeOf (undefined :: a) * 8
1167 {-# INLINE_LATE stepOuter #-}
1168 stepOuter _ GO_START =
1170 then return $ Skip $ GO_EMPTY_PAT state
1173 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1174 return $ Skip $ GO_SINGLE_PAT state r
1175 else if sizeOf (undefined :: a) * patLen
1176 <= sizeOf (undefined :: Word)
1177 then return $ Skip $ GO_SHORT_PAT state
1179 (rb, rhead) <- liftIO $ RB.new patLen
1180 return $ Skip $ GO_KARP_RABIN state rb rhead
1182 stepOuter gst (GO_SINGLE_PAT stt pat) = initial >>= go SPEC stt
1187 res <- step (adaptState gst) st
1193 return $ Yield r (GO_SINGLE_PAT s pat)
1194 else fstep acc x >>= go SPEC s
1195 Skip s -> go SPEC s acc
1196 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1198 stepOuter gst (GO_SHORT_PAT stt) = initial >>= go0 SPEC 0 (0 :: Word) stt
1203 mask = (1 `shiftL` (elemBits * patLen)) - 1
1205 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1208 patWord = mask .&. A.foldl' addToWord 0 patArr
1210 go0 !_ !idx wrd st !acc = do
1211 res <- step (adaptState gst) st
1214 let wrd' = addToWord wrd x
1217 if wrd' .&. mask == patWord
1220 return $ Yield r (GO_SHORT_PAT s)
1221 else go1 SPEC wrd' s acc
1222 else go0 SPEC (idx + 1) wrd' s acc
1223 Skip s -> go0 SPEC idx wrd s acc
1226 then go2 wrd idx acc
1228 done acc' >>= \r -> return $ Yield r GO_DONE
1231 go1 !_ wrd st !acc = do
1232 res <- step (adaptState gst) st
1235 let wrd' = addToWord wrd x
1236 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1237 acc' <- fstep acc (toEnum $ fromIntegral old)
1238 if wrd' .&. mask == patWord
1239 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1240 else go1 SPEC wrd' s acc'
1241 Skip s -> go1 SPEC wrd s acc
1243 acc' <- go2 wrd patLen acc
1244 done acc' >>= \r -> return $ Yield r GO_DONE
1246 go2 !wrd !n !acc | n > 0 = do
1247 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1248 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1249 go2 _ _ acc = return acc
1251 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1252 initial >>= go0 SPEC 0 rhead stt
1256 k = 2891336453 :: Word32
1258 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1259 deltaCksum cksum old new =
1260 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1262 -- XXX shall we use a random starting hash or 1 instead of 0?
1263 patHash = A.foldl' addCksum 0 patArr
1266 go0 !_ !idx !rh st !acc = do
1267 res <- step (adaptState gst) st
1270 rh' <- liftIO $ RB.unsafeInsert rb rh x
1273 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1274 let !ringHash = fold addCksum 0 rb
1275 if ringHash == patHash
1276 then go2 SPEC ringHash rh' s acc
1277 else go1 SPEC ringHash rh' s acc
1278 else go0 SPEC (idx + 1) rh' s acc
1279 Skip s -> go0 SPEC idx rh s acc
1281 !acc' <- if idx /= 0
1282 then RB.unsafeFoldRingM rh fstep acc rb
1284 done acc' >>= \r -> return $ Yield r GO_DONE
1286 -- XXX Theoretically this code can do 4 times faster if GHC generates
1287 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1288 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1289 -- the generated code changes drastically and becomes 4x slower. Need
1290 -- to investigate what is going on with GHC.
1292 go1 !_ !cksum !rh st !acc = do
1293 res <- step (adaptState gst) st
1296 old <- liftIO $ peek rh
1297 let cksum' = deltaCksum cksum old x
1298 acc' <- fstep acc old
1300 if (cksum' == patHash)
1302 rh' <- liftIO (RB.unsafeInsert rb rh x)
1303 go2 SPEC cksum' rh' s acc'
1305 rh' <- liftIO (RB.unsafeInsert rb rh x)
1306 go1 SPEC cksum' rh' s acc'
1307 Skip s -> go1 SPEC cksum rh s acc
1309 acc' <- RB.unsafeFoldRingFullM rh fstep acc rb
1310 done acc' >>= \r -> return $ Yield r GO_DONE
1312 go2 !_ !cksum' !rh' s !acc' = do
1313 if RB.unsafeEqArray rb rh' patArr
1316 return $ Yield r (GO_KARP_RABIN s rb rhead)
1317 else go1 SPEC cksum' rh' s acc'
1319 stepOuter gst (GO_EMPTY_PAT st) = do
1320 res <- step (adaptState gst) st
1325 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1326 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1329 stepOuter _ GO_DONE = return Stop
1331{-# INLINE_NORMAL splitSuffixOn #-}
1333 :: forall m a b. (MonadIO m, Storable a, Enum a, Eq a)
1339splitSuffixOn withSep patArr@Array{..} (Fold fstep initial done)
1340 (Stream step state) =
1341 Stream stepOuter GO_START
1345 patLen = A.length patArr
1346 maxIndex = patLen - 1
1347 elemBits = sizeOf (undefined :: a) * 8
1349 {-# INLINE_LATE stepOuter #-}
1350 stepOuter _ GO_START =
1352 then return $ Skip $ GO_EMPTY_PAT state
1355 r <- liftIO $ (A.unsafeIndexIO patArr 0)
1356 return $ Skip $ GO_SINGLE_PAT state r
1357 else if sizeOf (undefined :: a) * patLen
1358 <= sizeOf (undefined :: Word)
1359 then return $ Skip $ GO_SHORT_PAT state
1361 (rb, rhead) <- liftIO $ RB.new patLen
1362 return $ Skip $ GO_KARP_RABIN state rb rhead
1364 stepOuter gst (GO_SINGLE_PAT stt pat) = do
1365 -- This first part is the only difference between splitOn and
1367 -- If the last element is a separator do not issue a blank segment.
1368 res <- step (adaptState gst) stt
1374 acc' <- if withSep then fstep acc x else return acc
1375 done acc' >>= \r -> return $ Yield r (GO_SINGLE_PAT s pat)
1376 else fstep acc x >>= go SPEC s
1377 Skip s -> return $ Skip $ (GO_SINGLE_PAT s pat)
1382 -- This is identical for splitOn and splitSuffixOn
1384 res <- step (adaptState gst) st
1389 acc' <- if withSep then fstep acc x else return acc
1391 return $ Yield r (GO_SINGLE_PAT s pat)
1392 else fstep acc x >>= go SPEC s
1393 Skip s -> go SPEC s acc
1394 Stop -> done acc >>= \r -> return $ Yield r GO_DONE
1396 stepOuter gst (GO_SHORT_PAT stt) = do
1398 -- Call "initial" only if the stream yields an element, otherwise we
1399 -- may call "initial" but never yield anything. initial may produce a
1400 -- side effect, therefore we will end up doing and discard a side
1405 res <- step (adaptState gst) stt
1409 let wrd' = addToWord wrd x
1410 acc' <- if withSep then fstep acc x else return acc
1413 if wrd' .&. mask == patWord
1414 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1415 else go0 SPEC (idx + 1) wrd' s acc'
1416 else go0 SPEC (idx + 1) wrd' s acc'
1417 Skip s -> return $ Skip (GO_SHORT_PAT s)
1423 mask = (1 `shiftL` (elemBits * patLen)) - 1
1425 addToWord wrd a = (wrd `shiftL` elemBits) .|. fromIntegral (fromEnum a)
1428 patWord = mask .&. A.foldl' addToWord 0 patArr
1430 go0 !_ !idx wrd st !acc = do
1431 res <- step (adaptState gst) st
1434 let wrd' = addToWord wrd x
1435 acc' <- if withSep then fstep acc x else return acc
1438 if wrd' .&. mask == patWord
1441 return $ Yield r (GO_SHORT_PAT s)
1442 else go1 SPEC wrd' s acc'
1443 else go0 SPEC (idx + 1) wrd' s acc'
1444 Skip s -> go0 SPEC idx wrd s acc
1446 if (idx == maxIndex) && (wrd .&. mask == patWord)
1449 acc' <- if idx /= 0 && not withSep
1450 then go2 wrd idx acc
1452 done acc' >>= \r -> return $ Yield r GO_DONE
1455 go1 !_ wrd st !acc = do
1456 res <- step (adaptState gst) st
1459 let wrd' = addToWord wrd x
1460 old = (mask .&. wrd) `shiftR` (elemBits * (patLen - 1))
1463 else fstep acc (toEnum $ fromIntegral old)
1464 if wrd' .&. mask == patWord
1465 then done acc' >>= \r -> return $ Yield r (GO_SHORT_PAT s)
1466 else go1 SPEC wrd' s acc'
1467 Skip s -> go1 SPEC wrd s acc
1469 -- If the last sequence is a separator do not issue a blank
1471 if wrd .&. mask == patWord
1476 else go2 wrd patLen acc
1477 done acc' >>= \r -> return $ Yield r GO_DONE
1479 go2 !wrd !n !acc | n > 0 = do
1480 let old = (mask .&. wrd) `shiftR` (elemBits * (n - 1))
1481 fstep acc (toEnum $ fromIntegral old) >>= go2 wrd (n - 1)
1482 go2 _ _ acc = return acc
1484 stepOuter gst (GO_KARP_RABIN stt rb rhead) = do
1486 res <- step (adaptState gst) stt
1490 acc' <- if withSep then fstep acc x else return acc
1491 rh' <- liftIO (RB.unsafeInsert rb rhead x)
1494 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1495 let !ringHash = fold addCksum 0 rb
1496 if ringHash == patHash
1497 then go2 SPEC ringHash rh' s acc'
1498 else go0 SPEC (idx + 1) rh' s acc'
1499 else go0 SPEC (idx + 1) rh' s acc'
1500 Skip s -> return $ Skip (GO_KARP_RABIN s rb rhead)
1505 k = 2891336453 :: Word32
1507 addCksum cksum a = cksum * k + fromIntegral (fromEnum a)
1508 deltaCksum cksum old new =
1509 addCksum cksum new - coeff * fromIntegral (fromEnum old)
1511 -- XXX shall we use a random starting hash or 1 instead of 0?
1512 patHash = A.foldl' addCksum 0 patArr
1515 go0 !_ !idx !rh st !acc = do
1516 res <- step (adaptState gst) st
1519 acc' <- if withSep then fstep acc x else return acc
1520 rh' <- liftIO (RB.unsafeInsert rb rh x)
1523 let fold = RB.unsafeFoldRing (RB.ringBound rb)
1524 let !ringHash = fold addCksum 0 rb
1525 if ringHash == patHash
1526 then go2 SPEC ringHash rh' s acc'
1527 else go1 SPEC ringHash rh' s acc'
1528 else go0 SPEC (idx + 1) rh' s acc'
1529 Skip s -> go0 SPEC idx rh s acc
1531 -- do not issue a blank segment when we end at pattern
1532 if (idx == maxIndex) && RB.unsafeEqArray rb rh patArr
1535 !acc' <- if idx /= 0 && not withSep
1536 then RB.unsafeFoldRingM rh fstep acc rb
1538 done acc' >>= \r -> return $ Yield r GO_DONE
1540 -- XXX Theoretically this code can do 4 times faster if GHC generates
1541 -- optimal code. If we use just "(cksum' == patHash)" condition it goes
1542 -- 4x faster, as soon as we add the "RB.unsafeEqArray rb v" condition
1543 -- the generated code changes drastically and becomes 4x slower. Need
1544 -- to investigate what is going on with GHC.
1546 go1 !_ !cksum !rh st !acc = do
1547 res <- step (adaptState gst) st
1550 old <- liftIO $ peek rh
1551 let cksum' = deltaCksum cksum old x
1556 if (cksum' == patHash)
1558 rh' <- liftIO (RB.unsafeInsert rb rh x)
1559 go2 SPEC cksum' rh' s acc'
1561 rh' <- liftIO (RB.unsafeInsert rb rh x)
1562 go1 SPEC cksum' rh' s acc'
1563 Skip s -> go1 SPEC cksum rh s acc
1565 if RB.unsafeEqArray rb rh patArr
1570 else RB.unsafeFoldRingFullM rh fstep acc rb
1571 done acc' >>= \r -> return $ Yield r GO_DONE
1573 go2 !_ !cksum' !rh' s !acc' = do
1574 if RB.unsafeEqArray rb rh' patArr
1577 return $ Yield r (GO_KARP_RABIN s rb rhead)
1578 else go1 SPEC cksum' rh' s acc'
1580 stepOuter gst (GO_EMPTY_PAT st) = do
1581 res <- step (adaptState gst) st
1586 done acc' >>= \r -> return $ Yield r (GO_EMPTY_PAT s)
1587 Skip s -> return $ Skip (GO_EMPTY_PAT s)
1590 stepOuter _ GO_DONE = return Stop
1592------------------------------------------------------------------------------
1594------------------------------------------------------------------------------
1596{-# INLINE_NORMAL isPrefixOf #-}
1597isPrefixOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
1598isPrefixOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1600 go (sa, sb, Nothing) = do
1601 r <- stepa defState sa
1603 Yield x sa' -> go (sa', sb, Just x)
1604 Skip sa' -> go (sa', sb, Nothing)
1607 go (sa, sb, Just x) = do
1608 r <- stepb defState sb
1612 then go (sa, sb', Nothing)
1614 Skip sb' -> go (sa, sb', Just x)
1615 Stop -> return False
1617{-# INLINE_NORMAL isSubsequenceOf #-}
1618isSubsequenceOf :: (Eq a, Monad m) => Stream m a -> Stream m a -> m Bool
1619isSubsequenceOf (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1621 go (sa, sb, Nothing) = do
1622 r <- stepa defState sa
1624 Yield x sa' -> go (sa', sb, Just x)
1625 Skip sa' -> go (sa', sb, Nothing)
1628 go (sa, sb, Just x) = do
1629 r <- stepb defState sb
1633 then go (sa, sb', Nothing)
1634 else go (sa, sb', Just x)
1635 Skip sb' -> go (sa, sb', Just x)
1636 Stop -> return False
1638{-# INLINE_NORMAL stripPrefix #-}
1641 => Stream m a -> Stream m a -> m (Maybe (Stream m a))
1642stripPrefix (Stream stepa ta) (Stream stepb tb) = go (ta, tb, Nothing)
1644 go (sa, sb, Nothing) = do
1645 r <- stepa defState sa
1647 Yield x sa' -> go (sa', sb, Just x)
1648 Skip sa' -> go (sa', sb, Nothing)
1649 Stop -> return $ Just (Stream stepb sb)
1651 go (sa, sb, Just x) = do
1652 r <- stepb defState sb
1656 then go (sa, sb', Nothing)
1658 Skip sb' -> go (sa, sb', Just x)
1659 Stop -> return Nothing
1661------------------------------------------------------------------------------
1663------------------------------------------------------------------------------
1665-- | Execute a monadic action for each element of the 'Stream'
1666{-# INLINE_NORMAL mapM_ #-}
1667mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
1668mapM_ m = drain . mapM m
1670------------------------------------------------------------------------------
1672------------------------------------------------------------------------------
1674{-# INLINE fromStreamD #-}
1675fromStreamD :: (K.IsStream t, Monad m) => Stream m a -> t m a
1676fromStreamD = K.fromStream . toStreamK
1678------------------------------------------------------------------------------
1680------------------------------------------------------------------------------
1682-- | Run a side effect before the stream yields its first element.
1683before :: Monad m => m b -> Stream m a -> Stream m a
1684before action (Stream step state) = Stream step' Nothing
1688 {-# INLINE_LATE step' #-}
1689 step' _ Nothing = action >> return (Skip (Just state))
1691 step' gst (Just st) = do
1694 Yield x s -> return $ Yield x (Just s)
1695 Skip s -> return $ Skip (Just s)
1698-- | Run a side effect whenever the stream stops normally.
1699after :: Monad m => m b -> Stream m a -> Stream m a
1700after action (Stream step state) = Stream step' state
1704 {-# INLINE_LATE step' #-}
1708 Yield x s -> return $ Yield x s
1709 Skip s -> return $ Skip s
1710 Stop -> action >> return Stop
1712-- | Run a side effect whenever the stream aborts due to an exception. The
1713-- exception is not caught simply rethrown.
1714onException :: MonadCatch m => m b -> Stream m a -> Stream m a
1715onException action (Stream step state) = Stream step' state
1719 {-# INLINE_LATE step' #-}
1721 res <- step gst st `MC.onException` action
1723 Yield x s -> return $ Yield x s
1724 Skip s -> return $ Skip s
1725 Stop -> action >> return Stop
1727-- XXX check if a monolithic implementation would be more performant.
1729-- | Run a side effect whenever the stream stops normally or aborts due to an
1731finally :: MonadCatch m => m b -> Stream m a -> Stream m a
1732finally action xs = after action $ onException action xs
1734-- | Run the first action before the stream starts and remember its output,
1735-- generate a stream using the output, run the second action using the
1736-- remembered value as an argument whenever the stream ends normally or due to
1738bracket :: MonadCatch m => m b -> (b -> m c) -> (b -> Stream m a) -> Stream m a
1739bracket bef aft bet = Stream step' Nothing
1743 {-# INLINE_LATE step' #-}
1744 step' _ Nothing = bef >>= \x -> return (Skip (Just (bet x, x)))
1746 step' gst (Just (Stream step state, v)) = do
1747 res <- step gst state `MC.onException` aft v
1749 Yield x s -> return $ Yield x (Just (Stream step s, v))
1750 Skip s -> return $ Skip (Just (Stream step s, v))
1751 Stop -> aft v >> return Stop
1753-- | When evaluating a stream if an exception occurs, stream evaluation aborts
1754-- and the specified exception handler is run with the exception as argument.
1755handle :: (MonadCatch m, Exception e) => (e -> m a) -> Stream m a -> Stream m a
1756handle f (Stream step state) = Stream step' (Just state)
1760 {-# INLINE_LATE step' #-}
1761 step' gst (Just st) = do
1762 res <- MC.try $ step gst st
1764 Left e -> f e >>= \x -> return (Yield x Nothing)
1765 Right r -> case r of
1766 Yield x s -> return $ Yield x (Just s)
1767 Skip s -> return $ Skip (Just s)
1770 step' _ Nothing = return Stop
1772------------------------------------------------------------------------------
1773-- Transformation by Folding (Scans)
1774------------------------------------------------------------------------------
1776------------------------------------------------------------------------------
1778------------------------------------------------------------------------------
1780-- XXX Is a prescan useful, discarding the last step does not sound useful? I
1781-- am not sure about the utility of this function, so this is implemented but
1782-- not exposed. We can expose it if someone provides good reasons why this is
1785-- XXX We have to execute the stream one step ahead to know that we are at the
1786-- last step. The vector implementation of prescan executes the last fold step
1787-- but does not yield the result. This means we have executed the effect but
1788-- discarded value. This does not sound right. In this implementation we are
1789-- not executing the last fold step.
1790{-# INLINE_NORMAL prescanlM' #-}
1791prescanlM' :: Monad m => (b -> a -> m b) -> m b -> Stream m a -> Stream m b
1792prescanlM' f mz (Stream step state) = Stream step' (state, mz)
1794 {-# INLINE_LATE step' #-}
1795 step' gst (st, prev) = do
1796 r <- step (adaptState gst) st
1800 return $ Yield acc (s, f acc x)
1801 Skip s -> return $ Skip (s, prev)
1804{-# INLINE prescanl' #-}
1805prescanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
1806prescanl' f z = prescanlM' (\a b -> return (f a b)) (return z)
1808------------------------------------------------------------------------------
1809-- Monolithic postscans (postscan followed by a map)
1810------------------------------------------------------------------------------
1812-- The performance of a modular postscan followed by a map seems to be
1813-- equivalent to this monolithic scan followed by map therefore we may not need
1814-- this implementation. We just have it for performance comparison and in case
1815-- modular version does not perform well in some situation.
1817{-# INLINE_NORMAL postscanlMx' #-}
1818postscanlMx' :: Monad m
1819 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
1820postscanlMx' fstep begin done (Stream step state) = do
1821 Stream step' (state, begin)
1823 {-# INLINE_LATE step' #-}
1824 step' gst (st, acc) = do
1825 r <- step (adaptState gst) st
1831 v `seq` y `seq` return (Yield v (s, return y))
1832 Skip s -> return $ Skip (s, acc)
1835{-# INLINE_NORMAL postscanlx' #-}
1836postscanlx' :: Monad m
1837 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
1838postscanlx' fstep begin done s =
1839 postscanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
1841-- XXX do we need consM strict to evaluate the begin value?
1842{-# INLINE scanlMx' #-}
1844 => (x -> a -> m x) -> m x -> (x -> m b) -> Stream m a -> Stream m b
1845scanlMx' fstep begin done s =
1846 (begin >>= \x -> x `seq` done x) `consM` postscanlMx' fstep begin done s
1848{-# INLINE scanlx' #-}
1850 => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> Stream m b
1851scanlx' fstep begin done s =
1852 scanlMx' (\b a -> return (fstep b a)) (return begin) (return . done) s
1854------------------------------------------------------------------------------
1856------------------------------------------------------------------------------
1858-- XXX if we make the initial value of the accumulator monadic then should we
1859-- execute it even if the stream is empty? In that case we would have generated
1860-- the effect but discarded the value, but that is what a fold does when the
1861-- stream is empty. Whatever we decide, need to reconcile this with prescan.
1862-- If we execute the initial value here without even using it then it is ok to
1863-- execute the last step there as well without using the value.
1864-- Looking at the duality with right fold, in case of right fold we always
1865-- perform the action when the construction terminates, so in case of left fold
1866-- we should perform it only when the reduction starts.
1867{-# INLINE_NORMAL postscanlM' #-}
1868postscanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
1869postscanlM' fstep begin (Stream step state) =
1870 begin `seq` Stream step' (state, begin)
1872 {-# INLINE_LATE step' #-}
1873 step' gst (st, acc) = acc `seq` do
1874 r <- step (adaptState gst) st
1878 y `seq` return (Yield y (s, y))
1879 Skip s -> return $ Skip (s, acc)
1882{-# INLINE_NORMAL postscanl' #-}
1883postscanl' :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
1884postscanl' f = postscanlM' (\a b -> return (f a b))
1886{-# INLINE_NORMAL postscanlM #-}
1887postscanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
1888postscanlM fstep begin (Stream step state) = Stream step' (state, begin)
1890 {-# INLINE_LATE step' #-}
1891 step' gst (st, acc) = do
1892 r <- step (adaptState gst) st
1896 return (Yield y (s, y))
1897 Skip s -> return $ Skip (s, acc)
1900{-# INLINE_NORMAL postscanl #-}
1901postscanl :: Monad m => (a -> b -> a) -> a -> Stream m b -> Stream m a
1902postscanl f = postscanlM (\a b -> return (f a b))
1904{-# INLINE_NORMAL scanlM' #-}
1905scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
1906scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
1908{-# INLINE scanl' #-}
1909scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
1910scanl' f = scanlM' (\a b -> return (f a b))
1912{-# INLINE_NORMAL scanlM #-}
1913scanlM :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
1914scanlM fstep begin s = begin `cons` postscanlM fstep begin s
1917scanl :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
1918scanl f = scanlM (\a b -> return (f a b))
1920{-# INLINE_NORMAL scanl1M #-}
1921scanl1M :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
1922scanl1M fstep (Stream step state) = Stream step' (state, Nothing)
1924 {-# INLINE_LATE step' #-}
1925 step' gst (st, Nothing) = do
1928 Yield x s -> return $ Yield x (s, Just x)
1929 Skip s -> return $ Skip (s, Nothing)
1932 step' gst (st, Just acc) = do
1937 return $ Yield z (s, Just z)
1938 Skip s -> return $ Skip (s, Just acc)
1941{-# INLINE scanl1 #-}
1942scanl1 :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
1943scanl1 f = scanl1M (\x y -> return (f x y))
1945{-# INLINE_NORMAL scanl1M' #-}
1946scanl1M' :: Monad m => (a -> a -> m a) -> Stream m a -> Stream m a
1947scanl1M' fstep (Stream step state) = Stream step' (state, Nothing)
1949 {-# INLINE_LATE step' #-}
1950 step' gst (st, Nothing) = do
1953 Yield x s -> x `seq` return $ Yield x (s, Just x)
1954 Skip s -> return $ Skip (s, Nothing)
1957 step' gst (st, Just acc) = acc `seq` do
1962 z `seq` return $ Yield z (s, Just z)
1963 Skip s -> return $ Skip (s, Just acc)
1966{-# INLINE scanl1' #-}
1967scanl1' :: Monad m => (a -> a -> a) -> Stream m a -> Stream m a
1968scanl1' f = scanl1M' (\x y -> return (f x y))
1971tap :: Monad m => Sink m a -> Stream m a -> Stream m a
1972tap (Sink fstep) (Stream step state) = Stream step' state
1982 Skip s -> return $ Skip s
1983 Stop -> return $ Stop
1985-------------------------------------------------------------------------------
1987-------------------------------------------------------------------------------
1989{-# INLINE_NORMAL takeWhileM #-}
1990takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
1991takeWhileM f (Stream step state) = Stream step' state
1993 {-# INLINE_LATE step' #-}
1999 return $ if b then Yield x s else Stop
2000 Skip s -> return $ Skip s
2003{-# INLINE takeWhile #-}
2004takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
2005takeWhile f = takeWhileM (return . f)
2007{-# INLINE_NORMAL drop #-}
2008drop :: Monad m => Int -> Stream m a -> Stream m a
2009drop n (Stream step state) = Stream step' (state, Just n)
2011 {-# INLINE_LATE step' #-}
2012 step' gst (st, Just i)
2017 Yield _ s -> Skip (s, Just (i - 1))
2018 Skip s -> Skip (s, Just i)
2020 | otherwise = return $ Skip (st, Nothing)
2022 step' gst (st, Nothing) = do
2026 Yield x s -> Yield x (s, Nothing)
2027 Skip s -> Skip (s, Nothing)
2030data DropWhileState s a
2032 | DropWhileYield a s
2035{-# INLINE_NORMAL dropWhileM #-}
2036dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
2037dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
2039 {-# INLINE_LATE step' #-}
2040 step' gst (DropWhileDrop st) = do
2046 then return $ Skip (DropWhileDrop s)
2047 else return $ Skip (DropWhileYield x s)
2048 Skip s -> return $ Skip (DropWhileDrop s)
2051 step' gst (DropWhileNext st) = do
2054 Yield x s -> return $ Skip (DropWhileYield x s)
2055 Skip s -> return $ Skip (DropWhileNext s)
2058 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
2060{-# INLINE dropWhile #-}
2061dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
2062dropWhile f = dropWhileM (return . f)
2064{-# INLINE_NORMAL filterM #-}
2065filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
2066filterM f (Stream step state) = Stream step' state
2068 {-# INLINE_LATE step' #-}
2077 Skip s -> return $ Skip s
2080{-# INLINE filter #-}
2081filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
2082filter f = filterM (return . f)
2084{-# INLINE_NORMAL uniq #-}
2085uniq :: (Eq a, Monad m) => Stream m a -> Stream m a
2086uniq (Stream step state) = Stream step' (Nothing, state)
2088 {-# INLINE_LATE step' #-}
2089 step' gst (Nothing, st) = do
2092 Yield x s -> return $ Yield x (Just x, s)
2093 Skip s -> return $ Skip (Nothing, s)
2095 step' gst (Just x, st) = do
2098 Yield y s | x == y -> return $ Skip (Just x, s)
2099 | otherwise -> return $ Yield x (Just y, s)
2100 Skip s -> return $ Skip (Just x, s)
2103------------------------------------------------------------------------------
2104-- Transformation by Mapping
2105------------------------------------------------------------------------------
2107{-# INLINE_NORMAL sequence #-}
2108sequence :: Monad m => Stream m (m a) -> Stream m a
2109sequence (Stream step state) = Stream step' state
2111 {-# INLINE_LATE step' #-}
2113 r <- step (adaptState gst) st
2115 Yield x s -> x >>= \a -> return (Yield a s)
2116 Skip s -> return $ Skip s
2119------------------------------------------------------------------------------
2121------------------------------------------------------------------------------
2123{-# INLINE_NORMAL insertBy #-}
2124insertBy :: Monad m => (a -> a -> Ordering) -> a -> Stream m a -> Stream m a
2125insertBy cmp a (Stream step state) = Stream step' (state, False, Nothing)
2127 {-# INLINE_LATE step' #-}
2128 step' gst (st, False, _) = do
2131 Yield x s -> case cmp a x of
2132 GT -> return $ Yield x (s, False, Nothing)
2133 _ -> return $ Yield a (s, True, Just x)
2134 Skip s -> return $ Skip (s, False, Nothing)
2135 Stop -> return $ Yield a (st, True, Nothing)
2137 step' _ (_, True, Nothing) = return Stop
2139 step' gst (st, True, Just prev) = do
2142 Yield x s -> return $ Yield prev (s, True, Just x)
2143 Skip s -> return $ Skip (s, True, Just prev)
2144 Stop -> return $ Yield prev (st, True, Nothing)
2146------------------------------------------------------------------------------
2148------------------------------------------------------------------------------
2150{-# INLINE_NORMAL deleteBy #-}
2151deleteBy :: Monad m => (a -> a -> Bool) -> a -> Stream m a -> Stream m a
2152deleteBy eq x (Stream step state) = Stream step' (state, False)
2154 {-# INLINE_LATE step' #-}
2155 step' gst (st, False) = do
2158 Yield y s -> return $
2159 if eq x y then Skip (s, True) else Yield y (s, False)
2160 Skip s -> return $ Skip (s, False)
2163 step' gst (st, True) = do
2166 Yield y s -> return $ Yield y (s, True)
2167 Skip s -> return $ Skip (s, True)
2170------------------------------------------------------------------------------
2171-- Transformation by Map and Filter
2172------------------------------------------------------------------------------
2174-- XXX Will this always fuse properly?
2175{-# INLINE_NORMAL mapMaybe #-}
2176mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
2177mapMaybe f = fmap fromJust . filter isJust . map f
2179{-# INLINE_NORMAL mapMaybeM #-}
2180mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
2181mapMaybeM f = fmap fromJust . filter isJust . mapM f
2183------------------------------------------------------------------------------
2185------------------------------------------------------------------------------
2187{-# INLINE_NORMAL indexed #-}
2188indexed :: Monad m => Stream m a -> Stream m (Int, a)
2189indexed (Stream step state) = Stream step' (state, 0)
2191 {-# INLINE_LATE step' #-}
2192 step' gst (st, i) = i `seq` do
2193 r <- step (adaptState gst) st
2195 Yield x s -> return $ Yield (i, x) (s, i+1)
2196 Skip s -> return $ Skip (s, i)
2199{-# INLINE_NORMAL indexedR #-}
2200indexedR :: Monad m => Int -> Stream m a -> Stream m (Int, a)
2201indexedR m (Stream step state) = Stream step' (state, m)
2203 {-# INLINE_LATE step' #-}
2204 step' gst (st, i) = i `seq` do
2205 r <- step (adaptState gst) st
2207 Yield x s -> let i' = i - 1
2208 in return $ Yield (i, x) (s, i')
2209 Skip s -> return $ Skip (s, i)
2212{-# INLINE_NORMAL zipWithM #-}
2214 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
2215zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
2217 {-# INLINE_LATE step #-}
2218 step gst (sa, sb, Nothing) = do
2219 r <- stepa (adaptState gst) sa
2222 Yield x sa' -> Skip (sa', sb, Just x)
2223 Skip sa' -> Skip (sa', sb, Nothing)
2226 step gst (sa, sb, Just x) = do
2227 r <- stepb (adaptState gst) sb
2231 return $ Yield z (sa, sb', Nothing)
2232 Skip sb' -> return $ Skip (sa, sb', Just x)
2235{-# RULES "zipWithM xs xs"
2236 forall f xs. zipWithM f xs xs = mapM (\x -> f x x) xs #-}
2238{-# INLINE zipWith #-}
2239zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
2240zipWith f = zipWithM (\a b -> return (f a b))
2242------------------------------------------------------------------------------
2244------------------------------------------------------------------------------
2246{-# INLINE_NORMAL mergeByM #-}
2249 => (a -> a -> m Ordering) -> Stream m a -> Stream m a -> Stream m a
2250mergeByM cmp (Stream stepa ta) (Stream stepb tb) =
2251 Stream step (Just ta, Just tb, Nothing, Nothing)
2253 {-# INLINE_LATE step #-}
2255 -- one of the values is missing, and the corresponding stream is running
2256 step gst (Just sa, sb, Nothing, b) = do
2259 Yield a sa' -> Skip (Just sa', sb, Just a, b)
2260 Skip sa' -> Skip (Just sa', sb, Nothing, b)
2261 Stop -> Skip (Nothing, sb, Nothing, b)
2263 step gst (sa, Just sb, a, Nothing) = do
2266 Yield b sb' -> Skip (sa, Just sb', a, Just b)
2267 Skip sb' -> Skip (sa, Just sb', a, Nothing)
2268 Stop -> Skip (sa, Nothing, a, Nothing)
2270 -- both the values are available
2271 step _ (sa, sb, Just a, Just b) = do
2273 return $ case res of
2274 GT -> Yield b (sa, sb, Just a, Nothing)
2275 _ -> Yield a (sa, sb, Nothing, Just b)
2277 -- one of the values is missing, corresponding stream is done
2278 step _ (Nothing, sb, Nothing, Just b) =
2279 return $ Yield b (Nothing, sb, Nothing, Nothing)
2281 step _ (sa, Nothing, Just a, Nothing) =
2282 return $ Yield a (sa, Nothing, Nothing, Nothing)
2284 step _ (Nothing, Nothing, Nothing, Nothing) = return Stop
2286{-# INLINE mergeBy #-}
2289 => (a -> a -> Ordering) -> Stream m a -> Stream m a -> Stream m a
2290mergeBy cmp = mergeByM (\a b -> return $ cmp a b)
2292------------------------------------------------------------------------------
2293-- Transformation comprehensions
2294------------------------------------------------------------------------------
2296{-# INLINE_NORMAL the #-}
2297the :: (Eq a, Monad m) => Stream m a -> m (Maybe a)
2298the (Stream step state) = go state
2301 r <- step defState st
2303 Yield x s -> go' x s
2305 Stop -> return Nothing
2307 r <- step defState st
2309 Yield x s | x == n -> go' n s
2310 | otherwise -> return Nothing
2312 Stop -> return (Just n)
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