1{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
3module Main (main) where
6import Data.Semigroup (Sum(..), getSum)
7import Streamly.Test.Common (checkListEqual, listEquals)
21import Control.Monad.IO.Class (liftIO)
22import Test.QuickCheck.Monadic (monadicIO, assert, run)
24import qualified Data.Map
25import qualified Prelude
26import qualified Streamly.Internal.Data.Fold as F
27import qualified Streamly.Prelude as S
28import qualified Streamly.Internal.Data.Array.Foreign.Mut.Type as MA
29import qualified Streamly.Internal.Data.Stream.IsStream as Stream
30import qualified Streamly.Data.Fold as FL
33 (maximum, minimum, elem, notElem, null, product, sum, head, last, take)
35import Test.Hspec.QuickCheck
52chooseInt :: (Int, Int) -> Gen Int
55{-# INLINE maxStreamLen #-}
59rollingHashFirstN :: Property
61 forAll (choose (0, maxStreamLen)) $ \len ->
62 forAll (choose (0, len)) $ \n ->
63 forAll (vectorOf len (arbitrary :: Gen Int)) $ \vec ->
65 a <- run $ S.fold F.rollingHash $ S.take n $ S.fromList vec
66 b <- run $ S.fold (F.rollingHashFirstN n) $ S.fromList vec
69head :: [Int] -> Expectation
70head ls = S.fold FL.head (S.fromList ls) `shouldReturn` headl ls
72headl :: [a] -> Maybe a
76length :: [Int] -> Expectation
77length ls = S.fold FL.length (S.fromList ls) `shouldReturn` Prelude.length ls
79sum :: [Int] -> Expectation
80sum ls = S.fold FL.sum (S.fromList ls) `shouldReturn` Prelude.sum ls
82product :: [Int] -> Expectation
84 S.fold FL.product (S.fromList ls) `shouldReturn` Prelude.product ls
86lesser :: (a -> a -> Ordering) -> a -> a -> a
87lesser f x y = if f x y == LT then x else y
89greater :: (a -> a -> Ordering) -> a -> a -> a
90greater f x y = if f x y == GT then x else y
92foldMaybe :: (b -> a -> b) -> b -> [a] -> Maybe b
96 _ -> Just (foldl f acc ls)
98maximumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
99maximumBy genmin f ls =
100 S.fold (FL.maximumBy f) (S.fromList ls)
101 `shouldReturn` foldMaybe (greater f) genmin ls
103maximum :: (Show a, Ord a) => a -> [a] -> Expectation
105 S.fold FL.maximum (S.fromList ls)
106 `shouldReturn` foldMaybe (greater compare) genmin ls
108minimumBy :: (Ord a, Show a) => a -> (a -> a -> Ordering) -> [a] -> Expectation
109minimumBy genmax f ls =
110 S.fold (FL.minimumBy f) (S.fromList ls)
111 `shouldReturn` foldMaybe (lesser f) genmax ls
113minimum :: (Show a, Ord a) => a -> [a] -> Expectation
115 S.fold FL.minimum (S.fromList ls)
116 `shouldReturn` foldMaybe (lesser compare) genmax ls
118toList :: [Int] -> Expectation
119toList ls = S.fold FL.toList (S.fromList ls) `shouldReturn` ls
121toListRev :: [Int] -> Expectation
122toListRev ls = S.fold FL.toListRev (S.fromList ls) `shouldReturn` reverse ls
124safeLast :: [a] -> Maybe a
126safeLast (x:[]) = Just x
127safeLast (_:xs) = safeLast xs
129last :: [String] -> Expectation
130last ls = S.fold FL.last (S.fromList ls) `shouldReturn` safeLast ls
132mapMaybe :: [Int] -> Expectation
138 f = FL.mapMaybe maybeEven FL.toList
139 in S.fold f (S.fromList ls) `shouldReturn` filter even ls
141nth :: Int -> [a] -> Maybe a
145 | otherwise = nth (idx - 1) xs
148index :: Int -> [String] -> Expectation
150 let x = S.fold (FL.index idx) (S.fromList ls)
151 in x `shouldReturn` nth idx ls
153find :: (Show a, Eq a) => (a -> Bool) -> [a] -> Expectation
155 y <- S.fold (FL.findIndex f) (S.fromList ls)
158 let fld = S.fold (FL.find f) (S.fromList ls)
159 in fld `shouldReturn` Nothing
161 let fld = S.fold (FL.any f) (S.fromList $ Prelude.take idx ls)
162 in fld `shouldReturn` False
164neg :: (a -> Bool) -> a -> Bool
167findIndex :: (a -> Bool) -> [a] -> Expectation
169 y <- S.fold (FL.findIndex f) (S.fromList ls)
172 let fld = S.fold (FL.all $ neg f) (S.fromList ls)
173 in fld `shouldReturn` True
177 S.fold (FL.all f) (S.fromList []) `shouldReturn` True
179 S.fold (FL.all f) (S.fromList $ Prelude.take idx ls)
182predicate :: Int -> Bool
183predicate x = x * x < 100
185elemIndex :: Int -> [Int] -> Expectation
187 y <- S.fold (FL.elemIndex elm) (S.fromList ls)
190 let fld = S.fold (FL.any (== elm)) (S.fromList ls)
191 in fld `shouldReturn` False
194 S.fold (FL.any (== elm)) (S.fromList $ Prelude.take idx ls)
195 in fld `shouldReturn` False
197null :: [Int] -> Expectation
199 S.fold FL.null (S.fromList ls)
205elem :: Int -> [Int] -> Expectation
207 y <- S.fold (FL.elem elm) (S.fromList ls)
208 let fld = S.fold (FL.any (== elm)) (S.fromList ls)
211notElem :: Int -> [Int] -> Expectation
213 y <- S.fold (FL.notElem elm) (S.fromList ls)
214 let fld = S.fold (FL.any (== elm)) (S.fromList ls)
215 fld `shouldReturn` not y
217all :: (a -> Bool) -> [a] -> Expectation
219 S.fold (FL.all f) (S.fromList ls) `shouldReturn` Prelude.all f ls
221any :: (a -> Bool) -> [a] -> Expectation
222any f ls = S.fold (FL.any f) (S.fromList ls) `shouldReturn` Prelude.any f ls
224and :: [Bool] -> Expectation
225and ls = S.fold FL.and (S.fromList ls) `shouldReturn` Prelude.and ls
227or :: [Bool] -> Expectation
228or ls = S.fold FL.or (S.fromList ls) `shouldReturn` Prelude.or ls
230take :: [Int] -> Property
232 forAll (chooseInt (-1, Prelude.length ls + 2)) $ \n ->
233 S.fold (FL.take n FL.toList) (S.fromList ls)
234 `shouldReturn` Prelude.take n ls
236takeEndBy_ :: Property
238 forAll (listOf (chooseInt (0, 1))) $ \ls ->
240 f = FL.takeEndBy_ p FL.toList
241 ys = Prelude.takeWhile (not . p) ls
242 in case S.fold f (S.fromList ls) of
243 Right xs -> checkListEqual xs ys
244 Left _ -> property False
246takeEndByOrMax :: Property
248 forAll (chooseInt (min_value, max_value)) $ \n ->
249 forAll (listOf (chooseInt (0, 1))) $ \ls ->
251 f = FL.takeEndBy_ p (FL.take n FL.toList)
252 ys = Prelude.take n (Prelude.takeWhile (not . p) ls)
253 in case S.fold f (S.fromList ls) of
254 Right xs -> checkListEqual xs ys
255 Left _ -> property False
257chooseFloat :: (Float, Float) -> Gen Float
260drain :: [Int] -> Expectation
261drain ls = S.fold FL.drain (S.fromList ls) `shouldReturn` ()
263drainBy :: [Int] -> Expectation
264drainBy ls = S.fold (FL.drainBy return) (S.fromList ls) `shouldReturn` ()
268 forAll (listOf1 (chooseFloat (-100.0, 100.0)))
269 $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
274 v1 <- run $ S.fold FL.mean (S.fromList ls)
275 let v2 = Prelude.sum ls / fromIntegral (Prelude.length ls)
276 assert (abs (v1 - v2) < 0.0001)
280 forAll (listOf1 (chooseFloat (-100.0, 100.0)))
281 $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
286 v1 <- run $ S.fold FL.stdDev (S.fromList ls)
287 let avg = Prelude.sum ls / fromIntegral (Prelude.length ls)
288 se = Prelude.sum (fmap (\x -> (x - avg) * (x - avg)) ls)
289 sd = sqrt $ se / fromIntegral (Prelude.length ls)
290 assert (abs (v1 - sd) < 0.0001 )
294 forAll (listOf1 (chooseFloat (-100.0, 100.0)))
295 $ \ls0 -> withMaxSuccess 1000 $ monadicIO $ action ls0
300 v1 <- run $ S.fold FL.variance (S.fromList ls)
301 let avg = Prelude.sum ls / fromIntegral (Prelude.length ls)
302 se = Prelude.sum (fmap (\x -> (x - avg) * (x - avg)) ls)
303 vr = se / fromIntegral (Prelude.length ls)
304 assert (abs (v1 - vr) < 0.01 )
308 forAll (listOf1 (chooseInt (intMin, intMax)))
309 $ \ls0 -> monadicIO $ action ls0
314 v1 <- run $ S.fold FL.mconcat (S.map Sum $ S.fromList ls)
315 let v2 = Prelude.sum ls
316 assert (getSum v1 == v2)
320 forAll (listOf1 (chooseInt (intMin, intMax)))
321 $ \ls0 -> monadicIO $ action ls0
326 v1 <- run $ S.fold (FL.foldMap Sum) $ S.fromList ls
327 let v2 = Prelude.sum ls
328 assert (getSum v1 == v2)
332 forAll (listOf1 (chooseInt (intMin, intMax)))
333 $ \ls0 -> monadicIO $ action ls0
338 v1 <- run $ S.fold (FL.foldMapM (return . Sum)) $ S.fromList ls
339 let v2 = Prelude.sum ls
340 assert (getSum v1 == v2)
344 forAll (chooseInt (1, 15))
345 $ \key0 ->monadicIO $ action key0
350 let ls = [ (1, "first"), (2, "second"), (3, "third"), (4, "fourth")
351 , (5, "fifth"), (6, "fifth+first"), (7, "fifth+second")
352 , (8, "fifth+third"), (9, "fifth+fourth")
353 , (10, "fifth+fifth")
355 v1 <- run $ S.fold (FL.lookup key) $ S.fromList ls
356 let v2 = Prelude.lookup key ls
361 forAll (listOf1 (chooseInt (intMin, intMax)))
362 $ \ls0 -> monadicIO $ action ls0
367 let addLen x = return $ x + Prelude.length ls
368 fld = FL.rmapM addLen FL.sum
369 v2 = foldl (+) (Prelude.length ls) ls
370 v1 <- run $ S.fold fld $ S.fromList ls
373teeWithLength :: Property
375 forAll (listOf1 (chooseInt (intMin, intMax)))
376 $ \ls0 -> monadicIO $ action ls0
381 v1 <- run $ S.fold (FL.tee FL.sum FL.length) $ S.fromList ls
382 let v2 = Prelude.sum ls
383 v3 = Prelude.length ls
384 assert (v1 == (v2, v3))
386teeWithFstLength :: Property
388 forAll (listOf1 (chooseInt (intMin, intMax)))
389 $ \ls0 -> monadicIO $ action ls0
394 v1 <- run $ S.fold (F.teeWithFst (,) (FL.take 5 FL.sum) FL.length) $ S.fromList ls
395 let v2 = Prelude.sum (Prelude.take 5 ls)
396 v3 = Prelude.length (Prelude.take 5 ls)
397 assert (v1 == (v2, v3))
399partitionByM :: Property
401 forAll (listOf1 (chooseInt (intMin, intMax)))
402 $ \ls0 -> monadicIO $ action ls0
407 let f = \x -> if odd x then return (Left x) else return (Right x)
408 v1 <- run $ S.fold (F.partitionByM f FL.length FL.length) $ S.fromList ls
409 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ls
410 v3 = foldl (\b a -> if even a then b+1 else b) 0 ls
411 assert (v1 == (v2, v3))
413partitionByFstM :: Property
415 forAll (listOf1 (chooseInt (intMin, intMax)))
416 $ \ls0 -> monadicIO $ action ls0
421 let f = \x -> if odd x then return (Left x) else return (Right x)
422 v1 <- run $ S.fold (F.partitionByFstM f (FL.take 25 FL.length) FL.length) (S.fromList ([1..100]:: [Int]))
423 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ([1..49] :: [Int])
424 v3 = foldl (\b a -> if even a then b+1 else b) 0 ([1..49] :: [Int])
425 assert (v1 == (v2, v3))
427partitionByMinM1 :: Property
429 forAll (listOf1 (chooseInt (intMin, intMax)))
430 $ \ls0 -> monadicIO $ action ls0
435 let f = \x -> if odd x then return (Left x) else return (Right x)
436 v1 <- run $ S.fold (F.partitionByMinM f FL.length (FL.take 25 FL.length)) (S.fromList ([1..100]:: [Int]))
437 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ([1..50] :: [Int])
438 v3 = foldl (\b a -> if even a then b+1 else b) 0 ([1..50] :: [Int])
439 assert (v1 == (v2, v3))
441partitionByMinM2 :: Property
443 forAll (listOf1 (chooseInt (intMin, intMax)))
444 $ \ls0 -> monadicIO $ action ls0
449 let f = \x -> if odd x then return (Left x) else return (Right x)
450 v1 <- run $ S.fold (F.partitionByMinM f (FL.take 25 FL.length) FL.length) (S.fromList ([1..100]:: [Int]))
451 let v2 = foldl (\b a -> if odd a then b+1 else b) 0 ([1..49] :: [Int])
452 v3 = foldl (\b a -> if even a then b+1 else b) 0 ([1..49] :: [Int])
453 assert (v1 == (v2, v3))
455teeWithMinLength1 :: Property
457 forAll (listOf1 (chooseInt (intMin, intMax)))
458 $ \ls0 -> monadicIO $ action ls0
463 v1 <- run $ S.fold (F.teeWithMin (,) (FL.take 5 FL.sum) FL.length) $ S.fromList ls
464 let v2 = Prelude.sum (Prelude.take 5 ls)
465 v3 = Prelude.length (Prelude.take 5 ls)
466 assert (v1 == (v2, v3))
469teeWithMinLength2 :: Property
471 forAll (listOf1 (chooseInt (intMin, intMax)))
472 $ \ls0 -> monadicIO $ action ls0
477 v1 <- run $ S.fold (F.teeWithMin (,) FL.sum (FL.take 5 FL.length)) $ S.fromList ls
478 let v2 = Prelude.sum (Prelude.take 5 ls)
479 v3 = Prelude.length (Prelude.take 5 ls)
480 assert (v1 == (v2, v3))
481teeWithMax :: Property
483 forAll (listOf1 (chooseInt (intMin, intMax)))
484 $ \ls0 -> monadicIO $ action ls0
489 v1 <- run $ S.fold (FL.tee FL.sum FL.maximum) $ S.fromList ls
490 let v2 = Prelude.sum ls
491 v3 = foldMaybe (greater compare) intMin ls
492 assert (v1 == (v2, v3))
494distribute :: Property
496 forAll (listOf1 (chooseInt (intMin, intMax)))
497 $ \ls0 -> monadicIO $ action ls0
502 v1 <- run $ S.fold (FL.distribute [FL.sum, FL.length]) $ S.fromList ls
503 let v2 = Prelude.sum ls
504 v3 = Prelude.length ls
505 assert (v1 == [v2, v3])
510 v1 :: (Int, [String]) <-
512 $ S.fold (FL.partition FL.sum FL.toList)
514 [Left 1, Right "abc", Left 3, Right "xy", Right "pp2"]
515 let v2 = (4,["abc","xy","pp2"])
521 v1 :: (Int, [String]) <-
523 $ S.fold (FL.unzip FL.sum FL.toList)
524 $ S.fromList [(1, "aa"), (2, "bb"), (3, "cc")]
525 let v2 = (6, ["aa", "bb", "cc"])
529postscan = forAll (listOf (chooseInt (intMin, intMax))) $ \ls ->
533 $ S.fold (F.postscan FL.sum FL.toList)
535 let v2 = scanl1 (+) ls
540 forAll (listOf (chooseInt (0, 100))) $ \lst ->
541 forAll (chooseInt (1, 100)) $ \i ->
543 let strm = S.fromList lst
544 r1 <- S.fold (FL.many (split i) FL.toList) strm
545 r2 <- S.toList $ Stream.foldMany (split i) strm
550 split i = FL.take i FL.toList
552foldBreak :: [Int] -> Property
553foldBreak ls = monadicIO $ do
554 (mbh, rest) <- run $ Stream.foldBreak FL.head (S.fromList ls)
555 rests <- run $ S.toList rest
556 assert (mbh == headl ls)
557 listEquals (==) rests (taill ls)
567 let table "SUM" = return FL.sum
568 table "PRODUCT" = return FL.product
569 table _ = return FL.length
570 input = Stream.fromList (
580 ] :: [(String, Int)])
585 Data.Map.fromList [("PRODUCT", 8),("SUM", 4),("abc",3),("xyz",2)]
588demuxWith :: Expectation
590 let getKey x | even x = "SUM"
591 | otherwise = "PRODUCT"
593 getFold "SUM" = return FL.sum
594 getFold "PRODUCT" = return FL.product
595 getFold _ = error "demuxWith: bug"
597 input = Stream.fromList [1, 2, 3, 4 :: Int]
599 (F.demuxWith getKey (getFold . getKey))
602 Data.Map.fromList [("PRODUCT",3),("SUM",6)]
604classifyWith :: Expectation
606 let input = Stream.fromList [("ONE",1),("ONE",1.1),("TWO",2), ("TWO",2.2)]
608 (F.classifyWith fst (FL.lmap snd FL.toList))
612 [("ONE",[1.0, 1.1 :: Double]), ("TWO",[2.0, 2.2])]
614classify :: Expectation
620 , ("ONE", (1, 1.1:: Double))
625 (F.classify (FL.lmap snd FL.toList))
629 [("ONE",[1.0, 1.1 :: Double]), ("TWO",[2.0, 2.2])]
631splitAt :: Expectation
634 (F.splitAt 6 FL.toList FL.toList)
635 (Stream.fromList "Hello World!")
640scan = forAll (listOf (chooseInt (0, 100))) $ \lst ->
644 $ S.fold (F.scan FL.sum FL.toList)
646 let v2 = scanl (+) 0 lst
649topBy :: Bool -> Property
650topBy isTop = forAll (listOf (chooseInt (-50, 100))) $ \ls0 ->
651 monadicIO $ action ls0
657 let n0 = Prelude.length ls
658 n <- liftIO $ generate $ chooseInt (-2, n0 + 2)
661 lst <- S.fold (F.top n) (S.fromList ls) >>= MA.toList
662 assert ((Prelude.take n . Prelude.reverse . sort) ls == lst)
664 lst <- S.fold (F.bottom n) (S.fromList ls) >>= MA.toList
665 assert ((Prelude.take n . sort) ls == lst)
674moduleName = "Data.Fold"
678 describe moduleName $ do
681 prop "mconcat" Main.mconcat
682 prop "foldMap" Main.foldMap
683 prop "foldMapM" Main.foldMapM
685 prop "drain" Main.drain
686 prop "drainBy" Main.drainBy
688 prop "length" Main.length
690 prop "product" product
691 prop "maximumBy" $ maximumBy intMin compare
692 prop "maximum" $ maximum intMin
693 prop "minimumBy" $ minimumBy intMax compare
694 prop "minimum" $ minimum intMax
695 prop "mean" Main.mean
696 prop "stdDev" Main.stdDev
697 prop "variance" Main.variance
698 prop "rollingHashFirstN" rollingHashFirstN
701 prop "toListRev" toListRev
703 prop "demuxWith" demuxWith
704 prop "classifyWith" classifyWith
705 prop "classify" classify
710 prop "find" $ find predicate
711 prop "lookup" Main.lookup
712 prop "findIndex" $ findIndex predicate
713 prop "elemIndex" $ elemIndex 10
715 prop "elem" $ elem 10
716 prop "notElem" $ notElem 10
717 prop "all" $ Main.all predicate
718 prop "any" $ Main.any predicate
722 prop "bottom" Main.bottom
728 prop "postscan" Main.postscan
731 prop "rmapM" Main.rmapM
737 prop "mapMaybe" mapMaybe
742 prop "takeEndBy_" takeEndBy_
743 prop "takeEndByOrMax" takeEndByOrMax
750 prop "teeWithLength" Main.teeWithLength
751 prop "teeWithFstLength" Main.teeWithFstLength
752 prop "teeWithMinLength1" Main.teeWithMinLength1
753 prop "teeWithMinLength2" Main.teeWithMinLength2
754 prop "teeWithMax" Main.teeWithMax
755 prop "partitionByM" Main.partitionByM
756 prop "partitionByFstM" Main.partitionByFstM
757 prop "partitionByMinM1" Main.partitionByMinM1
758 prop "partitionByMinM2" Main.partitionByMinM2
759 prop "distribute" Main.distribute
762 prop "partition" Main.partition
763 prop "partitionByM" partitionByM
766 prop "unzip" Main.unzip
767 prop "splitAt" Main.splitAt
770 prop "many" Main.many
774 prop "foldBreak" foldBreak
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