“Chaining” asynchronous functions in F#

后端 未结 2 1565
伪装坚强ぢ
伪装坚强ぢ 2020-12-19 17:15

I have created a function in F# to recover historical data from Yahoo (the classic asynchronous example for F#):

let getCSV ticker dStart dEnd =
async   {
           


        
2条回答
  •  独厮守ぢ
    2020-12-19 18:13

    If you defined your getReturns function like this...

    let getReturns (prices:Async<(DateTime * float) list>) = async {
        let! prices = prices
        return [for i in 1..(prices.Length-1) -> i]
               |> List.map (fun i ->(fst (List.nth prices i), (snd (List.nth prices i))/(snd (List.nth prices (i-1)))))
    }
    

    Then you would be able to do this:

    let test=
        ["MSFT";"YHOO"]
        |> List.map (fun x -> getCSV x (DateTime(2000, 1, 1)) (DateTime(2010, 1, 1)))
        |> List.map getReturns
        |> Async.Parallel
        |> Async.RunSynchronously
    

    You could clean it up further by changing getCSV so that ticker is the last parameter instead of the first. This allows you to partially apply the date arguments to produce a function that only requires a ticker to execute. Then you can chain that function with getReturns.

    let test =
        let getRange = getCSV (DateTime(2000, 1, 1)) (DateTime(2010, 1, 1))
        ["MSFT"; "YHOO"]
        |> List.map (getRange >> getReturns)
        |> Async.Parallel
        |> Async.RunSynchronously
    

    Edit:

    All those List.nth calls in your getReturns function make me itchy. I'd rather use pattern-matching myself. I think you could write that function like this instead:

    let getReturns2 (prices: Async<(DateTime * float) list>) = async {
        let! prices = prices
        let rec loop items output =
            match items with
            | (_, last) :: (time, current) :: rest ->
                loop rest ((time, (last / current)) :: output)
            | [ item ] ->
                List.rev (item :: output)
            | [] ->
                List.rev output
        return loop prices []
    }
    

提交回复
热议问题