如何在异步中强制执行完整评估?

How to enforce full evaluation inside async?

我正在玩异步库,并试图在实践中找出它的 API。我注意到一个我没想到的奇怪行为。它看起来像一个错误,但也许它是一个功能,我只需要知道一个解决方法。

import Control.Concurrent
import Control.Concurrent.Async

> withAsync (putStrLn "HELLO") (\_ -> putStrLn "WORLD")
WORLHEDL

上面的代码片段工作正常 - 两条线都执行了,但部分评估了更复杂的异步主体。

> withAsync (putStrLn "XXXXXXXXXX" >> putStrLn "HELLO") (\_ -> putStrLn "WORLD")
WOXRXLXDX

看,第二个putStrLn没有执行。 我想我需要将整个异步主体包装在某种 bnf 中,但它看起来很奇怪。为什么 withAsync 不为我做那件事?


forkIO 工作得很好,但我不想费心去解除。 async 有一对库 unlift-async 自动传播 monad。

forkIO (Prelude.putStrLn "XXXXXXXXXX" >> Prelude.putStrLn "HELLO")
ThreadXIXdX X1X1X3X
XXX
HELLO

我找到了带分叉功能的 lifted-base。它用作 forkIO 并将父 monad 传递给子线程。

withAsync 在主线程(第二个参数)终止时中断分叉线程(第一个参数)。这在 documentation of withAsync:

中是明确的

When the function returns or throws an exception, uninterruptibleCancel is called on the Async.

(...) This is a useful variant of async that ensures an Async is never left running unintentionally.

如果你只想分叉一个线程,使用async

async (putStrLn "XXXXXXXX" >> putStrLn "WORLD") >> putStrLn "HELLO"