Как использовать асинхронный рабочий процесс в Seq.pick в F#

Я новичок в функциональном программировании в целом и недавно начал изучать 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) прибегая к императивному стилю зацикливания?

2 ответа

Решение

Мне неясно, что именно вы пытаетесь сделать. Если вы хотите конвертировать из Async<'T> в 'T неблокирующий, то вы хотите использовать let! в асинхронном рабочем процессе. Таким образом, seq-подобная логика, вероятно, должна быть записана как собственный цикл, как предложено ниже. Если это не поможет, то, возможно, поделитесь большим количеством кода, особенно предполагаемых типов items/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()

Важно взглянуть на сигнатуру функции, которую вы используете,

Seq.pick ожидает функцию, которая возвращает option<'t>, вы хотите использовать Seq.Filter который принимает функцию, которая возвращает bool.

У вас все еще будет другая проблема, хотя у вас есть Async<bool> - вам нужно будет преобразовать это в нормальный bool, но вы можете сделать это внутри вашей функции 'Seq.Filter'

Другие вопросы по тегам