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.filter私は両方と以前に気づき、ロックできる最初のアイテムが必要なので、それが私のニーズをよりよく満たすSeq.pickと判断しました. Seq.pickただし、関数の戻り値を変更するのを忘れていました。 を返す代わりに、 を返すtrue必要がありSome(item)ます。その更新により、1) 変換するスレッドをブロックし、2) 命令型のループに頼ることなく、これにアプローチするエレガントな方法はありAsync<'U option>ます'Uか?

4

2 に答える 2

2

あなたが何をしようとしているのか正確にはわかりません。Async<'T>から'Tノンブロッキングに変換する場合let!は、非同期ワークフローで使用します。したがって、seq のようなロジックは、以下に示すように、おそらく独自のループとして記述する必要があります。それが役に立たない場合は、おそらくより多くのコード、特にアイテム/アイテム/リターンIfLockedの意図されたタイプを共有してください.あなたの例では何が非同期なのかわかりません.

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を返す関数が必要です。bool を返す関数option<'t>を使用Seq.Filterする必要があります。

ただし、まだ別の問題がありますAsync<bool>-それを通常のに変換する必要がありboolますが、「Seq.Filter」関数内でこれを行うことができます

于 2011-08-17T02:03:41.627 に答える