Call the async method in inner lambda? "This construct can only be used in calculation expressions."

I have the following code

let rec consume() : Async<unit> = async {
    .....
    listA 
    |> Seq.iter(fun i ->
        .....
        let listB : seq<...> option = 
            let c = getListB a b
            match c with 
            | Some d -> Seq.filter(....) |> Some
            | None -> None 
        match listB with .....
    ....

Now the function is getListBconverted to return async<Seq<B>>instead Seq<B>. Thus, the code was converted to the following. However, it getListBblocked execution. How to rewrite it without blocking? It just let! c = getListB a bwon’t convert the string to , because the code is in the inner lambda? Error message: "This construct can only be used in calculation expressions."

let rec consume() : Async<unit> = async {
    .....
    listA 
    |> Seq.iter(fun i ->
        .....
        let listB : seq<...> option = 
            let c = getListB a b |> Async.RunSynchronously
            match c with 
            | Some d -> Seq.filter(....) |> Some
            | None -> None 
+4
source share
2 answers

The answer depends on whether you want to run each element of the sequence sequentially or in parallel.

Seq.map Seq.iter, lambda async, map seq<Async<'a>>.

async.

module Async = 
    let map f x =
        async{
            let! x = x
            return f x
        }

    let lift2 f x1 x2 = 
        async{
            let! x1 = x1
            let! x2 = x2
            return f x1 x2
        }

    let return' x = async { return x }

    let mapM mFunc sequ =
        let consF x ys = lift2 (fun h t -> h::t) (mFunc x) ys
        Seq.foldBack(consF) sequ (return' [])
        |> map (Seq.ofList)

    let sequence sequ = mapM id sequ

, mapM, traverse , .

sequence mapM, (id). seq<Async<'a>> -> Async<seq<'a>>, .. async Seq .

Seq.map sequence, async.

, , :

let sleep = Async.Sleep 100
let sleeps = Seq.init 15 (fun _ -> sleep)
let sequencedSleeps = Async.sequence sleeps
Async.RunSynchronously sequencedSleeps
Real: 00:00:01.632, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val it : seq<unit> =
  [null; null; null; null; null; null; null; null; null; null; null; null;
   null; null; null]

, , :

let pSequence sequ = Async.Parallel sequ |> Async.map (Seq.ofArray)

:

let pSleeps = pSequence sleeps;;
Async.RunSynchronously pSleeps;;
Real: 00:00:00.104, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val it : seq<unit> = seq [null; null; null; null; ...]

, .


, seq<unit> , , :

let sequenceIgnore sequ = sequ |> Async.sequence |> Async.map (ignore)

let pSequenceIgnore sequ = sequ |> pSequence |> Async.map (ignore)

unit, .

+2

, , , , seq<Async> Async<seq>. .

, , , . , , , Async<_>

let traverseSequence ( seqAsync : seq<Async<'a>>) = 

    let promiseOfAnEmptySequence = async  { return Seq.empty }

    let delayedCalculation (asyncHead : Async<'a>) (asyncTail : Async<seq<'a>>) = 
        async {
        let! calculatedHead = asyncHead
        return!
            async {
                let! calculatedTail = asyncTail
                return calculatedHead |> Seq.singleton |> Seq.append(calculatedTail)
            }
        }

    Seq.foldBack delayedCalculation seqAsync promiseOfAnEmptySequence
+2

Source: https://habr.com/ru/post/1648272/


All Articles