@@ -1,16 +1,31 @@
1module Main (main) where
1module Main (main) where
4+ (maximum, minimum, elem, notElem, null, product, sum, head, last)
5+import Data.Semigroup (Sum(..), getSum)
19+ (maximum, minimum, elem, notElem, null, product, sum, head, last)
3import Streamly.Test.Common (checkListEqual)
20import Streamly.Test.Common (checkListEqual)
4−import Prelude hiding (maximum, minimum, elem, notElem, null, product, sum, head, last)
21+import Test.QuickCheck.Monadic (monadicIO, assert, run)
5import qualified Streamly.Internal.Data.Fold as F
23import qualified Streamly.Internal.Data.Fold as F
6import qualified Streamly.Prelude as S
24import qualified Streamly.Prelude as S
7import qualified Streamly.Data.Fold as FL
25import qualified Streamly.Data.Fold as FL
9import Test.Hspec as H
27import Test.Hspec as H
10import Test.Hspec.QuickCheck
28import Test.Hspec.QuickCheck
11−import Test.QuickCheck
12− (Property, property, forAll, Gen, vectorOf, arbitrary, choose, listOf)
13−import Test.QuickCheck.Monadic (monadicIO, assert, run)
15maxStreamLen :: Int
30maxStreamLen :: Int
16maxStreamLen = 1000
31maxStreamLen = 1000
@@ -43,75 +58,75 @@ rollingHashFirstN =
43 b <- run $ S.fold (F.rollingHashFirstN n) $ S.fromList vec
58 b <- run $ S.fold (F.rollingHashFirstN n) $ S.fromList vec
44 assert $ a == b
59 assert $ a == b
47head :: [Int] -> Expectation
61head :: [Int] -> Expectation
48head ls = S.fold FL.head (S.fromList ls) `shouldReturn` headl ls
62head ls = S.fold FL.head (S.fromList ls) `shouldReturn` headl ls
54length :: [Int] -> Expectation
69length :: [Int] -> Expectation
55length ls = S.fold FL.length (S.fromList ls) `shouldReturn` Prelude.length ls
70length ls = S.fold FL.length (S.fromList ls) `shouldReturn` Prelude.length ls
58sum :: [Int] -> Expectation
72sum :: [Int] -> Expectation
59sum ls = S.fold FL.sum (S.fromList ls) `shouldReturn` foldl (+) 0 ls
73sum ls = S.fold FL.sum (S.fromList ls) `shouldReturn` foldl (+) 0 ls
62product :: [Int] -> Expectation
75product :: [Int] -> Expectation
63product ls = S.fold FL.product (S.fromList ls) `shouldReturn` foldl (*) 1 ls
76product ls = S.fold FL.product (S.fromList ls) `shouldReturn` foldl (*) 1 ls
66lesser :: (a -> a -> Ordering) -> a -> a -> a
78lesser :: (a -> a -> Ordering) -> a -> a -> a
67lesser f x y = if f x y == LT then x else y
79lesser f x y = if f x y == LT then x else y
70greater :: (a -> a -> Ordering) -> a -> a -> a
81greater :: (a -> a -> Ordering) -> a -> a -> a
71greater f x y = if f x y == GT then x else y
82greater f x y = if f x y == GT then x else y
74foldMaybe :: (b -> a -> b) -> b -> [a] -> Maybe b
84foldMaybe :: (b -> a -> b) -> b -> [a] -> Maybe b
75foldMaybe f acc ls =
85foldMaybe f acc ls =
76− case ls of
86+ case ls of
77− [] -> Nothing
87+ [] -> Nothing
78− _ -> Just (foldl f acc ls)
88+ _ -> Just (foldl f acc ls)
81maximumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
90maximumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
91+maximumBy genmin f ls =
82−maximumBy genmin f ls = S.fold (FL.maximumBy f) (S.fromList ls) `shouldReturn` foldMaybe (greater f) genmin ls
92+ S.fold (FL.maximumBy f) (S.fromList ls)
94+ foldMaybe (greater f) genmin ls
85maximum :: (Show a, Ord a) => a -> [a] -> Expectation
96maximum :: (Show a, Ord a) => a -> [a] -> Expectation
98+ S.fold FL.maximum (S.fromList ls)
86−maximum genmin ls = S.fold FL.maximum (S.fromList ls) `shouldReturn` foldMaybe (greater compare) genmin ls
99+ `shouldReturn` foldMaybe (greater compare) genmin ls
89minimumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
101minimumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
102+minimumBy genmax f ls =
103+ S.fold (FL.minimumBy f) (S.fromList ls)
90−minimumBy genmax f ls = S.fold (FL.minimumBy f) (S.fromList ls) `shouldReturn` foldMaybe (lesser f) genmax ls
104+ `shouldReturn` foldMaybe (lesser f) genmax ls
93minimum :: (Show a, Ord a) => a -> [a] -> Expectation
106minimum :: (Show a, Ord a) => a -> [a] -> Expectation
108+ S.fold FL.minimum (S.fromList ls)
94−minimum genmax ls = S.fold FL.minimum (S.fromList ls) `shouldReturn` foldMaybe (lesser compare) genmax ls
109+ `shouldReturn` foldMaybe (lesser compare) genmax ls
97toList :: [Int] -> Expectation
111toList :: [Int] -> Expectation
98toList ls = S.fold FL.toList (S.fromList ls) `shouldReturn` ls
112toList ls = S.fold FL.toList (S.fromList ls) `shouldReturn` ls
101safeLast :: [a] -> Maybe a
114safeLast :: [a] -> Maybe a
102safeLast [] = Nothing
115safeLast [] = Nothing
103safeLast (x:[]) = Just x
116safeLast (x:[]) = Just x
104safeLast (_:xs) = safeLast xs
117safeLast (_:xs) = safeLast xs
107last :: [String] -> Expectation
119last :: [String] -> Expectation
108last ls = S.fold FL.last (S.fromList ls) `shouldReturn` safeLast ls
120last ls = S.fold FL.last (S.fromList ls) `shouldReturn` safeLast ls
110mapMaybe :: [Int] -> Expectation
122mapMaybe :: [Int] -> Expectation
111mapMaybe ls =
123mapMaybe ls =
112− (let f = F.mapMaybe (\x -> if even x then Just x else Nothing) FL.toList
124+ let maybeEven x =
113− in S.fold f (S.fromList ls))
125+ if even x
128+ f = F.mapMaybe maybeEven FL.toList
114− `shouldReturn` filter even ls
129+ in S.fold f (S.fromList ls) `shouldReturn` filter even ls
116nth :: Int -> [a] -> Maybe a
131nth :: Int -> [a] -> Maybe a
117nth idx (x:xs) = if idx == 0
132nth idx (x:xs) = if idx == 0
@@ -121,48 +136,52 @@ nth idx (x:xs) = if idx == 0
121 else nth (idx - 1) xs
136 else nth (idx - 1) xs
122nth _ [] = Nothing
137nth _ [] = Nothing
125index :: Int -> [String] -> Expectation
139index :: Int -> [String] -> Expectation
126index idx ls = let x = S.fold (FL.index idx) (S.fromList ls)
140index idx ls = let x = S.fold (FL.index idx) (S.fromList ls)
127 in x `shouldReturn` (nth idx ls)
141 in x `shouldReturn` (nth idx ls)
130find :: (Show a, Eq a) => (a -> Bool) -> [a] -> Expectation
143find :: (Show a, Eq a) => (a -> Bool) -> [a] -> Expectation
131find f ls = do
144find f ls = do
132− let x = S.fold (FL.findIndex f) (S.fromList ls)
145+ y <- S.fold (FL.findIndex f) (S.fromList ls)
134− case y of
146+ case y of
135− Nothing -> S.fold (FL.find f) (S.fromList ls) `shouldReturn` Nothing
148+ let fld = S.fold (FL.find f) (S.fromList ls)
149+ in fld `shouldReturn` Nothing
136− Just idx -> S.fold (FL.any f) (S.fromList $ take idx ls) `shouldReturn` False
151+ let fld = S.fold (FL.any f) (S.fromList $ take idx ls)
137−
152+ in fld `shouldReturn` False
139neg :: (a -> Bool) -> a -> Bool
154neg :: (a -> Bool) -> a -> Bool
140neg f x = if f x == True then False else True
155neg f x = if f x == True then False else True
142findIndex :: (a -> Bool) -> [a] -> Expectation
157findIndex :: (a -> Bool) -> [a] -> Expectation
143findIndex f ls = do
158findIndex f ls = do
144− let x = S.fold (FL.findIndex f) (S.fromList ls)
159+ y <- S.fold (FL.findIndex f) (S.fromList ls)
146− case y of
160+ case y of
147− Nothing -> S.fold (FL.all $ neg f) (S.fromList ls) `shouldReturn` True
162+ let fld = S.fold (FL.all $ neg f) (S.fromList ls)
163+ in fld `shouldReturn` True
148− Just idx -> if idx == 0
164+ Just idx -> if idx == 0
149− then S.fold (FL.all f) (S.fromList []) `shouldReturn` True
166+ S.fold (FL.all f) (S.fromList []) `shouldReturn` True
150− else S.fold (FL.all f) (S.fromList $ (take idx ls)) `shouldReturn` False
168+ S.fold (FL.all f) (S.fromList $ (take idx ls))
152predicate :: Int -> Bool
172predicate :: Int -> Bool
153predicate x = if x * x < 100 then True else False
173predicate x = if x * x < 100 then True else False
155elemIndex :: Int -> [Int] -> Expectation
175elemIndex :: Int -> [Int] -> Expectation
156elemIndex elm ls = do
176elemIndex elm ls = do
157− let x = S.fold (FL.elemIndex elm) (S.fromList ls)
177+ y <- S.fold (FL.elemIndex elm) (S.fromList ls)
159− case y of
178+ case y of
160− Nothing -> S.fold (FL.any (\z -> if z == elm
180+ let fld = S.fold (FL.any (== elm)) (S.fromList ls)
162− else False)) (S.fromList ls) `shouldReturn` False
181+ in fld `shouldReturn` False
163− Just idx -> S.fold (FL.any (\z -> if z == elm
182+ Just idx ->
164− then True
183+ let fld = S.fold (FL.any (== elm)) (S.fromList $ (take idx ls))
165− else False)) (S.fromList $ (take idx ls)) `shouldReturn` False
184+ in fld `shouldReturn` False
167null :: [Int] -> Expectation
186null :: [Int] -> Expectation
168null ls = S.fold FL.null (S.fromList ls) `shouldReturn` case ls of
187null ls = S.fold FL.null (S.fromList ls) `shouldReturn` case ls of
@@ -170,36 +189,26 @@ null ls = S.fold FL.null (S.fromList ls) `shouldReturn` case ls of
170 _ -> False
189 _ -> False
171elem :: Int -> [Int] -> Expectation
190elem :: Int -> [Int] -> Expectation
172elem elm ls = do
191elem elm ls = do
173− let x = S.fold (FL.elem elm) (S.fromList ls)
192+ y <- S.fold (FL.elem elm) (S.fromList ls)
174− y <- x
193+ let fld = S.fold (FL.any (== elm)) (S.fromList ls)
175− S.fold (FL.any (\z -> if z == elm
177− else False)) (S.fromList ls) `shouldReturn` y
194+ fld `shouldReturn` y
180notElem :: Int -> [Int] -> Expectation
196notElem :: Int -> [Int] -> Expectation
181notElem elm ls = do
197notElem elm ls = do
182− let x = S.fold (FL.notElem elm) (S.fromList ls)
198+ y <- S.fold (FL.notElem elm) (S.fromList ls)
183− y <- x
199+ let fld = S.fold (FL.any (== elm)) (S.fromList ls)
184− S.fold (FL.any (\z -> if z == elm
186− else False)) (S.fromList ls) `shouldReturn` (if y == True
200+ fld `shouldReturn` not y
191all :: (a -> Bool) -> [a] -> Expectation
202all :: (a -> Bool) -> [a] -> Expectation
192−all f ls = S.fold (FL.all f) (S.fromList ls) `shouldReturn` Prelude.and (map f ls)
204+ S.fold (FL.all f) (S.fromList ls) `shouldReturn` Prelude.and (map f ls)
195any :: (a -> Bool) -> [a] -> Expectation
206any :: (a -> Bool) -> [a] -> Expectation
196any f ls = S.fold (FL.any f) (S.fromList ls) `shouldReturn` Prelude.any f ls
207any f ls = S.fold (FL.any f) (S.fromList ls) `shouldReturn` Prelude.any f ls
199and :: [Bool] -> Expectation
209and :: [Bool] -> Expectation
200and ls = S.fold FL.and (S.fromList ls) `shouldReturn` Prelude.and ls
210and ls = S.fold FL.and (S.fromList ls) `shouldReturn` Prelude.and ls
203or :: [Bool] -> Expectation
212or :: [Bool] -> Expectation
204or ls = S.fold FL.or (S.fromList ls) `shouldReturn` Prelude.or ls
213or ls = S.fold FL.or (S.fromList ls) `shouldReturn` Prelude.or ls
@@ -230,6 +239,181 @@ sliceSepByMax =
230 Right xs -> checkListEqual xs ys
239 Right xs -> checkListEqual xs ys
231 Left _ -> property False
240 Left _ -> property False
242+chooseFloat :: (Float, Float) -> Gen Float
245+drain :: [Int] -> Expectation
246+drain ls = S.fold FL.drain (S.fromList ls) `shouldReturn` ()
248+drainBy :: [Int] -> Expectation
249+drainBy ls = S.fold (FL.drainBy return) (S.fromList ls) `shouldReturn` ()
253+ forAll (listOf1 (chooseFloat (-100.0, 100.0)))
254+ $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
259+ v1 <- run $ S.fold FL.mean (S.fromList ls)
260+ let v2 = (foldl (+) 0 ls) / fromIntegral (Prelude.length ls)
261+ assert (abs (v1 - v2) < 0.0001)
265+ forAll (listOf1 (chooseFloat (-100.0, 100.0)))
266+ $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
271+ v1 <- run $ S.fold FL.stdDev (S.fromList ls)
272+ let avg = (foldl (+) 0 ls) / fromIntegral (Prelude.length ls)
273+ se = (foldl (+) 0 (map (\x -> (x - avg) * (x - avg)) ls))
274+ sd = sqrt $ se / fromIntegral (Prelude.length ls)
275+ assert (abs (v1 - sd) < 0.0001 )
279+ forAll (listOf1 (chooseFloat (-100.0, 100.0)))
280+ $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
285+ v1 <- run $ S.fold FL.variance (S.fromList ls)
286+ let avg = (foldl (+) 0 ls) / fromIntegral (Prelude.length ls)
287+ se = (foldl (+) 0 (map (\x -> (x - avg) * (x - avg)) ls))
288+ vr = se / fromIntegral (Prelude.length ls)
289+ assert (abs (v1 - vr) < 0.01 )
293+ forAll (listOf1 (chooseInt (intMin, intMax)))
294+ $ \ls0 -> monadicIO $ action ls0
299+ v1 <- run $ S.fold FL.mconcat (S.map Sum $ S.fromList ls)
300+ let v2 = (foldl (+) 0 ls)
301+ assert (getSum v1 == v2)
305+ forAll (listOf1 (chooseInt (intMin, intMax)))
306+ $ \ls0 -> monadicIO $ action ls0
311+ v1 <- run $ S.fold (FL.foldMap Sum) $ S.fromList ls
312+ let v2 = (foldl (+) 0 ls)
313+ assert (getSum v1 == v2)
317+ forAll (listOf1 (chooseInt (intMin, intMax)))
318+ $ \ls0 -> monadicIO $ action ls0
323+ v1 <- run $ S.fold (FL.foldMapM (return . Sum)) $ S.fromList ls
324+ let v2 = (foldl (+) 0 ls)
325+ assert (getSum v1 == v2)
329+ forAll (chooseInt (1, 15))
330+ $ \key0 ->monadicIO $ action key0
335+ let ls = [(1, "first"), (2, "second"), (3, "third"), (4, "fourth")
336+ , (5, "fifth"), (6, "fifth+first"), (7, "fifth+second")
337+ , (8, "fifth+third"), (9, "fifth+fourth")
338+ , (10, "fifth+fifth")]
339+ v1 <- run $ S.fold (FL.lookup key) $ S.fromList ls
340+ let v2 = Prelude.lookup key ls
345+ forAll (listOf1 (chooseInt (intMin, intMax)))
346+ $ \ls0 -> monadicIO $ action ls0
351+ let addLen x = return $ x + Prelude.length ls
352+ fld = FL.mapM addLen FL.sum
353+ v2 = foldl (+) (Prelude.length ls) ls
354+ v1 <- run $ S.fold fld $ S.fromList ls
357+teeWithLength :: Property
359+ forAll (listOf1 (chooseInt (intMin, intMax)))
360+ $ \ls0 -> monadicIO $ action ls0
365+ v1 <- run $ S.fold (FL.tee FL.sum FL.length) $ S.fromList ls
366+ let v2 = foldl (+) 0 ls
367+ v3 = Prelude.length ls
368+ assert (v1 == (v2, v3))
370+teeWithMax :: Property
372+ forAll (listOf1 (chooseInt (intMin, intMax)))
373+ $ \ls0 -> monadicIO $ action ls0
378+ v1 <- run $ S.fold (FL.tee FL.sum FL.maximum) $ S.fromList ls
379+ let v2 = foldl (+) 0 ls
380+ v3 = foldMaybe (greater compare) intMin ls
381+ assert (v1 == (v2, v3))
383+distribute :: Property
385+ forAll (listOf1 (chooseInt (intMin, intMax)))
386+ $ \ls0 -> monadicIO $ action ls0
391+ v1 <- run $ S.fold (FL.distribute [FL.sum, FL.length]) $ S.fromList ls
392+ let v2 = foldl (+) 0 ls
393+ v3 = Prelude.length ls
394+ assert (v1 == [v2, v3])
396+partition :: Property
399+ v1 :: (Int, [String]) <-
401+ $ S.fold (FL.partition FL.sum FL.toList)
403+ [Left 1, Right "abc", Left 3, Right "xy", Right "pp2"]
404+ let v2 = (4,["abc","xy","pp2"])
410+ v1 :: (Int, [String]) <-
412+ $ S.fold (FL.unzip FL.sum FL.toList)
413+ $ S.fromList [(1, "aa"), (2, "bb"), (3, "cc")]
414+ let v2 = (6, ["aa", "bb", "cc"])
233main :: IO ()
417main :: IO ()
234main = hspec $
418main = hspec $
235 describe "Fold s" $ do
419 describe "Fold s" $ do
@@ -259,3 +443,18 @@ main = hspec $
259 prop "ltake" ltake
443 prop "ltake" ltake
260 prop "sliceSepBy" sliceSepBy
444 prop "sliceSepBy" sliceSepBy
261 prop "sliceSepByMax" sliceSepByMax
445 prop "sliceSepByMax" sliceSepByMax
446+ prop "drain" Main.drain
447+ prop "drainBy" Main.drainBy
448+ prop "mean" Main.mean
449+ prop "stdDev" Main.stdDev
450+ prop "variance" Main.variance
451+ prop "mconcat" Main.mconcat
452+ prop "foldMap" Main.foldMap
453+ prop "foldMapM" Main.foldMapM
454+ prop "lookup" Main.lookup
455+ prop "mapM" Main.mapM
456+ prop "teeWithLength" Main.teeWithLength
457+ prop "teeWithMax" Main.teeWithMax
458+ prop "distribute" Main.distribute
459+ prop "partition" Main.partition
460+ prop "unzip" Main.unzip