1module Main (main) where
3import Data.Semigroup (Sum(..), getSum)
4import Streamly.Test.Common (checkListEqual, listEquals)
17import Test.QuickCheck.Monadic (monadicIO, assert, run)
19import qualified Data.Map
20import qualified Prelude
21import qualified Streamly.Internal.Data.Fold as F
22import qualified Streamly.Prelude as S
23import qualified Streamly.Internal.Data.Stream.IsStream as Stream
24import qualified Streamly.Data.Fold as FL
27 (maximum, minimum, elem, notElem, null, product, sum, head, last, take)
29import Test.Hspec.QuickCheck
46chooseInt :: (Int, Int) -> Gen Int
49{-# INLINE maxStreamLen #-}
53rollingHashFirstN :: Property
55 forAll (choose (0, maxStreamLen)) $ \len ->
56 forAll (choose (0, len)) $ \n ->
57 forAll (vectorOf len (arbitrary :: Gen Int)) $ \vec ->
59 a <- run $ S.fold F.rollingHash $ S.take n $ S.fromList vec
60 b <- run $ S.fold (F.rollingHashFirstN n) $ S.fromList vec
63head :: [Int] -> Expectation
64head ls = S.fold FL.head (S.fromList ls) `shouldReturn` headl ls
66headl :: [a] -> Maybe a
70length :: [Int] -> Expectation
71length ls = S.fold FL.length (S.fromList ls) `shouldReturn` Prelude.length ls
73sum :: [Int] -> Expectation
74sum ls = S.fold FL.sum (S.fromList ls) `shouldReturn` Prelude.sum ls
76product :: [Int] -> Expectation
78 S.fold FL.product (S.fromList ls) `shouldReturn` Prelude.product ls
80lesser :: (a -> a -> Ordering) -> a -> a -> a
81lesser f x y = if f x y == LT then x else y
83greater :: (a -> a -> Ordering) -> a -> a -> a
84greater f x y = if f x y == GT then x else y
86foldMaybe :: (b -> a -> b) -> b -> [a] -> Maybe b
90 _ -> Just (foldl f acc ls)
92maximumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
93maximumBy genmin f ls =
94 S.fold (FL.maximumBy f) (S.fromList ls)
95 `shouldReturn` foldMaybe (greater f) genmin ls
97maximum :: (Show a, Ord a) => a -> [a] -> Expectation
99 S.fold FL.maximum (S.fromList ls)
100 `shouldReturn` foldMaybe (greater compare) genmin ls
102minimumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
103minimumBy genmax f ls =
104 S.fold (FL.minimumBy f) (S.fromList ls)
105 `shouldReturn` foldMaybe (lesser f) genmax ls
107minimum :: (Show a, Ord a) => a -> [a] -> Expectation
109 S.fold FL.minimum (S.fromList ls)
110 `shouldReturn` foldMaybe (lesser compare) genmax ls
112toList :: [Int] -> Expectation
113toList ls = S.fold FL.toList (S.fromList ls) `shouldReturn` ls
115toListRev :: [Int] -> Expectation
116toListRev ls = S.fold FL.toListRev (S.fromList ls) `shouldReturn` reverse ls
118safeLast :: [a] -> Maybe a
120safeLast (x:[]) = Just x
121safeLast (_:xs) = safeLast xs
123last :: [String] -> Expectation
124last ls = S.fold FL.last (S.fromList ls) `shouldReturn` safeLast ls
126mapMaybe :: [Int] -> Expectation
132 f = FL.mapMaybe maybeEven FL.toList
133 in S.fold f (S.fromList ls) `shouldReturn` filter even ls
135nth :: Int -> [a] -> Maybe a
139 | otherwise = nth (idx - 1) xs
142index :: Int -> [String] -> Expectation
144 let x = S.fold (FL.index idx) (S.fromList ls)
145 in x `shouldReturn` nth idx ls
147find :: (Show a, Eq a) => (a -> Bool) -> [a] -> Expectation
149 y <- S.fold (FL.findIndex f) (S.fromList ls)
152 let fld = S.fold (FL.find f) (S.fromList ls)
153 in fld `shouldReturn` Nothing
155 let fld = S.fold (FL.any f) (S.fromList $ Prelude.take idx ls)
156 in fld `shouldReturn` False
158neg :: (a -> Bool) -> a -> Bool
161findIndex :: (a -> Bool) -> [a] -> Expectation
163 y <- S.fold (FL.findIndex f) (S.fromList ls)
166 let fld = S.fold (FL.all $ neg f) (S.fromList ls)
167 in fld `shouldReturn` True
171 S.fold (FL.all f) (S.fromList []) `shouldReturn` True
173 S.fold (FL.all f) (S.fromList $ Prelude.take idx ls)
176predicate :: Int -> Bool
177predicate x = x * x < 100
179elemIndex :: Int -> [Int] -> Expectation
181 y <- S.fold (FL.elemIndex elm) (S.fromList ls)
184 let fld = S.fold (FL.any (== elm)) (S.fromList ls)
185 in fld `shouldReturn` False
188 S.fold (FL.any (== elm)) (S.fromList $ Prelude.take idx ls)
189 in fld `shouldReturn` False
191null :: [Int] -> Expectation
193 S.fold FL.null (S.fromList ls)
199elem :: Int -> [Int] -> Expectation
201 y <- S.fold (FL.elem elm) (S.fromList ls)
202 let fld = S.fold (FL.any (== elm)) (S.fromList ls)
205notElem :: Int -> [Int] -> Expectation
207 y <- S.fold (FL.notElem elm) (S.fromList ls)
208 let fld = S.fold (FL.any (== elm)) (S.fromList ls)
209 fld `shouldReturn` not y
211all :: (a -> Bool) -> [a] -> Expectation
213 S.fold (FL.all f) (S.fromList ls) `shouldReturn` Prelude.all f ls
215any :: (a -> Bool) -> [a] -> Expectation
216any f ls = S.fold (FL.any f) (S.fromList ls) `shouldReturn` Prelude.any f ls
218and :: [Bool] -> Expectation
219and ls = S.fold FL.and (S.fromList ls) `shouldReturn` Prelude.and ls
221or :: [Bool] -> Expectation
222or ls = S.fold FL.or (S.fromList ls) `shouldReturn` Prelude.or ls
224take :: [Int] -> Property
226 forAll (chooseInt (-1, Prelude.length ls + 2)) $ \n ->
227 S.fold (FL.take n FL.toList) (S.fromList ls)
228 `shouldReturn` Prelude.take n ls
230takeEndBy_ :: Property
232 forAll (listOf (chooseInt (0, 1))) $ \ls ->
234 f = FL.takeEndBy_ p FL.toList
235 ys = Prelude.takeWhile (not . p) ls
236 in case S.fold f (S.fromList ls) of
237 Right xs -> checkListEqual xs ys
238 Left _ -> property False
240takeEndByOrMax :: Property
242 forAll (chooseInt (min_value, max_value)) $ \n ->
243 forAll (listOf (chooseInt (0, 1))) $ \ls ->
245 f = FL.takeEndBy_ p (FL.take n FL.toList)
246 ys = Prelude.take n (Prelude.takeWhile (not . p) ls)
247 in case S.fold f (S.fromList ls) of
248 Right xs -> checkListEqual xs ys
249 Left _ -> property False
251chooseFloat :: (Float, Float) -> Gen Float
254drain :: [Int] -> Expectation
255drain ls = S.fold FL.drain (S.fromList ls) `shouldReturn` ()
257drainBy :: [Int] -> Expectation
258drainBy ls = S.fold (FL.drainBy return) (S.fromList ls) `shouldReturn` ()
262 forAll (listOf1 (chooseFloat (-100.0, 100.0)))
263 $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
268 v1 <- run $ S.fold FL.mean (S.fromList ls)
269 let v2 = Prelude.sum ls / fromIntegral (Prelude.length ls)
270 assert (abs (v1 - v2) < 0.0001)
274 forAll (listOf1 (chooseFloat (-100.0, 100.0)))
275 $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
280 v1 <- run $ S.fold FL.stdDev (S.fromList ls)
281 let avg = Prelude.sum ls / fromIntegral (Prelude.length ls)
282 se = Prelude.sum (fmap (\x -> (x - avg) * (x - avg)) ls)
283 sd = sqrt $ se / fromIntegral (Prelude.length ls)
284 assert (abs (v1 - sd) < 0.0001 )
288 forAll (listOf1 (chooseFloat (-100.0, 100.0)))
289 $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
294 v1 <- run $ S.fold FL.variance (S.fromList ls)
295 let avg = Prelude.sum ls / fromIntegral (Prelude.length ls)
296 se = Prelude.sum (fmap (\x -> (x - avg) * (x - avg)) ls)
297 vr = se / fromIntegral (Prelude.length ls)
298 assert (abs (v1 - vr) < 0.01 )
302 forAll (listOf1 (chooseInt (intMin, intMax)))
303 $ \ls0 -> monadicIO $ action ls0
308 v1 <- run $ S.fold FL.mconcat (S.map Sum $ S.fromList ls)
309 let v2 = Prelude.sum ls
310 assert (getSum v1 == v2)
314 forAll (listOf1 (chooseInt (intMin, intMax)))
315 $ \ls0 -> monadicIO $ action ls0
320 v1 <- run $ S.fold (FL.foldMap Sum) $ S.fromList ls
321 let v2 = Prelude.sum ls
322 assert (getSum v1 == v2)
326 forAll (listOf1 (chooseInt (intMin, intMax)))
327 $ \ls0 -> monadicIO $ action ls0
332 v1 <- run $ S.fold (FL.foldMapM (return . Sum)) $ S.fromList ls
333 let v2 = Prelude.sum ls
334 assert (getSum v1 == v2)
338 forAll (chooseInt (1, 15))
339 $ \key0 ->monadicIO $ action key0
344 let ls = [ (1, "first"), (2, "second"), (3, "third"), (4, "fourth")
345 , (5, "fifth"), (6, "fifth+first"), (7, "fifth+second")
346 , (8, "fifth+third"), (9, "fifth+fourth")
347 , (10, "fifth+fifth")
349 v1 <- run $ S.fold (FL.lookup key) $ S.fromList ls
350 let v2 = Prelude.lookup key ls
355 forAll (listOf1 (chooseInt (intMin, intMax)))
356 $ \ls0 -> monadicIO $ action ls0
361 let addLen x = return $ x + Prelude.length ls
362 fld = FL.rmapM addLen FL.sum
363 v2 = foldl (+) (Prelude.length ls) ls
364 v1 <- run $ S.fold fld $ S.fromList ls
367teeWithLength :: Property
369 forAll (listOf1 (chooseInt (intMin, intMax)))
370 $ \ls0 -> monadicIO $ action ls0
375 v1 <- run $ S.fold (FL.tee FL.sum FL.length) $ S.fromList ls
376 let v2 = Prelude.sum ls
377 v3 = Prelude.length ls
378 assert (v1 == (v2, v3))
380teeWithFstLength :: Property
382 forAll (listOf1 (chooseInt (intMin, intMax)))
383 $ \ls0 -> monadicIO $ action ls0
388 v1 <- run $ S.fold (F.teeWithFst (,) (FL.take 5 FL.sum) FL.length) $ S.fromList ls
389 let v2 = Prelude.sum (Prelude.take 5 ls)
390 v3 = Prelude.length (Prelude.take 5 ls)
391 assert (v1 == (v2, v3))
393partitionByM :: Property
395 forAll (listOf1 (chooseInt (intMin, intMax)))
396 $ \ls0 -> monadicIO $ action ls0
401 let f = \x -> if odd x then return (Left x) else return (Right x)
402 v1 <- run $ S.fold (F.partitionByM f FL.length FL.length) $ S.fromList ls
403 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ls
404 v3 = foldl (\b a -> if even a then b+1 else b) 0 ls
405 assert (v1 == (v2, v3))
407partitionByFstM :: Property
409 forAll (listOf1 (chooseInt (intMin, intMax)))
410 $ \ls0 -> monadicIO $ action ls0
415 let f = \x -> if odd x then return (Left x) else return (Right x)
416 v1 <- run $ S.fold (F.partitionByFstM f (FL.take 25 FL.length) FL.length) (S.fromList ([1..100]:: [Int]))
417 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ([1..49] :: [Int])
418 v3 = foldl (\b a -> if even a then b+1 else b) 0 ([1..49] :: [Int])
419 assert (v1 == (v2, v3))
421partitionByMinM1 :: Property
423 forAll (listOf1 (chooseInt (intMin, intMax)))
424 $ \ls0 -> monadicIO $ action ls0
429 let f = \x -> if odd x then return (Left x) else return (Right x)
430 v1 <- run $ S.fold (F.partitionByMinM f FL.length (FL.take 25 FL.length)) (S.fromList ([1..100]:: [Int]))
431 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ([1..50] :: [Int])
432 v3 = foldl (\b a -> if even a then b+1 else b) 0 ([1..50] :: [Int])
433 assert (v1 == (v2, v3))
435partitionByMinM2 :: Property
437 forAll (listOf1 (chooseInt (intMin, intMax)))
438 $ \ls0 -> monadicIO $ action ls0
443 let f = \x -> if odd x then return (Left x) else return (Right x)
444 v1 <- run $ S.fold (F.partitionByMinM f (FL.take 25 FL.length) FL.length) (S.fromList ([1..100]:: [Int]))
445 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ([1..49] :: [Int])
446 v3 = foldl (\b a -> if even a then b+1 else b) 0 ([1..49] :: [Int])
447 assert (v1 == (v2, v3))
449teeWithMinLength1 :: Property
451 forAll (listOf1 (chooseInt (intMin, intMax)))
452 $ \ls0 -> monadicIO $ action ls0
457 v1 <- run $ S.fold (F.teeWithMin (,) (FL.take 5 FL.sum) FL.length) $ S.fromList ls
458 let v2 = Prelude.sum (Prelude.take 5 ls)
459 v3 = Prelude.length (Prelude.take 5 ls)
460 assert (v1 == (v2, v3))
463teeWithMinLength2 :: Property
465 forAll (listOf1 (chooseInt (intMin, intMax)))
466 $ \ls0 -> monadicIO $ action ls0
471 v1 <- run $ S.fold (F.teeWithMin (,) FL.sum (FL.take 5 FL.length)) $ S.fromList ls
472 let v2 = Prelude.sum (Prelude.take 5 ls)
473 v3 = Prelude.length (Prelude.take 5 ls)
474 assert (v1 == (v2, v3))
475teeWithMax :: Property
477 forAll (listOf1 (chooseInt (intMin, intMax)))
478 $ \ls0 -> monadicIO $ action ls0
483 v1 <- run $ S.fold (FL.tee FL.sum FL.maximum) $ S.fromList ls
484 let v2 = Prelude.sum ls
485 v3 = foldMaybe (greater compare) intMin ls
486 assert (v1 == (v2, v3))
488distribute :: Property
490 forAll (listOf1 (chooseInt (intMin, intMax)))
491 $ \ls0 -> monadicIO $ action ls0
496 v1 <- run $ S.fold (FL.distribute [FL.sum, FL.length]) $ S.fromList ls
497 let v2 = Prelude.sum ls
498 v3 = Prelude.length ls
499 assert (v1 == [v2, v3])
504 v1 :: (Int, [String]) <-
506 $ S.fold (FL.partition FL.sum FL.toList)
508 [Left 1, Right "abc", Left 3, Right "xy", Right "pp2"]
509 let v2 = (4,["abc","xy","pp2"])
515 v1 :: (Int, [String]) <-
517 $ S.fold (FL.unzip FL.sum FL.toList)
518 $ S.fromList [(1, "aa"), (2, "bb"), (3, "cc")]
519 let v2 = (6, ["aa", "bb", "cc"])
524 forAll (listOf (chooseInt (0, 100))) $ \lst ->
525 forAll (chooseInt (1, 100)) $ \i ->
527 let strm = S.fromList lst
528 r1 <- S.fold (FL.many (split i) FL.toList) strm
529 r2 <- S.toList $ Stream.foldMany (split i) strm
534 split i = FL.take i FL.toList
536headAndRest :: [Int] -> Property
537headAndRest ls = monadicIO $ do
538 (mbh, rest) <- run $ Stream.fold_ FL.head (S.fromList ls)
539 rests <- run $ S.toList rest
540 assert (mbh == headl ls)
541 listEquals (==) rests (taill ls)
551 let table = Data.Map.fromList [("SUM", FL.sum), ("PRODUCT", FL.product)]
552 input = Stream.fromList (
557 ] :: [(String, Int)])
562 Data.Map.fromList [("PRODUCT", 8),("SUM", 4)]
565demuxWithSum :: Expectation
567 let f x = ("SUM", x::Int)
568 table = Data.Map.fromList [("SUM", FL.sum)]
569 input = Stream.fromList [1, 4]
571 (F.demuxWith f table)
574 Data.Map.fromList [("SUM", 5)]
576demuxWithProduct :: Expectation
578 let f x = ("PRODUCT", x::Int)
579 table = Data.Map.fromList [("PRODUCT", FL.product)]
580 input = Stream.fromList [2, 4]
582 (F.demuxWith f table)
585 Data.Map.fromList [("PRODUCT", 8)]
587demuxDefaultWithSum :: Expectation
589 let f x = ("SUM", x::Int)
590 table = Data.Map.fromList [("SUM", FL.sum)]
591 input = Stream.fromList [2, 4]
593 (F.demuxDefaultWith f table (FL.lmap snd FL.sum))
596 (Data.Map.fromList [("SUM" , 6)] , 0)
598demuxDefaultWithProduct :: Expectation
599demuxDefaultWithProduct =
600 let f x = ("PRODUCT", x::Int)
601 table = Data.Map.fromList [("PRODUCT", FL.product)]
602 input = Stream.fromList [2, 4]
604 (F.demuxDefaultWith f table (FL.lmap snd FL.product))
607 (Data.Map.fromList [("PRODUCT" , 8)] , 1)
609demuxDefault :: Expectation
611 let table = Data.Map.fromList [("SUM", FL.sum), ("PRODUCT", FL.product)]
612 input = Stream.fromList
614 , ("PRODUCT", 2::Int)
616 , ("PRODUCT", 4::Int)
619 (F.demuxDefault table (FL.lmap snd FL.product))
622 (Data.Map.fromList [("PRODUCT", 8), ("SUM", 4)], 1)
624demuxDefaultEmpty :: Expectation
626 let table = Data.Map.empty
627 input = Stream.fromList []
629 (F.demuxDefault table (FL.lmap snd FL.product))
632 (Data.Map.fromList ([]::[(String, Int)]), 1)
634classifyWith :: Expectation
636 let input = Stream.fromList [("ONE",1),("ONE",1.1),("TWO",2), ("TWO",2.2)]
638 (F.classifyWith fst (FL.lmap snd FL.toList))
642 [("ONE",[1.0, 1.1 :: Double]), ("TWO",[2.0, 2.2])]
644classify :: Expectation
650 , ("ONE", (1, 1.1:: Double))
655 (F.classify (FL.lmap snd FL.toList))
659 [("ONE",[1.0, 1.1 :: Double]), ("TWO",[2.0, 2.2])]
661splitAt :: Expectation
664 (F.splitAt 6 FL.toList FL.toList)
665 (Stream.fromList "Hello World!")
670moduleName = "Data.Fold"
674 describe moduleName $ do
677 prop "mconcat" Main.mconcat
678 prop "foldMap" Main.foldMap
679 prop "foldMapM" Main.foldMapM
681 prop "drain" Main.drain
682 prop "drainBy" Main.drainBy
684 prop "length" Main.length
686 prop "product" product
687 prop "maximumBy" $ maximumBy intMin compare
688 prop "maximum" $ maximum intMin
689 prop "minimumBy" $ minimumBy intMax compare
690 prop "minimum" $ minimum intMax
691 prop "mean" Main.mean
692 prop "stdDev" Main.stdDev
693 prop "variance" Main.variance
694 prop "rollingHashFirstN" rollingHashFirstN
697 prop "toListRev" toListRev
699 prop "demuxWithSum" demuxWithSum
700 prop "demuxWithProduct" demuxWithProduct
701 prop "demuxDefaultWithSum" demuxDefaultWithSum
702 prop "demuxDefaultWithProduct" demuxDefaultWithProduct
703 prop "demuxDefault" demuxDefault
704 prop "demuxDefaultEmpty" demuxDefaultEmpty
705 prop "classifyWith" classifyWith
706 prop "classify" classify
711 prop "find" $ find predicate
712 prop "lookup" Main.lookup
713 prop "findIndex" $ findIndex predicate
714 prop "elemIndex" $ elemIndex 10
716 prop "elem" $ elem 10
717 prop "notElem" $ notElem 10
718 prop "all" $ Main.all predicate
719 prop "any" $ Main.any predicate
728 prop "rmapM" Main.rmapM
734 prop "mapMaybe" mapMaybe
739 prop "takeEndBy_" takeEndBy_
740 prop "takeEndByOrMax" takeEndByOrMax
747 prop "teeWithLength" Main.teeWithLength
748 prop "teeWithFstLength" Main.teeWithFstLength
749 prop "teeWithMinLength1" Main.teeWithMinLength1
750 prop "teeWithMinLength2" Main.teeWithMinLength2
751 prop "teeWithMax" Main.teeWithMax
752 prop "partitionByM" Main.partitionByM
753 prop "partitionByFstM" Main.partitionByFstM
754 prop "partitionByMinM1" Main.partitionByMinM1
755 prop "partitionByMinM2" Main.partitionByMinM2
756 prop "distribute" Main.distribute
759 prop "partition" Main.partition
760 prop "partitionByM" partitionByM
763 prop "unzip" Main.unzip
764 prop "splitAt" Main.splitAt
767 prop "many" Main.many
771 prop "head from fold_" headAndRest
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list