I wonder… are we talking about parallel or asynchronous here?
If I have parallel computations running, they are going to be running at the same time on my system. So >1 CPU will be active. This is generally what I understand by the term parallel, since it is frequently used in conjunction with talking about parallel processing.
If I have asynchronous processes, they could be running in sequence, or in parallel, so 1 CPU core or >1 CPU core. Synchronous processes could also be running in parallel with thread operators such as spawn
and join
.
I suppose we had better think about the term concurrent also. Its sort-of the same thing as parallel, except maybe not. The user could be moving their mouse concurrently to waiting for some HTTP request to complete. The mouse and the HTTP request are not processing jobs that happen on my machine, their are concurrent tasks happening in the real world, outside of my machine. So its a bit different than what I normally associate with the word parallel.
So I think we are talking about concurrent asynchronous event handling here.
Javascript in the browser is single threaded, so there is no parallel execution. Its programming model is asynchronous though. There are web workers that can run parallel CPU jobs in the browser, it is also worth noting. Web workers programming model is awkward and certainly not ideal for concurrent functional programming where you might want to be able to pass continuations between threads - it does not allow this.
To give an example, suppose I want to GET 2 HTTP endpoints. If I create 2 tasks, one for each, and run then with Task.map2. The docs say:
“Note: Say we were doing HTTP requests instead. map2
does each task in order, so it would try the first request and only continue after it succeeds. If it fails, the whole thing fails!”
map2 : (a -> b -> result) -> Task x a -> Task x b -> Task x result
map2 func taskA taskB =
taskA
|> andThen (\a -> taskB
|> andThen (\b -> succeed (func a b)))
It certainly seems possible that map2
could execute the 2 asynchronous tasks concurrently, then join
and combine their results once both have completed. It also seems correct that andThen
always processes sequentially, not starting the second task until the output of the first one completes. Presumably map2
could be re-written as a special case not making use of andThen
.
Would be interesting to see in code how this could be done? A hypothetical kernel function for example, can anyone write it to show how?
Does this run 2 Tasks concurrently? Process - core 1.0.5 . The description in the docs certainly seems to be suggesting that it does:
" Run a task in its own light-weight process. In the following example, task1
and task2
will be interleaved. If task1
makes a long HTTP request or is just taking a long time, we can hop over to task2
and do some work there.
spawn task1
|> Task.andThen (\_ -> spawn task2)
Note: This creates a relatively restricted kind of Process
because it cannot receive any messages. More flexibility for user-defined processes will come in a later release!"