asynchronous - 异步mapFold
问题描述
对于以下示例,Array.mapFold
生成结果([|1; 4; 12|], 7)
。
let mapping s x = (s * x, s + x)
[| 1..3 |]
|> Array.mapFold mapping 1
现在假设我们的映射是异步的。
let asyncMapping s x = async { return (s * x, s + x) }
我能够创建Array.mapFoldAsync
以下工作。
[| 1..3 |]
|> Array.mapFoldAsync asyncMapping 1
|> Async.RunSynchronously
有没有一种简洁的方法可以在不创建的情况下实现这一目标Array.mapFoldAsync
?
我要求作为学习其他技术的一种方式 - 我使用 Array.fold 的尝试非常糟糕。
解决方案
mapFold
我认为与函数结合通常不会有多大好处Async
,因为预期的结果是 tuple ('values * 'accumulator)
,但使用Async
函数最多会给你一个Async<'values * 'accumulator>
. 考虑以下尝试与 一起Array.mapFold
工作Async
:
let mapping s x = async {
let! s' = s
let! x' = x
return (s' * x', s' + x')
}
[| 1..3 |]
|> Array.map async.Return
|> Array.mapFold mapping (async.Return 1)
即使这样也行不通,因为类型不匹配: The type ''a * Async<'b>' does not match the type 'Async<'c * 'd>'
。
您可能还注意到,虽然有Array.Parallel.map
,但没有Array.Parallel.fold
or Array.Parallel.mapFold
。如果您尝试编写自己的mapFoldAsync
,您可能会明白原因。映射部分非常简单,只需部分应用Array.map
和组合Async.Parallel
:
let mapAsync f = Array.map f >> Async.Parallel
您也可以实现异步fold
,但由于每次评估都取决于先前的结果,因此您不能利用Async.Parallel
这次:
let foldAsync f state array =
match array |> Array.length with
| 0 -> async.Return state
| length ->
async {
let mutable acc = state
for i = 0 to length - 1 do
let! value = f acc array.[i]
acc <- value
return acc
}
现在,当我们尝试将这些组合起来构建 amapFoldAsync
时,很明显我们不能再利用映射上的并行执行,因为值和累加器都可以基于先前评估的结果。这意味着我们mapFoldAsync
将是一个修改后的“foldAsync”,而不是它的组合mapAsync
:
let mapFoldAsync (f: 's -> 'a -> Async<'b * 's>) (state: 's) (array: 'a []) =
match array |> Array.length with
| 0 -> async.Return ([||], state)
| length ->
async {
let mutable acc = state
let results = Array.init length <| fun _ -> Unchecked.defaultof<'b>
for i = 0 to length - 1 do
let! (x,y) = f acc array.[i]
results.[i] <- x
acc <- y
return (results, acc)
}
虽然这将为您提供一种mapFold
使用异步映射函数的方法,但唯一真正的好处是如果映射函数执行一些具有高延迟的操作,例如服务调用。您将无法利用并行执行来加速。如果可能,我建议根据您的实际情况考虑替代解决方案。
推荐阅读
- google-kubernetes-engine - 我们如何在裸机上安装 gke 以使用 Anthos 服务
- java - 具有特定字符的 Java pad 字符串
- django - Django Recaptcha 未能通过表单验证
- json - 如何在 webflux 的请求正文中获取 json 对象?
- reactjs - 连接不起作用,并且没有在 react-redux 中重新渲染
- javascript - 在嵌套组件中使用 react-router-dom 在主要内容组件之间导航
- java - 我有一个输入具有三个不同的值。如何从单个扫描仪中扫描三个值
- javascript - 如何使此代码每 5 分钟自动运行一次,以使视频标题与观看次数相匹配,即使我关闭计算机?
- python - 如何使用 python pandas 删除列索引?
- javascript - GLTF 加载警告---定时器 GLTF 加载器已经存在