on master help sign in
update documentation

- detailed doc for unfoldr/unfoldrM - notes and cautions on concurrency - concurrent API annotations

commit092ecb95f4e0540216323491e5a84f2ba9d1c84d authorHarendra Kumar <harendra.kumar@gmail.com> dateFri 25 May 2018, 09:01 (8 years ago) parent2b62821
3 files changed+73−7
src/Streamly/Prelude.hs+53−7 src/Streamly/Streams.hs+4 src/Streamly/Tutorial.hs+16
src/Streamly/Prelude.hs+53−7
@@ -26,8 +26,9 @@
2626-- provided for convenience and for consistency with other pure APIs in the
2727-- @base@ package.
2828--
29−-- Functions having a 'MonadAsync' constraint work concurrently when used
30−-- with appropriate stream type combinator.
29+-- Functions having a 'MonadAsync' constraint work concurrently when used with
30+-- appropriate stream type combinator. Please be careful to not use 'parallely'
31+-- with infinite streams.
3132--
3233-- Deconstruction and folds accept a 'SerialT' type instead of a polymorphic
3334-- type to ensure that streams always have a concrete monomorphic type by
@@ -45,7 +46,7 @@ module Streamly.Prelude
4546 , cons
4647 , (.:)
4748
48− -- * General Unfold
49+ -- * Generation by Unfolding
4950 , unfoldr
5051 , unfoldrM
5152
@@ -63,7 +64,7 @@ module Streamly.Prelude
6364 -- * Deconstruction
6465 , uncons
6566
66− -- * Folding
67+ -- * Elimination by Folding
6768 -- ** General Folds
6869 , foldr
6970 , foldrM
@@ -146,7 +147,21 @@ import Streamly.Streams
146147-- Construction
147148------------------------------------------------------------------------------
148149
149−-- | Build a Stream by unfolding pure steps starting from a seed.
150+-- | Build a stream by unfolding a /pure/ step function starting from a seed.
151+-- The step function returns the next element in the stream and the next seed
152+-- value. When it is done it returns 'Nothing' and the stream ends. For
153+-- example,
154+--
155+-- @
156+-- let f b =
157+-- if b > 3
158+-- then Nothing
159+-- else Just (b, b + 1)
160+-- in toList $ unfoldr f 0
161+-- @
162+-- @
163+-- [0,1,2,3]
164+-- @
150165--
151166-- @since 0.1.0
152167{-# INLINE unfoldr #-}
@@ -158,9 +173,28 @@ unfoldr step = fromStream . go
158173 Nothing -> stp
159174 Just (a, b) -> yld a (go b)
160175
161−-- | Build a Stream by unfolding monadic steps starting from a seed.
176+-- | Build a stream by unfolding a /monadic/ step function starting from a
177+-- seed. The step function returns the next element in the stream and the next
178+-- seed value. When it is done it returns 'Nothing' and the stream ends. For
179+-- example,
162180--
163−-- @since 0.1.0
181+-- @
182+-- let f b =
183+-- if b > 3
184+-- then return Nothing
185+-- else print b >> return (Just (b, b + 1))
186+-- in runStream $ unfoldrM f 0
187+-- @
188+-- @
189+-- 0
190+-- 1
191+-- 2
192+-- 3
193+-- @
194+--
195+-- /Concurrent/
196+--
197+-- /Since: 0.1.0/
164198{-# INLINE unfoldrM #-}
165199unfoldrM :: (IsStream t, MonadAsync m) => (b -> m (Maybe (a, b))) -> b -> t m a
166200unfoldrM step = go
@@ -181,6 +215,8 @@ fromFoldable = Prelude.foldr cons nil
181215
182216-- | Construct a stream from a 'Foldable' containing monadic actions.
183217--
218+-- /Concurrent (do not use with 'parallely' on infinite containers)/
219+--
184220-- @since 0.3.0
185221{-# INLINE fromFoldableM #-}
186222fromFoldableM :: (IsStream t, MonadAsync m, Foldable f) => f (m a) -> t m a
@@ -209,6 +245,8 @@ once = fromStream . S.once
209245
210246-- | Generate a stream by performing a monadic action @n@ times.
211247--
248+-- /Concurrent/
249+--
212250-- @since 0.1.1
213251replicateM :: (IsStream t, MonadAsync m) => Int -> m a -> t m a
214252replicateM n m = go n
@@ -217,6 +255,8 @@ replicateM n m = go n
217255
218256-- | Generate a stream by repeatedly executing a monadic action forever.
219257--
258+-- /Concurrent, infinite (do not use with 'parallely')/
259+--
220260-- @since 0.2.0
221261repeatM :: (IsStream t, MonadAsync m) => m a -> t m a
222262repeatM = go
@@ -233,6 +273,8 @@ iterate step = fromStream . go
233273-- | Iterate a monadic function from a seed value, streaming the results
234274-- forever.
235275--
276+-- /Concurrent, infinite (do not use with 'parallely')/
277+--
236278-- @since 0.1.2
237279iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> a -> t m a
238280iterateM step = go
@@ -657,6 +699,8 @@ maximum m = go Nothing (toStream m)
657699-- | Replace each element of the stream with the result of a monadic action
658700-- applied on the element.
659701--
702+-- /Concurrent (do not use with 'parallely' on infinite streams)/
703+--
660704-- @since 0.1.0
661705{-# INLINE mapM #-}
662706mapM :: (IsStream t, MonadAsync m) => (a -> m b) -> t m a -> t m b
@@ -684,6 +728,8 @@ mapM_ f m = go (toStream m)
684728-- | Reduce a stream of monadic actions to a stream of the output of those
685729-- actions.
686730--
731+-- /Concurrent (do not use with 'parallely' on infinite streams)/
732+--
687733-- @since 0.1.0
688734sequence :: (IsStream t, MonadAsync m) => t m (m a) -> t m a
689735sequence m = go (toStream m)
src/Streamly/Streams.hs+4
@@ -141,6 +141,8 @@ class IsStream t where
141141 -- ["hello","world"]
142142 -- @
143143 --
144+ -- /Concurrent (do not use 'parallely' to construct infinite streams)/
145+ --
144146 -- @since 0.2.0
145147 consM :: MonadAsync m => m a -> t m a -> t m a
146148 -- | Operator equivalent of 'consM'.
@@ -152,6 +154,8 @@ class IsStream t where
152154 -- ["hello","world"]
153155 -- @
154156 --
157+ -- /Concurrent (do not use 'parallely' to construct infinite streams)/
158+ --
155159 -- @since 0.2.0
156160 (|:) :: MonadAsync m => m a -> t m a -> t m a
157161
src/Streamly/Tutorial.hs+16
@@ -40,6 +40,9 @@ module Streamly.Tutorial
4040 -- * Flavors of Streams
4141 -- $flavors
4242
43+ -- * Writing Concurrent Programs
44+ -- $programs
45+
4346 -- * Imports and Supporting Code
4447 -- $imports
4548
@@ -231,6 +234,19 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
231234-- or 'zipAsyncly'. The default stream type is inferred as 'Serial' unless you
232235-- change it by using one of the combinators or using a type annotation.
233236
237+-- $programs
238+--
239+-- When writing concurrent programs it is advised to not use the concurrent
240+-- style stream combinators blindly at the top level. That might create too
241+-- much concurrency where it is not even required and therefore degrade
242+-- performance. Please be aware of what all APIs that you have used may become
243+-- concurrent when you use a concurrency combinator. For example if you have a
244+-- 'repeatM' somewhere in your program and you use 'parallely' on top, the
245+-- 'repeatM' becomes fully parallel, resulting into an infinite parallel
246+-- execution . Instead start with a default serial program and add concurrent
247+-- combinators where necessary, and use the 'serially' combinator to suppress
248+-- unnecessary concurrency.
249+
234250-- $monadtransformers
235251--
236252-- To represent streams in an arbitrary monad use the more general monad