优化F#中映射的异步序列的语法

Vag*_*lov 5 f# asynchronous sequence

我试图找出以下F#表达式的有效语法.假设我有一个F#异步计算:

let asyncComp n = async { return n }
Run Code Online (Sandbox Code Playgroud)

它有一个签名'a -> Async<'a>.现在我定义一系列的顺序:

let seqOfAsyncComps = 
    seq {
        yield asyncComp 1
        yield asyncComp 2
        yield asyncComp 3
    }
Run Code Online (Sandbox Code Playgroud)

现在我有一个项目seq<Async<int>>.如果我想从元素异步映射seq<Async<int>>seq<Async<int>>.这不起作用:

let seqOfAsyncSquares =
    seqOfAsyncComps |> Seq.map (fun x -> x * x) // ERROR!!!
Run Code Online (Sandbox Code Playgroud)

当然,x是的Async<int>,我必须提取int第一个,所以我可以做以下事情:

let seqOfAsyncSquares =
    seqOfAsyncComps |> Seq.map (fun x -> async { 
                                            let! y = x
                                            return y * y }) // OK
Run Code Online (Sandbox Code Playgroud)

这很好但语法很笨拙.它带走了F#compactness,如果我想链接几个seq处理,我必须在每个map,filter或者做同样的技巧iter.

我怀疑可能有更高效的语法来处理由异步计算组成的序列.

Mar*_*ann 5

你可以使用Async.map(我现在只是从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))
Run Code Online (Sandbox Code Playgroud)

如果你评估它,你会发现它似乎产生了预期的结果:

> seqOfAsyncSquares' |> Async.Parallel |> Async.RunSynchronously;;
val it : int [] = [|1; 4; 9|]
Run Code Online (Sandbox Code Playgroud)

  • 提交PR :)怎么样? (2认同)