1module Main (main) where
4import Data.Semigroup (Sum(..), getSum)
5import Streamly.Test.Common (checkListEqual, listEquals)
19import Control.Monad.IO.Class (liftIO)
20import Test.QuickCheck.Monadic (monadicIO, assert, run)
22import qualified Data.Map
23import qualified Prelude
24import qualified Streamly.Internal.Data.Fold as F
25import qualified Streamly.Prelude as S
26import qualified Streamly.Internal.Data.Array.Foreign.Mut.Type as MA
27import qualified Streamly.Internal.Data.Stream.IsStream as Stream
28import qualified Streamly.Data.Fold as FL
31 (maximum, minimum, elem, notElem, null, product, sum, head, last, take)
33import Test.Hspec.QuickCheck
50chooseInt :: (Int, Int) -> Gen Int
53{-# INLINE maxStreamLen #-}
57rollingHashFirstN :: Property
59 forAll (choose (0, maxStreamLen)) $ \len ->
60 forAll (choose (0, len)) $ \n ->
61 forAll (vectorOf len (arbitrary :: Gen Int)) $ \vec ->
63 a <- run $ S.fold F.rollingHash $ S.take n $ S.fromList vec
64 b <- run $ S.fold (F.rollingHashFirstN n) $ S.fromList vec
67head :: [Int] -> Expectation
68head ls = S.fold FL.head (S.fromList ls) `shouldReturn` headl ls
70headl :: [a] -> Maybe a
74length :: [Int] -> Expectation
75length ls = S.fold FL.length (S.fromList ls) `shouldReturn` Prelude.length ls
77sum :: [Int] -> Expectation
78sum ls = S.fold FL.sum (S.fromList ls) `shouldReturn` Prelude.sum ls
80product :: [Int] -> Expectation
82 S.fold FL.product (S.fromList ls) `shouldReturn` Prelude.product ls
84lesser :: (a -> a -> Ordering) -> a -> a -> a
85lesser f x y = if f x y == LT then x else y
87greater :: (a -> a -> Ordering) -> a -> a -> a
88greater f x y = if f x y == GT then x else y
90foldMaybe :: (b -> a -> b) -> b -> [a] -> Maybe b
94 _ -> Just (foldl f acc ls)
96maximumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
97maximumBy genmin f ls =
98 S.fold (FL.maximumBy f) (S.fromList ls)
99 `shouldReturn` foldMaybe (greater f) genmin ls
101maximum :: (Show a, Ord a) => a -> [a] -> Expectation
103 S.fold FL.maximum (S.fromList ls)
104 `shouldReturn` foldMaybe (greater compare) genmin ls
106minimumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
107minimumBy genmax f ls =
108 S.fold (FL.minimumBy f) (S.fromList ls)
109 `shouldReturn` foldMaybe (lesser f) genmax ls
111minimum :: (Show a, Ord a) => a -> [a] -> Expectation
113 S.fold FL.minimum (S.fromList ls)
114 `shouldReturn` foldMaybe (lesser compare) genmax ls
116toList :: [Int] -> Expectation
117toList ls = S.fold FL.toList (S.fromList ls) `shouldReturn` ls
119toListRev :: [Int] -> Expectation
120toListRev ls = S.fold FL.toListRev (S.fromList ls) `shouldReturn` reverse ls
122safeLast :: [a] -> Maybe a
124safeLast (x:[]) = Just x
125safeLast (_:xs) = safeLast xs
127last :: [String] -> Expectation
128last ls = S.fold FL.last (S.fromList ls) `shouldReturn` safeLast ls
130mapMaybe :: [Int] -> Expectation
136 f = FL.mapMaybe maybeEven FL.toList
137 in S.fold f (S.fromList ls) `shouldReturn` filter even ls
139nth :: Int -> [a] -> Maybe a
143 | otherwise = nth (idx - 1) xs
146index :: Int -> [String] -> Expectation
148 let x = S.fold (FL.index idx) (S.fromList ls)
149 in x `shouldReturn` nth idx ls
151find :: (Show a, Eq a) => (a -> Bool) -> [a] -> Expectation
153 y <- S.fold (FL.findIndex f) (S.fromList ls)
156 let fld = S.fold (FL.find f) (S.fromList ls)
157 in fld `shouldReturn` Nothing
159 let fld = S.fold (FL.any f) (S.fromList $ Prelude.take idx ls)
160 in fld `shouldReturn` False
162neg :: (a -> Bool) -> a -> Bool
165findIndex :: (a -> Bool) -> [a] -> Expectation
167 y <- S.fold (FL.findIndex f) (S.fromList ls)
170 let fld = S.fold (FL.all $ neg f) (S.fromList ls)
171 in fld `shouldReturn` True
175 S.fold (FL.all f) (S.fromList []) `shouldReturn` True
177 S.fold (FL.all f) (S.fromList $ Prelude.take idx ls)
180predicate :: Int -> Bool
181predicate x = x * x < 100
183elemIndex :: Int -> [Int] -> Expectation
185 y <- S.fold (FL.elemIndex elm) (S.fromList ls)
188 let fld = S.fold (FL.any (== elm)) (S.fromList ls)
189 in fld `shouldReturn` False
192 S.fold (FL.any (== elm)) (S.fromList $ Prelude.take idx ls)
193 in fld `shouldReturn` False
195null :: [Int] -> Expectation
197 S.fold FL.null (S.fromList ls)
203elem :: Int -> [Int] -> Expectation
205 y <- S.fold (FL.elem elm) (S.fromList ls)
206 let fld = S.fold (FL.any (== elm)) (S.fromList ls)
209notElem :: Int -> [Int] -> Expectation
211 y <- S.fold (FL.notElem elm) (S.fromList ls)
212 let fld = S.fold (FL.any (== elm)) (S.fromList ls)
213 fld `shouldReturn` not y
215all :: (a -> Bool) -> [a] -> Expectation
217 S.fold (FL.all f) (S.fromList ls) `shouldReturn` Prelude.all f ls
219any :: (a -> Bool) -> [a] -> Expectation
220any f ls = S.fold (FL.any f) (S.fromList ls) `shouldReturn` Prelude.any f ls
222and :: [Bool] -> Expectation
223and ls = S.fold FL.and (S.fromList ls) `shouldReturn` Prelude.and ls
225or :: [Bool] -> Expectation
226or ls = S.fold FL.or (S.fromList ls) `shouldReturn` Prelude.or ls
228take :: [Int] -> Property
230 forAll (chooseInt (-1, Prelude.length ls + 2)) $ \n ->
231 S.fold (FL.take n FL.toList) (S.fromList ls)
232 `shouldReturn` Prelude.take n ls
234takeEndBy_ :: Property
236 forAll (listOf (chooseInt (0, 1))) $ \ls ->
238 f = FL.takeEndBy_ p FL.toList
239 ys = Prelude.takeWhile (not . p) ls
240 in case S.fold f (S.fromList ls) of
241 Right xs -> checkListEqual xs ys
242 Left _ -> property False
244takeEndByOrMax :: Property
246 forAll (chooseInt (min_value, max_value)) $ \n ->
247 forAll (listOf (chooseInt (0, 1))) $ \ls ->
249 f = FL.takeEndBy_ p (FL.take n FL.toList)
250 ys = Prelude.take n (Prelude.takeWhile (not . p) ls)
251 in case S.fold f (S.fromList ls) of
252 Right xs -> checkListEqual xs ys
253 Left _ -> property False
255chooseFloat :: (Float, Float) -> Gen Float
258drain :: [Int] -> Expectation
259drain ls = S.fold FL.drain (S.fromList ls) `shouldReturn` ()
261drainBy :: [Int] -> Expectation
262drainBy ls = S.fold (FL.drainBy return) (S.fromList ls) `shouldReturn` ()
266 forAll (listOf1 (chooseFloat (-100.0, 100.0)))
267 $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
272 v1 <- run $ S.fold FL.mean (S.fromList ls)
273 let v2 = Prelude.sum ls / fromIntegral (Prelude.length ls)
274 assert (abs (v1 - v2) < 0.0001)
278 forAll (listOf1 (chooseFloat (-100.0, 100.0)))
279 $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
284 v1 <- run $ S.fold FL.stdDev (S.fromList ls)
285 let avg = Prelude.sum ls / fromIntegral (Prelude.length ls)
286 se = Prelude.sum (fmap (\x -> (x - avg) * (x - avg)) ls)
287 sd = sqrt $ se / fromIntegral (Prelude.length ls)
288 assert (abs (v1 - sd) < 0.0001 )
292 forAll (listOf1 (chooseFloat (-100.0, 100.0)))
293 $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
298 v1 <- run $ S.fold FL.variance (S.fromList ls)
299 let avg = Prelude.sum ls / fromIntegral (Prelude.length ls)
300 se = Prelude.sum (fmap (\x -> (x - avg) * (x - avg)) ls)
301 vr = se / fromIntegral (Prelude.length ls)
302 assert (abs (v1 - vr) < 0.01 )
306 forAll (listOf1 (chooseInt (intMin, intMax)))
307 $ \ls0 -> monadicIO $ action ls0
312 v1 <- run $ S.fold FL.mconcat (S.map Sum $ S.fromList ls)
313 let v2 = Prelude.sum ls
314 assert (getSum v1 == v2)
318 forAll (listOf1 (chooseInt (intMin, intMax)))
319 $ \ls0 -> monadicIO $ action ls0
324 v1 <- run $ S.fold (FL.foldMap Sum) $ S.fromList ls
325 let v2 = Prelude.sum ls
326 assert (getSum v1 == v2)
330 forAll (listOf1 (chooseInt (intMin, intMax)))
331 $ \ls0 -> monadicIO $ action ls0
336 v1 <- run $ S.fold (FL.foldMapM (return . Sum)) $ S.fromList ls
337 let v2 = Prelude.sum ls
338 assert (getSum v1 == v2)
342 forAll (chooseInt (1, 15))
343 $ \key0 ->monadicIO $ action key0
348 let ls = [ (1, "first"), (2, "second"), (3, "third"), (4, "fourth")
349 , (5, "fifth"), (6, "fifth+first"), (7, "fifth+second")
350 , (8, "fifth+third"), (9, "fifth+fourth")
351 , (10, "fifth+fifth")
353 v1 <- run $ S.fold (FL.lookup key) $ S.fromList ls
354 let v2 = Prelude.lookup key ls
359 forAll (listOf1 (chooseInt (intMin, intMax)))
360 $ \ls0 -> monadicIO $ action ls0
365 let addLen x = return $ x + Prelude.length ls
366 fld = FL.rmapM addLen FL.sum
367 v2 = foldl (+) (Prelude.length ls) ls
368 v1 <- run $ S.fold fld $ S.fromList ls
371teeWithLength :: Property
373 forAll (listOf1 (chooseInt (intMin, intMax)))
374 $ \ls0 -> monadicIO $ action ls0
379 v1 <- run $ S.fold (FL.tee FL.sum FL.length) $ S.fromList ls
380 let v2 = Prelude.sum ls
381 v3 = Prelude.length ls
382 assert (v1 == (v2, v3))
384teeWithFstLength :: Property
386 forAll (listOf1 (chooseInt (intMin, intMax)))
387 $ \ls0 -> monadicIO $ action ls0
392 v1 <- run $ S.fold (F.teeWithFst (,) (FL.take 5 FL.sum) FL.length) $ S.fromList ls
393 let v2 = Prelude.sum (Prelude.take 5 ls)
394 v3 = Prelude.length (Prelude.take 5 ls)
395 assert (v1 == (v2, v3))
397partitionByM :: Property
399 forAll (listOf1 (chooseInt (intMin, intMax)))
400 $ \ls0 -> monadicIO $ action ls0
405 let f = \x -> if odd x then return (Left x) else return (Right x)
406 v1 <- run $ S.fold (F.partitionByM f FL.length FL.length) $ S.fromList ls
407 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ls
408 v3 = foldl (\b a -> if even a then b+1 else b) 0 ls
409 assert (v1 == (v2, v3))
411partitionByFstM :: Property
413 forAll (listOf1 (chooseInt (intMin, intMax)))
414 $ \ls0 -> monadicIO $ action ls0
419 let f = \x -> if odd x then return (Left x) else return (Right x)
420 v1 <- run $ S.fold (F.partitionByFstM f (FL.take 25 FL.length) FL.length) (S.fromList ([1..100]:: [Int]))
421 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ([1..49] :: [Int])
422 v3 = foldl (\b a -> if even a then b+1 else b) 0 ([1..49] :: [Int])
423 assert (v1 == (v2, v3))
425partitionByMinM1 :: Property
427 forAll (listOf1 (chooseInt (intMin, intMax)))
428 $ \ls0 -> monadicIO $ action ls0
433 let f = \x -> if odd x then return (Left x) else return (Right x)
434 v1 <- run $ S.fold (F.partitionByMinM f FL.length (FL.take 25 FL.length)) (S.fromList ([1..100]:: [Int]))
435 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ([1..50] :: [Int])
436 v3 = foldl (\b a -> if even a then b+1 else b) 0 ([1..50] :: [Int])
437 assert (v1 == (v2, v3))
439partitionByMinM2 :: Property
441 forAll (listOf1 (chooseInt (intMin, intMax)))
442 $ \ls0 -> monadicIO $ action ls0
447 let f = \x -> if odd x then return (Left x) else return (Right x)
448 v1 <- run $ S.fold (F.partitionByMinM f (FL.take 25 FL.length) FL.length) (S.fromList ([1..100]:: [Int]))
449 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ([1..49] :: [Int])
450 v3 = foldl (\b a -> if even a then b+1 else b) 0 ([1..49] :: [Int])
451 assert (v1 == (v2, v3))
453teeWithMinLength1 :: Property
455 forAll (listOf1 (chooseInt (intMin, intMax)))
456 $ \ls0 -> monadicIO $ action ls0
461 v1 <- run $ S.fold (F.teeWithMin (,) (FL.take 5 FL.sum) FL.length) $ S.fromList ls
462 let v2 = Prelude.sum (Prelude.take 5 ls)
463 v3 = Prelude.length (Prelude.take 5 ls)
464 assert (v1 == (v2, v3))
467teeWithMinLength2 :: Property
469 forAll (listOf1 (chooseInt (intMin, intMax)))
470 $ \ls0 -> monadicIO $ action ls0
475 v1 <- run $ S.fold (F.teeWithMin (,) FL.sum (FL.take 5 FL.length)) $ S.fromList ls
476 let v2 = Prelude.sum (Prelude.take 5 ls)
477 v3 = Prelude.length (Prelude.take 5 ls)
478 assert (v1 == (v2, v3))
479teeWithMax :: Property
481 forAll (listOf1 (chooseInt (intMin, intMax)))
482 $ \ls0 -> monadicIO $ action ls0
487 v1 <- run $ S.fold (FL.tee FL.sum FL.maximum) $ S.fromList ls
488 let v2 = Prelude.sum ls
489 v3 = foldMaybe (greater compare) intMin ls
490 assert (v1 == (v2, v3))
492distribute :: Property
494 forAll (listOf1 (chooseInt (intMin, intMax)))
495 $ \ls0 -> monadicIO $ action ls0
500 v1 <- run $ S.fold (FL.distribute [FL.sum, FL.length]) $ S.fromList ls
501 let v2 = Prelude.sum ls
502 v3 = Prelude.length ls
503 assert (v1 == [v2, v3])
508 v1 :: (Int, [String]) <-
510 $ S.fold (FL.partition FL.sum FL.toList)
512 [Left 1, Right "abc", Left 3, Right "xy", Right "pp2"]
513 let v2 = (4,["abc","xy","pp2"])
519 v1 :: (Int, [String]) <-
521 $ S.fold (FL.unzip FL.sum FL.toList)
522 $ S.fromList [(1, "aa"), (2, "bb"), (3, "cc")]
523 let v2 = (6, ["aa", "bb", "cc"])
527postscan = forAll (listOf (chooseInt (intMin, intMax))) $ \ls ->
531 $ S.fold (F.postscan FL.sum FL.toList)
533 let v2 = scanl1 (+) ls
538 forAll (listOf (chooseInt (0, 100))) $ \lst ->
539 forAll (chooseInt (1, 100)) $ \i ->
541 let strm = S.fromList lst
542 r1 <- S.fold (FL.many (split i) FL.toList) strm
543 r2 <- S.toList $ Stream.foldMany (split i) strm
548 split i = FL.take i FL.toList
550headAndRest :: [Int] -> Property
551headAndRest ls = monadicIO $ do
552 (mbh, rest) <- run $ Stream.fold_ FL.head (S.fromList ls)
553 rests <- run $ S.toList rest
554 assert (mbh == headl ls)
555 listEquals (==) rests (taill ls)
565 let table "SUM" = return FL.sum
566 table "PRODUCT" = return FL.product
567 table _ = return FL.length
568 input = Stream.fromList (
578 ] :: [(String, Int)])
583 Data.Map.fromList [("PRODUCT", 8),("SUM", 4),("abc",3),("xyz",2)]
586demuxWith :: Expectation
588 let getKey x | even x = "SUM"
589 | otherwise = "PRODUCT"
591 getFold "SUM" = return FL.sum
592 getFold "PRODUCT" = return FL.product
593 getFold _ = error "demuxWith: bug"
595 input = Stream.fromList [1, 2, 3, 4 :: Int]
597 (F.demuxWith getKey (getFold . getKey))
600 Data.Map.fromList [("PRODUCT",3),("SUM",6)]
602classifyWith :: Expectation
604 let input = Stream.fromList [("ONE",1),("ONE",1.1),("TWO",2), ("TWO",2.2)]
606 (F.classifyWith fst (FL.lmap snd FL.toList))
610 [("ONE",[1.0, 1.1 :: Double]), ("TWO",[2.0, 2.2])]
612classify :: Expectation
618 , ("ONE", (1, 1.1:: Double))
623 (F.classify (FL.lmap snd FL.toList))
627 [("ONE",[1.0, 1.1 :: Double]), ("TWO",[2.0, 2.2])]
629splitAt :: Expectation
632 (F.splitAt 6 FL.toList FL.toList)
633 (Stream.fromList "Hello World!")
638scan = forAll (listOf (chooseInt (0, 100))) $ \lst ->
642 $ S.fold (F.scan FL.sum FL.toList)
644 let v2 = scanl (+) 0 lst
647topBy :: Bool -> Property
648topBy isTop = forAll (listOf (chooseInt (-50, 100))) $ \ls0 ->
649 monadicIO $ action ls0
655 let n0 = Prelude.length ls
656 n <- liftIO $ generate $ chooseInt (-2, n0 + 2)
659 lst <- S.fold (F.top n) (S.fromList ls) >>= MA.toList
660 assert ((Prelude.take n . Prelude.reverse . sort) ls == lst)
662 lst <- S.fold (F.bottom n) (S.fromList ls) >>= MA.toList
663 assert ((Prelude.take n . sort) ls == lst)
672moduleName = "Data.Fold"
676 describe moduleName $ do
679 prop "mconcat" Main.mconcat
680 prop "foldMap" Main.foldMap
681 prop "foldMapM" Main.foldMapM
683 prop "drain" Main.drain
684 prop "drainBy" Main.drainBy
686 prop "length" Main.length
688 prop "product" product
689 prop "maximumBy" $ maximumBy intMin compare
690 prop "maximum" $ maximum intMin
691 prop "minimumBy" $ minimumBy intMax compare
692 prop "minimum" $ minimum intMax
693 prop "mean" Main.mean
694 prop "stdDev" Main.stdDev
695 prop "variance" Main.variance
696 prop "rollingHashFirstN" rollingHashFirstN
699 prop "toListRev" toListRev
701 prop "demuxWith" demuxWith
702 prop "classifyWith" classifyWith
703 prop "classify" classify
708 prop "find" $ find predicate
709 prop "lookup" Main.lookup
710 prop "findIndex" $ findIndex predicate
711 prop "elemIndex" $ elemIndex 10
713 prop "elem" $ elem 10
714 prop "notElem" $ notElem 10
715 prop "all" $ Main.all predicate
716 prop "any" $ Main.any predicate
720 prop "bottom" Main.bottom
726 prop "postscan" Main.postscan
729 prop "rmapM" Main.rmapM
735 prop "mapMaybe" mapMaybe
740 prop "takeEndBy_" takeEndBy_
741 prop "takeEndByOrMax" takeEndByOrMax
748 prop "teeWithLength" Main.teeWithLength
749 prop "teeWithFstLength" Main.teeWithFstLength
750 prop "teeWithMinLength1" Main.teeWithMinLength1
751 prop "teeWithMinLength2" Main.teeWithMinLength2
752 prop "teeWithMax" Main.teeWithMax
753 prop "partitionByM" Main.partitionByM
754 prop "partitionByFstM" Main.partitionByFstM
755 prop "partitionByMinM1" Main.partitionByMinM1
756 prop "partitionByMinM2" Main.partitionByMinM2
757 prop "distribute" Main.distribute
760 prop "partition" Main.partition
761 prop "partitionByM" partitionByM
764 prop "unzip" Main.unzip
765 prop "splitAt" Main.splitAt
768 prop "many" Main.many
772 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