@@ -16,6 +16,7 @@ import Test.QuickCheck
1616 )
1717import Test.QuickCheck.Monadic (monadicIO, assert, run)
1818
19+import qualified Data.Map
1920import qualified Prelude
2021import qualified Streamly.Internal.Data.Fold as F
2122import qualified Streamly.Prelude as S
@@ -53,7 +54,8 @@ rollingHashFirstN :: Property
5354rollingHashFirstN =
5455 forAll (choose (0, maxStreamLen)) $ \len ->
5556 forAll (choose (0, len)) $ \n ->
56− forAll (vectorOf len (arbitrary :: Gen Int)) $ \vec -> monadicIO $ do
57+ forAll (vectorOf len (arbitrary :: Gen Int)) $ \vec ->
58+ monadicIO $ do
5759 a <- run $ S.fold F.rollingHash $ S.take n $ S.fromList vec
5860 b <- run $ S.fold (F.rollingHashFirstN n) $ S.fromList vec
5961 assert $ a == b
@@ -110,6 +112,9 @@ minimum genmax ls =
110112toList :: [Int] -> Expectation
111113toList ls = S.fold FL.toList (S.fromList ls) `shouldReturn` ls
112114
115+toListRev :: [Int] -> Expectation
116+toListRev ls = S.fold FL.toListRev (S.fromList ls) `shouldReturn` reverse ls
117+
113118safeLast :: [a] -> Maybe a
114119safeLast [] = Nothing
115120safeLast (x:[]) = Just x
@@ -124,7 +129,7 @@ mapMaybe ls =
124129 if even x
125130 then Just x
126131 else Nothing
127− f = F.mapMaybe maybeEven FL.toList
132+ f = FL.mapMaybe maybeEven FL.toList
128133 in S.fold f (S.fromList ls) `shouldReturn` filter even ls
129134
130135nth :: Int -> [a] -> Maybe a
@@ -179,7 +184,8 @@ elemIndex elm ls = do
179184 let fld = S.fold (FL.any (== elm)) (S.fromList ls)
180185 in fld `shouldReturn` False
181186 Just idx ->
182− let fld = S.fold (FL.any (== elm)) (S.fromList $ Prelude.take idx ls)
187+ let fld =
188+ S.fold (FL.any (== elm)) (S.fromList $ Prelude.take idx ls)
183189 in fld `shouldReturn` False
184190
185191null :: [Int] -> Expectation
@@ -218,14 +224,14 @@ or ls = S.fold FL.or (S.fromList ls) `shouldReturn` Prelude.or ls
218224take :: [Int] -> Property
219225take ls =
220226 forAll (chooseInt (-1, Prelude.length ls + 2)) $ \n ->
221− S.fold (F.take n FL.toList) (S.fromList ls)
227+ S.fold (FL.take n FL.toList) (S.fromList ls)
222228 `shouldReturn` Prelude.take n ls
223229
224230takeEndBy_ :: Property
225231takeEndBy_ =
226232 forAll (listOf (chooseInt (0, 1))) $ \ls ->
227233 let p = (== 1)
228− f = F.takeEndBy_ p FL.toList
234+ f = FL.takeEndBy_ p FL.toList
229235 ys = Prelude.takeWhile (not . p) ls
230236 in case S.fold f (S.fromList ls) of
231237 Right xs -> checkListEqual xs ys
@@ -236,7 +242,7 @@ takeEndByOrMax =
236242 forAll (chooseInt (min_value, max_value)) $ \n ->
237243 forAll (listOf (chooseInt (0, 1))) $ \ls ->
238244 let p = (== 1)
239− f = F.takeEndBy_ p (F.take n FL.toList)
245+ f = FL.takeEndBy_ p (FL.take n FL.toList)
240246 ys = Prelude.take n (Prelude.takeWhile (not . p) ls)
241247 in case S.fold f (S.fromList ls) of
242248 Right xs -> checkListEqual xs ys
@@ -335,10 +341,11 @@ lookup =
335341 where
336342
337343 action key = do
338− let ls = [(1, "first"), (2, "second"), (3, "third"), (4, "fourth")
339− , (5, "fifth"), (6, "fifth+first"), (7, "fifth+second")
340− , (8, "fifth+third"), (9, "fifth+fourth")
341− , (10, "fifth+fifth")]
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")
348+ ]
342349 v1 <- run $ S.fold (FL.lookup key) $ S.fromList ls
343350 let v2 = Prelude.lookup key ls
344351 assert (v1 == v2)
@@ -423,13 +430,13 @@ many =
423430 forAll (chooseInt (1, 100)) $ \i ->
424431 monadicIO $ do
425432 let strm = S.fromList lst
426− r1 <- S.fold (F.many (split i) F.toList) strm
433+ r1 <- S.fold (FL.many (split i) FL.toList) strm
427434 r2 <- S.toList $ Stream.foldMany (split i) strm
428435 assert $ r1 == r2
429436
430437 where
431438
432− split i = F.take i F.toList
439+ split i = FL.take i FL.toList
433440
434441headAndRest :: [Int] -> Property
435442headAndRest ls = monadicIO $ do
@@ -444,6 +451,143 @@ headAndRest ls = monadicIO $ do
444451 taill [] = []
445452 taill (_:xs) = xs
446453
454+partitionByM :: Property
455+partitionByM =
456+ forAll (listOf1 (chooseInt (intMin, intMax)))
457+ $ \ls0 -> monadicIO $ action ls0
458+
459+ where
460+
461+ action ls = do
462+ let f = \x -> if odd x then return (Left x) else return (Right x)
463+ v1 <-
464+ run
465+ $ S.fold (F.partitionByM f FL.length FL.length)
466+ $ S.fromList ls
467+ let v2 = Prelude.length $ filter odd ls
468+ v3 = Prelude.length $ filter even ls
469+ assert (v1 == (v2, v3))
470+
471+demux :: Expectation
472+demux =
473+ let table = Data.Map.fromList [("SUM", FL.sum), ("PRODUCT", FL.product)]
474+ input = Stream.fromList (
475+ [ ("SUM", 1)
476+ , ("PRODUCT", 2)
477+ , ("SUM",3)
478+ , ("PRODUCT", 4)
479+ ] :: [(String, Int)])
480+ in Stream.fold
481+ (F.demux table)
482+ input
483+ `shouldReturn`
484+ Data.Map.fromList [("PRODUCT", 8),("SUM", 4)]
485+
486+
487+demuxWithSum :: Expectation
488+demuxWithSum =
489+ let f x = ("SUM", x::Int)
490+ table = Data.Map.fromList [("SUM", FL.sum)]
491+ input = Stream.fromList [1, 4]
492+ in Stream.fold
493+ (F.demuxWith f table)
494+ input
495+ `shouldReturn`
496+ Data.Map.fromList [("SUM", 5)]
497+
498+demuxWithProduct :: Expectation
499+demuxWithProduct =
500+ let f x = ("PRODUCT", x::Int)
501+ table = Data.Map.fromList [("PRODUCT", FL.product)]
502+ input = Stream.fromList [2, 4]
503+ in Stream.fold
504+ (F.demuxWith f table)
505+ input
506+ `shouldReturn`
507+ Data.Map.fromList [("PRODUCT", 8)]
508+
509+demuxDefaultWithSum :: Expectation
510+demuxDefaultWithSum =
511+ let f x = ("SUM", x::Int)
512+ table = Data.Map.fromList [("SUM", FL.sum)]
513+ input = Stream.fromList [2, 4]
514+ in Stream.fold
515+ (F.demuxDefaultWith f table (FL.lmap snd FL.sum))
516+ input
517+ `shouldReturn`
518+ (Data.Map.fromList [("SUM" , 6)] , 0)
519+
520+demuxDefaultWithProduct :: Expectation
521+demuxDefaultWithProduct =
522+ let f x = ("PRODUCT", x::Int)
523+ table = Data.Map.fromList [("PRODUCT", FL.product)]
524+ input = Stream.fromList [2, 4]
525+ in Stream.fold
526+ (F.demuxDefaultWith f table (FL.lmap snd FL.product))
527+ input
528+ `shouldReturn`
529+ (Data.Map.fromList [("PRODUCT" , 8)] , 1)
530+
531+demuxDefault :: Expectation
532+demuxDefault =
533+ let table = Data.Map.fromList [("SUM", FL.sum), ("PRODUCT", FL.product)]
534+ input = Stream.fromList
535+ [ ("SUM", 1::Int)
536+ , ("PRODUCT", 2::Int)
537+ , ("SUM",3)
538+ , ("PRODUCT", 4::Int)
539+ ]
540+ in Stream.fold
541+ (F.demuxDefault table (FL.lmap snd FL.product))
542+ input
543+ `shouldReturn`
544+ (Data.Map.fromList [("PRODUCT", 8), ("SUM", 4)], 1)
545+
546+demuxDefaultEmpty :: Expectation
547+demuxDefaultEmpty =
548+ let table = Data.Map.empty
549+ input = Stream.fromList []
550+ in Stream.fold
551+ (F.demuxDefault table (FL.lmap snd FL.product))
552+ input
553+ `shouldReturn`
554+ (Data.Map.fromList ([]::[(String, Int)]), 1)
555+
556+classifyWith :: Expectation
557+classifyWith =
558+ let input = Stream.fromList [("ONE",1),("ONE",1.1),("TWO",2), ("TWO",2.2)]
559+ in Stream.fold
560+ (F.classifyWith fst (FL.lmap snd FL.toList))
561+ input
562+ `shouldReturn`
563+ Data.Map.fromList
564+ [("ONE",[1.0, 1.1 :: Double]), ("TWO",[2.0, 2.2])]
565+
566+classify :: Expectation
567+classify =
568+ let input =
569+ Stream.fromList
570+ [
571+ ("ONE", (1::Int, 1))
572+ , ("ONE", (1, 1.1:: Double))
573+ , ("TWO", (2, 2))
574+ , ("TWO",(2, 2.2))
575+ ]
576+ in Stream.fold
577+ (F.classify (FL.lmap snd FL.toList))
578+ input
579+ `shouldReturn`
580+ Data.Map.fromList
581+ [("ONE",[1.0, 1.1 :: Double]), ("TWO",[2.0, 2.2])]
582+
583+splitAt :: Expectation
584+splitAt =
585+ Stream.fold
586+ (F.splitAt 6 FL.toList FL.toList)
587+ (Stream.fromList "Hello World!")
588+ `shouldReturn`
589+ ("Hello ","World!")
590+
447591moduleName :: String
448592moduleName = "Data.Fold"
449593
@@ -472,6 +616,16 @@ main = hspec $ do
472616 prop "rollingHashFirstN" rollingHashFirstN
473617
474618 prop "toList" toList
619+ prop "toListRev" toListRev
620+ prop "demux" demux
621+ prop "demuxWithSum" demuxWithSum
622+ prop "demuxWithProduct" demuxWithProduct
623+ prop "demuxDefaultWithSum" demuxDefaultWithSum
624+ prop "demuxDefaultWithProduct" demuxDefaultWithProduct
625+ prop "demuxDefault" demuxDefault
626+ prop "demuxDefaultEmpty" demuxDefaultEmpty
627+ prop "classifyWith" classifyWith
628+ prop "classify" classify
475629
476630 -- Terminating folds
477631 prop "index" index
@@ -518,9 +672,11 @@ main = hspec $ do
518672
519673 -- Partitioning
520674 prop "partition" Main.partition
675+ prop "partitionByM" partitionByM
521676
522677 -- Unzipping
523678 prop "unzip" Main.unzip
679+ prop "splitAt" Main.splitAt
524680
525681 -- Nesting
526682 prop "many" Main.many