on master help sign in
Fix documentation in the Stream modules
4608fadHarendra Kumar
core/src/Streamly/Internal/Data/Stream/Eliminate.hs+9−4
@@ -18,23 +18,28 @@ import Streamly.Internal.Data.Stream.Type (Stream)
18import qualified Streamly.Internal.Data.Stream.Type as Stream
18import qualified Streamly.Internal.Data.Stream.Type as Stream
19import qualified Streamly.Internal.Data.Stream.StreamD.Type as StreamD
19import qualified Streamly.Internal.Data.Stream.StreamD.Type as StreamD
20
20
21+-- $setup
22+-- >>> import qualified Streamly.Data.Fold as Fold
23+-- >>> import qualified Streamly.Internal.Data.Unfold as Unfold
24+-- >>> import qualified Streamly.Internal.Data.Stream as Stream
25+
21-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
26-- | Fold a stream using the supplied left 'Fold' and reducing the resulting
22-- expression strictly at each step. The behavior is similar to 'foldl''. A
27-- expression strictly at each step. The behavior is similar to 'foldl''. A
23-- 'Fold' can terminate early without consuming the full stream. See the
28-- 'Fold' can terminate early without consuming the full stream. See the
24-- documentation of individual 'Fold's for termination behavior.
29-- documentation of individual 'Fold's for termination behavior.
25--
30--
26−-- >>> Stream.foldWith Fold.sum (Stream.enumerateFromTo 1 100)
31+-- >>> Stream.fold Fold.sum (Stream.unfold Unfold.enumerateFromTo (1,100))
27-- 5050
32-- 5050
28--
33--
29-- Folds never fail, therefore, they produce a default value even when no input
34-- Folds never fail, therefore, they produce a default value even when no input
30-- is provided. It means we can always fold an empty stream and get a valid
35-- is provided. It means we can always fold an empty stream and get a valid
31-- result. For example:
36-- result. For example:
32--
37--
33−-- >>> Stream.fold Fold.sum Stream.nil
38+-- >> Stream.fold Fold.sum Stream.nil
34−-- 0
39+-- >0
35--
40--
36-- However, 'foldMany' on an empty stream results in an empty stream.
41-- However, 'foldMany' on an empty stream results in an empty stream.
37−-- Therefore, @Stream.foldWith f@ is not the same as @Stream.head . Stream.foldMany
42+-- Therefore, @Stream.fold f@ is not the same as @Stream.head . Stream.foldMany
38-- f@.
43-- f@.
39--
44--
40-- @fold f = Stream.parse (Parser.fromFold f)@
45-- @fold f = Stream.parse (Parser.fromFold f)@
core/src/Streamly/Internal/Data/Stream/Generate.hs+43−22
@@ -10,6 +10,7 @@ module Streamly.Internal.Data.Stream.Generate
10 (
10 (
11 cons
11 cons
12 , consM
12 , consM
13+ , unfold
13 , append
14 , append
14 )
15 )
15where
16where
@@ -21,27 +22,30 @@ import Data.Semigroup (Semigroup(..))
21import Data.Semigroup (Semigroup(..))
22import Data.Semigroup (Semigroup(..))
22#endif
23#endif
23import Streamly.Internal.Data.Stream.Type (Stream)
24import Streamly.Internal.Data.Stream.Type (Stream)
25+import Streamly.Internal.Data.Unfold (Unfold)
24
26
25import qualified Streamly.Internal.Data.Stream.Type as Stream
27import qualified Streamly.Internal.Data.Stream.Type as Stream
28+import qualified Streamly.Internal.Data.Stream.StreamD.Type as StreamD
26import qualified Streamly.Internal.Data.Stream.StreamK.Type as StreamK
29import qualified Streamly.Internal.Data.Stream.StreamK.Type as StreamK
27
30
28-- $setup
31-- $setup
29-- >>> :m
32-- >>> :m
30−-- >>> import Control.Concurrent (threadDelay)
33+-- >>> import qualified Streamly.Data.Fold as Fold
31−-- >>> import Data.IORef
34+-- >>> import qualified Streamly.Data.Unfold as Unfold
32−-- >>> import Prelude hiding (zipWith, concatMap, concat)
33-- >>> import qualified Streamly.Internal.Data.Stream as Stream
35-- >>> import qualified Streamly.Internal.Data.Stream as Stream
34−--
36+
37+infixr 5 `cons`
35
38
36-- | Construct a stream by adding a pure value at the head of an existing
39-- | Construct a stream by adding a pure value at the head of an existing
37−-- stream. This is the same as @(return a) \`consM` r@ but
40+-- stream. Same as the following but more efficient:
38−-- more efficient. For concurrent streams this is not concurrent whereas
41+--
39−-- 'consM' is concurrent. For example:
42+-- For example:
40--
43--
41−-- @
44+-- >> s = 1 `Stream.cons` 2 `Stream.cons` 3 `Stream.cons` Stream.nil
42−-- > toList $ 1 \`cons` 2 \`cons` 3 \`cons` nil
45+-- >> Stream.fold Fold.toList s
43−-- [1,2,3]
46+-- >[1,2,3]
44−-- @
47+--
48+-- >>> cons x xs = return x `Stream.consM` xs
45--
49--
46-- /Pre-release/
50-- /Pre-release/
47--
51--
@@ -49,17 +53,16 @@ import qualified Streamly.Internal.Data.Stream.StreamK.Type as StreamK
49cons :: a -> Stream m a -> Stream m a
53cons :: a -> Stream m a -> Stream m a
50cons x = Stream.fromStreamK . StreamK.cons x . Stream.toStreamK
54cons x = Stream.fromStreamK . StreamK.cons x . Stream.toStreamK
51
55
56+infixr 5 `consM`
57+
52-- | Constructs a stream by adding a monadic action at the head of an
58-- | Constructs a stream by adding a monadic action at the head of an
53-- existing stream. For example:
59-- existing stream. For example:
54--
60--
55−-- @
61+-- >> s = putChar 'h' `Stream.consM` putChar 'i' `Stream.consM` Stream.nil
56−-- > toList $ getLine \`consM` getLine \`consM` nil
62+-- >> Stream.fold Fold.toList s
57−-- hello
63+-- >hi
58−-- world
59−-- ["hello","world"]
60−-- @
61--
64--
62−-- > consM x xs = fromEffect x `append` xs
65+-- >> consM x xs = Stream.fromEffect x `Stream.append` xs
63--
66--
64-- /Pre-release/
67-- /Pre-release/
65--
68--
@@ -68,17 +71,35 @@ cons x = Stream.fromStreamK . StreamK.cons x . Stream.toStreamK
68consM :: Monad m => m a -> Stream m a -> Stream m a
71consM :: Monad m => m a -> Stream m a -> Stream m a
69consM m = Stream.fromStreamK . StreamK.consM m . Stream.toStreamK
72consM m = Stream.fromStreamK . StreamK.consM m . Stream.toStreamK
70
73
74+------------------------------------------------------------------------------
75+-- From Unfold
76+------------------------------------------------------------------------------
77+
78+-- | Convert an 'Unfold' into a stream by supplying it an input seed.
79+--
80+-- >>> s = Stream.unfold (Unfold.replicateM 3) (putStrLn "hello")
81+-- >>> Stream.fold Fold.drain s
82+-- hello
83+-- hello
84+-- hello
85+--
86+-- /Pre-release/
87+{-# INLINE unfold #-}
88+unfold :: Monad m => Unfold m a b -> a -> Stream m b
89+unfold unf = Stream.fromStreamD . StreamD.unfold unf
90+
71------------------------------------------------------------------------------
91------------------------------------------------------------------------------
72-- Combining
92-- Combining
73------------------------------------------------------------------------------
93------------------------------------------------------------------------------
74
94
95+infixr 6 `append`
96+
75-- | Appends two streams sequentially, yielding all elements from the first
97-- | Appends two streams sequentially, yielding all elements from the first
76-- stream, and then all elements from the second stream.
98-- stream, and then all elements from the second stream.
77--
99--
78−-- >>> import Streamly.Internal.Data.Stream (append)
79−-- >>> stream1 = Stream.fromList [1,2]
100+-- >>> s1 = Stream.unfold Unfold.fromList [1,2]
80−-- >>> stream2 = Stream.fromList [3,4]
101+-- >>> s2 = Stream.unfold Unfold.fromList [3,4]
81−-- >>> Stream.toList $ stream1 `append` stream2
102+-- >>> Stream.fold Fold.toList $ s1 `Stream.append` s2
82-- [1,2,3,4]
103-- [1,2,3,4]
83--
104--
84-- This operation can be used to fold an infinite lazy container of streams.
105-- This operation can be used to fold an infinite lazy container of streams.
core/src/Streamly/Internal/Data/Stream/Transform.hs+14−32
@@ -26,43 +26,24 @@ import Prelude hiding (map, mapM, filter)
26--
26--
27-- $setup
27-- $setup
28-- >>> :m
28-- >>> :m
29−-- >>> import Streamly.Internal.Data.Stream as Stream
30−-- >>> import qualified Streamly.Data.Fold as Fold
31-- >>> import qualified Streamly.Internal.Data.Fold as Fold
29-- >>> import qualified Streamly.Internal.Data.Fold as Fold
32−-- >>> import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
30+-- >>> import qualified Streamly.Data.Unfold as Unfold
33−--
31+-- >>> import qualified Streamly.Internal.Data.Stream as Stream
34−-- >>> hSetBuffering stdout LineBuffering
35
32
36------------------------------------------------------------------------------
33------------------------------------------------------------------------------
37-- Transformation by Mapping
34-- Transformation by Mapping
38------------------------------------------------------------------------------
35------------------------------------------------------------------------------
39
36
40-- |
37-- |
41−-- @
42−-- mapM f = sequence . map f
38+-- >> mapM f = Stream.sequence . Stream.map f
43−-- @
44--
39--
45-- Apply a monadic function to each element of the stream and replace it with
40-- Apply a monadic function to each element of the stream and replace it with
46-- the output of the resulting action.
41-- the output of the resulting action.
47--
42--
48−-- @
49−-- > drain $ Stream.mapM putStr $ Stream.fromList ["a", "b", "c"]
43+-- >>> s = Stream.unfold Unfold.fromList ["a", "b", "c"]
44+-- >>> Stream.fold Fold.drain $ Stream.mapM putStr s
50-- abc
45-- abc
51--
46--
52−-- > :{
53−-- drain $ Stream.replicateM 10 (return 1)
54−-- & (fromSerial . Stream.mapM (\x -> threadDelay 1000000 >> print x))
55−-- :}
56−-- 1
57−-- ...
58−-- 1
59−--
60−-- > drain $ Stream.replicateM 10 (return 1)
61−-- & (fromAsync . Stream.mapM (\x -> threadDelay 1000000 >> print x))
62−-- @
63−--
64−-- /Concurrent (do not use with 'fromParallel' on infinite streams)/
65−--
66-- /Pre-release/
47-- /Pre-release/
67--
48--
68{-# INLINE mapM #-}
49{-# INLINE mapM #-}
@@ -70,16 +51,13 @@ mapM :: Monad m => (a -> m b) -> Stream m a -> Stream m b
70mapM f = Stream.fromStreamD . StreamD.mapM f . Stream.toStreamD
51mapM f = Stream.fromStreamD . StreamD.mapM f . Stream.toStreamD
71
52
72-- |
53-- |
73−-- @
74−-- map = fmap
54+-- >>> map = fmap
75−-- @
76--
55--
77-- Same as 'fmap'.
56-- Same as 'fmap'.
78--
57--
79−-- @
58+-- >>> s = Stream.unfold Unfold.fromList [1,2,3]
80−-- > S.toList $ S.map (+1) $ S.fromList [1,2,3]
59+-- >>> Stream.fold Fold.toList $ Stream.map (+1) s
81-- [2,3,4]
60-- [2,3,4]
82−-- @
83--
61--
84-- /Pre-release/
62-- /Pre-release/
85--
63--
@@ -95,8 +73,12 @@ filter p = Stream.fromStreamD . StreamD.filter p . Stream.toStreamD
95
73
96-- | Use a filtering fold on a stream.
74-- | Use a filtering fold on a stream.
97--
75--
76+-- >>> :{
77+-- Stream.fold Fold.sum
98−-- > Stream.sum $ Stream.foldFilter (Fold.satisfy (> 5)) $ Stream.fromList [1..10]
78+-- $ Stream.foldFilter (Fold.maybe (\x -> if x > 5 then Just x else Nothing))
79+-- $ Stream.unfold Unfold.fromList [1..10]
80+-- :}
99−-- 40
81+--40
100--
82--
101-- /Pre-release/
83-- /Pre-release/
102--
84--
core/src/Streamly/Internal/Data/Stream/Type.hs+17−15
@@ -48,24 +48,28 @@ import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
48#include "inline.hs"
48#include "inline.hs"
49
49
50-- $setup
50-- $setup
51−-- >>> import qualified Streamly.Prelude as Stream
51+-- >>> import qualified Streamly.Data.Fold as Fold
52+-- >>> import qualified Streamly.Data.Unfold as Unfold
53+-- >>> import qualified Streamly.Internal.Data.Stream as Stream
52
54
53------------------------------------------------------------------------------
55------------------------------------------------------------------------------
54-- Stream
56-- Stream
55------------------------------------------------------------------------------
57------------------------------------------------------------------------------
56
58
57−-- | For 'Stream' streams:
59+-- | Semigroup instance appends two streams:
58--
60--
59−-- @
61+-- > (<>) = Stream.append
60−-- (<>) = 'Streamly.Prelude.serial' -- 'Semigroup'
61−-- (>>=) = flip . 'Streamly.Prelude.concatMapWith' 'Streamly.Prelude.serial' -- 'Monad'
62−-- @
63--
62--
63+-- Monad bind maps a stream generator function on the stream and flattens the
64+-- resulting stream:
65+--
66+-- > (>>=) = flip . Stream.concatMapWith Stream.append
67+--
64−-- A single 'Monad' bind behaves like a @for@ loop:
68+-- A 'Monad' bind behaves like a @for@ loop:
65--
69--
66-- >>> :{
70-- >>> :{
67−-- Stream.toList $ do
71+-- Stream.fold Fold.toList $ do
68−-- x <- Stream.fromList [1,2] -- foreach x in stream
72+-- x <- Stream.unfold Unfold.fromList [1,2] -- foreach x in stream
69-- return x
73-- return x
70-- :}
74-- :}
71-- [1,2]
75-- [1,2]
@@ -73,16 +77,14 @@ import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
73-- Nested monad binds behave like nested @for@ loops:
77-- Nested monad binds behave like nested @for@ loops:
74--
78--
75-- >>> :{
79-- >>> :{
76−-- Stream.toList $ do
80+-- Stream.fold Fold.toList $ do
77−-- x <- Stream.fromList [1,2] -- foreach x in stream
81+-- x <- Stream.unfold Unfold.fromList [1,2] -- foreach x in stream
78−-- y <- Stream.fromList [3,4] -- foreach y in stream
82+-- y <- Stream.unfold Unfold.fromList [3,4] -- foreach y in stream
79-- return (x, y)
83-- return (x, y)
80-- :}
84-- :}
81-- [(1,3),(1,4),(2,3),(2,4)]
85-- [(1,3),(1,4),(2,3),(2,4)]
82--
86--
83−-- /Since: 0.2.0 ("Streamly")/
84−--
85−-- @since 0.8.0
87+-- @since 0.9.0
86newtype Stream m a = Stream (K.Stream m a)
88newtype Stream m a = Stream (K.Stream m a)
87 -- XXX when deriving do we inherit an INLINE?
89 -- XXX when deriving do we inherit an INLINE?
88 deriving (Semigroup, Monoid, MonadTrans)
90 deriving (Semigroup, Monoid, MonadTrans)