Как использовать асинхронный рабочий процесс в 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'