我是一般的函数式编程新手,最近开始学习F#。我想使用异步工作流程返回Async<'U option>
来选择序列中的项目。我发现了一个很好的Seq.pick
函数,但我不确定如何在异步工作流中使用它。
如果无法做到这一点,是否有另一种方法可以使用命令式样式程序从列表中选择项目。以下是我的程序的修改变体。任何反馈都非常感谢。
let run = async {
while not stopped do
use! resource = acquireResourceLockAsync
let! items = fetchItemsAsync 5
let! item = Seq.pick returnIfLocked items
let! status = performTaskAsync item
do! updateStatusAsync status
do! Async.Sleep 1000
}
感谢您的期待。
编辑:根据jpalmer的回答更新了我的问题。我之前注意到Seq.filter
和Seq.pick
,并认为Seq.pick
会更好地满足我的需求,因为我需要能够锁定的第一个项目。但是,我忘了更改函数的返回值 - 而不是返回true
,它应该返回Some(item)
。现在有了这个更新,有没有一种优雅的方法来解决这个问题,而没有1)阻止线程将Async<'U option>
转换为'U
和2)采用命令式样式循环?
答案 0 :(得分:2)
我不清楚你到底想要做什么。如果您想要从Async<'T>
转换为'T
非阻止,那么您希望在异步工作流中使用let!
。因此,类似seq的逻辑可能需要编写为自己的循环,如下所示。如果这没有帮助,那么可能会共享更多代码,特别是项目/ item / returnIfLocked的预期类型,因为我不清楚你的例子中的异步是什么。
let asyncPick f (s:seq<_>) =
async {
use e = s.GetEnumerator()
let r = ref None
while Option.isNone(!r) && e.MoveNext() do
let! x = f e.Current
r := x
match !r with
| Some z -> return z
| None -> return failwith "no matching item found"
}
let chooser ax =
async {
let! x = ax
if x%3 = 0 then
return Some x
else
return None
}
let s = seq { for i in 1..10 do yield async { return i } }
let main() =
async {
let! firstChosen = s |> asyncPick chooser
return firstChosen
}
|> Async.RunSynchronously
|> printfn "%d"
main()
答案 1 :(得分:0)
查看您正在使用的功能的签名非常重要,
Seq.pick
需要一个返回option<'t>
的函数,你想使用Seq.Filter
来获取一个返回bool的函数。
你仍然有另一个问题,因为你有Async<bool>
- 你需要将它转换为正常bool
,但你可以在你的'Seq.Filter'函数中执行此操作