I’m curious about how does the
Aff compare to them? How asynchronous is
Promises or callbacks. The big difference between
Promise is that a
Promise is started as soon as it’s defined, while an
Aff isn’t started until you call
runAff or something similar.
On the side, parallel computing is a completely separate thing, where you make use of multiple cores to run multiple threads at the same time. That might be useful for some heavy data processing or something like that where CPU is actually the bottleneck. Somebody else is going to have to chime in on if/how
Aff can be used for parallel computing. I’m pretty sure it’s possible in node, and not possible in the browser. I doubt that it’s the default for node, and would expect you have to do something to enable running code in parallel.
Because I was curious too, at one point in time, I tried to visualize the control flow of
Aff is in the same space as Promises, but with additional support for cancellation (async exceptions) and resource management (
bracket). It’s cooperative multi-tasking which yields on async constructors (
For node specifically, you can try https://github.com/natefaubion/purescript-node-workerbees which is a bit of hack, but really convenient. I used workerbees in
purs-tidy to distribute formatting multiple files over several actual threads.
So how do Web Workers (Using Web Workers - Web APIs | MDN) fit into that? The MDN manual claims that
Worker interface spawns real OS-level threads
and although their capabilities are limited, I’m pretty sure that you can, in fact, do things concurrently, even in the browser (see Worker APIs; for instance, you cannot access the DOM and you have to run the script from URL, so no “arbitrary forking”). I understand there is no library on Pursuit wrapping this API?
Edit: oh, I see, there is purescript-workly - Pursuit, I should check that.
Ah, yep, I stand corrected. I’ve never used Web Workers but that does indeed seem to let you run multiple parallel threads when running in a browser.
To launch a worker thread you actually supply it with a URI of JS script file (or you may pass to it
data: encoded source). You can interact with workers using standard messages.
In a real web app scenario, one of the ways to use it can be powered by a bundler: it will bundle the worker-related code, and while runtime it will initialize the worker and provide standard async api to interact with it for example using
Promises (which can be then converted to Aff and used within PS main thread). For webpack for example there is a loader. So in this case you’ll have to have some intermediate thin FFI layer between the main thread app and the worker app, but it all should be straightforward.
What does it mean to yield on async constructor? For instance, how can I reason about programs like:
someFunc :: Aff Unit
someFunc = do
ref <- liftEffect $ Ref.new 0
fiber <- forkAff do
liftEffect $ Ref.write 1 ref
liftEffect $ Ref.write 2 ref
-- joinFiber fiber
liftEffect $ Ref.read ref >>= logShow
What is the output of the program above and how does it depend on
It’s “implementation defined”. Since it’s forked, you should reason about it as if they are truly concurrent, even if there are implementation details that may define a specific ordering on a single threaded runtime. If you need ordering guarantees you should be using something like
AVar, otherwise you will be writing very difficult to debug code that is susceptible to race conditions.
In reality, the current Aff interpreter will greedily evaluate all
Effect code in a fiber (via
liftEffect). That is, an
Aff that is only comprised of synchronous Effect code, will run synchronously (
liftEffect a *> liftEffect b = liftEffect (a *> b). When it hits an async barrier (anything constructed via
makeAff), it will defer to the JS runtime, just like any other callback oriented code in JS.
Thanks! So any synchronous
Effectful function executed in a context of
Aff is “guaranteed” to be executed in one shot to completion, not interleaved with another function?
One synchronous thing at a time is how the js engine works.