on master help sign in
Changes the signature of iterateM. Fixes #190.
6ed211fPranay Sashank
src/Streamly/Prelude.hs+6−6
@@ -774,7 +774,7 @@ iterate step = fromStream . go
774
774
775-- |
775-- |
776-- @
776-- @
777−-- iterateM f m = m \`consM` iterateM f m
777+-- iterateM f m = m >>= \a -> return a \`consM` iterateM f (f a)
778-- @
778-- @
779--
779--
780-- Generate an infinite stream with the first element generated by the action
780-- Generate an infinite stream with the first element generated by the action
@@ -788,21 +788,21 @@ iterate step = fromStream . go
788--
788--
789-- @
789-- @
790-- drain $ serially $ S.take 10 $ S.iterateM
790-- drain $ serially $ S.take 10 $ S.iterateM
791−-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) 0
791+-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) (return 0)
792--
792--
793-- drain $ asyncly $ S.take 10 $ S.iterateM
793-- drain $ asyncly $ S.take 10 $ S.iterateM
794−-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) 0
794+-- (\\x -> threadDelay 1000000 >> print x >> return (x + 1)) (return 0)
795-- @
795-- @
796--
796--
797-- /Concurrent/
797-- /Concurrent/
798--
798--
799-- @since 0.1.2
799-- @since 0.1.2
800−iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> a -> t m a
800+iterateM :: (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a
801iterateM step = go
801iterateM step = go
802 where
802 where
803 go s = K.mkStream $ \st stp sng yld -> do
803 go s = K.mkStream $ \st stp sng yld -> do
804− next <- step s
804+ next <- s
805− K.foldStreamShared st stp sng yld (return s |: go next)
805+ K.foldStreamShared st stp sng yld (return next |: go (step next))
806
806
807------------------------------------------------------------------------------
807------------------------------------------------------------------------------
808-- Conversions
808-- Conversions
test/Prop.hs+39−11
@@ -12,7 +12,7 @@ import Control.Exception
12import Control.Monad (when, forM_, replicateM, replicateM_)
12import Control.Monad (when, forM_, replicateM, replicateM_)
13import Control.Monad.IO.Class (MonadIO(..))
13import Control.Monad.IO.Class (MonadIO(..))
14import Data.Function ((&))
14import Data.Function ((&))
15−import Data.IORef (readIORef, modifyIORef, newIORef)
15+import Data.IORef (readIORef, modifyIORef, newIORef, modifyIORef', IORef)
16import Data.List
16import Data.List
17 (sort, foldl', scanl', findIndices, findIndex, elemIndices,
17 (sort, foldl', scanl', findIndices, findIndex, elemIndices,
18 elemIndex, find, insertBy, intersperse, foldl1', (\\),
18 elemIndex, find, insertBy, intersperse, foldl1', (\\),
@@ -146,15 +146,33 @@ constructWithDoubleFromThenTo op l =
146 in constructWithLen stream list op l
146 in constructWithLen stream list op l
147#endif
147#endif
148
148
149+constructWithIterate ::
149−constructWithIterate :: IsStream t => (t IO Int -> SerialT IO Int) -> Spec
150+ IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
150−constructWithIterate t = do
151+constructWithIterate op len =
151− it "iterate" $
152+ withMaxSuccess maxTestCount $
153+ monadicIO $ do
154+ stream <-
155+ run $
156+ (S.toList . op . S.take (fromIntegral len))
152− (S.toList . t . S.take 100) (S.iterate (+ 1) (0 :: Int))
157+ (S.iterate (+ 1) (0 :: Int))
153− `shouldReturn` take 100 (iterate (+ 1) 0)
158+ let list = take (fromIntegral len) (iterate (+ 1) 0)
154− it "iterateM" $ do
159+ listEquals (==) stream list
160+
161+constructWithIterateM ::
162+ IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
163+constructWithIterateM op len =
164+ withMaxSuccess maxTestCount $
165+ monadicIO $ do
166+ mvl <- run (newIORef [] :: IO (IORef [Int]))
155− let addM y = return (y + 1)
167+ let addM mv x y = modifyIORef' mv (++ [y + x]) >> return (y + x)
168+ list = take (fromIntegral len) (iterate (+ 1) 0)
169+ run $
170+ S.drain . op $
171+ S.take (fromIntegral len) $
156− S.toList . t . S.take 100 $ S.iterateM addM (0 :: Int)
172+ S.iterateM (addM mvl 1) (addM mvl 0 0 :: IO Int)
157− `shouldReturn` take 100 (iterate (+ 1) 0)
173+ streamEffect <- run $ readIORef mvl
174+ listEquals (==) streamEffect list
175+
158
176
159-------------------------------------------------------------------------------
177-------------------------------------------------------------------------------
160-- Concurrent generation
178-- Concurrent generation
@@ -971,8 +989,18 @@ main = hspec
971 serialOps $ prop "serially DoubleFromThenTo" .
989 serialOps $ prop "serially DoubleFromThenTo" .
972 constructWithDoubleFromThenTo
990 constructWithDoubleFromThenTo
973#endif
991#endif
992+
993+ serialOps $ prop "serially iterate" . constructWithIterate
994+
974 -- XXX test for all types of streams
995 -- XXX test for all types of streams
975− constructWithIterate serially
996+ serialOps $ prop "serially iterateM" . constructWithIterateM
997+ -- take doesn't work well on concurrent streams. Even though it
998+ -- seems like take only has a problem when used with parallely.
999+ -- wSerialOps $ prop "wSerially iterateM" wSerially . constructWithIterate
1000+ -- aheadOps $ prop "aheadly iterateM" aheadly . onstructWithIterate
1001+ -- asyncOps $ prop "asyncly iterateM" asyncly . constructWithIterate
1002+ -- wAsyncOps $ prop "wAsyncly iterateM" wAsyncly . onstructWithIterate
1003+ -- parallelOps $ prop "parallely iterateM" parallely . onstructWithIterate
976 -- XXX add tests for fromIndices
1004 -- XXX add tests for fromIndices
977
1005
978 describe "Functor operations" $ do
1006 describe "Functor operations" $ do