@@ -1,6 +1,7 @@
1module Main (main) where
1module Main (main) where
3import Control.Concurrent (threadDelay)
3import Control.Concurrent (threadDelay)
4+import Data.Foldable (forM_)
4import Data.List (sort)
5import Data.List (sort)
5import Prelude hiding (take, drop)
6import Prelude hiding (take, drop)
6import Test.Hspec
7import Test.Hspec
@@ -25,32 +26,74 @@ main = hspec $ do
25 it "MonadPlus - mzero" $
26 it "MonadPlus - mzero" $
26 (toList mzero) `shouldReturn` ([] :: [Int])
27 (toList mzero) `shouldReturn` ([] :: [Int])
29+ ---------------------------------------------------------------------------
31+ ---------------------------------------------------------------------------
28− describe "Bind" bind
33+ describe "Bind then" thenBind
34+ describe "Pure bind serial" $ pureBind (>>=)
35+ describe "Pure bind serial interleaved" $ pureBind (>->)
36+ describe "Pure bind parallel DFS" $ pureBind (>>|)
37+ describe "Pure bind parallel BFS" $ pureBind (>|>)
39+ ---------------------------------------------------------------------------
41+ ---------------------------------------------------------------------------
30 describe "Serial Composition (<>)" $ compose (<>) id
43 describe "Serial Composition (<>)" $ compose (<>) id
31− describe "Serial interleaved (<=>)" $ interleaved (<=>) id
32 describe "Left biased parallel Composition (<|)" $ compose (<|) sort
44 describe "Left biased parallel Composition (<|)" $ compose (<|) sort
33 describe "Fair parallel Composition (<|>)" $ compose (<|>) sort
45 describe "Fair parallel Composition (<|>)" $ compose (<|>) sort
47+ ---------------------------------------------------------------------------
48+ -- Composition ordering checks
49+ ---------------------------------------------------------------------------
51+ describe "Serial interleaved (<=>)" $ interleaved (<=>) id
34 describe "Left biased parallel time order check" $ parallelCheck (<|)
52 describe "Left biased parallel time order check" $ parallelCheck (<|)
35 describe "Fair parallel time order check" $ parallelCheck (<|>)
53 describe "Fair parallel time order check" $ parallelCheck (<|>)
36 describe "Parallel interleaved (<|>)" $ interleaved (<|>) reverse
54 describe "Parallel interleaved (<|>)" $ interleaved (<|>) reverse
56+ ---------------------------------------------------------------------------
57+ -- Composition recursion loops
58+ ---------------------------------------------------------------------------
38 describe "Serial loops (<>)" $ loops (<>) id reverse
60 describe "Serial loops (<>)" $ loops (<>) id reverse
39 describe "Left biased parallel loops (<|)" $ loops (<|) sort sort
61 describe "Left biased parallel loops (<|)" $ loops (<|) sort sort
40 describe "Fair parallel loops (<|>)" $ loops (<|>) sort sort
62 describe "Fair parallel loops (<|>)" $ loops (<|>) sort sort
64+ ---------------------------------------------------------------------------
65+ -- Bind and Composition combinations
66+ ---------------------------------------------------------------------------
68+ forM_ [(>>=), (>->), (>>|), (>|>)] $ \f ->
69+ forM_ [(<>), (<=>), (<|), (<|>)] $ \g ->
70+ describe "Bind and compose" $ bindAndComposeSimple f g
72+ let fldr f = foldr f empty
73+ fldl f = foldl f empty
74+ in forM_ [(>>=), (>->), (>>|), (>|>)] $ \f ->
75+ forM_ [(<>), (<=>), (<|), (<|>)] $ \g ->
76+ forM_ [fldr, fldl] $ \k ->
77+ describe "Bind and compose" $
78+ bindAndComposeHierarchy f (k g)
80+ -- TBD combine all binds and all compose in one example
81+ describe "Miscellaneous combined examples" mixedOps
42 describe "Transformation" $ transformOps (<>)
83 describe "Transformation" $ transformOps (<>)
43− describe "Miscellaneouse combined examples" mixedOps
45−bind :: Spec
85+thenBind :: Spec
46−bind = do
86+thenBind = do
47 it "Simple runAsyncly and 'then' with IO" $
87 it "Simple runAsyncly and 'then' with IO" $
48 runAsyncly (liftIO (putStrLn "hello") >> liftIO (putStrLn "world"))
88 runAsyncly (liftIO (putStrLn "hello") >> liftIO (putStrLn "world"))
49 `shouldReturn` ()
89 `shouldReturn` ()
50 it "Then and toList" $
90 it "Then and toList" $
51 toList (return (1 :: Int) >> return 2) `shouldReturn` ([2] :: [Int])
91 toList (return (1 :: Int) >> return 2) `shouldReturn` ([2] :: [Int])
93+pureBind :: (AsyncT IO Int -> (Int -> AsyncT IO Int) -> AsyncT IO Int) -> Spec
52 it "Bind and toList" $
95 it "Bind and toList" $
53− toList (do x <- return 1; y <- return 2; return (x + y))
96+ toList (return 1 `f` \x -> return 2 `f` \y -> return (x + y))
54 `shouldReturn` ([3] :: [Int])
97 `shouldReturn` ([3] :: [Int])
56interleaved
99interleaved
@@ -102,13 +145,6 @@ compose f srt = do
102 it "Compose many" $
145 it "Compose many" $
103 ((toList $ forEachWith f [1..100] return) >>= return . srt)
146 ((toList $ forEachWith f [1..100] return) >>= return . srt)
104 `shouldReturn` [1..100]
147 `shouldReturn` [1..100]
105− it "Compose many (right fold) with bind" $
106− (toList (forEachWith f [1..10 :: Int] $ \x -> return x >>= return . id)
107− >>= return . srt) `shouldReturn` [1..10]
108− it "Compose many (left fold) with bind" $
109− let forL xs k = foldl f empty $ map k xs
110− in (toList (forL [1..10 :: Int] $ \x -> return x >>= return . id)
111− >>= return . srt) `shouldReturn` [1..10]
112 it "Compose hierarchical (multiple levels)" $
148 it "Compose hierarchical (multiple levels)" $
113 ((toList $ (((return 0 `f` return 1) `f` (return 2 `f` return 3))
149 ((toList $ (((return 0 `f` return 1) `f` (return 2 `f` return 3))
114 `f` ((return 4 `f` return 5) `f` (return 6 `f` return 7)))
150 `f` ((return 4 `f` return 5) `f` (return 6 `f` return 7)))
@@ -137,6 +173,85 @@ loops f tsrt hsrt = do
137 liftIO $ putStrLn "LoopTail..."
173 liftIO $ putStrLn "LoopTail..."
138 return x `f` (if x < 3 then loopTail (x + 1) else empty)
174 return x `f` (if x < 3 then loopTail (x + 1) else empty)
177+ :: (AsyncT IO Int -> (Int -> AsyncT IO Int) -> AsyncT IO Int)
178+ -> (AsyncT IO Int -> AsyncT IO Int -> AsyncT IO Int)
180+bindAndComposeSimple f g = do
181+ it "Compose many (right fold) with bind" $
182+ (toList (forEachWith g [1..10 :: Int] $ \x -> return x `f` (return . id))
183+ >>= return . sort) `shouldReturn` [1..10]
185+ it "Compose many (left fold) with bind" $
186+ let forL xs k = foldl g empty $ map k xs
187+ in (toList (forL [1..10 :: Int] $ \x -> return x `f` (return . id))
188+ >>= return . sort) `shouldReturn` [1..10]
190+bindAndComposeHierarchy
191+ :: (AsyncT IO Int -> (Int -> AsyncT IO Int) -> AsyncT IO Int)
192+ -> ([AsyncT IO Int] -> AsyncT IO Int)
194+bindAndComposeHierarchy f g = do
195+ it "Bind and compose nested" $
196+ (toList bindComposeNested >>= return . sort)
197+ `shouldReturn` (sort (
203+ ++ replicate 7 15) :: [Int])
207+ bindComposeNested :: AsyncT IO Int
209+ let c1 = tripleCompose (return 1) (return 2) (return 3)
210+ c2 = tripleCompose (return 4) (return 5) (return 6)
211+ c3 = tripleCompose (return 7) (return 8) (return 9)
212+ b = tripleBind c1 c2 c3
213+-- it seems to be causing a huge space leak in hspec so disabling this for now
214+-- c = tripleCompose b b b
215+-- m = tripleBind c c c
219+ tripleCompose a b c = g [a, b, c]
220+ tripleBind mx my mz =
223+ `f` \z -> return (x + y + z)
227+ it "Compose many ops" $
228+ (toList composeMixed >>= return . sort)
229+ `shouldReturn` ([8,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,11,11
230+ ,11,11,11,11,11,11,11,11,12,12,12,12,12,13
234+ composeMixed :: AsyncT IO Int
241+ x1 <- return 1 <|> return 2
244+ y1 <- return 1 <| return 2
246+ x11 <- return 1 <> return 2
247+ y11 <- return 1 <| return 2
248+ z11 <- return 1 <=> return 2
251+ return (x11 + y11 + z11)
252+ return (x1 + y1 + z1)
140transformOps :: (AsyncT IO Int -> AsyncT IO Int -> AsyncT IO Int) -> Spec
255transformOps :: (AsyncT IO Int -> AsyncT IO Int -> AsyncT IO Int) -> Spec
141transformOps f = do
256transformOps f = do
142 it "take all" $
257 it "take all" $
@@ -158,32 +273,3 @@ transformOps f = do
158 it "drop 5" $
273 it "drop 5" $
159 (toList $ drop 5 $ foldMapWith f return [1..10])
274 (toList $ drop 5 $ foldMapWith f return [1..10])
160 `shouldReturn` [6..10]
275 `shouldReturn` [6..10]
164− it "Compose many ops" $
165− (toList composeMixed >>= return . sort)
166− `shouldReturn` ([8,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,11,11
167− ,11,11,11,11,11,11,11,11,12,12,12,12,12,13
170−composeMixed :: AsyncT IO Int
177− x1 <- return 1 <|> return 2
180− y1 <- return 1 <| return 2
182− x11 <- return 1 <> return 2
183− y11 <- return 1 <| return 2
184− z11 <- return 1 <=> return 2
187− return (x11 + y11 + z11)
188− return (x1 + y1 + z1)