on 2ae9759 help sign in
658 lines 21 kB history raw
1{-# OPTIONS_GHC -Wno-orphans #-}
3-- |
4-- Module : Streamly.Internal.Data.Stream.IsStream.Generate
5-- Copyright : (c) 2017 Composewell Technologies
6-- License : BSD-3-Clause
7-- Maintainer : streamly@composewell.com
8-- Stability : experimental
9-- Portability : GHC
10--
11-- Most of the combinators in this module can be implemented as unfolds. Some
12-- of them however can only be expressed in terms StreamK e.g. cons/consM,
13-- fromFoldable, mfix. We can possibly remove those from this module which can
14-- be expressed as unfolds. Unless we want to use rewrite rules to rewrite them
15-- as StreamK when StreamK is used, avoiding conversion to StreamD. Will that
16-- help? Are there any other reasons to keep these and not use unfolds?
18module Streamly.Internal.Data.Stream.IsStream.Generate
19 (
20 -- * Primitives
21 IsStream.nil
22 , IsStream.nilM
23 , IsStream.cons
24 , (IsStream..:)
26 , consM
27 , (|:)
29 -- * From 'Unfold'
30 , unfold
31 , unfold0
33 -- * Unfolding
34 , unfoldr
35 , unfoldrM
37 -- * From Values
38 , fromPure
39 , fromEffect
40 , repeat
41 , repeatM
42 , replicate
43 , replicateM
45 -- * Enumeration
46 , Enumerable (..)
47 , enumerate
48 , enumerateTo
50 -- * Time Enumeration
51 , times
52 , absTimes
53 , absTimesWith
54 , relTimes
55 , relTimesWith
56 , durations
57 , ticks
58 , timeout
60 -- * From Generators
61 , fromIndices
62 , fromIndicesM
63 -- , generate
64 -- , generateM
66 -- * Iteration
67 , iterate
68 , iterateM
70 -- * Cyclic Elements
71 , mfix
73 -- * From Containers
74 , IsStream.fromList
75 , fromListM
76 , fromFoldable
77 , fromFoldableM
78 , fromCallback
79 , fromPrimIORef
81 -- * Deprecated
82 , yield
83 , yieldM
84 , fromHandle
85 , currentTime
86 )
87where
89#include "inline.hs"
91import Control.Monad.IO.Class (MonadIO(..))
92import Data.Void (Void)
93import Streamly.Internal.Control.Concurrent (MonadAsync)
94import Streamly.Internal.Data.Unfold.Type (Unfold)
95import Streamly.Internal.Data.SVar (Rate (..))
96import Streamly.Internal.Data.Stream.IsStream.Enumeration
97 (Enumerable(..), enumerate, enumerateTo)
98import Streamly.Internal.Data.Stream.IsStream.Common
99 ( absTimesWith, concatM, relTimesWith, timesWith, fromPure, fromEffect
100 , yield, yieldM, repeatM)
101import Streamly.Internal.Data.Stream.IsStream.Type
102 (IsStream (..), fromSerial, consM, fromStreamD)
103import Streamly.Internal.Data.Stream.Serial (SerialT)
104import Streamly.Internal.Data.Stream.WSerial (WSerialT)
105import Streamly.Internal.Data.Stream.Zip (ZipSerialM)
106import Streamly.Internal.Data.Time.Units (AbsTime , RelTime64, addToAbsTime64)
107import Streamly.Internal.Data.Unboxed (Unboxed)
109import qualified Streamly.Internal.Data.IORef.Unboxed as Unboxed
110import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
111import qualified Streamly.Internal.Data.Stream.Parallel as Par
112import qualified Streamly.Internal.Data.Stream.Serial as Serial
113import qualified Streamly.Internal.Data.Stream.StreamD.Generate as D
114import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
115import qualified Streamly.Internal.Data.Stream.Type as Stream
116import qualified System.IO as IO
118import Prelude hiding (iterate, replicate, repeat)
120-- $setup
121-- >>> :m
122-- >>> import Data.Function ((&))
123-- >>> import Prelude hiding (iterate, replicate, repeat)
124-- >>> import qualified Streamly.Prelude as Stream
125-- >>> import qualified Streamly.Internal.Data.Stream.IsStream as Stream
126-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
127-- >>> import Control.Concurrent (threadDelay)
128-- >>> import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
129--
130-- >>> hSetBuffering stdout LineBuffering
132------------------------------------------------------------------------------
133-- From Unfold
134------------------------------------------------------------------------------
136-- | Convert an 'Unfold' into a stream by supplying it an input seed.
137--
138-- >>> Stream.drain $ Stream.unfold (Unfold.replicateM 3) (putStrLn "hello")
139-- hello
140-- hello
141-- hello
142--
143-- /Since: 0.7.0/
144{-# INLINE unfold #-}
145unfold :: (IsStream t, Monad m) => Unfold m a b -> a -> t m b
146unfold unf x = fromStreamD $ D.unfold unf x
148-- | Convert an 'Unfold' with a closed input end into a stream.
149--
150-- /Pre-release/
151{-# INLINE unfold0 #-}
152unfold0 :: (IsStream t, Monad m) => Unfold m Void b -> t m b
153unfold0 unf = unfold unf (error "unfold0: unexpected void evaluation")
155------------------------------------------------------------------------------
156-- Generation by Unfolding
157------------------------------------------------------------------------------
159-- |
160-- >>> :{
161-- unfoldr step s =
162-- case step s of
163-- Nothing -> Stream.nil
164-- Just (a, b) -> a `Stream.cons` unfoldr step b
165-- :}
166--
167-- Build a stream by unfolding a /pure/ step function @step@ starting from a
168-- seed @s@. The step function returns the next element in the stream and the
169-- next seed value. When it is done it returns 'Nothing' and the stream ends.
170-- For example,
171--
172-- >>> :{
173-- let f b =
174-- if b > 2
175-- then Nothing
176-- else Just (b, b + 1)
177-- in Stream.toList $ Stream.unfoldr f 0
178-- :}
179-- [0,1,2]
180--
181-- @since 0.1.0
182{-# INLINE_EARLY unfoldr #-}
183unfoldr :: (Monad m, IsStream t) => (b -> Maybe (a, b)) -> b -> t m a
184unfoldr step seed = fromStreamD (D.unfoldr step seed)
185{-# RULES "unfoldr fallback to StreamK" [1]
186 forall a b. D.toStreamK (D.unfoldr a b) = K.unfoldr a b #-}
188-- | Build a stream by unfolding a /monadic/ step function starting from a
189-- seed. The step function returns the next element in the stream and the next
190-- seed value. When it is done it returns 'Nothing' and the stream ends. For
191-- example,
192--
193-- >>> :{
194-- let f b =
195-- if b > 2
196-- then return Nothing
197-- else return (Just (b, b + 1))
198-- in Stream.toList $ Stream.unfoldrM f 0
199-- :}
200-- [0,1,2]
201--
202-- When run concurrently, the next unfold step can run concurrently with the
203-- processing of the output of the previous step. Note that more than one step
204-- cannot run concurrently as the next step depends on the output of the
205-- previous step.
206--
207-- >>> :{
208-- let f b =
209-- if b > 2
210-- then return Nothing
211-- else threadDelay 1000000 >> return (Just (b, b + 1))
212-- in Stream.toList $ Stream.delay 1 $ Stream.fromAsync $ Stream.unfoldrM f 0
213-- :}
214-- [0,1,2]
215--
216-- /Concurrent/
217--
218-- /Since: 0.1.0/
219{-# INLINE_EARLY unfoldrM #-}
220unfoldrM :: forall t m b a. (IsStream t, MonadAsync m) =>
221 (b -> m (Maybe (a, b))) -> b -> t m a
222unfoldrM step = fromStream . K.unfoldrMWith (IsStream.toConsK (consM @t)) step
224{-# RULES "unfoldrM serial" unfoldrM = unfoldrMSerial #-}
225{-# INLINE_EARLY unfoldrMSerial #-}
226unfoldrMSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> SerialT m a
227unfoldrMSerial = Serial.unfoldrM
229{-# RULES "unfoldrM wSerial" unfoldrM = unfoldrMWSerial #-}
230{-# INLINE_EARLY unfoldrMWSerial #-}
231unfoldrMWSerial :: MonadAsync m => (b -> m (Maybe (a, b))) -> b -> WSerialT m a
232unfoldrMWSerial f = fromSerial . Serial.unfoldrM f
234{-# RULES "unfoldrM zipSerial" unfoldrM = unfoldrMZipSerial #-}
235{-# INLINE_EARLY unfoldrMZipSerial #-}
236unfoldrMZipSerial :: MonadAsync m =>
237 (b -> m (Maybe (a, b))) -> b -> ZipSerialM m a
238unfoldrMZipSerial f = fromSerial . Serial.unfoldrM f
240------------------------------------------------------------------------------
241-- From Values
242------------------------------------------------------------------------------
244-- |
245-- Generate an infinite stream by repeating a pure value.
246--
247-- @since 0.4.0
248{-# INLINE_NORMAL repeat #-}
249repeat :: (IsStream t, Monad m) => a -> t m a
250repeat = fromStreamD . D.repeat
252-- |
253-- >>> replicate n = Stream.take n . Stream.repeat
254--
255-- Generate a stream of length @n@ by repeating a value @n@ times.
256--
257-- @since 0.6.0
258{-# INLINE_NORMAL replicate #-}
259replicate :: (IsStream t, Monad m) => Int -> a -> t m a
260replicate n = fromStreamD . D.replicate n
262-- |
263-- >>> replicateM n = Stream.take n . Stream.repeatM
264--
265-- Generate a stream by performing a monadic action @n@ times. Same as:
266--
267-- >>> pr n = threadDelay 1000000 >> print n
268--
269-- This runs serially and takes 3 seconds:
270--
271-- >>> Stream.drain $ Stream.fromSerial $ Stream.replicateM 3 $ pr 1
272-- 1
273-- 1
274-- 1
275--
276-- This runs concurrently and takes just 1 second:
277--
278-- >>> Stream.drain $ Stream.fromAsync $ Stream.replicateM 3 $ pr 1
279-- 1
280-- 1
281-- 1
282--
283-- /Concurrent/
284--
285-- @since 0.1.1
286{-# INLINE_EARLY replicateM #-}
287replicateM :: forall t m a. (IsStream t, MonadAsync m) => Int -> m a -> t m a
288replicateM count =
289 fromStream . K.replicateMWith (IsStream.toConsK (consM @t)) count
291{-# RULES "replicateM serial" replicateM = replicateMSerial #-}
292{-# INLINE replicateMSerial #-}
293replicateMSerial :: MonadAsync m => Int -> m a -> SerialT m a
294replicateMSerial n = fromStreamD . D.replicateM n
296------------------------------------------------------------------------------
297-- Time Enumeration
298------------------------------------------------------------------------------
300-- | @times@ returns a stream of time value tuples with clock of 10 ms
301-- granularity. The first component of the tuple is an absolute time reference
302-- (epoch) denoting the start of the stream and the second component is a time
303-- relative to the reference.
304--
305-- >>> Stream.mapM_ (\x -> print x >> threadDelay 1000000) $ Stream.take 3 $ Stream.times
306-- (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
307-- (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
308-- (AbsTime (TimeSpec {sec = ..., nsec = ...}),RelTime64 (NanoSecond64 ...))
309--
310-- Note: This API is not safe on 32-bit machines.
311--
312-- /Pre-release/
313--
314{-# INLINE times #-}
315times :: (IsStream t, MonadAsync m) => t m (AbsTime, RelTime64)
316times = timesWith 0.01
318-- | @absTimes@ returns a stream of absolute timestamps using a clock of 10 ms
319-- granularity.
320--
321-- >>> Stream.mapM_ print $ Stream.delayPre 1 $ Stream.take 3 $ Stream.absTimes
322-- AbsTime (TimeSpec {sec = ..., nsec = ...})
323-- AbsTime (TimeSpec {sec = ..., nsec = ...})
324-- AbsTime (TimeSpec {sec = ..., nsec = ...})
325--
326-- Note: This API is not safe on 32-bit machines.
327--
328-- /Pre-release/
329--
330{-# INLINE absTimes #-}
331absTimes :: (IsStream t, MonadAsync m, Functor (t m)) => t m AbsTime
332absTimes = fmap (uncurry addToAbsTime64) times
334{-# DEPRECATED currentTime "Please use absTimes instead" #-}
335{-# INLINE currentTime #-}
336currentTime :: (IsStream t, MonadAsync m, Functor (t m))
337 => Double -> t m AbsTime
338currentTime = absTimesWith
340-- | @relTimes@ returns a stream of relative time values starting from 0,
341-- using a clock of granularity 10 ms.
342--
343-- >>> Stream.mapM_ print $ Stream.delayPre 1 $ Stream.take 3 $ Stream.relTimes
344-- RelTime64 (NanoSecond64 ...)
345-- RelTime64 (NanoSecond64 ...)
346-- RelTime64 (NanoSecond64 ...)
347--
348-- Note: This API is not safe on 32-bit machines.
349--
350-- /Pre-release/
351--
352{-# INLINE relTimes #-}
353relTimes :: (IsStream t, MonadAsync m, Functor (t m)) => t m RelTime64
354relTimes = fmap snd times
356-- | @durations g@ returns a stream of relative time values measuring the time
357-- elapsed since the immediate predecessor element of the stream was generated.
358-- The first element of the stream is always 0. @durations@ uses a clock of
359-- granularity @g@ specified in seconds. A low granularity clock is more
360-- expensive in terms of CPU usage. The minimum granularity is 1 millisecond.
361-- Durations lower than 1 ms will be 0.
362--
363-- Note: This API is not safe on 32-bit machines.
364--
365-- /Unimplemented/
366--
367{-# INLINE durations #-}
368durations :: -- (IsStream t, MonadAsync m) =>
369 Double -> t m RelTime64
370durations = undefined
372-- | Generate ticks at the specified rate. The rate is adaptive, the tick
373-- generation speed can be increased or decreased at different times to achieve
374-- the specified rate. The specific behavior for different styles of 'Rate'
375-- specifications is documented under 'Rate'. The effective maximum rate
376-- achieved by a stream is governed by the processor speed.
377--
378-- /Unimplemented/
379--
380{-# INLINE ticks #-}
381ticks :: -- (IsStream t, MonadAsync m) =>
382 Rate -> t m ()
383ticks = undefined
385-- | Generate a singleton event at or after the specified absolute time. Note
386-- that this is different from a threadDelay, a threadDelay starts from the
387-- time when the action is evaluated, whereas if we use AbsTime based timeout
388-- it will immediately expire if the action is evaluated too late.
389--
390-- /Unimplemented/
391--
392{-# INLINE timeout #-}
393timeout :: -- (IsStream t, MonadAsync m) =>
394 AbsTime -> t m ()
395timeout = undefined
397------------------------------------------------------------------------------
398-- From Generator functions
399------------------------------------------------------------------------------
401-- XXX we can remove it and recommend the definition in terms of enumerate and
402-- map. Check performance equivalence.
403--
404-- |
405-- >>> fromIndices f = fmap f $ Stream.enumerateFrom 0
406-- >>> fromIndices f = let g i = f i `Stream.cons` g (i + 1) in g 0
407--
408-- Generate an infinite stream, whose values are the output of a function @f@
409-- applied on the corresponding index. Index starts at 0.
410--
411-- >>> Stream.toList $ Stream.take 5 $ Stream.fromIndices id
412-- [0,1,2,3,4]
413--
414-- @since 0.6.0
415{-# INLINE fromIndices #-}
416fromIndices :: (IsStream t, Monad m) => (Int -> a) -> t m a
417fromIndices = fromStreamD . D.fromIndices
419--
420-- |
421-- >>> fromIndicesM f = Stream.mapM f $ Stream.enumerateFrom 0
422-- >>> fromIndicesM f = let g i = f i `Stream.consM` g (i + 1) in g 0
423--
424-- Generate an infinite stream, whose values are the output of a monadic
425-- function @f@ applied on the corresponding index. Index starts at 0.
426--
427-- /Concurrent/
428--
429-- @since 0.6.0
430{-# INLINE_EARLY fromIndicesM #-}
431fromIndicesM :: forall t m a. (IsStream t, MonadAsync m) =>
432 (Int -> m a) -> t m a
433fromIndicesM = fromStream . K.fromIndicesMWith (IsStream.toConsK (consM @t))
435{-# RULES "fromIndicesM serial" fromIndicesM = fromIndicesMSerial #-}
436{-# INLINE fromIndicesMSerial #-}
437fromIndicesMSerial :: MonadAsync m => (Int -> m a) -> SerialT m a
438fromIndicesMSerial = fromStreamD . D.fromIndicesM
440------------------------------------------------------------------------------
441-- Iterating functions
442------------------------------------------------------------------------------
444-- |
445-- >>> iterate f x = x `Stream.cons` iterate f x
446--
447-- Generate an infinite stream with @x@ as the first element and each
448-- successive element derived by applying the function @f@ on the previous
449-- element.
450--
451-- >>> Stream.toList $ Stream.take 5 $ Stream.iterate (+1) 1
452-- [1,2,3,4,5]
453--
454-- @since 0.1.2
455{-# INLINE_NORMAL iterate #-}
456iterate :: (IsStream t, Monad m) => (a -> a) -> a -> t m a
457iterate step = fromStreamD . D.iterate step
459-- |
460-- >>> iterateM f m = m >>= \a -> return a `Stream.consM` iterateM f (f a)
461--
462-- Generate an infinite stream with the first element generated by the action
463-- @m@ and each successive element derived by applying the monadic function
464-- @f@ on the previous element.
465--
466-- >>> pr n = threadDelay 1000000 >> print n
467-- >>> :{
468-- Stream.iterateM (\x -> pr x >> return (x + 1)) (return 0)
469-- & Stream.take 3
470-- & Stream.fromSerial
471-- & Stream.toList
472-- :}
473-- 0
474-- 1
475-- [0,1,2]
476--
477-- When run concurrently, the next iteration can run concurrently with the
478-- processing of the previous iteration. Note that more than one iteration
479-- cannot run concurrently as the next iteration depends on the output of the
480-- previous iteration.
481--
482-- >>> :{
483-- Stream.iterateM (\x -> pr x >> return (x + 1)) (return 0)
484-- & Stream.delay 1
485-- & Stream.take 3
486-- & Stream.fromAsync
487-- & Stream.toList
488-- :}
489-- 0
490-- 1
491-- ...
492--
493-- /Concurrent/
494--
495-- /Since: 0.1.2/
496--
497-- /Since: 0.7.0 (signature change)/
498{-# INLINE_EARLY iterateM #-}
499iterateM :: forall t m a. (IsStream t, MonadAsync m) =>
500 (a -> m a) -> m a -> t m a
501iterateM f = fromStream . K.iterateMWith (IsStream.toConsK (consM @t)) f
503{-# RULES "iterateM serial" iterateM = iterateMSerial #-}
504{-# INLINE iterateMSerial #-}
505iterateMSerial :: MonadAsync m => (a -> m a) -> m a -> SerialT m a
506iterateMSerial step = fromStreamD . D.iterateM step
508-- | We can define cyclic structures using @let@:
509--
510-- >>> let (a, b) = ([1, b], head a) in (a, b)
511-- ([1,1],1)
512--
513-- The function @fix@ defined as:
514--
515-- >>> fix f = let x = f x in x
516--
517-- ensures that the argument of a function and its output refer to the same
518-- lazy value @x@ i.e. the same location in memory. Thus @x@ can be defined
519-- in terms of itself, creating structures with cyclic references.
520--
521-- >>> f ~(a, b) = ([1, b], head a)
522-- >>> fix f
523-- ([1,1],1)
524--
525-- 'Control.Monad.mfix' is essentially the same as @fix@ but for monadic
526-- values.
527--
528-- Using 'mfix' for streams we can construct a stream in which each element of
529-- the stream is defined in a cyclic fashion. The argument of the function
530-- being fixed represents the current element of the stream which is being
531-- returned by the stream monad. Thus, we can use the argument to construct
532-- itself.
533--
534-- In the following example, the argument @action@ of the function @f@
535-- represents the tuple @(x,y)@ returned by it in a given iteration. We define
536-- the first element of the tuple in terms of the second.
537--
538-- >>> import Streamly.Internal.Data.Stream.IsStream as Stream
539-- >>> import System.IO.Unsafe (unsafeInterleaveIO)
540--
541-- >>> :{
542-- main = Stream.mapM_ print $ Stream.mfix f
543-- where
544-- f action = do
545-- let incr n act = fmap ((+n) . snd) $ unsafeInterleaveIO act
546-- x <- Stream.fromListM [incr 1 action, incr 2 action]
547-- y <- Stream.fromList [4,5]
548-- return (x, y)
549-- :}
550--
551-- Note: you cannot achieve this by just changing the order of the monad
552-- statements because that would change the order in which the stream elements
553-- are generated.
554--
555-- Note that the function @f@ must be lazy in its argument, that's why we use
556-- 'unsafeInterleaveIO' on @action@ because IO monad is strict.
557--
558-- /Pre-release/
559{-# INLINE mfix #-}
560mfix :: (IsStream t, Monad m) => (m a -> t m a) -> t m a
561mfix f = fromStream $ K.mfix (toStream . f)
563------------------------------------------------------------------------------
564-- Conversions
565------------------------------------------------------------------------------
567-- |
568-- >>> fromFoldable = Prelude.foldr Stream.cons Stream.nil
569--
570-- Construct a stream from a 'Foldable' containing pure values:
571--
572-- @since 0.2.0
573{-# INLINE fromFoldable #-}
574fromFoldable :: (IsStream t, Foldable f) => f a -> t m a
575fromFoldable = fromStream . K.fromFoldable
577-- |
578-- >>> fromFoldableM = Prelude.foldr Stream.consM Stream.nil
579--
580-- Construct a stream from a 'Foldable' containing monadic actions.
581--
582-- >>> pr n = threadDelay 1000000 >> print n
583-- >>> Stream.drain $ Stream.fromSerial $ Stream.fromFoldableM $ map pr [1,2,3]
584-- 1
585-- 2
586-- 3
587--
588-- >>> Stream.drain $ Stream.fromAsync $ Stream.fromFoldableM $ map pr [1,2,3]
589-- ...
590-- ...
591-- ...
592--
593-- /Concurrent (do not use with 'fromParallel' on infinite containers)/
594--
595-- @since 0.3.0
596{-# INLINE fromFoldableM #-}
597fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a
598fromFoldableM = Prelude.foldr consM IsStream.nil
600-- |
601-- >>> fromListM = Stream.fromFoldableM
602-- >>> fromListM = Stream.sequence . Stream.fromList
603-- >>> fromListM = Stream.mapM id . Stream.fromList
604-- >>> fromListM = Prelude.foldr Stream.consM Stream.nil
605--
606-- Construct a stream from a list of monadic actions. This is more efficient
607-- than 'fromFoldableM' for serial streams.
608--
609-- @since 0.4.0
610{-# INLINE_EARLY fromListM #-}
611fromListM :: (MonadAsync m, IsStream t) => [m a] -> t m a
612fromListM = fromFoldableM
613{-# RULES "fromListM fallback to StreamK" [1]
614 forall a. D.toStreamK (D.fromListM a) = K.fromFoldableM a #-}
616{-# RULES "fromListM serial" fromListM = fromListMSerial #-}
617{-# INLINE_EARLY fromListMSerial #-}
618fromListMSerial :: MonadAsync m => [m a] -> SerialT m a
619fromListMSerial = fromStreamD . D.fromListM
621-- | Read lines from an IO Handle into a stream of Strings.
622--
623-- @since 0.1.0
624{-# DEPRECATED fromHandle
625 "Please use Streamly.FileSystem.Handle module (see the changelog)" #-}
626fromHandle :: (IsStream t, MonadIO m) => IO.Handle -> t m String
627fromHandle h = go
628 where
629 go = IsStream.mkStream $ \_ yld _ stp -> do
630 eof <- liftIO $ IO.hIsEOF h
631 if eof
632 then stp
633 else do
634 str <- liftIO $ IO.hGetLine h
635 yld str go
637-- XXX This should perhaps be moved to Parallel
638--
639-- | Takes a callback setter function and provides it with a callback. The
640-- callback when invoked adds a value at the tail of the stream. Returns a
641-- stream of values generated by the callback.
642--
643-- /Pre-release/
644--
645{-# INLINE fromCallback #-}
646fromCallback :: MonadAsync m => ((a -> m ()) -> m ()) -> SerialT m a
647fromCallback setCallback = concatM $ do
648 (callback, stream) <- Par.newCallbackStream
649 setCallback callback
650 return $ Stream.fromStreamK stream
652-- | Construct a stream by reading an 'Unboxed' 'IORef' repeatedly.
653--
654-- /Pre-release/
655--
656{-# INLINE fromPrimIORef #-}
657fromPrimIORef :: (IsStream t, MonadIO m, Unboxed a) => Unboxed.IORef a -> t m a
658fromPrimIORef = fromStreamD . Unboxed.toStreamD