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

时间:2015-04-05 15:44:23

标签: asynchronous f# sequence

我试图找出以下F#表达式的有效语法。让我们说我有一个F#异步计算:

let asyncComp n = async { return n }

它有一个签名'a -> Async<'a>。现在我定义一系列的那些:

let seqOfAsyncComps = 
    seq {
        yield asyncComp 1
        yield asyncComp 2
        yield asyncComp 3
    }

现在我有一个seq<Async<int>>的项目。如果我想异步映射seq<Async<int>>seq<Async<int>>的元素,该怎么办?这不会起作用:

let seqOfAsyncSquares =
    seqOfAsyncComps |> Seq.map (fun x -> x * x) // ERROR!!!

当然,xAsync<int>,我必须首先提取int,所以我可以改为:

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

这很好用,但语法很笨拙。它会消除F#compactness,如果我想链接多个seq处理,我必须在每个mapfilteriter中执行相同的操作。

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

1 个答案:

答案 0 :(得分:5)

您可以使用Async.map(我现在只是公然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))

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

> seqOfAsyncSquares' |> Async.Parallel |> Async.RunSynchronously;;
val it : int [] = [|1; 4; 9|]