Обычно я пишу вызов функции непосредственно в асинхронном рабочем процессе. Это в основном вопрос стиля или предпочтений - я думаю, что код, написанный с использованием асинхронных рабочих процессов, как правило, более явный и не использует функции высшего порядка так часто (хотя они все еще иногда полезны):
let test=
[ for stock in ["MSFT";"YHOO"] ->
async { let! data = getCSV stock (DateTime(2000, 1, 1)) (DateTime(2010, 1, 1))
return getReturns data } ]
|> Async.Parallel
|> Async.RunSynchronously
Это означает, что рабочие процессы, выполняемые параллельно, сначала получают данные, а затем вызывают getRteurns
для извлечения данных. Затем вся операция распараллеливается.
В качестве альтернативы, вы можете использовать решение Джоэла (изменить функцию getReturns
так, чтобы она брала асинхронный рабочий процесс и возвращал асинхронный рабочий процесс) или определить функцию Async.map
, которая принимает асинхронный рабочий процесс и создает новый, который применяется некоторая функция к результату.
Используя исходную функцию getReturns
, вы можете написать:
let test=
["MSFT";"YHOO"]
// For every stock name, generate an asynchronous workflow
|> List.map (fun x -> getCSV x (DateTime(2000, 1, 1)) (DateTime(2010, 1, 1)))
// For every workflow, transform it into a workflow that
// applies 'getReturns' to the result of the original workflow
|> List.map (Async.map getReturns)
// Run them all in parallel
|> Async.Parallel
|> Async.RunSynchronously
Определение Async.map
довольно просто:
module Async =
let map f workflow = async {
let! res = workflow
return f res }