@@ -9,9 +9,12 @@
10module Main (main) where
10module Main (main) where
12+import Streamly.Internal.Data.Unfold (Unfold)
12import qualified Streamly.Internal.Data.Unfold as UF
14import qualified Streamly.Internal.Data.Unfold as UF
13import qualified Streamly.Internal.Data.Stream.IsStream as S
15import qualified Streamly.Internal.Data.Stream.IsStream as S
14−import qualified Prelude as P
16+import qualified Prelude
17+import qualified Data.List as List
16import Control.Monad.Trans.State.Strict
19import Control.Monad.Trans.State.Strict
17import Data.Functor.Identity
20import Data.Functor.Identity
@@ -22,208 +25,191 @@ import Test.Hspec.QuickCheck
22import Test.QuickCheck
25import Test.QuickCheck
23import Test.QuickCheck.Function
26import Test.QuickCheck.Function
25−fromStream :: Property
28+-- We check for side effects in most cases
27− property $ \n -> do
30+-------------------------------------------------------------------------------
28− let strm = S.fromList n :: SerialT IO Int
31+-- Helper functions
29− n1 <- S.toList $ S.unfold UF.fromStream strm
32+-------------------------------------------------------------------------------
30− n1 `shouldBe` (n :: [Int])
33+
35+ (Eq s, Eq b) => Unfold (State s) a b -> s -> s -> a -> [b] -> Bool
36+testUnfoldA unf si sf seed lst = evalState action si
33−nilM = evalState action undefined
35 action = do
40 action = do
36− x <- S.toList $ S.unfold (UF.nilM put) (1 :: Int)
41+ x <- S.toList $ S.unfold unf seed
38− return $ x == ([] :: [Int]) && y == 1
43+ return $ x == lst && y == sf
45+testUnfoldAD :: Unfold (State Int) a Int -> Int -> Int -> a -> [Int] -> Bool
46+testUnfoldAD = testUnfoldA
48+testUnfold :: Eq b => Unfold Identity a b -> a -> [b] -> Bool
49+testUnfold unf seed lst = runIdentity action
41−consM = evalState action 0
43 action = do
53 action = do
45− S.toList $
54+ x <- S.toList $ S.unfold unf seed
46− S.unfold
55+ return $ x == lst
47− (UF.consM (\a -> modify (+ a) >> get) $
56+
57+testUnfoldD :: Unfold Identity a Int -> a -> [Int] -> Bool
58+testUnfoldD = testUnfold
60+-------------------------------------------------------------------------------
62+-------------------------------------------------------------------------------
64+fromStream :: Property
68+ testUnfoldD UF.fromStream (S.fromList n :: SerialT Identity Int) n
48− UF.consM (\a -> modify (+ a) >> get) $ UF.nilM put)
72+ let unf = UF.nilM put
49− 1
73+ in testUnfoldAD unf 0 1 1 []
51− return $ x == ([1, 2] :: [Int]) && y == 1
75+consM :: Bool
77+ let cns = UF.consM (\a -> modify (+ a) >> get)
78+ unf = cns $ cns $ UF.nilM $ \a -> modify (+ a)
79+ in testUnfoldAD unf 0 3 1 [1, 2]
53effect :: Bool
81effect :: Bool
54−effect = evalState action undefined
82+effect =
55− where
83+ let unf = UF.effect (modify (+ 1) >> get)
56− action = do
84+ in testUnfoldAD unf 0 1 undefined [1]
57− x <- S.toList $ S.unfold (UF.effect (put (1 :: Int))) undefined
59− return $ x == [()] && y == 1
61singletonM :: Bool
86singletonM :: Bool
62−singletonM = evalState action undefined
87+singletonM =
63− where
88+ let unf = UF.singletonM (\a -> modify (+ a) >> get)
64− action = do
89+ in testUnfoldAD unf 0 1 1 [1]
65− x <- S.toList $ S.unfold (UF.singletonM put) (1 :: Int)
67− return $ x == [()] && y == 1
69const :: Bool
91const :: Bool
70−const = evalState action 0
92+const =
75− S.take 10 $ S.unfold (UF.const (modify (+ 1) >> get)) undefined
93+ let unf = UF.take 10 $ UF.const (modify (+ 1) >> get)
76− y <- get
94+ in testUnfoldAD unf 0 10 (0 :: Int) [1 .. 10]
77− let rList = [1..10] :: [Int]
78− return $ x == rList && y == 10
80fromListM :: Property
96fromListM :: Property
81−fromListM = property $ \x -> evalState (action x) 0
97+fromListM =
83− action x = do
99+ $ \n ->
84− let list = P.map (\a -> modify (+ a) >> return a) (x :: [Int])
100+ let lst = Prelude.map (\x -> modify (+ 1) >> return x) n
85− x1 <- S.toList $ S.unfold UF.fromListM list
101+ in testUnfoldAD UF.fromListM 0 (length n) lst n
87− return $ x == x1 && y == foldr (+) 0 x
89replicateM :: Property
103replicateM :: Property
90replicateM =
104replicateM =
91− property $ \x ->
105+ property
92− runIdentity $ do
106+ $ \i ->
93− x1 <- S.toList $ S.unfold (UF.replicateM x) (return ())
107+ let ns = max 0 i + 1
94− let x2 = P.replicate x ()
108+ seed = modify (+ 1) >> get
95− return $ x1 == x2
109+ in testUnfoldAD (UF.replicateM i) 0 ns seed [1 .. i]
97−repeatM :: Property
111+repeatM :: Bool
99− property $ \x ->
113+ testUnfoldAD (UF.take 10 UF.repeatM) 0 10 (modify (+ 1) >> get) [1 .. 10]
101− x1 <- S.toList $ S.take x $ S.unfold UF.repeatM (return ())
102− let x2 = P.take x $ P.repeat ()
105take :: Property
115take :: Property
107− property $ \x ->
117+ property
108− runIdentity $ do
118+ $ \i ->
109− x1 <- S.toList $ S.unfold (UF.take x UF.repeatM) (return ())
120+ (UF.take i UF.repeatM)
110− x2 <- S.toList $ S.take x $ S.unfold UF.repeatM (return ())
121+ (return 1)
111− return $ x1 == x2
122+ (Prelude.take i (Prelude.repeat 1))
113takeWhileM :: Property
124takeWhileM :: Property
114−takeWhileM = property $ \f x -> evalState (action f x) 0
125+takeWhileM =
116− action f x = do
127+ $ \f n ->
117− let f' z = if apply f z
129+ if apply f x
118− then modify (+ 1) >> return True
130+ then modify (+ 1) >> return True
119− else return False
131+ else return False
120− x1 <-
132+ unf = UF.takeWhileM fM UF.fromList
121− S.toList $ S.unfold (UF.takeWhileM f' UF.fromListM) (P.map return x)
122− let x2 = P.takeWhile (apply f) (x :: [Int])
133+ fL = Prelude.takeWhile (apply f) n
123− y1 <- get
134+ fS = Prelude.length fL
124− let y2 = P.length x2
135+ in testUnfoldAD unf 0 fS n fL
125− return $ x1 == x2 && y1 == y2
127filterM :: Property
137filterM :: Property
128−filterM = property $ \f x -> evalState (action f x) 0
138+filterM =
130− action f x = do
140+ $ \f n ->
131− let f' z = if apply f z
142+ if apply f x
132− then modify (+ 1) >> return True
143+ then modify (+ 1) >> return True
133− else return False
144+ else return False
134− x1 <-
145+ unf = UF.filterM fM UF.fromList
135− S.toList $ S.unfold (UF.filterM f' UF.fromListM) (P.map return x)
136− let x2 = P.filter (apply f) (x :: [Int])
146+ fL = Prelude.filter (apply f) n
137− y1 <- get
147+ fS = Prelude.length fL
138− let y2 = P.length x2
148+ in testUnfoldAD unf 0 fS n fL
139− return $ x1 == x2 && y1 == y2
141drop :: Property
150drop :: Property
143− property $ \x y ->
152+ property
144− runIdentity $ do
153+ $ \i n ->
145− x1 <- S.toList
154+ let unf = UF.drop i UF.fromList
146− $ S.unfold (UF.drop x (UF.replicateM (x + y))) (return ())
155+ fL = Prelude.drop i n
147− x2 <- S.toList
156+ in testUnfoldD unf n fL
148− $ S.drop x $ S.unfold (UF.replicateM (x + y)) (return ())
151dropWhileM :: Property
158dropWhileM :: Property
152−dropWhileM = property $ \f x -> evalState (action f x) 0
159+dropWhileM =
154− action f x = do
161+ $ \f n ->
155− let f' z = if apply f z
163+ if apply f x
156− then modify (+ 1) >> return True
164+ then modify (+ 1) >> return True
157− else return False
165+ else return False
158− x1 <-
166+ unf = UF.dropWhileM fM UF.fromList
159− S.toList $ S.unfold (UF.dropWhileM f' UF.fromListM) (P.map return x)
160− let x2 = P.dropWhile (apply f) (x :: [Int])
167+ fL = Prelude.dropWhile (apply f) n
162− let y2 = P.length x - P.length x2
168+ fS = Prelude.length n - Prelude.length fL
163− return $ x1 == x2 && y1 == y2
169+ in testUnfoldAD unf 0 fS n fL
165enumerateFromStepIntegral :: Property
171enumerateFromStepIntegral :: Property
166enumerateFromStepIntegral =
172enumerateFromStepIntegral =
167− property $ \x y ->
173+ property
168− runIdentity $ do
174+ $ \f s ->
169− x1 <-
175+ let unf = UF.take 10 UF.enumerateFromStepIntegral
170− S.toList $
176+ lst = Prelude.take 10 $ List.unfoldr (\x -> Just (x, x + s)) f
171− S.unfold (UF.take y UF.enumerateFromStepIntegral) (0, x)
177+ in testUnfoldD unf (f, s) lst
172− let x2 = P.take y $ P.map (x *) [0 .. y]
175enumerateFromToIntegral :: Property
179enumerateFromToIntegral :: Property
176enumerateFromToIntegral =
180enumerateFromToIntegral =
177− property $ \x ->
181+ property
178− runIdentity $ do
182+ $ \f t ->
179− x1 <- S.toList $ S.unfold (UF.enumerateFromToIntegral x) 0
183+ let unf = UF.enumerateFromToIntegral t
180− let x2 = [0 .. x] :: [Int]
184+ in testUnfoldD unf f [f .. t]
183zipWithM :: Property
186zipWithM :: Property
184−zipWithM = property $ \x -> evalState (action x) (0 :: Int)
187+zipWithM =
186− action x = do
189+ $ \f ->
190+ let unf1 = UF.enumerateFromToIntegral 10
191+ unf2 = UF.enumerateFromToIntegral 20
192+ fA = applyFun2 f :: Int -> Int -> Int
187− let f a b = modify (+ 1) >> return (a + b)
193+ fM a b = modify (+ 1) >> return (fA a b)
191− (UF.zipWithM
194+ unf = UF.zipWithM fM unf1 unf2
192− f
195+ lst = Prelude.zipWith fA [1 .. 10] [1 .. 20]
193− (UF.enumerateFromToIntegral x)
196+ in testUnfoldAD unf 0 10 (1, 1) lst
194− (UF.enumerateFromToIntegral x))
197+
196− let x2 = P.zipWith (+) ([1 .. x] :: [Int]) ([1 .. x] :: [Int])
198− return $ x1 == x2 && y == max 0 x
200−concat :: Property
198+concat :: Bool
202− property $ \x y ->
200+ let unfIn = UF.replicateM 10
203− runIdentity $ do
201+ unfOut = UF.map return $ UF.enumerateFromToIntegral 10
204− x1 <-
202+ unf = UF.concat unfOut unfIn
205− S.toList $
203+ lst = Prelude.concat $ Prelude.map (Prelude.replicate 10) [1 .. 10]
206− S.unfold
204+ in testUnfoldD unf 1 lst
208− (UF.enumerateFromToIntegral (x :: Int))
209− (UF.enumerateFromToIntegral (y :: Int)))
211− let x2 = P.concat $ P.map (\k -> [k..y]) [0 .. x]
214−outerProduct :: Property
206+outerProduct :: Bool
215outerProduct =
207outerProduct =
216− property $ \x y ->
208+ let unf1 = UF.enumerateFromToIntegral 10
217− runIdentity $ do
209+ unf2 = UF.enumerateFromToIntegral 20
221− (UF.outerProduct
210+ unf = UF.outerProduct unf1 unf2
222− (UF.enumerateFromToIntegral (x :: Int))
211+ lst = [(a, b) :: (Int, Int) | a <- [0 .. 10], b <- [0 .. 20]]
223− (UF.enumerateFromToIntegral (y :: Int)))
212+ in testUnfold unf ((0, 0) :: (Int, Int)) lst
225− let x2 = [(a, b) | a <- [0 .. x], b <- [0 .. y]]
228main :: IO ()
214main :: IO ()
229main = hspec $
215main = hspec $