on master help sign in
Changes the signature of iterateM. Fixes #190.

Now, iterateM is (IsStream t, MonadAsync m) => (a -> m a) -> m a -> t m a

commit6ed211f28ace9805dc5c423cf91a80896311351e authorPranay Sashank <pranaysashank@gmail.com> dateWed 22 May 2019, 01:56 (7 years ago) parent22ccf96
2 files changed+45−17
src/Streamly/Prelude.hs+6−6 test/Prop.hs+39−11
src/Streamly/Prelude.hs+6−6
@@ -774,7 +774,7 @@ iterate step = fromStream . go
774774
775775-- |
776776-- @
777−-- iterateM f m = m \`consM` iterateM f m
777+-- iterateM f m = m >>= \a -> return a \`consM` iterateM f (f a)
778778-- @
779779--
780780-- Generate an infinite stream with the first element generated by the action
@@ -788,21 +788,21 @@ iterate step = fromStream . go
788788--
789789-- @
790790-- 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)
792792--
793793-- 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)
795795-- @
796796--
797797-- /Concurrent/
798798--
799799-- @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
801801iterateM step = go
802802 where
803803 go s = K.mkStream $ \st stp sng yld -> do
804− next <- step s
805− K.foldStreamShared st stp sng yld (return s |: go next)
804+ next <- s
805+ K.foldStreamShared st stp sng yld (return next |: go (step next))
806806
807807------------------------------------------------------------------------------
808808-- Conversions
test/Prop.hs+39−11
@@ -12,7 +12,7 @@ import Control.Exception
1212import Control.Monad (when, forM_, replicateM, replicateM_)
1313import Control.Monad.IO.Class (MonadIO(..))
1414import Data.Function ((&))
15−import Data.IORef (readIORef, modifyIORef, newIORef)
15+import Data.IORef (readIORef, modifyIORef, newIORef, modifyIORef', IORef)
1616import Data.List
1717 (sort, foldl', scanl', findIndices, findIndex, elemIndices,
1818 elemIndex, find, insertBy, intersperse, foldl1', (\\),
@@ -146,15 +146,33 @@ constructWithDoubleFromThenTo op l =
146146 in constructWithLen stream list op l
147147#endif
148148
149−constructWithIterate :: IsStream t => (t IO Int -> SerialT IO Int) -> Spec
150−constructWithIterate t = do
151− it "iterate" $
152− (S.toList . t . S.take 100) (S.iterate (+ 1) (0 :: Int))
153− `shouldReturn` take 100 (iterate (+ 1) 0)
154− it "iterateM" $ do
155− let addM y = return (y + 1)
156− S.toList . t . S.take 100 $ S.iterateM addM (0 :: Int)
157− `shouldReturn` take 100 (iterate (+ 1) 0)
149+constructWithIterate ::
150+ IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
151+constructWithIterate op len =
152+ withMaxSuccess maxTestCount $
153+ monadicIO $ do
154+ stream <-
155+ run $
156+ (S.toList . op . S.take (fromIntegral len))
157+ (S.iterate (+ 1) (0 :: Int))
158+ let list = take (fromIntegral len) (iterate (+ 1) 0)
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]))
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) $
172+ S.iterateM (addM mvl 1) (addM mvl 0 0 :: IO Int)
173+ streamEffect <- run $ readIORef mvl
174+ listEquals (==) streamEffect list
175+
158176
159177-------------------------------------------------------------------------------
160178-- Concurrent generation
@@ -971,8 +989,18 @@ main = hspec
971989 serialOps $ prop "serially DoubleFromThenTo" .
972990 constructWithDoubleFromThenTo
973991#endif
992+
993+ serialOps $ prop "serially iterate" . constructWithIterate
994+
974995 -- 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
9761004 -- XXX add tests for fromIndices
9771005
9781006 describe "Functor operations" $ do