2

Is there any primitive in the langage to compose async1 then async2, akin to what parallel does for parallel execution planning ?

to further clarify, I have 2 async computations

  let toto1 = Async.Sleep(1000)
  let toto2 = Async.Sleep(1000)

I would like to create a new async computation made of the sequential composition of toto1 and toto2

  let toto = Async.Sequential [|toto1; toto2|]

upon start, toto would run toto1 then toto2, and would end after 2000 time units

9
  • What is there to "try" here ? yeah I "tried" answering my question reading the API on msdn.. Commented Mar 8, 2012 at 16:26
  • Is Async.StartChild what you want? Commented Mar 8, 2012 at 16:26
  • 1
    @nicolas You didn't even indicate that you'd read anything. By telling us what you've looked at or showing code that you've tried to solve this you can prevent us from duplicating or responding as if you've just decided to ask rather than do anything. Commented Mar 8, 2012 at 16:32
  • 1
    @nicolas I would call looking at the documentation "trying" to find an answer, wouldn't you? That said Async isn't a primitive, it's part of the .Net Framework. You're going to need to move up into the framework and write some code. Couldn't you use a continuation that spawns async2? Commented Mar 8, 2012 at 16:43
  • 1
    What's toto in your example? Is it the result of toto1 or toto2? What do you want to do with the other result? Ignore it? Do you want to combine them? If so, how? Commented Mar 8, 2012 at 17:03

2 Answers 2

4

The async.Bind operation is the basic primitive that asynchronous workflows provide for sequential composition - in the async block syntax, that corresponds to let!. You can use that to express sequential composition of two computations (as demonstrated by Daniel).

However, if you have an operation <|> that Daniel defined, than that's not expressive enough to implement async.Bind, because when you compose things sequentially using async.Bind, the second computation may depend on the result of the first one. The <e2> may use v1:

async.Bind(<e1>, fun v1 -> <e2>)

If you were writing <e1> <|> <e2> then the two operations have to be independent. This is a reason why the libraries are based on Bind - because it is more expressive form of sequential composition than the one you would get if you were following the structure of Async.Parallel.

If you want something that behaves like Async.Parallel and takes an array, then the easiest option is to implement that imperatively using let! in a loop (but you could use recursion and lists too):

let Sequential (ops:Async<'T>[]) = async {
  let res = Array.zeroCreate ops.Length
  for i in 0 .. ops.Length - 1 do
    let! value = ops.[i]
    res.[i] <- value 
  return res }
Sign up to request clarification or add additional context in comments.

3 Comments

Out of curiosity, would this function any differently than async1 <|> async2 <|> ... asyncN using the combinator in my answer?
Of interest is that it is not Async.Bind, but async.Bind I had missed entirely this, and was looking at the control.Async module in MSDN. (Might be good to add this to Async for regularity)
@nicolas Ah, yes, sorry for the confusion :-) The Bind operation is poart of the async computation builder (the async value) which is used in the translation of async { .. } block. Additional combinators are exposed in a module (as static members).
2

I'm not sure what you mean by "primitive." Async.Parallel is a function. Here are a few ways to run two asyncs:

In parallel:

Async.Parallel([|async1; async2|])

or

async {
  let! child = Async.StartChild async2
  let! result1 = child
  let! result2 = async1
  return [|result1; result2|]
}

Sequentially:

async {
  let! result1 = async1
  let! result2 = async2
  return [|result1; result2|]
}

You could return tuples in the last two. I kept the return types the same as the first one.

I would say let! and do! in an async { } block is as close as you'll get to using a primitive for this.

EDIT

If all this nasty syntax is getting to you, you could define a combinator:

let (<|>) async1 async2 = 
  async {
    let! r1 = async1
    let! r2 = async2
    return r1, r2
  }

and then do:

async1 <|> async2 |> Async.RunSynchronously

5 Comments

by primitive, I mean a function that is not made of a combination simpler functions, aka something in the langage.
let! and do! are syntactic sugar for continuations, which is what you want. Are they not "primitive" enough?
thank you Daniel, I figured out early I could write a combinator, but just like there is one for // computations, I was just wondering if another was hidden somewhere.
May be they did not add it as it is not as straightforward if you want to handle the general case with composition, where types of the call chain have to be compatible. for unit, of course it is trivial. (actually for unlimited sequence it is probably not representable in the type system)
Yeah, I don't think a general-purpose bind is possible. You can't know, for every M<'T>, which values of 'T are failure/success.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.