You need more than that for the example with setTimeout().
It requires to be able to freeze the stack and then go back later.
You need stackful coroutine (like goroutine) for that.
You need stackful coroutine (like goroutine) for that.
-- ghci> example
-- Hello
-- World
-- Timed out
example = runEff $ \io -> awaitYield (receiver io) sender
receiver ::
(e1 <: es, e2 <: es) =>
IOE e1 ->
Await String e2 ->
Eff es ()
receiver io a = do
r1 <- await a
effIO io (putStrLn r1)
r2 <- await a
effIO io (putStrLn r2)
mr3 <- timeout io 0 (await a)
effIO io $ case mr3 of
Nothing -> putStrLn "Timed out"
Just r3 -> putStrLn r3
sender ::
e1 <: es =>
Yield String e1 ->
Eff es ()
sender y = do
yield y "Hello"
yield y "World"
yield y "More"
timeout ::
e1 <: es =>
IOE e1 ->
Int ->
Eff es r ->
Eff es (Maybe r)
timeout io t m = withEffToIO
(\effToIO -> System.Timeout.timeout t (effToIO (\_ -> useImpl m)))
ioAnd so then the outer code is a loop around coroutine.resume, and the inner code uses coroutine.yield to perform an effect.