1

我一般是函数式编程的新手,最近开始学习 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.filterSeq.pick更早的情况,并决定这Seq.pick将更好地满足我的需求,因为我需要我能够锁定的第一个项目。但是,我忘记更改函数的返回值 - 而不是返回true,它应该返回Some(item)。现在有了这个更新,有没有一种优雅的方法来解决这个问题,而无需 1)阻塞要转换的线程Async<'U option>'U2)诉诸命令式循环?

4

2 回答 2

2

我不清楚你到底想做什么。如果要从非阻塞转换Async<'T>'T非阻塞,let!则要在异步工作流中使用。因此,类似 seq 的逻辑可能需要编写为自己的循环,如下所示。如果这没有帮助,那么也许共享更多代码,尤其是项目/项目/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()
于 2011-08-17T03:03:35.963 回答
0

查看您正在使用的函数的签名很重要,

Seq.pick期望一个返回的函数option<'t>,你想使用Seq.Filter它接受一个返回布尔值的函数。

您仍然会遇到另一个问题Async<bool>- 您需要将其转换为 normal bool,但您可以在 'Seq.Filter' 函数中执行此操作

于 2011-08-17T02:03:41.627 回答