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)
121import Data.Maybe (fromJust, isJust)
122import GHC.Types ( SPEC(..) )
124 hiding (map, mapM, mapM_, repeat, foldr, last, take, filter,
125 takeWhile, drop, dropWhile, all, any, maximum, minimum, elem,
126 notElem, null, head, tail, zipWith)
128import Streamly.SVar (MonadAsync, State(..), defState, rstState)
129import qualified Streamly.Streams.StreamK as K
131------------------------------------------------------------------------------
132-- The direct style stream type
133------------------------------------------------------------------------------
135-- | A stream is a succession of 'Step's. A 'Yield' produces a single value and
136-- the next state of the stream. 'Stop' indicates there are no more values in
138data Step s a = Yield a s | Stop
140instance Functor (Step s) where
142 fmap f (Yield x s) = Yield (f x) s
146-- | A stream consists of a step function that generates the next step given a
147-- current state, and the current state.
148data Stream m a = forall s. Stream (State K.Stream m a -> s -> m (Step s a)) s
150------------------------------------------------------------------------------
152------------------------------------------------------------------------------
154-- | An empty 'Stream'.
155{-# INLINE_NORMAL nil #-}
156nil :: Monad m => Stream m a
157nil = Stream (\_ _ -> return Stop) ()
159-- | Can fuse but has O(n^2) complexity.
160cons :: Monad m => a -> Stream m a -> Stream m a
161cons x (Stream step state) = Stream step1 Nothing
163 step1 _ Nothing = return $ Yield x (Just state)
164 step1 gst (Just st) = do
165 r <- step (rstState gst) st
167 Yield a s -> return $ Yield a (Just s)
170-------------------------------------------------------------------------------
172-------------------------------------------------------------------------------
174-- Does not fuse, has the same performance as the StreamK version.
175{-# INLINE_NORMAL uncons #-}
176uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a))
177uncons (Stream step state) = go state
180 r <- step defState st
182 Yield x s -> Just (x, Stream step s)
185------------------------------------------------------------------------------
186-- Generation by unfold
187------------------------------------------------------------------------------
189{-# INLINE_NORMAL unfoldrM #-}
190unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a
191unfoldrM next state = Stream step state
193 {-# INLINE_LATE step #-}
197 Just (x, s) -> Yield x s
200{-# INLINE_LATE unfoldr #-}
201unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a
202unfoldr f = unfoldrM (return . f)
204------------------------------------------------------------------------------
205-- Specialized Generation
206------------------------------------------------------------------------------
208repeat :: Monad m => a -> Stream m a
209repeat x = Stream (\_ _ -> return $ Yield x ()) ()
211{-# INLINE_NORMAL enumFromStepN #-}
212enumFromStepN :: (Num a, Monad m) => a -> a -> Int -> Stream m a
213enumFromStepN from stride n =
214 from `seq` stride `seq` n `seq` Stream step (from, n)
216 {-# INLINE_LATE step #-}
217 step _ (x, i) | i > 0 = return $ Yield x (x + stride, i - 1)
218 | otherwise = return Stop
220-------------------------------------------------------------------------------
221-- Generation by Conversion
222-------------------------------------------------------------------------------
224-- | Create a singleton 'Stream' from a pure value.
225{-# INLINE_NORMAL yield #-}
226yield :: Monad m => a -> Stream m a
227yield x = Stream (\_ s -> return $ step undefined s) True
229 {-# INLINE_LATE step #-}
230 step _ True = Yield x False
233-- | Create a singleton 'Stream' from a monadic action.
234{-# INLINE_NORMAL yieldM #-}
235yieldM :: Monad m => m a -> Stream m a
236yieldM m = Stream step True
238 {-# INLINE_LATE step #-}
239 step _ True = m >>= \x -> return $ Yield x False
240 step _ False = return Stop
242-- XXX we need the MonadAsync constraint because of a rewrite rule.
243-- | Convert a list of monadic actions to a 'Stream'
244{-# INLINE_LATE fromListM #-}
245fromListM :: MonadAsync m => [m a] -> Stream m a
246fromListM = Stream step
248 {-# INLINE_LATE step #-}
249 step _ (m:ms) = m >>= \x -> return $ Yield x ms
250 step _ [] = return Stop
252-- | Convert a list of pure values to a 'Stream'
253{-# INLINE_LATE fromList #-}
254fromList :: Monad m => [a] -> Stream m a
255fromList = Stream step
257 {-# INLINE_LATE step #-}
258 step _ (x:xs) = return $ Yield x xs
259 step _ [] = return Stop
261-- XXX pass the state to streamD
262{-# INLINE_LATE fromStreamK #-}
263fromStreamK :: Monad m => K.Stream m a -> Stream m a
264fromStreamK = Stream step
267 let stop = return Stop
268 single a = return $ Yield a K.nil
269 yieldk a r = return $ Yield a r
270 in K.unStream m1 gst stop single yieldk
272------------------------------------------------------------------------------
273-- Elimination by Folds
274------------------------------------------------------------------------------
276{-# INLINE_NORMAL foldrM #-}
277foldrM :: Monad m => (a -> b -> m b) -> b -> Stream m a -> m b
278foldrM f z (Stream step state) = go SPEC state
281 r <- step defState st
283 Yield x s -> go SPEC s >>= f x
286{-# INLINE_NORMAL foldr #-}
287foldr :: Monad m => (a -> b -> b) -> b -> Stream m a -> m b
288foldr f = foldrM (\a b -> return (f a b))
290{-# INLINE_NORMAL foldlM' #-}
291foldlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> m b
292foldlM' fstep begin (Stream step state) = go SPEC begin state
294 go !_ acc st = acc `seq` do
295 r <- step defState st
303foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b
304foldl' fstep = foldlM' (\b a -> return (fstep b a))
306------------------------------------------------------------------------------
308------------------------------------------------------------------------------
310-- | Run a streaming composition, discard the results.
311{-# INLINE_LATE runStream #-}
312runStream :: Monad m => Stream m a -> m ()
313runStream (Stream step state) = go SPEC state
316 r <- step defState st
318 Yield _ s -> go SPEC s
321{-# INLINE_NORMAL null #-}
322null :: Monad m => Stream m a -> m Bool
323null (Stream step state) = go state
326 r <- step defState st
328 Yield _ _ -> return False
332{-# INLINE_NORMAL head #-}
333head :: Monad m => Stream m a -> m (Maybe a)
334head (Stream step state) = go state
337 r <- step defState st
339 Yield x _ -> return (Just x)
340 Stop -> return Nothing
342-- Does not fuse, has the same performance as the StreamK version.
343{-# INLINE_NORMAL tail #-}
344tail :: Monad m => Stream m a -> m (Maybe (Stream m a))
345tail (Stream step state) = go state
348 r <- step defState st
350 Yield _ s -> return (Just $ Stream step s)
351 Stop -> return Nothing
353-- XXX will it fuse? need custom impl?
354{-# INLINE_NORMAL last #-}
355last :: Monad m => Stream m a -> m (Maybe a)
356last = foldl' (\_ y -> Just y) Nothing
358{-# INLINE_NORMAL elem #-}
359elem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
360elem e (Stream step state) = go state
363 r <- step defState st
371{-# INLINE_NORMAL notElem #-}
372notElem :: (Monad m, Eq a) => a -> Stream m a -> m Bool
373notElem e (Stream step state) = go state
376 r <- step defState st
384{-# INLINE_NORMAL all #-}
385all :: Monad m => (a -> Bool) -> Stream m a -> m Bool
386all p (Stream step state) = go state
389 r <- step defState st
397{-# INLINE_NORMAL any #-}
398any :: Monad m => (a -> Bool) -> Stream m a -> m Bool
399any p (Stream step state) = go state
402 r <- step defState st
410{-# INLINE_NORMAL maximum #-}
411maximum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
412maximum (Stream step state) = go Nothing state
415 r <- step defState st
417 Yield x s -> go (Just x) s
418 Stop -> return Nothing
419 go (Just acc) st = do
420 r <- step defState st
426 Stop -> return (Just acc)
428{-# INLINE_NORMAL minimum #-}
429minimum :: (Monad m, Ord a) => Stream m a -> m (Maybe a)
430minimum (Stream step state) = go Nothing state
433 r <- step defState st
435 Yield x s -> go (Just x) s
436 Stop -> return Nothing
437 go (Just acc) st = do
438 r <- step defState st
444 Stop -> return (Just acc)
446------------------------------------------------------------------------------
448------------------------------------------------------------------------------
450-- | Execute a monadic action for each element of the 'Stream'
451{-# INLINE_NORMAL mapM_ #-}
452mapM_ :: Monad m => (a -> m b) -> Stream m a -> m ()
453mapM_ m = runStream . mapM m
455------------------------------------------------------------------------------
457------------------------------------------------------------------------------
460toList :: Monad m => Stream m a -> m [a]
463-- Convert a direct stream to and from CPS encoded stream
464{-# INLINE_LATE toStreamK #-}
465toStreamK :: Monad m => Stream m a -> K.Stream m a
466toStreamK (Stream step state) = go state
468 go st = K.Stream $ \gst stp _ yld -> do
471 Yield x s -> yld x (go s)
474#ifndef DISABLE_FUSION
475{-# RULES "fromStreamK/toStreamK fusion"
476 forall s. toStreamK (fromStreamK s) = s #-}
477{-# RULES "toStreamK/fromStreamK fusion"
478 forall s. fromStreamK (toStreamK s) = s #-}
481------------------------------------------------------------------------------
482-- Transformation by Folding (Scans)
483------------------------------------------------------------------------------
485{-# INLINE_NORMAL postscanlM' #-}
486postscanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
487postscanlM' fstep begin (Stream step state) =
488 begin `seq` Stream step' (state, begin)
490 {-# INLINE_LATE step' #-}
491 step' gst (st, acc) = acc `seq` do
492 r <- step (rstState gst) st
496 y `seq` return (Yield y (s, y))
499{-# INLINE scanlM' #-}
500scanlM' :: Monad m => (b -> a -> m b) -> b -> Stream m a -> Stream m b
501scanlM' fstep begin s = begin `seq` (begin `cons` postscanlM' fstep begin s)
503-------------------------------------------------------------------------------
505-------------------------------------------------------------------------------
507{-# INLINE_NORMAL take #-}
508take :: Monad m => Int -> Stream m a -> Stream m a
509take n (Stream step state) = n `seq` Stream step' (state, 0)
511 {-# INLINE_LATE step' #-}
512 step' gst (st, i) | i < n = do
513 r <- step (rstState gst) st
515 Yield x s -> Yield x (s, i + 1)
517 step' _ (_, _) = return Stop
519{-# INLINE_NORMAL takeWhileM #-}
520takeWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
521takeWhileM f (Stream step state) = Stream step' state
523 {-# INLINE_LATE step' #-}
525 r <- step (rstState gst) st
529 return $ if b then Yield x s else Stop
532{-# INLINE takeWhile #-}
533takeWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
534takeWhile f = takeWhileM (return . f)
536{-# INLINE_NORMAL drop #-}
537drop :: Monad m => Int -> Stream m a -> Stream m a
538drop n (Stream step state) = Stream step' (state, n)
540 {-# INLINE_LATE step' #-}
541 step' gst (st, i) = do
542 r <- step (rstState gst) st
544 Yield _ s | i > 0 -> step' gst (s, i - 1)
545 Yield x s -> return $ Yield x (s, 0)
548data DropWhileState s a
553{-# INLINE_NORMAL dropWhileM #-}
554dropWhileM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
555dropWhileM f (Stream step state) = Stream step' (DropWhileDrop state)
557 {-# INLINE_LATE step' #-}
558 step' gst (DropWhileDrop st) = do
559 r <- step (rstState gst) st
564 then step' gst (DropWhileDrop s)
565 else step' gst (DropWhileYield x s)
568 step' gst (DropWhileNext st) = do
569 r <- step (rstState gst) st
571 Yield x s -> step' gst (DropWhileYield x s)
574 step' _ (DropWhileYield x st) = return $ Yield x (DropWhileNext st)
576{-# INLINE dropWhile #-}
577dropWhile :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
578dropWhile f = dropWhileM (return . f)
580{-# INLINE_NORMAL filterM #-}
581filterM :: Monad m => (a -> m Bool) -> Stream m a -> Stream m a
582filterM f (Stream step state) = Stream step' state
584 {-# INLINE_LATE step' #-}
586 r <- step (rstState gst) st
591 then return $ Yield x s
596filter :: Monad m => (a -> Bool) -> Stream m a -> Stream m a
597filter f = filterM (return . f)
599------------------------------------------------------------------------------
600-- Transformation by Mapping
601------------------------------------------------------------------------------
603-- | Map a monadic function over a 'Stream'
604{-# INLINE_NORMAL mapM #-}
605mapM :: Monad m => (a -> m b) -> Stream m a -> Stream m b
606mapM f (Stream step state) = Stream step' state
608 {-# INLINE_LATE step' #-}
610 r <- step (rstState gst) st
612 Yield x s -> f x >>= \a -> return $ Yield a s
616map :: Monad m => (a -> b) -> Stream m a -> Stream m b
617map f = mapM (return . f)
619------------------------------------------------------------------------------
620-- Transformation by Map and Filter
621------------------------------------------------------------------------------
623-- XXX Will this always fuse properly?
624{-# INLINE_NORMAL mapMaybe #-}
625mapMaybe :: Monad m => (a -> Maybe b) -> Stream m a -> Stream m b
626mapMaybe f = fmap fromJust . filter isJust . map f
628{-# INLINE_NORMAL mapMaybeM #-}
629mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Stream m a -> Stream m b
630mapMaybeM f = fmap fromJust . filter isJust . mapM f
632------------------------------------------------------------------------------
634------------------------------------------------------------------------------
636{-# INLINE_NORMAL zipWithM #-}
638 => (a -> b -> m c) -> Stream m a -> Stream m b -> Stream m c
639zipWithM f (Stream stepa ta) (Stream stepb tb) = Stream step (ta, tb, Nothing)
641 {-# INLINE_LATE step #-}
642 step gst (sa, sb, Nothing) = do
643 r <- stepa (rstState gst) sa
645 Yield x sa' -> step gst (sa', sb, Just x)
648 step gst (sa, sb, Just x) = do
649 r <- stepb (rstState gst) sb
653 return $ Yield z (sa, sb', Nothing)
656{-# RULES "zipWithM xs xs"
657 forall f xs. zipWithM f xs xs = mapM (\x -> f x x) xs #-}
659{-# INLINE zipWith #-}
660zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c
661zipWith f = zipWithM (\a b -> return (f a b))
663------------------------------------------------------------------------------
665------------------------------------------------------------------------------
667instance 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