on 52ddfee help sign in
701 lines 24 kB history raw
1-- |
2-- Module : Main
3-- Copyright : (c) 2020 Composewell Technologies
4--
5-- License : BSD-3-Clause
6-- Maintainer : streamly@composewell.com
7-- Stability : experimental
8-- Portability : GHC
9--
10module Main (main) where
12import Streamly.Internal.Data.Unfold (Unfold)
14import qualified Data.List as List
15import qualified Prelude
16import qualified Streamly.Internal.Data.Fold as Fold
17import qualified Streamly.Internal.Data.Unfold as UF
18import qualified Streamly.Internal.Data.Stream as S
19import qualified Streamly.Internal.Data.Stream as D
20import qualified Streamly.Internal.Data.StreamK as K
22import Control.Monad.Trans.State.Strict
23import Data.Functor.Identity
24import Prelude hiding (const, take, drop, concat, mapM)
25import Test.Hspec as H
26import Test.Hspec.QuickCheck
27import Test.QuickCheck
28import Test.QuickCheck.Function
30-------------------------------------------------------------------------------
31-- Helper functions
32-------------------------------------------------------------------------------
34-- | @testUnfoldM unf seed initial final xs@, runs an unfold under state monad
35-- using @initial@ as the initial state. @final@ is the expected state after
36-- running it and @xs@ is the list of elements the stream must produce.
37testUnfoldM ::
38 (Eq s, Eq b) => Unfold (State s) a b -> a -> s -> s -> [b] -> Bool
39testUnfoldM unf seed si sf lst = evalState action si
41 where
43 action = do
44 x <- S.fold Fold.toList $ S.unfold unf seed
45 y <- get
46 return $ x == lst && y == sf
48testUnfoldMD :: Unfold (State Int) a Int -> a -> Int -> Int -> [Int] -> Bool
49testUnfoldMD = testUnfoldM
51-- | This is similar to 'testUnfoldM' but without the state monad.
52testUnfold :: Eq b => Unfold Identity a b -> a -> [b] -> Bool
53testUnfold unf seed lst = runIdentity action
55 where
57 action = do
58 x <- S.fold Fold.toList $ S.unfold unf seed
59 return $ x == lst
61testUnfoldD :: Unfold Identity a Int -> a -> [Int] -> Bool
62testUnfoldD = testUnfold
64-------------------------------------------------------------------------------
65-- Operations on input
66-------------------------------------------------------------------------------
68lmapM :: Bool
69lmapM =
70 let unf = UF.lmapM (\x -> modify (+ 1) >> return x) (UF.function id)
71 in testUnfoldMD unf 1 0 1 [1]
73both :: Bool
74both =
75 let unf = UF.both 1 (UF.function id)
76 in testUnfold unf undefined ([1] :: [Int])
78first :: Bool
79first =
80 let unf = UF.first 1 (UF.function id)
81 in testUnfold unf 2 ([(1, 2)] :: [(Int, Int)])
83second :: Bool
84second =
85 let unf = UF.second 1 (UF.function id)
86 in testUnfold unf 2 ([(2, 1)] :: [(Int, Int)])
88discardFirst :: Bool
89discardFirst =
90 let unf = UF.discardFirst (UF.function id)
91 in testUnfold unf ((1, 2) :: (Int, Int)) [2]
93discardSecond :: Bool
94discardSecond =
95 let unf = UF.discardSecond (UF.function id)
96 in testUnfold unf ((1, 2) :: (Int, Int)) [1]
98swap :: Bool
99swap =
100 let unf = UF.swap (UF.function id)
101 in testUnfold unf ((1, 2) :: (Int, Int)) [(2, 1)]
103-------------------------------------------------------------------------------
104-- Stream generation
105-------------------------------------------------------------------------------
107fromStream :: Property
108fromStream =
109 property
110 $ \list ->
111 testUnfoldD
112 UF.fromStream
113 (S.fromList list :: S.Stream Identity Int)
114 list
116fromStreamD :: Property
117fromStreamD =
118 property
119 $ \list -> testUnfoldD UF.fromStreamD (D.fromList list) (list :: [Int])
121fromStreamK :: Property
122fromStreamK =
123 property
124 $ \list -> testUnfoldD UF.fromStreamK (K.fromList list) (list :: [Int])
126nilM :: Bool
127nilM =
128 let unf = UF.nilM put
129 in testUnfoldMD unf 1 0 1 []
131consM :: Bool
132consM =
133 let cns = UF.consM (\a -> modify (+ a) >> get)
134 unf = cns $ cns $ UF.nilM $ \a -> modify (+ a)
135 in testUnfoldMD unf 1 0 3 [1, 2]
137functionM :: Bool
138functionM =
139 let unf = UF.functionM (\a -> modify (+ a) >> get)
140 in testUnfoldMD unf 1 0 1 [1]
142const :: Bool
143const =
144 let unf = UF.fromEffect (modify (+ 1) >> get)
145 in testUnfoldMD unf (0 :: Int) 0 1 [1]
147unfoldrM :: Property
148unfoldrM =
149 property
150 $ \gen ->
151 let genA = apply gen :: Int -> Maybe (Int, Int)
152 genM x = modify (+ 1) >> return (genA x)
153 list = Prelude.take 100 $ List.unfoldr genA 1
154 unf = UF.take 100 $ UF.unfoldrM genM
155 ll = length list
156 fs = if ll < 100 then ll + 1 else 100
157 in testUnfoldMD unf 1 0 fs list
159fromListM :: Property
160fromListM =
161 property
162 $ \list ->
163 let listM = Prelude.map (\x -> modify (+ 1) >> return x) list
164 in testUnfoldMD UF.fromListM listM 0 (length list) list
166replicateM :: Property
167replicateM =
168 property
169 $ \i ->
170 let ns = max 0 i
171 seed = (i, modify (+ 1) >> get)
172 in testUnfoldMD UF.replicateM seed 0 ns [1 .. i]
174repeatM :: Bool
175repeatM =
176 testUnfoldMD (UF.take 10 UF.repeatM) (modify (+ 1) >> get) 0 10 [1 .. 10]
178iterateM :: Property
179iterateM =
180 property
181 $ \next ->
182 let nextA = apply next :: Int -> Int
183 nextM x = modify (+ 1) >> return (nextA x)
184 list = Prelude.take 100 $ List.iterate nextA 1
185 unf = UF.take 100 $ UF.iterateM nextM
186 in testUnfoldMD unf (modify (+ 10) >> return 1) 0 110 list
188fromIndicesM :: Property
189fromIndicesM =
190 property
191 $ \indF ->
192 let indFA = apply indF :: Int -> Int
193 indFM x = modify (+ 1) >> return (indFA x)
194 list = Prelude.take 100 $ Prelude.map indFA [1 ..]
195 unf = UF.take 100 $ UF.fromIndicesM indFM
196 in testUnfoldMD unf 1 0 (length list) list
198-------------------------------------------------------------------------------
199-- Test for Num type
200-------------------------------------------------------------------------------
201enumerateFromNum :: Property
202enumerateFromNum =
203 property
204 $ \f ->
205 let unf = UF.take 50 UF.enumerateFromNum
206 in testUnfold unf (f :: Int) $
207 Prelude.take 50 $ Prelude.enumFrom f
209enumerateFromThenNum :: Property
210enumerateFromThenNum =
211 property
212 $ \f th ->
213 let unf = UF.take 50 UF.enumerateFromThenNum
214 in testUnfold unf (f :: Int, th) $
215 Prelude.take 50 $ Prelude.enumFromThen f th
217-------------------------------------------------------------------------------
218-- Test for Integral type
219-------------------------------------------------------------------------------
220enumerateFromIntegral :: Property
221enumerateFromIntegral =
222 property
223 $ \f ->
224 let unf = UF.take 50 UF.enumerateFromIntegral
225 in testUnfold unf (f :: Integer) $
226 Prelude.take 50 $ Prelude.enumFrom f
228enumerateFromThenIntegral :: Property
229enumerateFromThenIntegral =
230 property
231 $ \f th ->
232 let unf = UF.take 50 UF.enumerateFromThenIntegral
233 in testUnfold unf (f :: Integer, th) $
234 Prelude.take 50 $ Prelude.enumFromThen f th
236enumerateFromThenToIntegral :: Property
237enumerateFromThenToIntegral =
238 property
239 $ \f th to ->
240 let unf = UF.take 50 UF.enumerateFromThenToIntegral
241 in testUnfold unf (f :: Integer, th, to) $
242 Prelude.take 50 $ Prelude.enumFromThenTo f th to
244enumerateFromToIntegral :: Property
245enumerateFromToIntegral =
246 property
247 $ \f to ->
248 let unf = UF.take 50 UF.enumerateFromToIntegral
249 in testUnfold unf (f :: Integer, to) $
250 Prelude.take 50 $ Prelude.enumFromTo f to
252enumerateFromIntegralBounded :: Property
253enumerateFromIntegralBounded =
254 property
255 $ \f ->
256 let unf = UF.take 50 UF.enumerateFromIntegralBounded
257 in testUnfold unf (f :: Int) $
258 Prelude.take 50 $ Prelude.enumFrom f
260enumerateFromThenIntegralBounded :: Property
261enumerateFromThenIntegralBounded =
262 property
263 $ \f th ->
264 let unf = UF.take 50 UF.enumerateFromThenIntegralBounded
265 in testUnfold unf (f :: Int, th) $
266 Prelude.take 50 $ Prelude.enumFromThen f th
268enumerateFromToIntegralBounded :: Property
269enumerateFromToIntegralBounded =
270 property
271 $ \f to ->
272 let unf = UF.take 50 UF.enumerateFromToIntegralBounded
273 in testUnfold unf (f :: Int, to) $
274 Prelude.take 50 $ Prelude.enumFromTo f to
276enumerateFromThenToIntegralBounded :: Property
277enumerateFromThenToIntegralBounded =
278 property
279 $ \f th to ->
280 let unf = UF.take 50 UF.enumerateFromThenToIntegralBounded
281 in testUnfold unf (f :: Int, th, to) $
282 Prelude.take 50 $ Prelude.enumFromThenTo f th to
284enumerateFromSmallBounded :: Property
285enumerateFromSmallBounded =
286 property
287 $ \f ->
288 let unf = UF.take 50 UF.enumerateFromSmallBounded
289 in testUnfold unf (f :: Char) $
290 Prelude.take 50 $ Prelude.enumFrom f
292enumerateFromThenSmallBounded :: Property
293enumerateFromThenSmallBounded =
294 property
295 $ \f th ->
296 let unf = UF.take 50 UF.enumerateFromThenSmallBounded
297 in testUnfold unf (f :: Char, th) $
298 Prelude.take 50 $ Prelude.enumFromThen f th
300enumerateFromToSmall :: Property
301enumerateFromToSmall =
302 property
303 $ \f to ->
304 let unf = UF.take 50 UF.enumerateFromToSmall
305 in testUnfold unf (f :: Char, to) $
306 Prelude.take 50 $ Prelude.enumFromTo f to
308enumerateFromThenToSmall :: Property
309enumerateFromThenToSmall =
310 property
311 $ \f th to ->
312 let unf = UF.take 50 UF.enumerateFromThenToSmall
313 in testUnfold unf (f :: Char, th, to) $
314 Prelude.take 50 $ Prelude.enumFromThenTo f th to
316enumerateFromSmallBoundedOrd :: Property
317enumerateFromSmallBoundedOrd =
318 property
319 $ \f ->
320 let unf = UF.take 3 UF.enumerateFromSmallBounded
321 in testUnfold unf (f :: Ordering) $
322 Prelude.take 3 $ Prelude.enumFrom f
324enumerateFromThenSmallBoundedOrd :: Property
325enumerateFromThenSmallBoundedOrd =
326 property
327 $ \f th ->
328 let unf = UF.take 3 UF.enumerateFromThenSmallBounded
329 in testUnfold unf (f :: Ordering, th) $
330 Prelude.take 3 $ Prelude.enumFromThen f th
332enumerateFromToSmallOrd :: Property
333enumerateFromToSmallOrd =
334 property
335 $ \f to ->
336 let unf = UF.take 3 UF.enumerateFromToSmall
337 in testUnfold unf (f :: Ordering, to) $
338 Prelude.take 3 $ Prelude.enumFromTo f to
340enumerateFromThenToSmallOrd :: Property
341enumerateFromThenToSmallOrd =
342 property
343 $ \f th to ->
344 let unf = UF.take 3 UF.enumerateFromThenToSmall
345 in testUnfold unf (f :: Ordering, th, to) $
346 Prelude.take 3 $ Prelude.enumFromThenTo f th to
348-------------------------------------------------------------------------------
349enumerateFromSmallBoundedBool :: Property
350enumerateFromSmallBoundedBool =
351 property
352 $ \f ->
353 let unf = UF.take 2 UF.enumerateFromSmallBounded
354 in testUnfold unf (f :: Bool) $
355 Prelude.take 2 $ Prelude.enumFrom f
357enumerateFromThenSmallBoundedBool :: Property
358enumerateFromThenSmallBoundedBool =
359 property
360 $ \f th ->
361 let unf = UF.take 2 UF.enumerateFromThenSmallBounded
362 in testUnfold unf (f :: Bool, th) $
363 Prelude.take 2 $ Prelude.enumFromThen f th
365enumerateFromToSmallBool :: Property
366enumerateFromToSmallBool =
367 property
368 $ \f to ->
369 let unf = UF.take 2 UF.enumerateFromToSmall
370 in testUnfold unf (f :: Bool, to) $
371 Prelude.take 2 $ Prelude.enumFromTo f to
373enumerateFromThenToSmallBool :: Property
374enumerateFromThenToSmallBool =
375 property
376 $ \f th to ->
377 let unf = UF.take 2 UF.enumerateFromThenToSmall
378 in testUnfold unf (f :: Bool, th, to) $
379 Prelude.take 2 $ Prelude.enumFromThenTo f th to
380-------------------------------------------------------------------------------
381enumerateFromSmallBoundedUnit :: Property
382enumerateFromSmallBoundedUnit =
383 property
384 $ \f ->
385 let unf = UF.take 1 UF.enumerateFromSmallBounded
386 in testUnfold unf (f :: ()) $
387 Prelude.take 1 $ Prelude.enumFrom f
389enumerateFromThenSmallBoundedUnit :: Property
390enumerateFromThenSmallBoundedUnit =
391 property
392 $ \f th ->
393 let unf = UF.take 1 UF.enumerateFromThenSmallBounded
394 in testUnfold unf (f :: (), th) $
395 Prelude.take 1 $ Prelude.enumFromThen f th
397enumerateFromToSmallUnit :: Property
398enumerateFromToSmallUnit =
399 property
400 $ \f to ->
401 let unf = UF.take 1 UF.enumerateFromToSmall
402 in testUnfold unf (f :: (), to) $
403 Prelude.take 1 $ Prelude.enumFromTo f to
405enumerateFromThenToSmallUnit :: Property
406enumerateFromThenToSmallUnit =
407 property
408 $ \f th to ->
409 let unf = UF.take 1 UF.enumerateFromThenToSmall
410 in testUnfold unf (f :: (), th, to) $
411 Prelude.take 1 $ Prelude.enumFromThenTo f th to
413enumerateFromFractional :: Property
414enumerateFromFractional =
415 property
416 $ \f ->
417 let unf = UF.take 50 UF.enumerateFromFractional
418 in testUnfold unf (f :: Double) $
419 Prelude.take 50 $ Prelude.enumFrom f
421enumerateFromThenFractional :: Property
422enumerateFromThenFractional =
423 property
424 $ \f th ->
425 let unf = UF.take 50 UF.enumerateFromThenFractional
426 in testUnfold unf (f :: Double, th) $
427 Prelude.take 50 $ Prelude.enumFromThen f th
429enumerateFromThenToFractional :: Property
430enumerateFromThenToFractional =
431 property
432 $ \f th to ->
433 let unf = UF.take 50 UF.enumerateFromThenToFractional
434 in testUnfold unf (f :: Double, th, to) $
435 Prelude.take 50 $ Prelude.enumFromThenTo f th to
437enumerateFromToFractional :: Property
438enumerateFromToFractional =
439 property
440 $ \f t ->
441 let unf = UF.enumerateFromToFractional
442 in testUnfold unf (f :: Double, t) [f..(t :: Double)]
444-------------------------------------------------------------------------------
445-- Stream transformation
446-------------------------------------------------------------------------------
448postscan :: Property
449postscan =
450 property
451 $ \(ls :: [Int]) ->
452 let unf = UF.postscan Fold.sum UF.fromList
453 mList = scanl1 (+) ls
454 in testUnfold unf ls mList
456mapM :: Property
457mapM =
458 property
459 $ \f list ->
460 let fA = apply f :: Int -> Int
461 fM x = modify (+ 1) >> return (fA x)
462 unf = UF.mapM fM UF.fromList
463 mList = Prelude.map fA list
464 in testUnfoldMD unf list 0 (length list) mList
466mapM2 :: Property
467mapM2 =
468 property
469 $ \f list ->
470 let fA = applyFun2 f :: [Int] -> Int -> Int
471 fM x y = modify (+ 1) >> return (fA x y)
472 unf = UF.mapM2 fM UF.fromList
473 mList = Prelude.map (fA list) list
474 in testUnfoldMD unf list 0 (length list) mList
476take :: Property
477take =
478 property
479 $ \i ->
480 testUnfoldD
481 (UF.take i UF.repeatM)
482 (return 1)
483 (Prelude.take i (Prelude.repeat 1))
485takeWhileM :: Property
486takeWhileM =
487 property
488 $ \f list ->
489 let fM x =
490 if apply f x
491 then modify (+ 1) >> return True
492 else return False
493 unf = UF.takeWhileM fM UF.fromList
494 fL = Prelude.takeWhile (apply f) list
495 fS = Prelude.length fL
496 in testUnfoldMD unf list 0 fS fL
498filterM :: Property
499filterM =
500 property
501 $ \f list ->
502 let fM x =
503 if apply f x
504 then modify (+ 1) >> return True
505 else return False
506 unf = UF.filterM fM UF.fromList
507 fL = Prelude.filter (apply f) list
508 fS = Prelude.length fL
509 in testUnfoldMD unf list 0 fS fL
511drop :: Property
512drop =
513 property
514 $ \i list ->
515 let unf = UF.drop i UF.fromList
516 fL = Prelude.drop i list
517 in testUnfoldD unf list fL
519dropWhileM :: Property
520dropWhileM =
521 property
522 $ \f list ->
523 let fM x =
524 if apply f x
525 then modify (+ 1) >> return True
526 else return False
527 unf = UF.dropWhileM fM UF.fromList
528 fL = Prelude.dropWhile (apply f) list
529 fS = Prelude.length list - Prelude.length fL
530 in testUnfoldMD unf list 0 fS fL
532-------------------------------------------------------------------------------
533-- Stream combination
534-------------------------------------------------------------------------------
536zipWithM :: Property
537zipWithM =
538 property
539 $ \f ->
540 let unf1 = UF.enumerateFromToIntegral
541 unf2 = UF.enumerateFromToIntegral
542 fA = applyFun2 f :: Int -> Int -> Int
543 fM a b = modify (+ 1) >> return (fA a b)
544 unf = UF.zipWithM fM (UF.lmap fst unf1) (UF.lmap snd unf2)
545 lst = Prelude.zipWith fA [1 .. 10] [1 .. 20]
546 in testUnfoldMD unf ((1,10), (1,20)) 0 10 lst
548concat :: Bool
549concat =
550 let unfIn = UF.replicateM
551 unfOut = UF.map ((10,) . return) UF.enumerateFromToIntegral
552 unf = UF.many unfIn unfOut
553 lst = Prelude.concat $ Prelude.map (Prelude.replicate 10) [1 .. 10]
554 in testUnfoldD unf (1, 10) lst
556outerProduct :: Bool
557outerProduct =
558 let unf1 = UF.enumerateFromToIntegral
559 unf2 = UF.enumerateFromToIntegral
560 unf = crossProduct unf1 unf2
561 lst = [(a, b) :: (Int, Int) | a <- [0 .. 10], b <- [0 .. 20]]
562 in testUnfold unf (((0,10) ,(0,20)) :: ((Int, Int), (Int, Int))) lst
564 where
566 crossProduct u1 u2 = UF.cross (UF.lmap fst u1) (UF.lmap snd u2)
568concatMapM :: Bool
569concatMapM =
570 let inner b =
571 let u = UF.lmap (\_ -> (10, modify (+ 1) >> return b)) UF.replicateM
572 in modify (+ 1) >> return u
573 unf = UF.concatMapM inner UF.enumerateFromToIntegral
574 list = List.concatMap (replicate 10) [1 .. 10]
575 in testUnfoldMD unf (1, 10) 0 110 list
577-------------------------------------------------------------------------------
578-- Test groups
579-------------------------------------------------------------------------------
581testInputOps :: Spec
582testInputOps =
583 describe "Input"
584 $ do
585 -- prop "lmap" lmap
586 prop "lmapM" lmapM
587 prop "both" both
588 prop "first" first
589 prop "second" second
590 prop "discardFirst" discardFirst
591 prop "discardSecond" discardSecond
592 prop "swap" swap
594testGeneration :: Spec
595testGeneration =
596 describe "Generation"
597 $ do
598 prop "fromStream" fromStream
599 prop "fromStreamK" fromStreamK
600 prop "fromStreamD" fromStreamD
601 prop "nilM" nilM
602 prop "consM" consM
603 prop "functionM" functionM
604 -- prop "function" function
605 -- prop "identity" identity
606 prop "const" const
607 prop "unfoldrM" unfoldrM
608 -- prop "fromList" fromList
609 prop "fromListM" fromListM
610 -- prop "fromSVar" fromSVar
611 -- prop "fromProducer" fromProducer
612 prop "replicateM" replicateM
613 prop "repeatM" repeatM
614 prop "iterateM" iterateM
615 prop "fromIndicesM" fromIndicesM
616 ----------- Enumerate from Num ------------------------------------
617 prop "enumerateFromNum" enumerateFromNum
618 prop "enumerateFromThenNum" enumerateFromThenNum
619 ----------- Enumerate from Integral -------------------------------
620 prop "enumerateFromIntegral" enumerateFromIntegral
621 prop "enumerateFromThenIntegral" enumerateFromThenIntegral
622 prop "enumerateFromToIntegral" enumerateFromToIntegral
623 prop "enumerateFromThenToIntegral" enumerateFromThenToIntegral
625 prop "enumerateFromIntegralBounded" enumerateFromIntegralBounded
626 prop "enumerateFromThenIntegralBounded" enumerateFromThenIntegralBounded
627 prop "enumerateFromToIntegralBounded" enumerateFromToIntegralBounded
628 prop "enumerateFromThenToIntegralBounded" enumerateFromThenToIntegralBounded
629 ----------- Enumerate from Small Integral -------------------------
630 prop "enumerateFromSmallBounded" enumerateFromSmallBounded
631 prop "enumerateFromThenSmallBounded" enumerateFromThenSmallBounded
632 prop "enumerateFromToSmall" enumerateFromToSmall
633 prop "enumerateFromThenToSmall" enumerateFromThenToSmall
634 --
635 prop "enumerateFromSmallBoundedOrd" enumerateFromSmallBoundedOrd
636 prop "enumerateFromThenSmallBoundedOrd" enumerateFromThenSmallBoundedOrd
637 prop "enumerateFromToSmallOrd" enumerateFromToSmallOrd
638 prop "enumerateFromThenToSmallOrd" enumerateFromThenToSmallOrd
640 prop "enumerateFromSmallBoundedUnit" enumerateFromSmallBoundedUnit
641 prop "enumerateFromThenSmallBoundedUnit" enumerateFromThenSmallBoundedUnit
642 prop "enumerateFromToSmallUnit" enumerateFromToSmallUnit
643 prop "enumerateFromThenToSmallUnit" enumerateFromThenToSmallUnit
645 prop "enumerateFromSmallBoundedUnit" enumerateFromSmallBoundedBool
646 prop "enumerateFromThenSmallBoundedBool" enumerateFromThenSmallBoundedBool
647 prop "enumerateFromToSmallBool" enumerateFromToSmallBool
648 prop "enumerateFromThenToSmallBool" enumerateFromThenToSmallBool
650 prop "enumerateFromFractional" enumerateFromFractional
651 prop "enumerateFromThenFractional" enumerateFromThenFractional
652 prop "enumerateFromToFractional" enumerateFromToFractional
653 prop "enumerateFromThenToFractional" enumerateFromThenToFractional
655testTransformation :: Spec
656testTransformation =
657 describe "Transformation"
658 $ do
659 -- prop "map" map
660 prop "postscan" postscan
661 prop "mapM" mapM
662 prop "mapM2" mapM2
663 prop "takeWhileM" takeWhileM
664 -- prop "takeWhile" takeWhile
665 prop "take" take
666 -- prop "filter" filter
667 prop "filterM" filterM
668 prop "drop" drop
669 -- prop "dropWhile" dropWhile
670 prop "dropWhileM" dropWhileM
672testCombination :: Spec
673testCombination =
674 describe "Transformation"
675 $ do
676 prop "zipWithM" zipWithM
677 -- prop "zipWith" zipWith
678 -- prop "teeZipWith" teeZipWith
679 prop "concat" concat
680 prop "concatMapM" concatMapM
681 prop "outerProduct" outerProduct
682 -- prop "ap" ap
683 -- prop "apDiscardFst" apDiscardFst
684 -- prop "apDiscardSnd" apDiscardSnd
686-------------------------------------------------------------------------------
687-- Main
688-------------------------------------------------------------------------------
690moduleName :: String
691moduleName = "Data.Unfold"
693main :: IO ()
694main =
695 hspec
696 $ describe moduleName
697 $ do
698 testInputOps
699 testGeneration
700 testTransformation
701 testCombination