Optimizing syntax for mapped async sequences in F#

耗尽温柔 提交于 2020-01-03 13:30:03

问题


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.


回答1:


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|]


来源:https://stackoverflow.com/questions/29459042/optimizing-syntax-for-mapped-async-sequences-in-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!