优化 F# 中映射异步序列的语法
Optimizing syntax for mapped async sequences in F#
我正在尝试找出以下 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!!!
当然,x
就是Async<int>
,我得先提取一个int
,这样我就可以改为:
let seqOfAsyncSquares =
seqOfAsyncComps |> Seq.map (fun x -> async {
let! y = x
return y * y }) // OK
这很好用,但语法很笨拙。它带走了 F# 的紧凑性,如果我想链接多个 seq
处理,我必须在每个 map
、filter
或 iter
.[=25= 中执行相同的技巧]
我怀疑可能有更有效的语法来处理由异步计算组成的序列。
您可以使用 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|]
我正在尝试找出以下 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!!!
当然,x
就是Async<int>
,我得先提取一个int
,这样我就可以改为:
let seqOfAsyncSquares =
seqOfAsyncComps |> Seq.map (fun x -> async {
let! y = x
return y * y }) // OK
这很好用,但语法很笨拙。它带走了 F# 的紧凑性,如果我想链接多个 seq
处理,我必须在每个 map
、filter
或 iter
.[=25= 中执行相同的技巧]
我怀疑可能有更有效的语法来处理由异步计算组成的序列。
您可以使用 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|]