@@ -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,56 @@ constructWithDoubleFromThenTo op l =
146 in constructWithLen stream list op l
146 in constructWithLen stream list op l
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 $
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
161+constructWithIterateM ::
162+ IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
163+constructWithIterateM op len =
164+ withMaxSuccess maxTestCount $
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)
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
176+constructWithFromIndices ::
177+ IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
178+constructWithFromIndices op len =
179+ withMaxSuccess maxTestCount $
182+ run $ (S.toList . op . S.take (fromIntegral len)) (S.fromIndices id)
183+ let list = take (fromIntegral len) (iterate (+ 1) 0)
184+ listEquals (==) stream list
186+constructWithFromIndicesM ::
187+ IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
188+constructWithFromIndicesM op len =
189+ withMaxSuccess maxTestCount $
191+ mvl <- run (newIORef [] :: IO (IORef [Int]))
192+ let addIndex mv i = modifyIORef' mv (++ [i]) >> return i
193+ list = take (fromIntegral len) (iterate (+ 1) 0)
196+ S.take (fromIntegral len) $ S.fromIndicesM (addIndex mvl)
197+ streamEffect <- run $ readIORef mvl
198+ listEquals (==) streamEffect list
159-------------------------------------------------------------------------------
200-------------------------------------------------------------------------------
160-- Concurrent generation
201-- Concurrent generation
@@ -560,7 +601,8 @@ transformCombineOpsOrdered constr desc eq t = do
560 transform (dropWhile (> 0)) t (S.dropWhile (> 0))
601 transform (dropWhile (> 0)) t (S.dropWhile (> 0))
561 prop (desc <> " scan") $ transform (scanl' (+) 0) t (S.scanl' (+) 0)
602 prop (desc <> " scan") $ transform (scanl' (+) 0) t (S.scanl' (+) 0)
563− -- XXX add uniq
604+ prop (desc <> " uniq") $ transform referenceUniq t S.uniq
564 prop (desc <> " deleteBy (<=) 0") $
606 prop (desc <> " deleteBy (<=) 0") $
565 transform (deleteBy (<=) 0) t (S.deleteBy (<=) 0)
607 transform (deleteBy (<=) 0) t (S.deleteBy (<=) 0)
@@ -599,10 +641,23 @@ wrapOutOfBounds f i x | null x = Nothing
599 | otherwise = Just (f x i)
641 | otherwise = Just (f x i)
601wrapThe :: Eq a => [a] -> Maybe a
643wrapThe :: Eq a => [a] -> Maybe a
602−wrapThe (x:xs) | all (x ==) xs = Just x
645+ | all (x ==) xs = Just x
603− | otherwise = Nothing
646+ | otherwise = Nothing
604wrapThe [] = Nothing
647wrapThe [] = Nothing
649+-- This is the reference uniq implementation to compare uniq against,
650+-- we can use uniq from vector package, but for now this should
652+referenceUniq :: Eq a => [a] -> [a]
658+ | x == y = go (x : xs)
659+ | otherwise = x : go (y : xs)
606eliminationOps
661eliminationOps
607 :: ([Int] -> t IO Int)
662 :: ([Int] -> t IO Int)
608 -> String
663 -> String
@@ -971,10 +1026,24 @@ main = hspec
971 serialOps $ prop "serially DoubleFromThenTo" .
1026 serialOps $ prop "serially DoubleFromThenTo" .
972 constructWithDoubleFromThenTo
1027 constructWithDoubleFromThenTo
1030+ serialOps $ prop "serially iterate" . constructWithIterate
974 -- XXX test for all types of streams
1032 -- XXX test for all types of streams
975− constructWithIterate serially
1033+ serialOps $ prop "serially iterateM" . constructWithIterateM
1034+ -- take doesn't work well on concurrent streams. Even though it
1035+ -- seems like take only has a problem when used with parallely.
1036+ -- wSerialOps $ prop "wSerially iterateM" wSerially . constructWithIterate
1037+ -- aheadOps $ prop "aheadly iterateM" aheadly . onstructWithIterate
1038+ -- asyncOps $ prop "asyncly iterateM" asyncly . constructWithIterate
1039+ -- wAsyncOps $ prop "wAsyncly iterateM" wAsyncly . onstructWithIterate
1040+ -- parallelOps $ prop "parallely iterateM" parallely . onstructWithIterate
976 -- XXX add tests for fromIndices
1041 -- XXX add tests for fromIndices
1043+ serialOps $ prop "serially fromIndices" . constructWithFromIndices
1045+ serialOps $ prop "serially fromIndicesM" . constructWithFromIndicesM
978 describe "Functor operations" $ do
1047 describe "Functor operations" $ do
979 serialOps $ functorOps S.fromFoldable "serially" (==)
1048 serialOps $ functorOps S.fromFoldable "serially" (==)
980 serialOps $ functorOps folded "serially folded" (==)
1049 serialOps $ functorOps folded "serially folded" (==)