如何在F#中的Seq.pick中使用异步工作流

时间:2011-08-17 01:47:27

标签: f# async-workflow

我是一般的函数式编程新手,最近开始学习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>转换为'U和2)采用命令式样式循环?

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'函数中执行此操作