on d1146fb help sign in
698 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.Unfold as UF
17import qualified Streamly.Internal.Data.Stream.IsStream as S
18import qualified Streamly.Internal.Data.Stream.StreamD as D
19import qualified Streamly.Internal.Data.Stream.StreamK as K
21import Control.Monad.Trans.State.Strict
22import Data.Functor.Identity
23import Prelude hiding (const, take, drop, concat, mapM)
24import Streamly.Prelude (SerialT)
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.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.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]
73supply :: Bool
74supply =
75 let unf = UF.supply 1 (UF.function id)
76 in testUnfold unf undefined ([1] :: [Int])
78supplyFirst :: Bool
79supplyFirst =
80 let unf = UF.supplyFirst 1 (UF.function id)
81 in testUnfold unf 2 ([(1, 2)] :: [(Int, Int)])
83supplySecond :: Bool
84supplySecond =
85 let unf = UF.supplySecond 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 :: SerialT 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 = modify (+ 1) >> get
172 in testUnfoldMD (UF.replicateM i) 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
414#if MIN_VERSION_base(4,12,0)
415enumerateFromFractional :: Property
416enumerateFromFractional =
417 property
418 $ \f ->
419 let unf = UF.take 50 UF.enumerateFromFractional
420 in testUnfold unf (f :: Double) $
421 Prelude.take 50 $ Prelude.enumFrom f
423enumerateFromThenFractional :: Property
424enumerateFromThenFractional =
425 property
426 $ \f th ->
427 let unf = UF.take 50 UF.enumerateFromThenFractional
428 in testUnfold unf (f :: Double, th) $
429 Prelude.take 50 $ Prelude.enumFromThen f th
431enumerateFromThenToFractional :: Property
432enumerateFromThenToFractional =
433 property
434 $ \f th to ->
435 let unf = UF.take 50 UF.enumerateFromThenToFractional
436 in testUnfold unf (f :: Double, th, to) $
437 Prelude.take 50 $ Prelude.enumFromThenTo f th to
439enumerateFromToFractional :: Property
440enumerateFromToFractional =
441 property
442 $ \f t ->
443 let unf = UF.enumerateFromToFractional
444 in testUnfold unf (f :: Double, t) [f..(t :: Double)]
446#endif
448-------------------------------------------------------------------------------
449-- Stream transformation
450-------------------------------------------------------------------------------
452mapM :: Property
453mapM =
454 property
455 $ \f list ->
456 let fA = apply f :: Int -> Int
457 fM x = modify (+ 1) >> return (fA x)
458 unf = UF.mapM fM UF.fromList
459 mList = Prelude.map fA list
460 in testUnfoldMD unf list 0 (length list) mList
462mapMWithInput :: Property
463mapMWithInput =
464 property
465 $ \f list ->
466 let fA = applyFun2 f :: [Int] -> Int -> Int
467 fM x y = modify (+ 1) >> return (fA x y)
468 unf = UF.mapMWithInput fM UF.fromList
469 mList = Prelude.map (fA list) list
470 in testUnfoldMD unf list 0 (length list) mList
472take :: Property
473take =
474 property
475 $ \i ->
476 testUnfoldD
477 (UF.take i UF.repeatM)
478 (return 1)
479 (Prelude.take i (Prelude.repeat 1))
481takeWhileM :: Property
482takeWhileM =
483 property
484 $ \f list ->
485 let fM x =
486 if apply f x
487 then modify (+ 1) >> return True
488 else return False
489 unf = UF.takeWhileM fM UF.fromList
490 fL = Prelude.takeWhile (apply f) list
491 fS = Prelude.length fL
492 in testUnfoldMD unf list 0 fS fL
494filterM :: Property
495filterM =
496 property
497 $ \f list ->
498 let fM x =
499 if apply f x
500 then modify (+ 1) >> return True
501 else return False
502 unf = UF.filterM fM UF.fromList
503 fL = Prelude.filter (apply f) list
504 fS = Prelude.length fL
505 in testUnfoldMD unf list 0 fS fL
507drop :: Property
508drop =
509 property
510 $ \i list ->
511 let unf = UF.drop i UF.fromList
512 fL = Prelude.drop i list
513 in testUnfoldD unf list fL
515dropWhileM :: Property
516dropWhileM =
517 property
518 $ \f list ->
519 let fM x =
520 if apply f x
521 then modify (+ 1) >> return True
522 else return False
523 unf = UF.dropWhileM fM UF.fromList
524 fL = Prelude.dropWhile (apply f) list
525 fS = Prelude.length list - Prelude.length fL
526 in testUnfoldMD unf list 0 fS fL
528-------------------------------------------------------------------------------
529-- Stream combination
530-------------------------------------------------------------------------------
532zipWithM :: Property
533zipWithM =
534 property
535 $ \f ->
536 let unf1 = UF.enumerateFromToIntegral
537 unf2 = UF.enumerateFromToIntegral
538 fA = applyFun2 f :: Int -> Int -> Int
539 fM a b = modify (+ 1) >> return (fA a b)
540 unf = UF.zipWithM fM (UF.lmap fst unf1) (UF.lmap snd unf2)
541 lst = Prelude.zipWith fA [1 .. 10] [1 .. 20]
542 in testUnfoldMD unf ((1,10), (1,20)) 0 10 lst
544concat :: Bool
545concat =
546 let unfIn = UF.replicateM 10
547 unfOut = UF.map return UF.enumerateFromToIntegral
548 unf = UF.many unfOut unfIn
549 lst = Prelude.concat $ Prelude.map (Prelude.replicate 10) [1 .. 10]
550 in testUnfoldD unf (1, 10) lst
552outerProduct :: Bool
553outerProduct =
554 let unf1 = UF.enumerateFromToIntegral
555 unf2 = UF.enumerateFromToIntegral
556 unf = crossProduct unf1 unf2
557 lst = [(a, b) :: (Int, Int) | a <- [0 .. 10], b <- [0 .. 20]]
558 in testUnfold unf (((0,10) ,(0,20)) :: ((Int, Int), (Int, Int))) lst
560 where
562 crossProduct u1 u2 = UF.cross (UF.lmap fst u1) (UF.lmap snd u2)
564concatMapM :: Bool
565concatMapM =
566 let inner b =
567 let u = UF.lmap (\_ -> modify (+ 1) >> return b) (UF.replicateM 10)
568 in modify (+ 1) >> return u
569 unf = UF.concatMapM inner UF.enumerateFromToIntegral
570 list = List.concatMap (replicate 10) [1 .. 10]
571 in testUnfoldMD unf (1, 10) 0 110 list
573-------------------------------------------------------------------------------
574-- Test groups
575-------------------------------------------------------------------------------
577testInputOps :: Spec
578testInputOps =
579 describe "Input"
580 $ do
581 -- prop "lmap" lmap
582 prop "lmapM" lmapM
583 prop "supply" supply
584 prop "supplyFirst" supplyFirst
585 prop "supplySecond" supplySecond
586 prop "discardFirst" discardFirst
587 prop "discardSecond" discardSecond
588 prop "swap" swap
590testGeneration :: Spec
591testGeneration =
592 describe "Generation"
593 $ do
594 prop "fromStream" fromStream
595 prop "fromStreamK" fromStreamK
596 prop "fromStreamD" fromStreamD
597 prop "nilM" nilM
598 prop "consM" consM
599 prop "functionM" functionM
600 -- prop "function" function
601 -- prop "identity" identity
602 prop "const" const
603 prop "unfoldrM" unfoldrM
604 -- prop "fromList" fromList
605 prop "fromListM" fromListM
606 -- prop "fromSVar" fromSVar
607 -- prop "fromProducer" fromProducer
608 prop "replicateM" replicateM
609 prop "repeatM" repeatM
610 prop "iterateM" iterateM
611 prop "fromIndicesM" fromIndicesM
612 ----------- Enumerate from Num ------------------------------------
613 prop "enumerateFromNum" enumerateFromNum
614 prop "enumerateFromThenNum" enumerateFromThenNum
615 ----------- Enumerate from Integral -------------------------------
616 prop "enumerateFromIntegral" enumerateFromIntegral
617 prop "enumerateFromThenIntegral" enumerateFromThenIntegral
618 prop "enumerateFromToIntegral" enumerateFromToIntegral
619 prop "enumerateFromThenToIntegral" enumerateFromThenToIntegral
621 prop "enumerateFromIntegralBounded" enumerateFromIntegralBounded
622 prop "enumerateFromThenIntegralBounded" enumerateFromThenIntegralBounded
623 prop "enumerateFromToIntegralBounded" enumerateFromToIntegralBounded
624 prop "enumerateFromThenToIntegralBounded" enumerateFromThenToIntegralBounded
625 ----------- Enumerate from Small Integral -------------------------
626 prop "enumerateFromSmallBounded" enumerateFromSmallBounded
627 prop "enumerateFromThenSmallBounded" enumerateFromThenSmallBounded
628 prop "enumerateFromToSmall" enumerateFromToSmall
629 prop "enumerateFromThenToSmall" enumerateFromThenToSmall
630 --
631 prop "enumerateFromSmallBoundedOrd" enumerateFromSmallBoundedOrd
632 prop "enumerateFromThenSmallBoundedOrd" enumerateFromThenSmallBoundedOrd
633 prop "enumerateFromToSmallOrd" enumerateFromToSmallOrd
634 prop "enumerateFromThenToSmallOrd" enumerateFromThenToSmallOrd
636 prop "enumerateFromSmallBoundedUnit" enumerateFromSmallBoundedUnit
637 prop "enumerateFromThenSmallBoundedUnit" enumerateFromThenSmallBoundedUnit
638 prop "enumerateFromToSmallUnit" enumerateFromToSmallUnit
639 prop "enumerateFromThenToSmallUnit" enumerateFromThenToSmallUnit
641 prop "enumerateFromSmallBoundedUnit" enumerateFromSmallBoundedBool
642 prop "enumerateFromThenSmallBoundedBool" enumerateFromThenSmallBoundedBool
643 prop "enumerateFromToSmallBool" enumerateFromToSmallBool
644 prop "enumerateFromThenToSmallBool" enumerateFromThenToSmallBool
646#if MIN_VERSION_base(4,12,0)
647 prop "enumerateFromFractional" enumerateFromFractional
648 prop "enumerateFromThenFractional" enumerateFromThenFractional
649 prop "enumerateFromToFractional" enumerateFromToFractional
650 prop "enumerateFromThenToFractional" enumerateFromThenToFractional
651#endif
653testTransformation :: Spec
654testTransformation =
655 describe "Transformation"
656 $ do
657 -- prop "map" map
658 prop "mapM" mapM
659 prop "mapMWithInput" mapMWithInput
660 prop "takeWhileM" takeWhileM
661 -- prop "takeWhile" takeWhile
662 prop "take" take
663 -- prop "filter" filter
664 prop "filterM" filterM
665 prop "drop" drop
666 -- prop "dropWhile" dropWhile
667 prop "dropWhileM" dropWhileM
669testCombination :: Spec
670testCombination =
671 describe "Transformation"
672 $ do
673 prop "zipWithM" zipWithM
674 -- prop "zipWith" zipWith
675 -- prop "teeZipWith" teeZipWith
676 prop "concat" concat
677 prop "concatMapM" concatMapM
678 prop "outerProduct" outerProduct
679 -- prop "ap" ap
680 -- prop "apDiscardFst" apDiscardFst
681 -- prop "apDiscardSnd" apDiscardSnd
683-------------------------------------------------------------------------------
684-- Main
685-------------------------------------------------------------------------------
687moduleName :: String
688moduleName = "Data.Unfold"
690main :: IO ()
691main =
692 hspec
693 $ describe moduleName
694 $ do
695 testInputOps
696 testGeneration
697 testTransformation
698 testCombination