1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE RankNTypes #-}
4module Main (main) where
6import Control.Concurrent (threadDelay)
7import Control.Monad (replicateM)
8import Data.Foldable (forM_)
13import qualified Streamly.Prelude as A
15toListSerial :: StreamT IO a -> IO [a]
16toListSerial = A.toList . serially
18toListInterleaved :: InterleavedT IO a -> IO [a]
19toListInterleaved = A.toList . interleaving
21toListAsync :: AsyncT IO a -> IO [a]
22toListAsync = A.toList . asyncly
24toListParallel :: Ord a => ParallelT IO a -> IO [a]
25toListParallel = fmap sort . A.toList . parallely
29 describe "Runners" $ do
30 it "simple serially" $
31 (runStreaming . serially) (return (0 :: Int)) `shouldReturn` ()
32 it "simple serially with IO" $
33 (runStreaming . serially) (liftIO $ putStrLn "hello") `shouldReturn` ()
34 it "Captures a return value using toList" $
35 toListSerial (return 0) `shouldReturn` ([0] :: [Int])
38 it "Monoid - mempty" $
39 (toListSerial mempty) `shouldReturn` ([] :: [Int])
40 it "Alternative - empty" $
41 (toListSerial empty) `shouldReturn` ([] :: [Int])
42 it "MonadPlus - mzero" $
43 (toListSerial mzero) `shouldReturn` ([] :: [Int])
45 ---------------------------------------------------------------------------
47 ---------------------------------------------------------------------------
49 describe "Functor (fmap)" $ do
51 (toListSerial $ fmap (+1) (return 1)) `shouldReturn` ([2] :: [Int])
52 it "fmap on composed (<>)" $
53 (toListSerial $ fmap (+1) (return 1 <> return 2))
54 `shouldReturn` ([2,3] :: [Int])
55 it "fmap on composed (<|>)" $
56 (toListSerial $ fmap (+1) (return 1 <|> return 2))
57 `shouldReturn` ([2,3] :: [Int])
59 ---------------------------------------------------------------------------
61 ---------------------------------------------------------------------------
63 describe "Applicative" $ do
65 (toListSerial $ (,) <$> (return 1) <*> (return 2))
66 `shouldReturn` ([(1,2)] :: [(Int, Int)])
68 it "Apply - serial composed first argument" $
69 (toListSerial $ (,) <$> (return 1 <> return 2) <*> (return 3))
70 `shouldReturn` ([(1,3),(2,3)] :: [(Int, Int)])
72 it "Apply - serial composed second argument" $
73 (toListSerial $ (,) <$> (return 1) <*> (return 2 <> return 3))
74 `shouldReturn` ([(1,2),(1,3)] :: [(Int, Int)])
76 it "Apply - parallel composed first argument" $
77 (toListSerial $ (,) <$> (return 1 <|> return 2) <*> (return 3))
78 `shouldReturn` ([(1,3),(2,3)] :: [(Int, Int)])
80 it "Apply - parallel composed second argument" $
81 (toListSerial $ (,) <$> (return 1) <*> (return 2 <|> return 3))
82 `shouldReturn` ([(1,2),(1,3)] :: [(Int, Int)])
84 ---------------------------------------------------------------------------
86 ---------------------------------------------------------------------------
88 describe "Bind then" thenBind
89 describe "Pure bind serial" $ pureBind toListSerial
90 describe "Pure bind serial interleaved" $ pureBind toListInterleaved
91 describe "Pure bind parallel DFS" $ pureBind toListAsync
92 describe "Pure bind parallel BFS" $ pureBind toListParallel
94 describe "Bind (>>=) with empty" $ bindEmpty toListSerial
95 describe "Bind (>->) with empty" $ bindEmpty toListInterleaved
96 describe "Bind (>|>) with empty" $ bindEmpty toListAsync
97 describe "Bind (>>|) with empty" $ bindEmpty toListParallel
99 ---------------------------------------------------------------------------
100 -- Monoidal Compositions
101 ---------------------------------------------------------------------------
103 describe "Serial Composition (<>)" $ compose (<>) id
104 describe "Serial Composition (mappend)" $ compose mappend id
105 describe "Interleaved Composition (<>)" $ compose (<=>) sort
106 describe "Left biased parallel Composition (<|)" $ compose (<|) sort
107 describe "Fair parallel Composition (<|>)" $ compose (<|>) sort
108 describe "Fair parallel Composition (mplus)" $ compose mplus sort
110 ---------------------------------------------------------------------------
111 -- Monoidal Composition ordering checks
112 ---------------------------------------------------------------------------
114 describe "Serial interleaved ordering check (<=>)" $ interleaveCheck (<=>)
115 describe "Parallel interleaved ordering check (<|>)" $ interleaveCheck (<|>)
116 describe "Left biased parallel time order check" $ parallelCheck (<|)
117 describe "Fair parallel time order check" $ parallelCheck (<|>)
119 ---------------------------------------------------------------------------
120 -- TBD Monoidal composition combinations
121 ---------------------------------------------------------------------------
123 -- TBD need more such combinations to be tested.
124 describe "<> and <>" $ composeAndComposeSimple (<>) (<>) (cycle [[1 .. 9]])
126 describe "<> and <=>" $ composeAndComposeSimple
131 , [1, 3, 2, 4, 6, 5, 7, 9, 8]
132 , [1, 3, 2, 4, 6, 5, 7, 9, 8]
135 describe "<=> and <=>" $ composeAndComposeSimple
138 ([ [1, 4, 2, 7, 3, 5, 8, 6, 9]
139 , [1, 7, 4, 8, 2, 9, 5, 3, 6]
140 , [1, 4, 3, 7, 2, 6, 9, 5, 8]
141 , [1, 7, 4, 9, 3, 8, 6, 2, 5]
144 describe "<=> and <>" $ composeAndComposeSimple
147 ([ [1, 4, 2, 7, 3, 5, 8, 6, 9]
148 , [1, 7, 4, 8, 2, 9, 5, 3, 6]
149 , [1, 4, 2, 7, 3, 5, 8, 6, 9]
150 , [1, 7, 4, 8, 2, 9, 5, 3, 6]
153 describe "Nested parallel and serial compositions" $ do
155 -- This is not correct, the result can also be [4,4,8,0,8,0,2,2]
156 -- because of parallelism of [8,0] and [8,0].
157 it "Nest <|>, <>, <|> (1)" $
160 ((t 8 <|> t 4) <> (t 2 <|> t 0))
161 <|> ((t 8 <|> t 4) <> (t 2 <|> t 0)))
162 `shouldReturn` ([4,4,8,8,0,0,2,2])
164 it "Nest <|>, <>, <|> (2)" $
167 ((t 4 <|> t 8) <> (t 1 <|> t 2))
168 <|> ((t 4 <|> t 8) <> (t 1 <|> t 2)))
169 `shouldReturn` ([4,4,8,8,1,1,2,2])
170 -- FIXME: These two keep failing intermittently on Mac OS X
171 -- Need to examine and fix the tests.
173 it "Nest <|>, <=>, <|> (1)" $
176 ((t 8 <|> t 4) <=> (t 2 <|> t 0))
177 <|> ((t 9 <|> t 4) <=> (t 2 <|> t 0)))
178 `shouldReturn` ([4,4,0,0,8,2,9,2])
179 it "Nest <|>, <=>, <|> (2)" $
182 ((t 4 <|> t 8) <=> (t 1 <|> t 2))
183 <|> ((t 4 <|> t 9) <=> (t 1 <|> t 2)))
184 `shouldReturn` ([4,4,1,1,8,2,9,2])
186 it "Nest <|>, <|>, <|>" $
189 ((t 4 <|> t 8) <|> (t 0 <|> t 2))
190 <|> ((t 4 <|> t 8) <|> (t 0 <|> t 2)))
191 `shouldReturn` ([0,0,2,2,4,4,8,8])
193 ---------------------------------------------------------------------------
194 -- Monoidal composition recursion loops
195 ---------------------------------------------------------------------------
197 describe "Serial loops (<>)" $ loops (<>) id reverse
198 describe "Left biased parallel loops (<|)" $ loops (<|) sort sort
199 describe "Fair parallel loops (<|>)" $ loops (<|>) sort sort
201 ---------------------------------------------------------------------------
202 -- Bind and monoidal composition combinations
203 ---------------------------------------------------------------------------
205 forM_ [(<>), (<=>), (<|), (<|>)] $ \g ->
206 describe "Bind and compose" $ bindAndComposeSimple toListSerial g
208 forM_ [(<>), (<=>), (<|), (<|>)] $ \g ->
209 describe "Bind and compose" $ bindAndComposeSimple toListInterleaved g
211 forM_ [(<>), (<=>), (<|), (<|>)] $ \g ->
212 describe "Bind and compose" $ bindAndComposeSimple toListAsync g
214 forM_ [(<>), (<=>), (<|), (<|>)] $ \g ->
215 describe "Bind and compose" $ bindAndComposeSimple toListParallel g
217 let fldr f = foldr f empty
218 fldl f = foldl f empty
220 forM_ [(<>), (<=>), (<|), (<|>)] $ \g ->
221 forM_ [fldr, fldl] $ \k ->
222 describe "Bind and compose" $
223 bindAndComposeHierarchy toListSerial (k g)
224 forM_ [(<>), (<=>), (<|), (<|>)] $ \g ->
225 forM_ [fldr, fldl] $ \k ->
226 describe "Bind and compose" $
227 bindAndComposeHierarchy toListInterleaved (k g)
228 forM_ [(<>), (<=>), (<|), (<|>)] $ \g ->
229 forM_ [fldr, fldl] $ \k ->
230 describe "Bind and compose" $
231 bindAndComposeHierarchy toListAsync (k g)
232 forM_ [(<>), (<=>), (<|), (<|>)] $ \g ->
233 forM_ [fldr, fldl] $ \k ->
234 describe "Bind and compose" $
235 bindAndComposeHierarchy toListParallel (k g)
237 -- Nest two lists using different styles of product compositions
238 it "Nests two streams using monadic serial composition" nestTwoSerial
239 it "Nests two streams using monadic interleaved composition" nestTwoInterleaved
240 it "Nests two streams using monadic async composition" nestTwoAsync
241 it "Nests two streams using monadic parallel composition" nestTwoParallel
243 it "Nests two streams using applicative serial composition" nestTwoSerialApp
244 it "Nests two streams using applicative interleaved composition" nestTwoInterleavedApp
245 it "Nests two streams using applicative async composition" nestTwoAsyncApp
246 it "Nests two streams using applicative parallel composition" nestTwoParallelApp
248 it "Nests two streams using Num serial composition" nestTwoSerialNum
249 it "Nests two streams using Num interleaved composition" nestTwoInterleavedNum
250 it "Nests two streams using Num async composition" nestTwoAsyncNum
251 -- This test fails intermittently, need to investigate
252 -- it "Nests two streams using Num parallel composition" nestTwoParallelNum
254 ---------------------------------------------------------------------------
255 -- TBD Bind and Bind combinations
256 ---------------------------------------------------------------------------
258 -- TBD combine all binds and all compose in one example
259 describe "Miscellaneous combined examples" mixedOps
261 ---------------------------------------------------------------------------
263 ---------------------------------------------------------------------------
265 -- XXX for streams other than StreamT
266 describe "Stream Ops empty" $ streamOperations makeEmptyStream
267 describe "Stream ops singleton constr" $ streamOperations makeSingletonStream1
268 describe "Stream ops singleton folded" $ streamOperations makeSingletonStream2
269 describe "Stream Ops constr" $ streamOperations makeStream1
270 describe "Stream Ops folded" $ streamOperations $ makeStream2
271 ((<>) :: StreamT IO Int -> StreamT IO Int -> StreamT IO Int)
273 describe "Serial zipping" $
274 zipOps A.zipWith A.zipWithM zipping
275 describe "Async zipping" $
276 zipOps A.zipAsyncWith A.zipAsyncWithM zippingAsync
278makeEmptyStream :: (StreamT IO Int, [Int], Int)
279makeEmptyStream = (A.nil, [], 0)
281makeSingletonStream1 :: (StreamT IO Int, [Int], Int)
282makeSingletonStream1 = (1 `A.cons` A.nil, [1], 1)
284makeSingletonStream2 :: (StreamT IO Int, [Int], Int)
285makeSingletonStream2 = (return 1, [1], 1)
287-- Streams that indicate an end via the stop continuation
288makeStream1 :: (StreamT IO Int, [Int], Int)
292 in (stream, list, 10)
294-- Streams that indicate an end via the yield continuation
295makeStream2 :: (Streaming t, Monad (t IO))
296 => (t IO Int -> t IO Int -> t IO Int)
297 -> (t IO Int, [Int], Int)
300 stream = foldMapWith f return list
301 in (stream, list, 10)
303nestTwoSerial :: Expectation
305 let s1 = foldMapWith (<>) return [1..4]
306 s2 = foldMapWith (<>) return [5..8]
311 ) `shouldReturn` ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
313nestTwoSerialApp :: Expectation
315 let s1 = foldMapWith (<>) return [1..4]
316 s2 = foldMapWith (<>) return [5..8]
317 in toListSerial ((+) <$> s1 <*> s2)
318 `shouldReturn` ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
320nestTwoSerialNum :: Expectation
322 let s1 = foldMapWith (<>) return [1..4]
323 s2 = foldMapWith (<>) return [5..8]
324 in toListSerial (s1 + s2)
325 `shouldReturn` ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
327nestTwoInterleaved :: Expectation
329 let s1 = foldMapWith (<>) return [1..4]
330 s2 = foldMapWith (<>) return [5..8]
331 in toListInterleaved (do
335 ) `shouldReturn` ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
337nestTwoInterleavedApp :: Expectation
338nestTwoInterleavedApp =
339 let s1 = foldMapWith (<>) return [1..4]
340 s2 = foldMapWith (<>) return [5..8]
341 in toListInterleaved ((+) <$> s1 <*> s2)
342 `shouldReturn` ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
344nestTwoInterleavedNum :: Expectation
345nestTwoInterleavedNum =
346 let s1 = foldMapWith (<>) return [1..4]
347 s2 = foldMapWith (<>) return [5..8]
348 in toListInterleaved (s1 + s2)
349 `shouldReturn` ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
351nestTwoAsync :: Expectation
353 let s1 = foldMapWith (<>) return [1..4]
354 s2 = foldMapWith (<>) return [5..8]
359 ) `shouldReturn` ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
361nestTwoAsyncApp :: Expectation
363 let s1 = foldMapWith (<>) return [1..4]
364 s2 = foldMapWith (<>) return [5..8]
365 in toListAsync ((+) <$> s1 <*> s2)
366 `shouldReturn` ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
368nestTwoAsyncNum :: Expectation
370 let s1 = foldMapWith (<>) return [1..4]
371 s2 = foldMapWith (<>) return [5..8]
372 in toListAsync (s1 + s2)
373 `shouldReturn` ([6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12] :: [Int])
375nestTwoParallel :: Expectation
377 let s1 = foldMapWith (<>) return [1..4]
378 s2 = foldMapWith (<>) return [5..8]
379 in toListParallel (do
383 ) `shouldReturn` ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
385nestTwoParallelApp :: Expectation
387 let s1 = foldMapWith (<>) return [1..4]
388 s2 = foldMapWith (<>) return [5..8]
389 in toListParallel ((+) <$> s1 <*> s2)
390 `shouldReturn` ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
393nestTwoParallelNum :: Expectation
395 let s1 = foldMapWith (<>) return [1..4]
396 s2 = foldMapWith (<>) return [5..8]
397 in toListParallel (s1 + s2)
398 `shouldReturn` ([6,7,7,8,8,8,9,9,9,9,10,10,10,11,11,12] :: [Int])
401zipOps :: (Streaming t, Applicative (t IO))
402 => (forall a b c. (a -> b -> c)
403 -> StreamT IO a -> StreamT IO b -> StreamT IO c)
404 -> (forall a b c. (a -> b -> StreamT IO c)
405 -> StreamT IO a -> StreamT IO b -> StreamT IO c)
406 -> (forall a. t IO a -> t IO a)
410 let s1 = foldMapWith (<>) return [1..10]
411 s2 = foldMapWith (<>) return [1..]
412 in toListSerial (z (+) s1 s2)
413 `shouldReturn` ([2,4..20] :: [Int])
416 let s1 = foldMapWith (<>) return [1..10]
417 s2 = foldMapWith (<>) return [1..]
418 in toListSerial (zM (\a b -> return (a + b)) s1 s2)
419 `shouldReturn` ([2,4..20] :: [Int])
421 it "Applicative zip" $
422 let s1 = adapt $ serially $ foldMapWith (<>) return [1..10]
423 s2 = adapt $ serially $ foldMapWith (<>) return [1..]
424 in (A.toList . app) ((+) <$> s1 <*> s2)
425 `shouldReturn` ([2,4..20] :: [Int])
427timed :: Int -> StreamT IO Int
428timed x = liftIO (threadDelay (x * 100000)) >> return x
432 it "Simple runStreaming and 'then' with IO" $
433 (runStreaming . serially) (liftIO (putStrLn "hello") >> liftIO (putStrLn "world"))
435 it "Then and toList" $
436 toListSerial (return (1 :: Int) >> return 2) `shouldReturn` ([2] :: [Int])
438type ToListType s = (forall a. Ord a => s IO a -> IO [a])
439pureBind :: Monad (s IO) => ToListType s -> Spec
441 it "Bind and toList" $
442 l (return 1 `f` \x -> return 2 `f` \y -> return (x + y))
443 `shouldReturn` ([3] :: [Int])
446bindEmpty :: (Monad (s IO), Alternative (s IO)) => ToListType s -> Spec
447bindEmpty l = it "Binds with empty" $
448 (l (return (1 :: Int) `f` \_ -> empty `f` \_ -> return 2))
449 `shouldReturn` ([] :: [Int])
453 :: (StreamT IO Int -> StreamT IO Int -> StreamT IO Int)
456 it "Interleave four" $
457 toListSerial ((return 0 <> return 1) `f` (return 100 <> return 101))
458 `shouldReturn` ([0, 100, 1, 101])
460parallelCheck :: (StreamT IO Int -> StreamT IO Int -> StreamT IO Int) -> Spec
462 it "Parallel ordering left associated" $
463 toListSerial (((event 4 `f` event 3) `f` event 2) `f` event 1)
464 `shouldReturn` ([1..4])
466 it "Parallel ordering right associated" $
467 toListSerial (event 4 `f` (event 3 `f` (event 2 `f` event 1)))
468 `shouldReturn` ([1..4])
470 where event n = (liftIO $ threadDelay (n * 100000)) >> (return n)
473 :: (StreamT IO Int -> StreamT IO Int -> StreamT IO Int)
477 it "Compose mempty, mempty" $
478 (tl (mempty `f` mempty)) `shouldReturn` []
479 it "Compose empty, empty" $
480 (tl (empty `f` empty)) `shouldReturn` []
481 it "Compose empty at the beginning" $
482 (tl $ (empty `f` return 1)) `shouldReturn` [1]
483 it "Compose empty at the end" $
484 (tl $ (return 1 `f` empty)) `shouldReturn` [1]
486 (tl (return 0 `f` return 1) >>= return . srt)
487 `shouldReturn` [0, 1]
488 it "Compose three - empty in the middle" $
489 ((tl $ (return 0 `f` empty `f` return 1)) >>= return . srt)
490 `shouldReturn` [0, 1]
491 it "Compose left associated" $
492 ((tl $ (((return 0 `f` return 1) `f` return 2) `f` return 3))
493 >>= return . srt) `shouldReturn` [0, 1, 2, 3]
494 it "Compose right associated" $
495 ((tl $ (return 0 `f` (return 1 `f` (return 2 `f` return 3))))
496 >>= return . srt) `shouldReturn` [0, 1, 2, 3]
498 ((tl $ forEachWith f [1..100] return) >>= return . srt)
499 `shouldReturn` [1..100]
500 it "Compose hierarchical (multiple levels)" $
501 ((tl $ (((return 0 `f` return 1) `f` (return 2 `f` return 3))
502 `f` ((return 4 `f` return 5) `f` (return 6 `f` return 7)))
503 ) >>= return . srt) `shouldReturn` [0..7]
504 where tl = toListSerial
506composeAndComposeSimple
507 :: (StreamT IO Int -> StreamT IO Int -> StreamT IO Int)
508 -> (StreamT IO Int -> StreamT IO Int -> StreamT IO Int)
511composeAndComposeSimple f g answer = do
512 it "Compose right associated outer expr, right folded inner" $
513 let fold = foldMapWith g return
514 in (toListSerial (fold [1,2,3] `f` (fold [4,5,6] `f` fold [7,8,9])))
515 `shouldReturn` (answer !! 0)
517 it "Compose left associated outer expr, right folded inner" $
518 let fold = foldMapWith g return
519 in (toListSerial ((fold [1,2,3] `f` fold [4,5,6]) `f` fold [7,8,9]))
520 `shouldReturn` (answer !! 1)
522 it "Compose right associated outer expr, left folded inner" $
523 let fold xs = foldl g empty $ map return xs
524 in (toListSerial (fold [1,2,3] `f` (fold [4,5,6] `f` fold [7,8,9])))
525 `shouldReturn` (answer !! 2)
527 it "Compose left associated outer expr, left folded inner" $
528 let fold xs = foldl g empty $ map return xs
529 in (toListSerial ((fold [1,2,3] `f` fold [4,5,6]) `f` fold [7,8,9]))
530 `shouldReturn` (answer !! 3)
534 :: (StreamT IO Int -> StreamT IO Int -> StreamT IO Int)
538loops f tsrt hsrt = do
539 it "Tail recursive loop" $ (toListSerial (loopTail 0) >>= return . tsrt)
540 `shouldReturn` [0..3]
542 it "Head recursive loop" $ (toListSerial (loopHead 0) >>= return . hsrt)
543 `shouldReturn` [0..3]
547 -- this print line is important for the test (causes a bind)
548 liftIO $ putStrLn "LoopHead..."
549 (if x < 3 then loopHead (x + 1) else empty) `f` return x
552 -- this print line is important for the test (causes a bind)
553 liftIO $ putStrLn "LoopTail..."
554 return x `f` (if x < 3 then loopTail (x + 1) else empty)
557 :: (Streaming t, Alternative (t IO), Monad (t IO))
558 => (forall a. Ord a => t IO a -> IO [a])
559 -> (t IO Int -> t IO Int -> t IO Int)
561bindAndComposeSimple tl g = do
562 it "Compose many (right fold) with bind" $
563 (tl (forEachWith g [1..10 :: Int] $ \x -> return x `f` (return . id))
564 >>= return . sort) `shouldReturn` [1..10]
566 it "Compose many (left fold) with bind" $
567 let forL xs k = foldl g empty $ map k xs
568 in (tl (forL [1..10 :: Int] $ \x -> return x `f` (return . id))
569 >>= return . sort) `shouldReturn` [1..10]
572bindAndComposeHierarchy
573 :: Monad (s IO) => (forall a. Ord a => s IO a -> IO [a])
574 -> ([s IO Int] -> s IO Int)
576bindAndComposeHierarchy tl g = do
577 it "Bind and compose nested" $
578 (tl bindComposeNested >>= return . sort)
579 `shouldReturn` (sort (
585 ++ replicate 7 15) :: [Int])
589 -- bindComposeNested :: AsyncT IO Int
591 let c1 = tripleCompose (return 1) (return 2) (return 3)
592 c2 = tripleCompose (return 4) (return 5) (return 6)
593 c3 = tripleCompose (return 7) (return 8) (return 9)
594 b = tripleBind c1 c2 c3
595-- it seems to be causing a huge space leak in hspec so disabling this for now
596-- c = tripleCompose b b b
597-- m = tripleBind c c c
601 tripleCompose a b c = g [a, b, c]
602 tripleBind mx my mz =
605 `f` \z -> return (x + y + z)
610 it "Compose many ops" $
611 (toListSerial composeMixed >>= return . sort)
612 `shouldReturn` ([8,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,11,11
613 ,11,11,11,11,11,11,11,11,12,12,12,12,12,13
617 composeMixed :: StreamT IO Int
624 x1 <- return 1 <|> return 2
627 y1 <- return 1 <| return 2
629 x11 <- return 1 <> return 2
630 y11 <- return 1 <| return 2
631 z11 <- return 1 <=> return 2
634 return (x11 + y11 + z11)
635 return (x1 + y1 + z1)
638streamOperations :: Streaming t => (t IO Int, [Int], Int) -> Spec
639streamOperations (stream, list, len) = do
643 let x = return (1 :: Int)
644 str <- A.toList . serially $ A.replicateM len x
645 lst <- replicateM len x
650 it "filter all out" $ transform (A.filter (> len)) (filter (> len))
651 it "filter all in" $ transform (A.filter (<= len)) (filter (<= len))
652 it "filter even" $ transform (A.filter even) (filter even)
654 it "take all" $ transform (A.take len) (take len)
655 it "take none" $ transform (A.take 0) (take 0)
656 it "take some" $ transform (A.take $ len - 1) (take $ len - 1)
657 it "take one" $ transform (A.take 1) (take 1)
659 it "takeWhile true" $ transform (A.takeWhile (const True))
660 (takeWhile (const True))
661 it "takeWhile false" $ transform (A.takeWhile (const False))
662 (takeWhile (const False))
663 it "takeWhile < some" $ transform (A.takeWhile (< (len `div` 2)))
664 (takeWhile (< (len `div` 2)))
666 it "drop all" $ transform (A.drop len) (drop len)
667 it "drop none" $ transform (A.drop 0) (drop 0)
668 it "drop some" $ transform (A.drop $ len - 1) (drop $ len - 1)
669 it "drop one" $ transform (A.drop 1) (drop 1)
671 it "dropWhile true" $ transform (A.dropWhile (const True))
672 (dropWhile (const True))
673 it "dropWhile false" $ transform (A.dropWhile (const False))
674 (dropWhile (const False))
675 it "dropWhile < some" $ transform (A.dropWhile (< (len `div` 2)))
676 (dropWhile (< (len `div` 2)))
678 it "scan left" $ transform (A.scan (+) 0 id) (scanl (+) 0)
681 it "foldl" $ elimination (A.foldl (+) 0 id) (foldl (+) 0)
682 it "all" $ elimination (A.all even) (all even)
683 it "any" $ elimination (A.any even) (any even)
684 it "length" $ elimination A.length length
685 it "elem" $ elimination (A.elem (len - 1)) (elem (len - 1))
686 it "elem" $ elimination (A.elem (len + 1)) (elem (len + 1))
687 it "notElem" $ elimination (A.notElem (len - 1)) (notElem (len - 1))
688 it "notElem" $ elimination (A.notElem (len + 1)) (notElem (len + 1))
689 it "sum" $ elimination A.sum sum
690 it "product" $ elimination A.product product
694 it "head empty" $ A.head stream `shouldReturn` Nothing
695 it "last empty" $ A.last stream `shouldReturn` Nothing
696 it "maximum empty" $ A.maximum stream `shouldReturn` Nothing
697 it "minimum empty" $ A.minimum stream `shouldReturn` Nothing
699 it "head nonEmpty" $ A.head stream `shouldReturn` Just (head list)
700 it "last nonEmpty" $ A.last stream `shouldReturn` Just (last list)
701 it "maximum nonEmpty" $ A.maximum stream `shouldReturn` Just (maximum list)
702 it "minimum nonEmpty" $ A.minimum stream `shouldReturn` Just (minimum list)
706 -- XXX run on empty stream as well
707 transform streamOp listOp =
708 (A.toList $ streamOp stream) `shouldReturn` listOp list
710 elimination streamOp listOp = (streamOp stream) `shouldReturn` listOp list
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list