2{-# LANGUAGE FlexibleContexts #-}
4#if __GLASGOW_HASKELL__ >= 800
5{-# OPTIONS_GHC -Wno-orphans #-}
8#include "Streams/inline.hs"
11-- Module : Streamly.Prelude
12-- Copyright : (c) 2017 Harendra Kumar
15-- Maintainer : harendra.kumar@gmail.com
16-- Stability : experimental
19-- This module is designed to be imported qualified:
22-- import qualified Streamly.Prelude as S
25-- Functions with the suffix @M@ are general functions that work on monadic
26-- arguments. The corresponding functions without the suffix @M@ work on pure
27-- arguments and can in general be derived from their monadic versions but are
28-- provided for convenience and for consistency with other pure APIs in the
31-- Functions having a 'MonadAsync' constraint work concurrently when used with
32-- appropriate stream type combinator. Please be careful to not use 'parallely'
33-- with infinite streams.
35-- Deconstruction and folds accept a 'SerialT' type instead of a polymorphic
36-- type to ensure that streams always have a concrete monomorphic type by
37-- default, reducing type errors. In case you want to use any other type of
38-- stream you can use one of the type combinators provided in the "Streamly"
39-- module to convert the stream type.
41module Streamly.Prelude
44 -- | All other stream construction and generation combinators described
45 -- later, and even more custom combinators can be expressed in terms of
46 -- these primitives. However, the special versions provided in this module
47 -- can be more efficient in some situations.
50 -- | Primitives to construct a stream from pure values or monadic actions.
61 -- | You can construct streams by appending or merging existing streams.
62 -- When constructing streams from streams, '<>' and 'mempty' are the
63 -- intuitive equivalents of 'K.cons' and 'K.nil', respectively. These
64 -- primitives can be very useful when constructing your own custom stream
65 -- combinators. Also see the variants of '<>' defined in the "Streamly"
66 -- module. Note that appending streams is inexpensive, it is much more
67 -- efficient than appending lists.
70 -- ** Unfold and Iterate
71 -- | Note that the generative steps of unfold and iterate are inherently
72 -- serial as the next step depends on the result of the previous step.
73 -- However, consumption of the result from the previous step can happen in
74 -- parallel with the generation by the next step.
80 -- ** Replicate and Repeat
81 -- | Generate a monadic stream from a seed value or function. Note that
82 -- these functions can generate a stream fully concurrently as, unlike
83 -- unfolds, there is no dependency between steps, therefore, an unbounded
84 -- number of steps can run concurrently. All of these can be expressed in
85 -- terms of 'K.cons' and 'K.nil' primitives.
91 -- | Convert an input structure, container or source into a stream. All of
92 -- these can be expressed in terms of primitives.
105 -- | All the folds can be implemented in terms of 'uncons', however the
106 -- specific implementations provided here are generally more efficient.
107 -- Folds are inherently serial as each step needs to use the result of
108 -- the previous step.
118 -- ** Specialized Folds
119 -- | These folds can be expressed in terms of the general fold routines but
120 -- the special versions here can be more efficient in many cases.
122 -- Filtering folds: extract parts of the stream
128 -- Conditional folds: may terminate early based on a condition
143 -- Full folds - need to go through all elements
151 -- | Convert or divert a stream into an output structure, container or
157 -- | One to one transformations, each element in the input stream is
158 -- transformed into a corresponding element in the output stream.
159 -- Therefore, the length of the stream and the ordering of elements in the
160 -- stream remains unchanged after the transformation.
163 -- | Scan is a transformation by continuously folding the result with the
164 -- next element of the stream. This is the generalized way to transform a
165 -- stream carrying state from previous transformation steps, other forms of
166 -- transformation like map can be expressed in terms of this.
172 -- | Map is a special form of scan where no state is carried from one step
180 -- * Filtering and Insertion
181 -- | Adding or removing elements from the stream thus changing the length
200 -- * Hybrid Operations
208 -- ** Scan and filter
227import Control.Monad.IO.Class (MonadIO(..))
228import Data.Maybe (isJust, fromJust)
230 hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
231 foldl, mapM, mapM_, sequence, all, any, sum, product, elem,
232 notElem, maximum, minimum, head, last, tail, length, null,
233 reverse, iterate, init, and, or, lookup, foldr1)
234import qualified Prelude
235import qualified System.IO as IO
237import Streamly.SVar (MonadAsync, defState, rstState)
238import Streamly.Streams.Combinators (maxYields)
239import Streamly.Streams.Prelude (fromStreamS, toStreamS)
240import Streamly.Streams.StreamD (fromStreamD, toStreamD)
241import Streamly.Streams.StreamK (IsStream(..))
242import Streamly.Streams.Serial (SerialT)
244import qualified Streamly.Streams.Prelude as P
245import qualified Streamly.Streams.StreamK as K
246import qualified Streamly.Streams.StreamD as D
247import qualified Streamly.Streams.Zip as Z
249#ifdef USE_STREAMK_ONLY
250import qualified Streamly.Streams.StreamK as S
251import qualified Streamly.Streams.Zip as S
253import qualified Streamly.Streams.StreamD as S
256import qualified Streamly.Streams.Serial as Serial
258------------------------------------------------------------------------------
260------------------------------------------------------------------------------
262-- | Decompose a stream into its head and tail. If the stream is empty, returns
263-- 'Nothing'. If the stream is non-empty, returns @Just (a, ma)@, where @a@ is
264-- the head of the stream and @ma@ its tail.
267uncons :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (a, t m a))
268uncons m = K.uncons (K.adapt m)
270------------------------------------------------------------------------------
271-- Generation by Unfolding
272------------------------------------------------------------------------------
274-- | Build a stream by unfolding a /pure/ step function starting from a seed.
275-- The step function returns the next element in the stream and the next seed
276-- value. When it is done it returns 'Nothing' and the stream ends. For
283-- else Just (b, b + 1)
284-- in toList $ unfoldr f 0
290-- unfoldr can be expressed in terms of 'yield' and '<>' as follows:
296-- Just (a, b) -> 'yield' a '<>' (unfoldr step b)
300{-# INLINE_EARLY unfoldr #-}
301unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a
302unfoldr step seed = fromStreamS (S.unfoldr step seed)
303{-# RULES "unfoldr fallback to StreamK" [1]
304 forall a b. S.toStreamK (S.unfoldr a b) = K.unfoldr a b #-}
306-- | Build a stream by unfolding a /monadic/ step function starting from a
307-- seed. The step function returns the next element in the stream and the next
308-- seed value. When it is done it returns 'Nothing' and the stream ends. For
314-- then return Nothing
315-- else print b >> return (Just (b, b + 1))
316-- in runStream $ unfoldrM f 0
324-- When run concurrently, the next unfold step can run concurrently with the
325-- processing of the output of the previous step. Note that more than one step
326-- cannot run concurrently as the next step depends on the output of the
330-- (asyncly $ S.unfoldrM (\\n -> liftIO (threadDelay 1000000) >> return (Just (n, n + 1))) 0)
331-- & S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
337{-# INLINE_EARLY unfoldrM #-}
338unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
341{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
342{-# INLINE_EARLY unfoldrMSerial #-}
343unfoldrMSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
344unfoldrMSerial step seed = fromStreamS (S.unfoldrM step seed)
346------------------------------------------------------------------------------
347-- Specialized Generation
348------------------------------------------------------------------------------
350-- Faster than yieldM because there is no bind.
352-- | Create a singleton stream from a pure value. Same as @a `cons` nil@ but
353-- slighly more efficient. Note that in monadic streams, 'yield' is the same
354-- as 'pure' or 'return', however, in Zip applicative streams it is not the
355-- same as 'pure' because in that case 'pure' is equivalent to 'repeat'
356-- instead. In all other stream types, 'yield' is the same as @yieldM . pure@
357-- but more efficient.
361yield :: IsStream t => a -> t m a
364-- | Create a singleton stream from a monadic action. Same as @m \`consM` nil@
365-- but more efficient.
368-- > toList $ yieldM getLine
375yieldM :: (Monad m, IsStream t) => m a -> t m a
378-- | Generate a stream by performing a monadic action @n@ times. Can be
379-- expressed as @stimes n (yieldM m)@.
383-- runStream $ serially $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
384-- runStream $ asyncly $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
390replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
393 go cnt = if cnt <= 0 then K.nil else m |: go (cnt - 1)
395-- | Generate a stream by repeatedly executing a monadic action forever. Can be
396-- expressed as @cycle1 . yieldM@.
399-- runStream $ serially $ S.take 10 $ S.repeatM $ (threadDelay 1000000 >> print 1)
400-- runStream $ asyncly $ S.take 10 $ S.repeatM $ (threadDelay 1000000 >> print 1)
403-- /Concurrent, infinite (do not use with 'parallely')/
406repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
408 where go m = m |: go m
410-- | Iterate a pure function from a seed value, streaming the results forever.
413iterate :: IsStream t => (a -> a) -> a -> t m a
414iterate step = fromStream . go
416 go s = K.cons s (go (step s))
418-- | Iterate a monadic function from a seed value, streaming the results
421-- When run concurrently, the next iteration can run concurrently with the
422-- processing of the previous iteration. Note that more than one iteration
423-- cannot run concurrently as the next iteration depends on the output of the
424-- previous iteration.
427-- runStream $ serially $ S.take 10 $ S.iterateM
428-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) 0
430-- runStream $ asyncly $ S.take 10 $ S.iterateM
431-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) 0
437iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> a -> t m a
440 go s = fromStream $ K.Stream $ \svr stp sng yld -> do
442 K.unStream (toStream (return s |: go next)) svr stp sng yld
444------------------------------------------------------------------------------
446------------------------------------------------------------------------------
448-- | Construct a stream from a list containing monadic actions. More efficient
449-- list specific implementation of 'fromFoldableM' especially for serial
450-- streams as it works well with fusion optimization.
453{-# INLINE_EARLY fromListM #-}
454fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a
455fromListM = fromStreamD . D.fromListM
456{-# RULES "fromListM fallback to StreamK" [1]
457 forall a. D.toStreamK (D.fromListM a) = fromFoldableM a #-}
459-- | Construct a stream from a 'Foldable' containing monadic actions. Same as
460-- @'Prelude.foldr' 'consM' 'K.nil'@.
463-- runStream $ serially $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
464-- runStream $ asyncly $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
467-- /Concurrent (do not use with 'parallely' on infinite containers)/
470{-# INLINE fromFoldableM #-}
471fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a
472fromFoldableM = Prelude.foldr consM K.nil
474-- | Same as 'fromFoldable'.
477{-# DEPRECATED each "Please use fromFoldable instead." #-}
479each :: (IsStream t, Foldable f) => f a -> t m a
482-- | Read lines from an IO Handle into a stream of Strings.
485fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
486fromHandle h = fromStream go
488 go = K.Stream $ \_ stp _ yld -> do
489 eof <- liftIO $ IO.hIsEOF h
493 str <- liftIO $ IO.hGetLine h
496------------------------------------------------------------------------------
497-- Elimination by Folding
498------------------------------------------------------------------------------
500-- | Lazy right fold with a monadic step function. For example, to fold a
501-- stream into a list:
504-- >> runIdentity $ foldrM (\\x xs -> return (x : xs)) [] (serially $ fromFoldable [1,2,3])
510foldrM :: Monad m => (a -> b -> m b) -> b -> SerialT m a -> m b
511foldrM step acc m = S.foldrM step acc $ toStreamS m
513-- | Lazy right associative fold. For example, to fold a stream into a list:
516-- >> runIdentity $ foldr (:) [] (serially $ fromFoldable [1,2,3])
522foldr :: Monad m => (a -> b -> b) -> b -> SerialT m a -> m b
523-- XXX somehow this definition does not perform well, need to investigate
524-- foldr step acc m = S.foldr step acc $ S.fromStreamK (toStream m)
525foldr f = foldrM (\a b -> return (f a b))
527-- | Right fold, for non-empty streams, using first element as the starting
528-- value. Returns 'Nothing' if the stream is empty.
532foldr1 :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a)
535-- | Strict left fold with an extraction function. Like the standard strict
536-- left fold, but applies a user supplied extraction function (the third
537-- argument) to the folded value at the end. This is designed to work with the
538-- @foldl@ library. The suffix @x@ is a mnemonic for extraction.
542foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
547{-# DEPRECATED foldl "Please use foldx instead." #-}
548foldl :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
551-- | Strict left associative fold.
555foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
558-- | Strict left fold, for non-empty streams, using first element as the
559-- starting value. Returns 'Nothing' if the stream is empty.
562{-# INLINE foldl1' #-}
563foldl1' :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a)
567 Nothing -> return Nothing
569 res <- foldl' step h t
572-- XXX replace the recursive "go" with explicit continuations.
573-- | Like 'foldx', but with a monadic step function.
576foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
581{-# DEPRECATED foldlM "Please use foldxM instead." #-}
582foldlM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
585-- | Like 'foldl'' but with a monadic step function.
588foldlM' :: Monad m => (b -> a -> m b) -> b -> SerialT m a -> m b
589foldlM' step begin m = S.foldlM' step begin $ toStreamS m
591------------------------------------------------------------------------------
593------------------------------------------------------------------------------
595-- | Determine whether the stream is empty.
599null :: Monad m => SerialT m a -> m Bool
602-- | Extract the first element of the stream, if any.
606head :: Monad m => SerialT m a -> m (Maybe a)
609-- | Extract all but the first element of the stream, if any.
613tail :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
614tail m = K.tail (K.adapt m)
616-- | Extract all but the last element of the stream, if any.
620init :: (IsStream t, Monad m) => SerialT m a -> m (Maybe (t m a))
621init m = K.init (K.adapt m)
623-- | Extract the last element of the stream, if any.
627last :: Monad m => SerialT m a -> m (Maybe a)
628last m = S.last $ toStreamS m
630-- | Determine whether an element is present in the stream.
634elem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
635elem e m = S.elem e (toStreamS m)
637-- | Determine whether an element is not present in the stream.
640{-# INLINE notElem #-}
641notElem :: (Monad m, Eq a) => a -> SerialT m a -> m Bool
642notElem e m = S.notElem e (toStreamS m)
644-- | Determine the length of the stream.
648length :: Monad m => SerialT m a -> m Int
649length = foldl' (\n _ -> n + 1) 0
651-- | Determine whether all elements of a stream satisfy a predicate.
655all :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
656all p m = S.all p (toStreamS m)
658-- | Determine whether any of the elements of a stream satisfy a predicate.
662any :: Monad m => (a -> Bool) -> SerialT m a -> m Bool
663any p m = S.any p (toStreamS m)
665-- | Determines if all elements of a boolean stream are True.
669and :: Monad m => SerialT m Bool -> m Bool
672-- | Determines wheter at least one element of a boolean stream is True.
676or :: Monad m => SerialT m Bool -> m Bool
679-- | Determine the sum of all elements of a stream of numbers
683sum :: (Monad m, Num a) => SerialT m a -> m a
686-- | Determine the product of all elements of a stream of numbers
689{-# INLINE product #-}
690product :: (Monad m, Num a) => SerialT m a -> m a
691product = foldl' (*) 1
693-- | Determine the minimum element in a stream.
696{-# INLINE minimum #-}
697minimum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
698minimum m = S.minimum (toStreamS m)
700-- | Determine the maximum element in a stream.
703{-# INLINE maximum #-}
704maximum :: (Monad m, Ord a) => SerialT m a -> m (Maybe a)
705maximum m = S.maximum (toStreamS m)
707-- | Looks the given key up, treating the given stream as an association list.
711lookup :: (Monad m, Eq a) => a -> SerialT m (a, b) -> m (Maybe b)
714-- | Returns the first element of the stream satisfying the given predicate,
719find :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe a)
722-- | Find all the indices where the element in the stream satisfies the given
726{-# INLINE findIndices #-}
727findIndices :: IsStream t => (a -> Bool) -> t m a -> t m Int
728findIndices = K.findIndices
730-- | Gives the index of the first stream element satisfying the given
734{-# INLINE findIndex #-}
735findIndex :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe Int)
736findIndex p = head . findIndices p
738-- | Find all the indices where the value of the element in the stream is equal
739-- to the given value.
742{-# INLINE elemIndices #-}
743elemIndices :: (IsStream t, Eq a) => a -> t m a -> t m Int
744elemIndices a = findIndices (==a)
746-- | Gives the first index of an element in the stream, which equals the given.
749{-# INLINE elemIndex #-}
750elemIndex :: (Monad m, Eq a) => a -> SerialT m a -> m (Maybe Int)
751elemIndex a = findIndex (==a)
753------------------------------------------------------------------------------
755------------------------------------------------------------------------------
757-- XXX this can utilize parallel mapping if we implement it as runStream . mapM
758-- | Apply a monadic action to each element of the stream and discard the
759-- output of the action.
763mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
764mapM_ f m = S.mapM_ f $ toStreamS m
766------------------------------------------------------------------------------
768------------------------------------------------------------------------------
770-- | Convert a stream into a list in the underlying monad.
774toList :: Monad m => SerialT m a -> m [a]
777-- | Write a stream of Strings to an IO Handle.
780toHandle :: MonadIO m => IO.Handle -> SerialT m String -> m ()
781toHandle h m = go (toStream m)
785 single a = liftIO (IO.hPutStrLn h a)
786 yieldk a r = liftIO (IO.hPutStrLn h a) >> go r
787 in K.unStream m1 defState stop single yieldk
789------------------------------------------------------------------------------
790-- Transformation by Folding (Scans)
791------------------------------------------------------------------------------
793-- | Strict left scan with an extraction function. Like 'scanl'', but applies a
794-- user supplied extraction function (the third argument) at each step. This is
795-- designed to work with the @foldl@ library. The suffix @x@ is a mnemonic for
800scanx :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
805{-# DEPRECATED scan "Please use scanx instead." #-}
806scan :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
809-- | Like 'scanl'' but with a monadic step function.
812{-# INLINE scanlM' #-}
813scanlM' :: (IsStream t, Monad m) => (b -> a -> m b) -> b -> t m a -> t m b
814scanlM' step begin m = fromStreamD $ D.scanlM' step begin $ toStreamD m
816-- | Strict left scan. Like 'foldl'', but returns the folded value at each
817-- step, generating a stream of all intermediate fold results. The first
818-- element of the stream is the user supplied initial value, and the last
819-- element of the stream is the same as the result of 'foldl''.
823scanl' :: (IsStream t, Monad m) => (b -> a -> b) -> b -> t m a -> t m b
824scanl' step z m = fromStreamS $ S.scanl' step z $ toStreamS m
826------------------------------------------------------------------------------
827-- Transformation by Filtering
828------------------------------------------------------------------------------
830-- | Include only those elements that pass a predicate.
834#if __GLASGOW_HASKELL__ != 802
835-- GHC 8.2.2 crashes with this code, when used with "stack"
836filter :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
837filter p m = fromStreamS $ S.filter p $ toStreamS m
839filter :: IsStream t => (a -> Bool) -> t m a -> t m a
843-- | Same as 'filter' but with a monadic predicate.
846{-# INLINE filterM #-}
847filterM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
848filterM p m = fromStreamD $ D.filterM p $ toStreamD m
850-- | Take first 'n' elements from the stream and discard the rest.
854take :: (IsStream t, Monad m) => Int -> t m a -> t m a
855take n m = fromStreamS $ S.take n $ toStreamS
856 (maxYields (Just (fromIntegral n)) m)
858-- | End the stream as soon as the predicate fails on an element.
861{-# INLINE takeWhile #-}
862takeWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
863takeWhile p m = fromStreamS $ S.takeWhile p $ toStreamS m
865-- | Same as 'takeWhile' but with a monadic predicate.
868{-# INLINE takeWhileM #-}
869takeWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
870takeWhileM p m = fromStreamD $ D.takeWhileM p $ toStreamD m
872-- | Discard first 'n' elements from the stream and take the rest.
876drop :: (IsStream t, Monad m) => Int -> t m a -> t m a
877drop n m = fromStreamS $ S.drop n $ toStreamS m
879-- | Drop elements in the stream as long as the predicate succeeds and then
880-- take the rest of the stream.
883{-# INLINE dropWhile #-}
884dropWhile :: (IsStream t, Monad m) => (a -> Bool) -> t m a -> t m a
885dropWhile p m = fromStreamS $ S.dropWhile p $ toStreamS m
887-- | Same as 'dropWhile' but with a monadic predicate.
890{-# INLINE dropWhileM #-}
891dropWhileM :: (IsStream t, Monad m) => (a -> m Bool) -> t m a -> t m a
892dropWhileM p m = fromStreamD $ D.dropWhileM p $ toStreamD m
894------------------------------------------------------------------------------
895-- Transformation by Mapping
896------------------------------------------------------------------------------
898-- | Replace each element of the stream with the result of a monadic action
899-- applied on the element.
902-- runStream $ S.replicateM 10 (return 1)
903-- & (serially . S.mapM (\\x -> threadDelay 1000000 >> print x))
905-- runStream $ S.replicateM 10 (return 1)
906-- & (asyncly . S.mapM (\\x -> threadDelay 1000000 >> print x))
909-- /Concurrent (do not use with 'parallely' on infinite streams)/
912{-# INLINE_EARLY mapM #-}
913mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
916{-# RULES "mapM serial" mapM = mapMSerial #-}
917{-# INLINE mapMSerial #-}
918mapMSerial :: Monad m => (a -> m b) -> SerialT m a -> SerialT m b
919mapMSerial = Serial.mapM
921-- | Reduce a stream of monadic actions to a stream of the output of those
925-- runStream $ S.replicateM 10 (return $ threadDelay 1000000 >> print 1)
926-- & (serially . S.sequence)
928-- runStream $ S.replicateM 10 (return $ threadDelay 1000000 >> print 1)
929-- & (asyncly . S.sequence)
932-- /Concurrent (do not use with 'parallely' on infinite streams)/
935{-# INLINE sequence #-}
936sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
939------------------------------------------------------------------------------
940-- Transformation by Map and Filter
941------------------------------------------------------------------------------
943-- | Map a 'Maybe' returning function to a stream, filter out the 'Nothing'
944-- elements, and return a stream of values extracted from 'Just'.
947{-# INLINE mapMaybe #-}
948mapMaybe :: (IsStream t, Monad m) => (a -> Maybe b) -> t m a -> t m b
949mapMaybe f m = fromStreamS $ S.mapMaybe f $ toStreamS m
951-- | Like 'mapMaybe' but maps a monadic function.
953-- /Concurrent (do not use with 'parallely' on infinite streams)/
956{-# INLINE_EARLY mapMaybeM #-}
957mapMaybeM :: (IsStream t, MonadAsync m, Functor (t m))
958 => (a -> m (Maybe b)) -> t m a -> t m b
959mapMaybeM f = fmap fromJust . filter isJust . K.mapM f
961{-# RULES "mapMaybeM serial" mapMaybeM = mapMaybeMSerial #-}
962{-# INLINE mapMaybeMSerial #-}
963mapMaybeMSerial :: Monad m => (a -> m (Maybe b)) -> SerialT m a -> SerialT m b
964mapMaybeMSerial f m = fromStreamD $ D.mapMaybeM f $ toStreamD m
966------------------------------------------------------------------------------
967-- Transformation by Reordering
968------------------------------------------------------------------------------
970-- XXX to scale this we need to use a slab allocated array backed
971-- representation for temporary storage.
973-- | Returns the elements of the stream in reverse order.
974-- The stream must be finite.
977reverse :: (IsStream t) => t m a -> t m a
978reverse m = fromStream $ go K.nil (toStream m)
980 go rev rest = K.Stream $ \st stp sng yld ->
981 let runIt x = K.unStream x (rstState st) stp sng yld
983 single a = runIt $ a `K.cons` rev
984 yieldk a r = runIt $ go (a `K.cons` rev) r
985 in K.unStream rest (rstState st) stop single yieldk
987------------------------------------------------------------------------------
988-- Transformation by Inserting
989------------------------------------------------------------------------------
991-- | Generate a stream by performing the monadic action inbetween all elements
992-- of the given stream.
995{-# INLINE intersperseM #-}
996intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
997intersperseM = K.intersperseM
999------------------------------------------------------------------------------
1001------------------------------------------------------------------------------
1003-- | Zip two streams serially using a monadic zipping function.
1006{-# INLINABLE zipWithM #-}
1007zipWithM :: (IsStream t, Monad m) => (a -> b -> m c) -> t m a -> t m b -> t m c
1008zipWithM f m1 m2 = fromStreamS $ S.zipWithM f (toStreamS m1) (toStreamS m2)
1010-- | Zip two streams serially using a pure zipping function.
1013{-# INLINABLE zipWith #-}
1014zipWith :: (IsStream t, Monad m) => (a -> b -> c) -> t m a -> t m b -> t m c
1015zipWith f m1 m2 = fromStreamS $ S.zipWith f (toStreamS m1) (toStreamS m2)
1017------------------------------------------------------------------------------
1019------------------------------------------------------------------------------
1021-- | Compare two streams for equality using a equality function.
1024{-# INLINABLE eqBy #-}
1025eqBy :: Monad m => (a -> b -> Bool) -> SerialT m a -> SerialT m b -> m Bool
1028-- | Compare two streams using a comparison function.
1031{-# INLINABLE cmpBy #-}
1034 => (a -> b -> Ordering) -> SerialT m a -> SerialT m b -> m Ordering
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