@@ -1,16 +1,31 @@
11module Main (main) where
22
3+import Prelude hiding
4+ (maximum, minimum, elem, notElem, null, product, sum, head, last)
5+import Data.Semigroup (Sum(..), getSum)
6+import Test.QuickCheck
7+ ( Gen
8+ , Property
9+ , arbitrary
10+ , choose
11+ , forAll
12+ , listOf
13+ , listOf1
14+ , property
15+ , vectorOf
16+ , withMaxSuccess
17+ )
18+import Prelude hiding
19+ (maximum, minimum, elem, notElem, null, product, sum, head, last)
320import 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)
22+
523import qualified Streamly.Internal.Data.Fold as F
624import qualified Streamly.Prelude as S
725import qualified Streamly.Data.Fold as FL
826
927import Test.Hspec as H
1028import Test.Hspec.QuickCheck
11−import Test.QuickCheck
12− (Property, property, forAll, Gen, vectorOf, arbitrary, choose, listOf)
13−import Test.QuickCheck.Monadic (monadicIO, assert, run)
1429
1530maxStreamLen :: Int
1631maxStreamLen = 1000
@@ -43,75 +58,75 @@ rollingHashFirstN =
4358 b <- run $ S.fold (F.rollingHashFirstN n) $ S.fromList vec
4459 assert $ a == b
4560
46−
4761head :: [Int] -> Expectation
4862head ls = S.fold FL.head (S.fromList ls) `shouldReturn` headl ls
49− where
50− headl [] = Nothing
51− headl (x:_) = Just x
5263
64+ where
65+
66+ headl [] = Nothing
67+ headl (x:_) = Just x
5368
5469length :: [Int] -> Expectation
5570length ls = S.fold FL.length (S.fromList ls) `shouldReturn` Prelude.length ls
5671
57−
5872sum :: [Int] -> Expectation
5973sum ls = S.fold FL.sum (S.fromList ls) `shouldReturn` foldl (+) 0 ls
6074
61−
6275product :: [Int] -> Expectation
6376product ls = S.fold FL.product (S.fromList ls) `shouldReturn` foldl (*) 1 ls
6477
65−
6678lesser :: (a -> a -> Ordering) -> a -> a -> a
6779lesser f x y = if f x y == LT then x else y
6880
69−
7081greater :: (a -> a -> Ordering) -> a -> a -> a
7182greater f x y = if f x y == GT then x else y
7283
73−
7484foldMaybe :: (b -> a -> b) -> b -> [a] -> Maybe b
7585foldMaybe f acc ls =
76− case ls of
77− [] -> Nothing
78− _ -> Just (foldl f acc ls)
79−
86+ case ls of
87+ [] -> Nothing
88+ _ -> Just (foldl f acc ls)
8089
8190maximumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
82−maximumBy genmin f ls = S.fold (FL.maximumBy f) (S.fromList ls) `shouldReturn` foldMaybe (greater f) genmin ls
83−
91+maximumBy genmin f ls =
92+ S.fold (FL.maximumBy f) (S.fromList ls)
93+ `shouldReturn`
94+ foldMaybe (greater f) genmin ls
8495
8596maximum :: (Show a, Ord a) => a -> [a] -> Expectation
86−maximum genmin ls = S.fold FL.maximum (S.fromList ls) `shouldReturn` foldMaybe (greater compare) genmin ls
87−
97+maximum genmin ls =
98+ S.fold FL.maximum (S.fromList ls)
99+ `shouldReturn` foldMaybe (greater compare) genmin ls
88100
89101minimumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
90−minimumBy genmax f ls = S.fold (FL.minimumBy f) (S.fromList ls) `shouldReturn` foldMaybe (lesser f) genmax ls
91−
102+minimumBy genmax f ls =
103+ S.fold (FL.minimumBy f) (S.fromList ls)
104+ `shouldReturn` foldMaybe (lesser f) genmax ls
92105
93106minimum :: (Show a, Ord a) => a -> [a] -> Expectation
94−minimum genmax ls = S.fold FL.minimum (S.fromList ls) `shouldReturn` foldMaybe (lesser compare) genmax ls
95−
107+minimum genmax ls =
108+ S.fold FL.minimum (S.fromList ls)
109+ `shouldReturn` foldMaybe (lesser compare) genmax ls
96110
97111toList :: [Int] -> Expectation
98112toList ls = S.fold FL.toList (S.fromList ls) `shouldReturn` ls
99113
100−
101114safeLast :: [a] -> Maybe a
102115safeLast [] = Nothing
103116safeLast (x:[]) = Just x
104117safeLast (_:xs) = safeLast xs
105118
106−
107119last :: [String] -> Expectation
108120last ls = S.fold FL.last (S.fromList ls) `shouldReturn` safeLast ls
109121
110122mapMaybe :: [Int] -> Expectation
111123mapMaybe ls =
112− (let f = F.mapMaybe (\x -> if even x then Just x else Nothing) FL.toList
113− in S.fold f (S.fromList ls))
114− `shouldReturn` filter even ls
124+ let maybeEven x =
125+ if even x
126+ then Just x
127+ else Nothing
128+ f = F.mapMaybe maybeEven FL.toList
129+ in S.fold f (S.fromList ls) `shouldReturn` filter even ls
115130
116131nth :: Int -> [a] -> Maybe a
117132nth idx (x:xs) = if idx == 0
@@ -121,48 +136,52 @@ nth idx (x:xs) = if idx == 0
121136 else nth (idx - 1) xs
122137nth _ [] = Nothing
123138
124−
125139index :: Int -> [String] -> Expectation
126140index idx ls = let x = S.fold (FL.index idx) (S.fromList ls)
127141 in x `shouldReturn` (nth idx ls)
128142
129−
130143find :: (Show a, Eq a) => (a -> Bool) -> [a] -> Expectation
131144find f ls = do
132− let x = S.fold (FL.findIndex f) (S.fromList ls)
133− y <- x
134− case y of
135− Nothing -> S.fold (FL.find f) (S.fromList ls) `shouldReturn` Nothing
136− Just idx -> S.fold (FL.any f) (S.fromList $ take idx ls) `shouldReturn` False
137−
145+ y <- S.fold (FL.findIndex f) (S.fromList ls)
146+ case y of
147+ Nothing ->
148+ let fld = S.fold (FL.find f) (S.fromList ls)
149+ in fld `shouldReturn` Nothing
150+ Just idx ->
151+ let fld = S.fold (FL.any f) (S.fromList $ take idx ls)
152+ in fld `shouldReturn` False
138153
139154neg :: (a -> Bool) -> a -> Bool
140155neg f x = if f x == True then False else True
141156
142157findIndex :: (a -> Bool) -> [a] -> Expectation
143158findIndex f ls = do
144− let x = S.fold (FL.findIndex f) (S.fromList ls)
145− y <- x
146− case y of
147− Nothing -> S.fold (FL.all $ neg f) (S.fromList ls) `shouldReturn` True
148− Just idx -> if idx == 0
149− then S.fold (FL.all f) (S.fromList []) `shouldReturn` True
150− else S.fold (FL.all f) (S.fromList $ (take idx ls)) `shouldReturn` False
159+ y <- S.fold (FL.findIndex f) (S.fromList ls)
160+ case y of
161+ Nothing ->
162+ let fld = S.fold (FL.all $ neg f) (S.fromList ls)
163+ in fld `shouldReturn` True
164+ Just idx -> if idx == 0
165+ then
166+ S.fold (FL.all f) (S.fromList []) `shouldReturn` True
167+ else
168+ S.fold (FL.all f) (S.fromList $ (take idx ls))
169+ `shouldReturn`
170+ False
151171
152172predicate :: Int -> Bool
153173predicate x = if x * x < 100 then True else False
154174
155175elemIndex :: Int -> [Int] -> Expectation
156176elemIndex elm ls = do
157− let x = S.fold (FL.elemIndex elm) (S.fromList ls)
158− y <- x
159− case y of
160− Nothing -> S.fold (FL.any (\z -> if z == elm
161− then True
162− else False)) (S.fromList ls) `shouldReturn` False
163− Just idx -> S.fold (FL.any (\z -> if z == elm
164− then True
165− else False)) (S.fromList $ (take idx ls)) `shouldReturn` False
177+ y <- S.fold (FL.elemIndex elm) (S.fromList ls)
178+ case y of
179+ Nothing ->
180+ let fld = S.fold (FL.any (== elm)) (S.fromList ls)
181+ in fld `shouldReturn` False
182+ Just idx ->
183+ let fld = S.fold (FL.any (== elm)) (S.fromList $ (take idx ls))
184+ in fld `shouldReturn` False
166185
167186null :: [Int] -> Expectation
168187null 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
170189 _ -> False
171190elem :: Int -> [Int] -> Expectation
172191elem elm ls = do
173− let x = S.fold (FL.elem elm) (S.fromList ls)
174− y <- x
175− S.fold (FL.any (\z -> if z == elm
176− then True
177− else False)) (S.fromList ls) `shouldReturn` y
178−
192+ y <- S.fold (FL.elem elm) (S.fromList ls)
193+ let fld = S.fold (FL.any (== elm)) (S.fromList ls)
194+ fld `shouldReturn` y
179195
180196notElem :: Int -> [Int] -> Expectation
181197notElem elm ls = do
182− let x = S.fold (FL.notElem elm) (S.fromList ls)
183− y <- x
184− S.fold (FL.any (\z -> if z == elm
185− then True
186− else False)) (S.fromList ls) `shouldReturn` (if y == True
187− then False
188− else True)
189−
198+ y <- S.fold (FL.notElem elm) (S.fromList ls)
199+ let fld = S.fold (FL.any (== elm)) (S.fromList ls)
200+ fld `shouldReturn` not y
190201
191202all :: (a -> Bool) -> [a] -> Expectation
192−all f ls = S.fold (FL.all f) (S.fromList ls) `shouldReturn` Prelude.and (map f ls)
193−
203+all f ls =
204+ S.fold (FL.all f) (S.fromList ls) `shouldReturn` Prelude.and (map f ls)
194205
195206any :: (a -> Bool) -> [a] -> Expectation
196207any f ls = S.fold (FL.any f) (S.fromList ls) `shouldReturn` Prelude.any f ls
197208
198−
199209and :: [Bool] -> Expectation
200210and ls = S.fold FL.and (S.fromList ls) `shouldReturn` Prelude.and ls
201211
202−
203212or :: [Bool] -> Expectation
204213or ls = S.fold FL.or (S.fromList ls) `shouldReturn` Prelude.or ls
205214
@@ -230,6 +239,181 @@ sliceSepByMax =
230239 Right xs -> checkListEqual xs ys
231240 Left _ -> property False
232241
242+chooseFloat :: (Float, Float) -> Gen Float
243+chooseFloat = choose
244+
245+drain :: [Int] -> Expectation
246+drain ls = S.fold FL.drain (S.fromList ls) `shouldReturn` ()
247+
248+drainBy :: [Int] -> Expectation
249+drainBy ls = S.fold (FL.drainBy return) (S.fromList ls) `shouldReturn` ()
250+
251+mean :: Property
252+mean =
253+ forAll (listOf1 (chooseFloat (-100.0, 100.0)))
254+ $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
255+
256+ where
257+
258+ action ls = do
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)
262+
263+stdDev :: Property
264+stdDev =
265+ forAll (listOf1 (chooseFloat (-100.0, 100.0)))
266+ $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
267+
268+ where
269+
270+ action ls = do
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 )
276+
277+variance :: Property
278+variance =
279+ forAll (listOf1 (chooseFloat (-100.0, 100.0)))
280+ $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
281+
282+ where
283+
284+ action ls = do
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 )
290+
291+mconcat :: Property
292+mconcat =
293+ forAll (listOf1 (chooseInt (intMin, intMax)))
294+ $ \ls0 -> monadicIO $ action ls0
295+
296+ where
297+
298+ action ls = do
299+ v1 <- run $ S.fold FL.mconcat (S.map Sum $ S.fromList ls)
300+ let v2 = (foldl (+) 0 ls)
301+ assert (getSum v1 == v2)
302+
303+foldMap :: Property
304+foldMap =
305+ forAll (listOf1 (chooseInt (intMin, intMax)))
306+ $ \ls0 -> monadicIO $ action ls0
307+
308+ where
309+
310+ action ls = do
311+ v1 <- run $ S.fold (FL.foldMap Sum) $ S.fromList ls
312+ let v2 = (foldl (+) 0 ls)
313+ assert (getSum v1 == v2)
314+
315+foldMapM :: Property
316+foldMapM =
317+ forAll (listOf1 (chooseInt (intMin, intMax)))
318+ $ \ls0 -> monadicIO $ action ls0
319+
320+ where
321+
322+ action ls = do
323+ v1 <- run $ S.fold (FL.foldMapM (return . Sum)) $ S.fromList ls
324+ let v2 = (foldl (+) 0 ls)
325+ assert (getSum v1 == v2)
326+
327+lookup :: Property
328+lookup =
329+ forAll (chooseInt (1, 15))
330+ $ \key0 ->monadicIO $ action key0
331+
332+ where
333+
334+ action key = do
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
341+ assert (v1 == v2)
342+
343+mapM :: Property
344+mapM =
345+ forAll (listOf1 (chooseInt (intMin, intMax)))
346+ $ \ls0 -> monadicIO $ action ls0
347+
348+ where
349+
350+ action ls = do
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
355+ assert (v1 == v2)
356+
357+teeWithLength :: Property
358+teeWithLength =
359+ forAll (listOf1 (chooseInt (intMin, intMax)))
360+ $ \ls0 -> monadicIO $ action ls0
361+
362+ where
363+
364+ action ls = do
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))
369+
370+teeWithMax :: Property
371+teeWithMax =
372+ forAll (listOf1 (chooseInt (intMin, intMax)))
373+ $ \ls0 -> monadicIO $ action ls0
374+
375+ where
376+
377+ action ls = do
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))
382+
383+distribute :: Property
384+distribute =
385+ forAll (listOf1 (chooseInt (intMin, intMax)))
386+ $ \ls0 -> monadicIO $ action ls0
387+
388+ where
389+
390+ action ls = do
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])
395+
396+partition :: Property
397+partition =
398+ monadicIO $ do
399+ v1 :: (Int, [String]) <-
400+ run
401+ $ S.fold (FL.partition FL.sum FL.toList)
402+ $ S.fromList
403+ [Left 1, Right "abc", Left 3, Right "xy", Right "pp2"]
404+ let v2 = (4,["abc","xy","pp2"])
405+ assert (v1 == v2)
406+
407+unzip :: Property
408+unzip =
409+ monadicIO $ do
410+ v1 :: (Int, [String]) <-
411+ run
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"])
415+ assert (v1 == v2)
416+
233417main :: IO ()
234418main = hspec $
235419 describe "Fold s" $ do
@@ -259,3 +443,18 @@ main = hspec $
259443 prop "ltake" ltake
260444 prop "sliceSepBy" sliceSepBy
261445 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