Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@zhangchiqing
Last active July 17, 2017 17:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save zhangchiqing/34f299aeb96cee2dba329a9d2ff6463d to your computer and use it in GitHub Desktop.
Save zhangchiqing/34f299aeb96cee2dba329a9d2ff6463d to your computer and use it in GitHub Desktop.
Purescript Async
module Main where
import Prelude
import Control.Monad.Aff
import Control.Parallel (sequential, parallel)
import Control.Monad.Eff.Class (liftEff)
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (CONSOLE, log)
type A = String
type B = String
type C = String
type D = String
type E = String
type AffConsole e a = Aff (console :: CONSOLE | e) a
getA :: forall e. String -> AffConsole e A
getA a = do
liftEff $ log "getA"
a <- later' 2000 $ pure "A"
liftEff $ log "finish getA"
pure a
getB :: forall e. String -> AffConsole e B
getB b = do
liftEff $ log "getB"
b <- later' 1000 $ pure "B"
liftEff $ log "finish getB"
pure b
getCWithAB :: forall e. A -> B -> A -> AffConsole e C
getCWithAB a b c = do
liftEff $ log "getCWithAB"
c <- later' 1000 $ pure $ a <> b <> "C"
liftEff $ log "finish getCWithAB"
pure c
getDWithB :: forall e. B -> AffConsole e D
getDWithB b = do
liftEff $ log "getDWithB"
d <- later' 3000 $ pure $ b <> "D"
liftEff $ log "finish getDWithB"
pure d
getEWithCD :: forall e. C -> D -> AffConsole e E
getEWithCD c d = do
liftEff $ log "getEWithCD"
e <- later' 2000 $ pure $ c <> d <> "E"
liftEff $ log "finish getEWithCD"
pure e
-- 0 1 2 3 4 5 6 7
--getA |--------->
--getB |---->
--getCWithAB |---->
--getDWithB |-------------->
--getEWithCD |-------->
-- Done
-- The above chart is the async requests flow that I want.
-- I want to send `getA` and `getB` together.
-- When both of them are finished, the results of them will be used to send `getCWithAB`.
-- When `getB` is finished, its result will be used to send `getDWithB`
-- When both `getCWithAB` and `getDWithB` are finished, the results of them will be used to send `getEWithCD`
-- When `getEWithCD` is finished, return the result of E.
-- I expect the log to be
-- ```
-- * Build successful.
-- getA
-- getB
-- finish getB
-- getDWithB
-- finish getA
-- getCWithAB
-- finish getCWithAB
-- finish getDWithB
-- getEWithCD
-- finish getEWithCD
-- ABCBDE
-- ```
-- But actually got this
-- ```
-- * Build successful.
-- getA
-- getB
-- getA
-- finish getB
-- finish getA
-- finish getA
-- getCWithAB
-- getB
-- finish getCWithAB
-- finish getB
-- getDWithB
-- finish getDWithB
-- getEWithCD
-- finish getEWithCD
-- ABCBDE
-- ```
main = launchAff do
let aA = getA "a"
let bA = getB "b"
let cAA = sequential $ getCWithAB <$> parallel aA <*> parallel bA <*> parallel aA
cA <- cAA
let dA = bA >>= getDWithB
let eAA = sequential $ getEWithCD <$> parallel cA <*> parallel dA
eA <- eAA
e <- eA
liftEff $ log e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment