Как использовать асинхронный рабочий процесс в Seq.pick в F # - PullRequest
1 голос
/ 17 августа 2011

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

2 голосов
/ 17 августа 2011

Мне неясно, что именно вы пытаетесь сделать. Если вы хотите преобразовать из 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()
0 голосов
/ 17 августа 2011

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

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

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

...