@@ -0,0 +1,258 @@
3+-- Copyright : (c) 2020 Composewell Technologies
5+-- License : BSD-3-Clause
6+-- Maintainer : streamly@composewell.com
7+-- Stability : experimental
10+module Main (main) where
12+import qualified Streamly.Internal.Data.Unfold as UF
13+import qualified Streamly.Internal.Data.Stream.IsStream as S
14+import qualified Prelude as P
16+import Control.Monad.Trans.State.Strict
17+import Data.Functor.Identity
18+import Prelude hiding (const, take, drop, concat)
19+import Streamly.Prelude (SerialT)
20+import Test.Hspec as H
21+import Test.Hspec.QuickCheck
22+import Test.QuickCheck
23+import Test.QuickCheck.Function
25+fromStream :: Property
28+ let strm = S.fromList n :: SerialT IO Int
29+ n1 <- S.toList $ S.unfold UF.fromStream strm
30+ n1 `shouldBe` (n :: [Int])
33+nilM = evalState action undefined
36+ x <- S.toList $ S.unfold (UF.nilM put) (1 :: Int)
38+ return $ x == ([] :: [Int]) && y == 1
41+consM = evalState action 0
47+ (UF.consM (\a -> modify (+ a) >> get) $
48+ UF.consM (\a -> modify (+ a) >> get) $ UF.nilM put)
51+ return $ x == ([1, 2] :: [Int]) && y == 1
54+effect = evalState action undefined
57+ x <- S.toList $ S.unfold (UF.effect (put (1 :: Int))) undefined
59+ return $ x == [()] && y == 1
62+singletonM = evalState action undefined
65+ x <- S.toList $ S.unfold (UF.singletonM put) (1 :: Int)
67+ return $ x == [()] && y == 1
70+const = evalState action 0
75+ S.take 10 $ S.unfold (UF.const (modify (+ 1) >> get)) undefined
77+ let rList = [1..10] :: [Int]
78+ return $ x == rList && y == 10
81+fromListM = property $ \x -> evalState (action x) 0
84+ let list = P.map (\a -> modify (+ a) >> return a) (x :: [Int])
85+ x1 <- S.toList $ S.unfold UF.fromListM list
87+ return $ x == x1 && y == foldr (+) 0 x
89+replicateM :: Property
93+ x1 <- S.toList $ S.unfold (UF.replicateM x) ()
94+ let x2 = P.replicate x ()
101+ x1 <- S.toList $ S.take x $ S.unfold UF.repeatM ()
102+ let x2 = P.take x $ P.repeat ()
109+ x1 <- S.toList $ S.unfold (UF.take x UF.repeatM) (return ())
110+ x2 <- S.toList $ S.take x $ S.unfold UF.repeatM (return ())
113+takeWhileM :: Property
114+takeWhileM = property $ \f x -> evalState (action f x) 0
117+ let f' z = if apply f z
118+ then modify (+ 1) >> return True
121+ S.toList $ S.unfold (UF.takeWhileM f' UF.fromListM) (P.map return x)
122+ let x2 = P.takeWhile (apply f) (x :: [Int])
124+ let y2 = P.length x2
125+ return $ x1 == x2 && y1 == y2
128+filterM = property $ \f x -> evalState (action f x) 0
131+ let f' z = if apply f z
132+ then modify (+ 1) >> return True
135+ S.toList $ S.unfold (UF.filterM f' UF.fromListM) (P.map return x)
136+ let x2 = P.filter (apply f) (x :: [Int])
138+ let y2 = P.length x2
139+ return $ x1 == x2 && y1 == y2
145+ x1 <- S.toList $ S.unfold (UF.drop x (UF.replicateM (x + y))) ()
146+ x2 <- S.toList $ S.drop x $ S.unfold (UF.replicateM (x + y)) ()
149+dropWhileM :: Property
150+dropWhileM = property $ \f x -> evalState (action f x) 0
153+ let f' z = if apply f z
154+ then modify (+ 1) >> return True
157+ S.toList $ S.unfold (UF.dropWhileM f' UF.fromListM) (P.map return x)
158+ let x2 = P.dropWhile (apply f) (x :: [Int])
160+ let y2 = P.length x - P.length x2
161+ return $ x1 == x2 && y1 == y2
163+enumerateFromStepIntegral :: Property
164+enumerateFromStepIntegral =
169+ S.unfold (UF.take y UF.enumerateFromStepIntegral) (0, x)
170+ let x2 = P.take y $ P.map (x *) [0 .. y]
173+enumerateFromToIntegral :: Property
174+enumerateFromToIntegral =
177+ x1 <- S.toList $ S.unfold (UF.enumerateFromToIntegral x) 0
178+ let x2 = [0 .. x] :: [Int]
182+zipWithM = property $ \x -> evalState (action x) (0 :: Int)
185+ let f a b = modify (+ 1) >> return (a + b)
191+ (UF.enumerateFromToIntegral x)
192+ (UF.enumerateFromToIntegral x))
194+ let x2 = P.zipWith (+) ([1 .. x] :: [Int]) ([1 .. x] :: [Int])
196+ return $ x1 == x2 && y == max 0 x
206+ (UF.enumerateFromToIntegral (x :: Int))
207+ (UF.enumerateFromToIntegral (y :: Int)))
209+ let x2 = P.concat $ P.map (\k -> [k..y]) [0 .. x]
212+outerProduct :: Property
220+ (UF.enumerateFromToIntegral (x :: Int))
221+ (UF.enumerateFromToIntegral (y :: Int)))
223+ let x2 = [(a, b) | a <- [0 .. x], b <- [0 .. y]]
228+ describe "Unfold tests" $ do
229+ prop "fromStream" fromStream
232+ prop "effect" effect
233+ prop "singletonM" singletonM
235+ prop "fromListM" fromListM
236+ prop "replicateM" replicateM
237+ prop "repeatM" repeatM
239+ prop "takeWhileM" takeWhileM
240+ prop "filterM" filterM
242+ prop "dropWhileM" dropWhileM
243+ prop "enumerateFromStepIntegral" enumerateFromStepIntegral
244+ prop "enumerateFromToIntegral" enumerateFromToIntegral
245+ prop "zipWithM" zipWithM
246+ prop "concat" concat
247+ prop "outerProduct" outerProduct
248+ -- prop "concatMapM" concatMapM
249+ -- prop "gbracket" gbracket
250+ -- prop "gbracketIO" gbracketIO
251+ -- prop "before" before
252+ -- prop "after" after
253+ -- prop "afterIO" afterIO
254+ -- prop "onException" onException
255+ -- prop "finally" finally
256+ -- prop "finallyIO" finallyIO
257+ -- prop "bracket" bracket
258+ -- prop "bracketIO" bracketIO