1{-# LANGUAGE BangPatterns #-}
3{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE ExistentialQuantification #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE RankNTypes #-}
13-- Module : Streamly.Streams.StreamD
14-- Copyright : (c) 2018 Harendra Kumar
17-- Maintainer : harendra.kumar@gmail.com
18-- Stability : experimental
21-- Direct style re-implementation of CPS style stream in StreamK module. The
22-- symbol or suffix 'D' in this module denotes the "Direct" style. GHC is able
23-- to INLINE and fuse direct style better, providing better performance than
27-- import qualified Streamly.Streams.StreamD as D
30-- Some of functions in this file have been adapted from the vector
31-- library, https://hackage.haskell.org/package/vector.
33module Streamly.Streams.StreamD
51 -- ** Specialized Generation
52 -- | Generate a monadic stream from a seed.
57 -- | Transform an input structure into a stream.
58 -- | Direct style stream does not support @fromFoldable@.
72 -- ** Specialized Folds
89 -- | Transform a stream into another type.
94 -- ** By folding (scans)
122import Data.Maybe (fromJust, isJust)
123import GHC.Types ( SPEC(..) )
125 hiding (map, mapM, mapM_, repeat, foldr, last, take, filter,
126 takeWhile, drop, dropWhile, all, any, maximum, minimum, elem,
127 notElem, null, head, tail, zipWith)
129import Streamly.SVar (MonadAsync, State(..), defState, rstState)
130import qualified Streamly.Streams.StreamK as K
132------------------------------------------------------------------------------
133-- The direct style stream type
134------------------------------------------------------------------------------
136-- | A stream is a succession of 'Step's. A 'Yield' produces a single value and
137-- the next state of the stream. 'Stop' indicates there are no more values in
139data Step s a = Yield a s | Skip s | Stop
141instance Functor (Step s) where
143 fmap f (Yield x s) = Yield (f x) s
144 fmap _ (Skip s) = Skip s
148-- | A stream consists of a step function that generates the next step given a
149-- current state, and the current state.
150data Stream m a = forall s. Stream (State K.Stream m a -> s -> m (Step s a)) s
152------------------------------------------------------------------------------
154------------------------------------------------------------------------------
156-- | An empty 'Stream'.
157{-# INLINE_NORMAL nil #-}
158nil :: Monad m => Stream m a
159nil = Stream (\_ _ -> return Stop) ()
161-- | Can fuse but has O(n^2) complexity.
162{-# INLINE_NORMAL cons #-}
163cons :: Monad m => a -> Stream m a -> Stream m a
164cons x (Stream step state) = Stream step1 Nothing
166 {-# INLINE_LATE step1 #-}
167 step1 _ Nothing = return $ Yield x (Just state)
168 step1 gst (Just st) = do
169 r <- step (rstState gst) st
172 Yield a s -> Yield a (Just s)
173 Skip s -> Skip (Just s)
176-------------------------------------------------------------------------------
178-------------------------------------------------------------------------------
180-- Does not fuse, has the same performance as the StreamK version.
181{-# INLINE_NORMAL uncons #-}
182uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
183uncons (Stream step state) = go state
186 r <- step defState st
188 Yield x s -> return $ Just (x, Stream step s)
190 Stop -> return Nothing
192------------------------------------------------------------------------------
193-- Generation by unfold
194------------------------------------------------------------------------------
196{-# INLINE_NORMAL unfoldrM #-}
197unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
198unfoldrM next state = Stream step state
200 {-# INLINE_LATE step #-}
204 Just (x, s) -> Yield x s
207{-# INLINE_LATE unfoldr #-}
208unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
209unfoldr f = unfoldrM (return . f)
211------------------------------------------------------------------------------
212-- Specialized Generation
213------------------------------------------------------------------------------
215repeat :: Monad m => a -> Stream m a
216repeat x = Stream (\_ _ -> return $ Yield x ()) ()
218{-# INLINE_NORMAL enumFromStepN #-}
219enumFromStepN :: (Num a, Monad m) => a -> a -> Int -> Stream m a
220enumFromStepN from stride n =
221 from `seq` stride `seq` n `seq` Stream step (from, n)
223 {-# INLINE_LATE step #-}
224 step _ (x, i) | i > 0 = return $ Yield x (x + stride, i - 1)
225 | otherwise = return Stop
227-------------------------------------------------------------------------------
228-- Generation by Conversion
229-------------------------------------------------------------------------------
231-- | Create a singleton 'Stream' from a pure value.
232{-# INLINE_NORMAL yield #-}
233yield :: Monad m => a -> Stream m a
234yield x = Stream (\_ s -> return $ step undefined s) True
236 {-# INLINE_LATE step #-}
237 step _ True = Yield x False
240-- | Create a singleton 'Stream' from a monadic action.
241{-# INLINE_NORMAL yieldM #-}
242yieldM :: Monad m => m a -> Stream m a
243yieldM m = Stream step True
245 {-# INLINE_LATE step #-}
246 step _ True = m >>= \x -> return $ Yield x False
247 step _ False = return Stop
249-- XXX we need the MonadAsync constraint because of a rewrite rule.
250-- | Convert a list of monadic actions to a 'Stream'
251{-# INLINE_LATE fromListM #-}
252fromListM :: MonadAsync m => [m a] -> Stream m a
253fromListM = Stream step
255 {-# INLINE_LATE step #-}
256 step _ (m:ms) = m >>= \x -> return $ Yield x ms
257 step _ [] = return Stop
259-- | Convert a list of pure values to a 'Stream'
260{-# INLINE_LATE fromList #-}
261fromList :: Monad m => [a] -> Stream m a
262fromList = Stream step
264 {-# INLINE_LATE step #-}
265 step _ (x:xs) = return $ Yield x xs
266 step _ [] = return Stop
268-- XXX pass the state to streamD
269{-# INLINE_LATE fromStreamK #-}
270fromStreamK :: Monad m => K.Stream m a -> Stream m a
271fromStreamK = Stream step
274 let stop = return Stop
275 single a = return $ Yield a K.nil
276 yieldk a r = return $ Yield a r
277 in K.unStream m1 gst stop single yieldk
279------------------------------------------------------------------------------
280-- Elimination by Folds
281------------------------------------------------------------------------------
283{-# INLINE_NORMAL foldrM #-}
284foldrM :: Monad m => (a -> b -> m b) -> b -> Stream m a -> m b
285foldrM f z (Stream step state) = go SPEC state
288 r <- step defState st
290 Yield x s -> go SPEC s >>= f x
294{-# INLINE_NORMAL foldr #-}
295foldr :: Monad m => (a -> b -> b) -> b -> Stream m a -> m b
296foldr f = foldrM (\a b -> return (f a b))
298{-# INLINE_NORMAL foldlM' #-}
299foldlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> m b
300foldlM' fstep begin (Stream step state) = go SPEC begin state
302 go !_ acc st = acc `seq` do
303 r <- step defState st
308 Skip s -> go SPEC acc s
312foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b
313foldl' fstep = foldlM' (\b a -> return (fstep b a))
315------------------------------------------------------------------------------
317------------------------------------------------------------------------------
319-- | Run a streaming composition, discard the results.
320{-# INLINE_LATE runStream #-}
321runStream :: Monad m => Stream m a -> m ()
322runStream (Stream step state) = go SPEC state
325 r <- step defState st
327 Yield _ s -> go SPEC s
331{-# INLINE_NORMAL null #-}
332null :: Monad m => Stream m a -> m Bool
333null (Stream step state) = go state
336 r <- step defState st
338 Yield _ _ -> return False
343{-# INLINE_NORMAL head #-}
344head :: Monad m => Stream m a -> m (Maybe a)
345head (Stream step state) = go state
348 r <- step defState st
350 Yield x _ -> return (Just x)
352 Stop -> return Nothing
354-- Does not fuse, has the same performance as the StreamK version.
355{-# INLINE_NORMAL tail #-}
356tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
357tail (Stream step state) = go state
360 r <- step defState st
362 Yield _ s -> return (Just $ Stream step s)
364 Stop -> return Nothing
366-- XXX will it fuse? need custom impl?
367{-# INLINE_NORMAL last #-}
368last :: Monad m => Stream m a -> m (Maybe a)
369last = foldl' (\_ y -> Just y) Nothing
371{-# INLINE_NORMAL elem #-}
372elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
373elem e (Stream step state) = go state
376 r <- step defState st
379 | x == e -> return True
384{-# INLINE_NORMAL notElem #-}
385notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
386notElem e s = fmap not (elem e s)
388{-# INLINE_NORMAL all #-}
389all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
390all p (Stream step state) = go state
393 r <- step defState st
397 | otherwise -> return False
401{-# INLINE_NORMAL any #-}
402any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
403any p (Stream step state) = go state
406 r <- step defState st
414{-# INLINE_NORMAL maximum #-}
415maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
416maximum (Stream step state) = go Nothing state
419 r <- step defState st
421 Yield x s -> go (Just x) s
422 Skip s -> go Nothing s
423 Stop -> return Nothing
424 go (Just acc) st = do
425 r <- step defState st
428 | acc <= x -> go (Just x) s
429 | otherwise -> go (Just acc) s
430 Skip s -> go (Just acc) s
431 Stop -> return (Just acc)
433{-# INLINE_NORMAL minimum #-}
434minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
435minimum (Stream step state) = go Nothing state
438 r <- step defState st
440 Yield x s -> go (Just x) s
441 Skip s -> go Nothing s
442 Stop -> return Nothing
443 go (Just acc) st = do
444 r <- step defState st
447 | acc <= x -> go (Just acc) s
448 | otherwise -> go (Just x) s
449 Skip s -> go (Just acc) s
450 Stop -> return (Just acc)
452------------------------------------------------------------------------------
454------------------------------------------------------------------------------
456-- | Execute a monadic action for each element of the 'Stream'
457{-# INLINE_NORMAL mapM_ #-}
458mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
459mapM_ m = runStream . mapM m
461------------------------------------------------------------------------------
463------------------------------------------------------------------------------
466toList :: Monad m => Stream m a -> m [a]
469-- Convert a direct stream to and from CPS encoded stream
470{-# INLINE_LATE toStreamK #-}
471toStreamK :: Monad m => Stream m a -> K.Stream m a
472toStreamK (Stream step state) = go state
474 go st = K.Stream $ \gst stp sng yld -> do
477 Yield x s -> yld x (go s)
478 Skip s -> K.unStream (go s) gst stp sng yld
481#ifndef DISABLE_FUSION
482{-# RULES "fromStreamK/toStreamK fusion"
483 forall s. toStreamK (fromStreamK s) = s #-}
484{-# RULES "toStreamK/fromStreamK fusion"
485 forall s. fromStreamK (toStreamK s) = s #-}
488------------------------------------------------------------------------------
489-- Transformation by Folding (Scans)
490------------------------------------------------------------------------------
492{-# INLINE_NORMAL postscanlM' #-}
493postscanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
494postscanlM' fstep begin (Stream step state) =
495 begin `seq` Stream step' (state, begin)
497 {-# INLINE_LATE step' #-}
498 step' gst (st, acc) = acc `seq` do
499 r <- step (rstState gst) st
503 y `seq` return (Yield y (s, y))
504 Skip s -> return $ Skip (s, acc)
507{-# INLINE_LATE scanlM' #-}
508scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
509scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
512scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b
513scanl' f = scanlM' (\a b -> return (f a b))
515-------------------------------------------------------------------------------
517-------------------------------------------------------------------------------
519{-# INLINE_NORMAL take #-}
520take :: Monad m => Int -> Stream m a -> Stream m a
521take n (Stream step state) = n `seq` Stream step' (state, 0)
523 {-# INLINE_LATE step' #-}
524 step' gst (st, i) | i < n = do
525 r <- step (rstState gst) st
527 Yield x s -> Yield x (s, i + 1)
528 Skip s -> Skip (s, i)
530 step' _ (_, _) = return Stop
532{-# INLINE_NORMAL takeWhileM #-}
533takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
534takeWhileM f (Stream step state) = Stream step' state
536 {-# INLINE_LATE step' #-}
538 r <- step (rstState gst) st
542 return $ if b then Yield x s else Stop
543 Skip s -> return $ Skip s
546{-# INLINE takeWhile #-}
547takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
548takeWhile f = takeWhileM (return . f)
550{-# INLINE_NORMAL drop #-}
551drop :: Monad m => Int -> Stream m a -> Stream m a
552drop n (Stream step state) = Stream step' (state, Just n)
554 {-# INLINE_LATE step' #-}
555 step' gst (st, Just i)
557 r <- step (rstState gst) st
560 Yield _ s -> Skip (s, Just (i - 1))
561 Skip s -> Skip (s, Just i)
563 | otherwise = return $ Skip (st, Nothing)
565 step' gst (st, Nothing) = do
566 r <- step (rstState gst) st
569 Yield x s -> Yield x (s, Nothing)
570 Skip s -> Skip (s, Nothing)
573data DropWhileState s a
578{-# INLINE_NORMAL dropWhileM #-}
579dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
580dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
582 {-# INLINE_LATE step' #-}
583 step' gst (DropWhileDrop st) = do
584 r <- step (rstState gst) st
589 then return $ Skip (DropWhileDrop s)
590 else return $ Skip (DropWhileYield x s)
591 Skip s -> return $ Skip (DropWhileDrop s)
594 step' gst (DropWhileNext st) = do
595 r <- step (rstState gst) st
597 Yield x s -> return $ Skip (DropWhileYield x s)
598 Skip s -> return $ Skip (DropWhileNext s)
601 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
603{-# INLINE dropWhile #-}
604dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
605dropWhile f = dropWhileM (return . f)
607{-# INLINE_NORMAL filterM #-}
608filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
609filterM f (Stream step state) = Stream step' state
611 {-# INLINE_LATE step' #-}
613 r <- step (rstState gst) st
620 Skip s -> return $ Skip s
624filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
625filter f = filterM (return . f)
627------------------------------------------------------------------------------
628-- Transformation by Mapping
629------------------------------------------------------------------------------
631-- | Map a monadic function over a 'Stream'
632{-# INLINE_NORMAL mapM #-}
633mapM :: Monad m => (a -> m b) -> Stream m a -> Stream m b
634mapM f (Stream step state) = Stream step' state
636 {-# INLINE_LATE step' #-}
638 r <- step (rstState gst) st
640 Yield x s -> f x >>= \a -> return $ Yield a s
641 Skip s -> return $ Skip s
645map :: Monad m => (a -> b) -> Stream m a -> Stream m b
646map f = mapM (return . f)
648------------------------------------------------------------------------------
649-- Transformation by Map and Filter
650------------------------------------------------------------------------------
652-- XXX Will this always fuse properly?
653{-# INLINE_NORMAL mapMaybe #-}
654mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
655mapMaybe f = fmap fromJust . filter isJust . map f
657{-# INLINE_NORMAL mapMaybeM #-}
658mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
659mapMaybeM f = fmap fromJust . filter isJust . mapM f
661------------------------------------------------------------------------------
663------------------------------------------------------------------------------
665{-# INLINE_NORMAL zipWithM #-}
667 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
668zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
670 {-# INLINE_LATE step #-}
671 step gst (sa, sb, Nothing) = do
672 r <- stepa (rstState gst) sa
675 Yield x sa' -> Skip (sa', sb, Just x)
676 Skip sa' -> Skip (sa', sb, Nothing)
679 step gst (sa, sb, Just x) = do
680 r <- stepb (rstState gst) sb
684 return $ Yield z (sa, sb', Nothing)
685 Skip sb' -> return $ Skip (sa, sb', Just x)
688{-# RULES "zipWithM xs xs"
689 forall f xs. zipWithM f xs xs = mapM (\x -> f x x) xs #-}
691{-# INLINE zipWith #-}
692zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
693zipWith f = zipWithM (\a b -> return (f a b))
695------------------------------------------------------------------------------
697------------------------------------------------------------------------------
699instance Monad m => Functor (Stream m) where
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