I am trying to figure out efficient syntax for the following F# expression. Let's say I have an F# async computation:
let asyncComp n = async { return n }
It has a signature 'a -> Async<'a>
. Now I define a sequence of those:
let seqOfAsyncComps =
seq {
yield asyncComp 1
yield asyncComp 2
yield asyncComp 3
}
Now I have an item of seq<Async<int>>
. What if I want to asynchronously map the elements from seq<Async<int>>
to seq<Async<int>>
. This won't work:
let seqOfAsyncSquares =
seqOfAsyncComps |> Seq.map (fun x -> x * x) // ERROR!!!
Of course, x
is Async<int>
, I have to extract an int
first, so I can do the following instead:
let seqOfAsyncSquares =
seqOfAsyncComps |> Seq.map (fun x -> async {
let! y = x
return y * y }) // OK
This works fine but the syntax is clumsy. It takes away F# compactness, and if I want to chain several seq
processing I have to do the same trick in every map
, filter
or iter
.
I suspect there might be a more efficient syntax to deal with sequences that consist of async computations.
You could use Async.map
(that I've only now blatantly stolen from Tomas Petricek):
module Async =
let map f workflow = async {
let! res = workflow
return f res }
let seqOfAsyncSquares' =
seqOfAsyncComps |> Seq.map (Async.map (fun x -> x * x))
If you evaluate it, you'll see that it seems to produce the expected outcome:
> seqOfAsyncSquares' |> Async.Parallel |> Async.RunSynchronously;;
val it : int [] = [|1; 4; 9|]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With