Asynchronous F中嵌套异步序列的展平#
考虑一系列F#序列:Asynchronous F中嵌套异步序列的展平#,asynchronous,f#,sequence,Asynchronous,F#,Sequence,考虑一系列F#序列: let seqOf123 = seq { for i in 1..3 do yield i } let seqOf456 = seq { for i in 4..6 do yield i } let seqOf789 = seq { for i in 7..9 do yield i } let asyncSeqOf123 = async { return seqOf123 } let asyncSeqOf456 = async { return seqOf456 } le
let seqOf123 = seq { for i in 1..3 do yield i }
let seqOf456 = seq { for i in 4..6 do yield i }
let seqOf789 = seq { for i in 7..9 do yield i }
let asyncSeqOf123 = async { return seqOf123 }
let asyncSeqOf456 = async { return seqOf456 }
let asyncSeqOf789 = async { return seqOf789 }
。。。以及包含所有这些元素的序列:
let seqOfSeqOfNums =
seq {
yield seqOf123
yield seqOf456
yield seqOf789
}
现在我们有了一个序列,我们可以使用内置的Seq.concat函数和wrap in async子句将其展平以异步执行:
let firstAsyncSeqOfNums = async { return Seq.concat seqOfSeqOfNums }
我们得到了一个9个数字的异步序列,带有签名async
,我们将回到这里
现在考虑一系列异步序列:
let seqOf123 = seq { for i in 1..3 do yield i }
let seqOf456 = seq { for i in 4..6 do yield i }
let seqOf789 = seq { for i in 7..9 do yield i }
let asyncSeqOf123 = async { return seqOf123 }
let asyncSeqOf456 = async { return seqOf456 }
let asyncSeqOf789 = async { return seqOf789 }
。。。以及包含它们的序列:
let seqOfAsyncSeqOfNums =
seq {
yield asyncSeqOf123
yield asyncSeqOf456
yield asyncSeqOf789
}
我们现在有一个类型为seq
的序列。我们不能使用Seq.concat展平这个,因为它是一个异步序列序列。那么,我们如何将其转换为一种类型Async
,其中所有整数数据都被展平?我们可以尝试执行以下操作:
let secondAsyncSeqOfNums =
async {
return seqOfAsyncSeqOfNums
|> Seq.map (fun x -> x |> Async.RunSynchronously)
|> Seq.concat
}
它似乎完成了它的工作:它有一个类型
Async
,如果我们将它管道化为Async.RunSynchronously,它将生成相同的9个整数序列。但它产生相同序列的方式并不等同于上面出现的firstAsyncSeqOfNums。secondAsyncSeqOfNums的实现在生成单个展平序列期间对每个嵌套的整数序列调用Async.runsynchronous。但这能避免吗?请注意,我们正在生成一个异步展平序列,理想情况下只需对async.RunSynchronously进行一次调用即可评估其内容。但是,如果不多次调用Async.RunSynchronously,我无法找到重写代码的方法。您是否正在寻找类似这样的方法:
> let aMap f wf = async {
- let! a = wf
- return f a
- };;
val aMap : f:('a -> 'b) -> wf:Async<'a> -> Async<'b>
> let aConcat wf = Async.Parallel wf |> aMap Seq.concat;;
val aConcat : wf:seq<Async<#seq<'b>>> -> Async<seq<'b>>
>让aMap f wf=async{
-设!a=wf
-返回f a
- };;
valamap:f:('a->'b)->wf:Async
>设aConcat wf=Async.Parallel wf |>aMap Seq.concat;;
val aConcat:wf:seq>
它的名称稍有不同,但我认为您需要的是(您可能希望将它与前面提到的其他一些函数一起使用-只需播放一点;))Async.Parallel将序列转换为数组以进行并行执行,但它不能用于展平嵌套异步序列的序列,可以吗?它基本上会让你seq>
(因此它会把异步的拉出来)`-不,你可以继续你用seq.concat所做的事情(或者我会这么做)
)-在我看来,这比同步运行一切要好,因为你失去了异步的所有优势)顺便说一句:很遗憾(有些奇怪)没有Async.map
所以你不能把它们很好地结合在一起,你必须深入到Async{…}
或者自己把Async
变成一个函子你能用一个例子来说明吗?我确实使用了Async.Parallel,但无法让它按我的目的工作。关于Async.map,很容易编写一个,如我的另一个问题的答案所示:谢谢,它成功了!是的,Async.Parallel和Async.map(aMap)的组合成功了。很高兴我能提供帮助-FP中的好东西是:正确地获取类型,并且通常很好地使用;)是的,我花了一段时间努力摆脱对Async.RunSynchronously的多次调用。现在一切都很完美:-)