on 0839d4f help sign in
streamly/src/Streamly/Prelude.hs
1035 lines 32 kB history raw
1{-# LANGUAGE CPP #-}
2{-# LANGUAGE FlexibleContexts #-}
4#if __GLASGOW_HASKELL__ >= 800
5{-# OPTIONS_GHC -Wno-orphans #-}
6#endif
8#include "Streams/inline.hs"
10-- |
11-- Module : Streamly.Prelude
12-- Copyright : (c) 2017 Harendra Kumar
13--
14-- License : BSD3
15-- Maintainer : harendra.kumar@gmail.com
16-- Stability : experimental
17-- Portability : GHC
18--
19-- This module is designed to be imported qualified:
20--
21-- @
22-- import qualified Streamly.Prelude as S
23-- @
24--
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
29-- @base@ package.
30--
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.
34--
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
42 (
43 -- * Construction
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.
49 -- ** From Elements
50 -- | Primitives to construct a stream from pure values or monadic actions.
51 K.nil
52 , K.cons
53 , (K..:)
55 , consM
56 , (|:)
57 , yield
58 , yieldM
60 -- ** From Streams
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.
69 -- * Generation
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.
75 , unfoldr
76 , unfoldrM
77 , iterate
78 , iterateM
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.
86 , replicateM
87 , K.repeat
88 , repeatM
90 -- ** Generate From
91 -- | Convert an input structure, container or source into a stream. All of
92 -- these can be expressed in terms of primitives.
93 , P.fromList
94 , fromListM
95 , K.fromFoldable
96 , fromFoldableM
97 , fromHandle
99 -- * Deconstruction
100 , uncons
102 -- * Elimination
104 -- ** General Folds
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.
109 , foldr
110 , foldr1
111 , foldrM
112 , foldl'
113 , foldl1'
114 , foldlM'
115 , foldx
116 , foldxM
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
123 , head
124 , tail
125 , last
126 , init
128 -- Conditional folds: may terminate early based on a condition
129 , null
130 , elem
131 , elemIndex
132 , notElem
133 , lookup
134 , find
135 , findIndex
136 , all
137 , any
138 , and
139 , or
140 , eqBy
141 , cmpBy
143 -- Full folds - need to go through all elements
144 , length
145 , maximum
146 , minimum
147 , sum
148 , product
150 -- ** Fold To
151 -- | Convert or divert a stream into an output structure, container or
152 -- sink.
153 , toList
154 , toHandle
156 -- * Transformation
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.
162 -- ** Scanning
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.
167 , scanl'
168 , scanlM'
169 , scanx
171 -- ** Mapping
172 -- | Map is a special form of scan where no state is carried from one step
173 -- to the next.
174 , Serial.map
175 , mapM
177 -- ** Flattening
178 , sequence
180 -- * Filtering and Insertion
181 -- | Adding or removing elements from the stream thus changing the length
182 -- of the stream.
184 -- ** Filtering
185 , filter
186 , filterM
187 , take
188 , takeWhile
189 , takeWhileM
190 , drop
191 , dropWhile
192 , dropWhileM
194 -- ** Inserting
195 , intersperseM
197 -- * Reordering
198 , reverse
200 -- * Hybrid Operations
201 -- ** Map and Fold
202 , mapM_
204 -- ** Map and Filter
205 , mapMaybe
206 , mapMaybeM
208 -- ** Scan and filter
209 , findIndices
210 , elemIndices
212 -- * Zipping
213 , zipWith
214 , zipWithM
215 , Z.zipAsyncWith
216 , Z.zipAsyncWithM
218 -- * Deprecated
219 , K.once
220 , each
221 , scan
222 , foldl
223 , foldlM
224 )
225where
227import Control.Monad.IO.Class (MonadIO(..))
228import Data.Maybe (isJust, fromJust)
229import Prelude
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
252#else
253import qualified Streamly.Streams.StreamD as S
254#endif
256import qualified Streamly.Streams.Serial as Serial
258------------------------------------------------------------------------------
259-- Deconstruction
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.
265--
266-- @since 0.1.0
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
277-- example,
278--
279-- @
280-- let f b =
281-- if b > 3
282-- then Nothing
283-- else Just (b, b + 1)
284-- in toList $ unfoldr f 0
285-- @
286-- @
287-- [0,1,2,3]
288-- @
289--
290-- unfoldr can be expressed in terms of 'yield' and '<>' as follows:
291--
292-- @
293-- unfoldr step s =
294-- case step s of
295-- Nothing -> mempty
296-- Just (a, b) -> 'yield' a '<>' (unfoldr step b)
297-- @
298--
299-- @since 0.1.0
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
309-- example,
310--
311-- @
312-- let f b =
313-- if b > 3
314-- then return Nothing
315-- else print b >> return (Just (b, b + 1))
316-- in runStream $ unfoldrM f 0
317-- @
318-- @
319-- 0
320-- 1
321-- 2
322-- 3
323-- @
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
327-- previous step.
328--
329-- @
330-- (asyncly $ S.unfoldrM (\\n -> liftIO (threadDelay 1000000) >> return (Just (n, n + 1))) 0)
331-- & S.foldlM' (\\_ a -> threadDelay 1000000 >> print a) ()
332-- @
333--
334-- /Concurrent/
335--
336-- /Since: 0.1.0/
337{-# INLINE_EARLY unfoldrM #-}
338unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
339unfoldrM = K.unfoldrM
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.
351--
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.
358--
359-- @since 0.4.0
360{-# INLINE yield #-}
361yield :: IsStream t => a -> t m a
362yield = K.yield
364-- | Create a singleton stream from a monadic action. Same as @m \`consM` nil@
365-- but more efficient.
366--
367-- @
368-- > toList $ yieldM getLine
369-- hello
370-- ["hello"]
371-- @
372--
373-- @since 0.4.0
374{-# INLINE yieldM #-}
375yieldM :: (Monad m, IsStream t) => m a -> t m a
376yieldM = K.yieldM
378-- | Generate a stream by performing a monadic action @n@ times. Can be
379-- expressed as @stimes n (yieldM m)@.
380--
381--
382-- @
383-- runStream $ serially $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
384-- runStream $ asyncly $ S.replicateM 10 $ (threadDelay 1000000 >> print 1)
385-- @
386--
387-- /Concurrent/
388--
389-- @since 0.1.1
390replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
391replicateM n m = go n
392 where
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@.
397--
398-- @
399-- runStream $ serially $ S.take 10 $ S.repeatM $ (threadDelay 1000000 >> print 1)
400-- runStream $ asyncly $ S.take 10 $ S.repeatM $ (threadDelay 1000000 >> print 1)
401-- @
402--
403-- /Concurrent, infinite (do not use with 'parallely')/
404--
405-- @since 0.2.0
406repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
407repeatM = go
408 where go m = m |: go m
410-- | Iterate a pure function from a seed value, streaming the results forever.
411--
412-- @since 0.1.2
413iterate :: IsStream t => (a -> a) -> a -> t m a
414iterate step = fromStream . go
415 where
416 go s = K.cons s (go (step s))
418-- | Iterate a monadic function from a seed value, streaming the results
419-- forever.
420--
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.
425--
426-- @
427-- runStream $ serially $ S.take 10 $ S.iterateM
428-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) 0
429--
430-- runStream $ asyncly $ S.take 10 $ S.iterateM
431-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) 0
432-- @
433--
434-- /Concurrent/
435--
436-- @since 0.1.2
437iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> a -> t m a
438iterateM step = go
439 where
440 go s = fromStream $ K.Stream $ \svr stp sng yld -> do
441 next <- step s
442 K.unStream (toStream (return s |: go next)) svr stp sng yld
444------------------------------------------------------------------------------
445-- Conversions
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.
451--
452-- @since 0.4.0
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'@.
461--
462-- @
463-- runStream $ serially $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
464-- runStream $ asyncly $ S.fromFoldableM $ replicateM 10 (threadDelay 1000000 >> print 1)
465-- @
466--
467-- /Concurrent (do not use with 'parallely' on infinite containers)/
468--
469-- @since 0.3.0
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'.
475--
476-- @since 0.1.0
477{-# DEPRECATED each "Please use fromFoldable instead." #-}
478{-# INLINE each #-}
479each :: (IsStream t, Foldable f) => f a -> t m a
480each = K.fromFoldable
482-- | Read lines from an IO Handle into a stream of Strings.
483--
484-- @since 0.1.0
485fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
486fromHandle h = fromStream go
487 where
488 go = K.Stream $ \_ stp _ yld -> do
489 eof <- liftIO $ IO.hIsEOF h
490 if eof
491 then stp
492 else do
493 str <- liftIO $ IO.hGetLine h
494 yld str go
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:
502--
503-- @
504-- >> runIdentity $ foldrM (\\x xs -> return (x : xs)) [] (serially $ fromFoldable [1,2,3])
505-- [1,2,3]
506-- @
507--
508-- @since 0.2.0
509{-# INLINE foldrM #-}
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:
514--
515-- @
516-- >> runIdentity $ foldr (:) [] (serially $ fromFoldable [1,2,3])
517-- [1,2,3]
518-- @
519--
520-- @since 0.1.0
521{-# INLINE foldr #-}
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.
529--
530-- @since 0.5.0
531{-# INLINE foldr1 #-}
532foldr1 :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a)
533foldr1 = K.foldr1
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.
539--
540-- @since 0.2.0
541{-# INLINE foldx #-}
542foldx :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
543foldx = K.foldx
545-- |
546-- @since 0.1.0
547{-# DEPRECATED foldl "Please use foldx instead." #-}
548foldl :: Monad m => (x -> a -> x) -> x -> (x -> b) -> SerialT m a -> m b
549foldl = foldx
551-- | Strict left associative fold.
552--
553-- @since 0.2.0
554{-# INLINE foldl' #-}
555foldl' :: Monad m => (b -> a -> b) -> b -> SerialT m a -> m b
556foldl' = P.foldl'
558-- | Strict left fold, for non-empty streams, using first element as the
559-- starting value. Returns 'Nothing' if the stream is empty.
560--
561-- @since 0.5.0
562{-# INLINE foldl1' #-}
563foldl1' :: Monad m => (a -> a -> a) -> SerialT m a -> m (Maybe a)
564foldl1' step m = do
565 r <- uncons m
566 case r of
567 Nothing -> return Nothing
568 Just (h, t) -> do
569 res <- foldl' step h t
570 return $ Just res
572-- XXX replace the recursive "go" with explicit continuations.
573-- | Like 'foldx', but with a monadic step function.
574--
575-- @since 0.2.0
576foldxM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
577foldxM = K.foldxM
579-- |
580-- @since 0.1.0
581{-# DEPRECATED foldlM "Please use foldxM instead." #-}
582foldlM :: Monad m => (x -> a -> m x) -> m x -> (x -> m b) -> SerialT m a -> m b
583foldlM = foldxM
585-- | Like 'foldl'' but with a monadic step function.
586--
587-- @since 0.2.0
588foldlM' :: Monad m => (b -> a -> m b) -> b -> SerialT m a -> m b
589foldlM' step begin m = S.foldlM' step begin $ toStreamS m
591------------------------------------------------------------------------------
592-- Specialized folds
593------------------------------------------------------------------------------
595-- | Determine whether the stream is empty.
596--
597-- @since 0.1.1
598{-# INLINE null #-}
599null :: Monad m => SerialT m a -> m Bool
600null = K.null
602-- | Extract the first element of the stream, if any.
603--
604-- @since 0.1.0
605{-# INLINE head #-}
606head :: Monad m => SerialT m a -> m (Maybe a)
607head = K.head
609-- | Extract all but the first element of the stream, if any.
610--
611-- @since 0.1.1
612{-# INLINE tail #-}
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.
617--
618-- @since 0.5.0
619{-# INLINE init #-}
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.
624--
625-- @since 0.1.1
626{-# INLINE last #-}
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.
631--
632-- @since 0.1.0
633{-# INLINE elem #-}
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.
638--
639-- @since 0.1.0
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.
645--
646-- @since 0.1.0
647{-# INLINE length #-}
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.
652--
653-- @since 0.1.0
654{-# INLINE all #-}
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.
659--
660-- @since 0.1.0
661{-# INLINE any #-}
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.
666--
667-- @since 0.5.0
668{-# INLINE and #-}
669and :: Monad m => SerialT m Bool -> m Bool
670and = all (==True)
672-- | Determines wheter at least one element of a boolean stream is True.
673--
674-- @since 0.5.0
675{-# INLINE or #-}
676or :: Monad m => SerialT m Bool -> m Bool
677or = any (==True)
679-- | Determine the sum of all elements of a stream of numbers
680--
681-- @since 0.1.0
682{-# INLINE sum #-}
683sum :: (Monad m, Num a) => SerialT m a -> m a
684sum = foldl' (+) 0
686-- | Determine the product of all elements of a stream of numbers
687--
688-- @since 0.1.1
689{-# INLINE product #-}
690product :: (Monad m, Num a) => SerialT m a -> m a
691product = foldl' (*) 1
693-- | Determine the minimum element in a stream.
694--
695-- @since 0.1.0
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.
701--
702-- @since 0.1.0
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.
708--
709-- @since 0.5.0
710{-# INLINE lookup #-}
711lookup :: (Monad m, Eq a) => a -> SerialT m (a, b) -> m (Maybe b)
712lookup = K.lookup
714-- | Returns the first element of the stream satisfying the given predicate,
715-- if any.
716--
717-- @since 0.5.0
718{-# INLINE find #-}
719find :: Monad m => (a -> Bool) -> SerialT m a -> m (Maybe a)
720find = K.find
722-- | Find all the indices where the element in the stream satisfies the given
723-- predicate.
724--
725-- @since 0.5.0
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
731-- preficate.
732--
733-- @since 0.5.0
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.
740--
741-- @since 0.5.0
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.
747--
748-- @since 0.5.0
749{-# INLINE elemIndex #-}
750elemIndex :: (Monad m, Eq a) => a -> SerialT m a -> m (Maybe Int)
751elemIndex a = findIndex (==a)
753------------------------------------------------------------------------------
754-- Map and Fold
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.
760--
761-- @since 0.1.0
762{-# INLINE mapM_ #-}
763mapM_ :: Monad m => (a -> m b) -> SerialT m a -> m ()
764mapM_ f m = S.mapM_ f $ toStreamS m
766------------------------------------------------------------------------------
767-- Conversions
768------------------------------------------------------------------------------
770-- | Convert a stream into a list in the underlying monad.
771--
772-- @since 0.1.0
773{-# INLINE toList #-}
774toList :: Monad m => SerialT m a -> m [a]
775toList = P.toList
777-- | Write a stream of Strings to an IO Handle.
778--
779-- @since 0.1.0
780toHandle :: MonadIO m => IO.Handle -> SerialT m String -> m ()
781toHandle h m = go (toStream m)
782 where
783 go m1 =
784 let stop = return ()
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
796-- extraction.
797--
798-- @since 0.2.0
799{-# INLINE scanx #-}
800scanx :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
801scanx = K.scanx
803-- |
804-- @since 0.1.1
805{-# DEPRECATED scan "Please use scanx instead." #-}
806scan :: IsStream t => (x -> a -> x) -> x -> (x -> b) -> t m a -> t m b
807scan = scanx
809-- | Like 'scanl'' but with a monadic step function.
810--
811-- @since 0.4.0
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''.
820--
821-- @since 0.2.0
822{-# INLINE scanl' #-}
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.
831--
832-- @since 0.1.0
833{-# INLINE filter #-}
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
838#else
839filter :: IsStream t => (a -> Bool) -> t m a -> t m a
840filter = K.filter
841#endif
843-- | Same as 'filter' but with a monadic predicate.
844--
845-- @since 0.4.0
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.
851--
852-- @since 0.1.0
853{-# INLINE take #-}
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.
859--
860-- @since 0.1.0
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.
866--
867-- @since 0.4.0
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.
873--
874-- @since 0.1.0
875{-# INLINE drop #-}
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.
881--
882-- @since 0.1.0
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.
888--
889-- @since 0.4.0
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.
900--
901-- @
902-- runStream $ S.replicateM 10 (return 1)
903-- & (serially . S.mapM (\\x -> threadDelay 1000000 >> print x))
904--
905-- runStream $ S.replicateM 10 (return 1)
906-- & (asyncly . S.mapM (\\x -> threadDelay 1000000 >> print x))
907-- @
908--
909-- /Concurrent (do not use with 'parallely' on infinite streams)/
910--
911-- @since 0.1.0
912{-# INLINE_EARLY mapM #-}
913mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
914mapM = K.mapM
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
922-- actions.
923--
924-- @
925-- runStream $ S.replicateM 10 (return $ threadDelay 1000000 >> print 1)
926-- & (serially . S.sequence)
927--
928-- runStream $ S.replicateM 10 (return $ threadDelay 1000000 >> print 1)
929-- & (asyncly . S.sequence)
930-- @
931--
932-- /Concurrent (do not use with 'parallely' on infinite streams)/
933--
934-- @since 0.1.0
935{-# INLINE sequence #-}
936sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
937sequence = K.sequence
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'.
945--
946-- @since 0.3.0
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.
952--
953-- /Concurrent (do not use with 'parallely' on infinite streams)/
954--
955-- @since 0.3.0
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.
972--
973-- | Returns the elements of the stream in reverse order.
974-- The stream must be finite.
975--
976-- @since 0.1.1
977reverse :: (IsStream t) => t m a -> t m a
978reverse m = fromStream $ go K.nil (toStream m)
979 where
980 go rev rest = K.Stream $ \st stp sng yld ->
981 let runIt x = K.unStream x (rstState st) stp sng yld
982 stop = runIt rev
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.
993--
994-- @since 0.5.0
995{-# INLINE intersperseM #-}
996intersperseM :: (IsStream t, MonadAsync m) => m a -> t m a -> t m a
997intersperseM = K.intersperseM
999------------------------------------------------------------------------------
1000-- Zipping
1001------------------------------------------------------------------------------
1003-- | Zip two streams serially using a monadic zipping function.
1005-- @since 0.4.0
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.
1012-- @since 0.1.0
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------------------------------------------------------------------------------
1018-- Comparison
1019------------------------------------------------------------------------------
1021-- | Compare two streams for equality using a equality function.
1023-- @since 0.5.3
1024{-# INLINABLE eqBy #-}
1025eqBy :: Monad m => (a -> b -> Bool) -> SerialT m a -> SerialT m b -> m Bool
1026eqBy = P.eqBy
1028-- | Compare two streams using a comparison function.
1030-- @since 0.5.3
1031{-# INLINABLE cmpBy #-}
1032cmpBy
1033 :: Monad m
1034 => (a -> b -> Ordering) -> SerialT m a -> SerialT m b -> m Ordering
1035cmpBy = P.cmpBy