'try/with in an asyncResult block, in F#?

How is the try / finally working in an asyncResult block:

let loadAndParseTrades ticker (dayDate: DateTime) : Async<Result<TradeData list, ExchangeError>> =
    asyncResult {
        try
            // wait for loading semaphore
            loadingSemaphores.WaitOne() |> ignore
        
            // load the data
            let date  = dayDate.Floor (TimeSpan.FromDays(1))
            let func  = client.GetAsync(buildTradesRequest ticker date) |> Async.AwaitTask
            let! data = getDataAsync func

            // parse it and return it                
            return Parser.parseTrades ticker data []
        
        finally
            loadingSemaphores.Release() |> ignore
    }

I have this function loading a large zip file and parsing it.

I would like to catch exceptions here and return an Error:

try
    try
        // wait for loading semaphore
        loadingSemaphores.WaitOne() |> ignore
    
        // load the data
        let date  = dayDate.Floor (TimeSpan.FromDays(1))
        let func  = client.GetAsync(buildTradesRequest ticker date) |> Async.AwaitTask
        let! data = getDataAsync func

        // parse it and return it                
        return Parser.parseTrades ticker data []

    with ex ->
        let err = Error (ExchangeError.ServiceException ex)  // <- Result<'a,ExchangeError>
        AsyncResult.returnError err             
    
finally
    loadingSemaphores.Release() |> ignore

but then this doesn't seem to be possible here:

  Loader.fs(75, 21): [FS0193] Type constraint mismatch. The type 
    'Async<Result<unit,'a>>'    
is not compatible with type
    'Async<Result<TradeData list,ExchangeError>>'

what am I missing here?


Edit:

Added a sample that everyone can compile

let testSomethingAsync x =
    async {
        if x % 2 = 0 then
            return Ok x
        else
            return Error "oh, no!"
    }        

let doSomethingAsync x =
    asyncResult {
        try    
            let! a = testSomethingAsync x
            return a * 2
        with ex ->

            // none of these compile
            // AsyncResult.returnError "no no no"            
            // Error (AsyncResult.returnError "no no no")             
            // return (AsyncResult.returnError "no no no")
            // return (Error (AsyncResult.returnError "no no no"))             
               

since:

let returnError x = Error x |> Async.singleton

we can assume that the lines:

Error (AsyncResult.returnError "no no no")             
return (Error (AsyncResult.returnError "no no no" 

will not compile for sure.

The line:

AsyncResult.returnError "no no no"           

will fail to compile with:

Type constraint mismatch. The type 'Async<Result<unit,'a>>' is not compatible with type 'Async<Result<int,string>>' 

And the line:

return (AsyncResult.returnError "no no no")

will fail to compile with:

This expression was expected to have type 'int' but here has type 'Async<Result<'a,'b>>'

I'm a bit lost here...

f#


Solution 1:[1]

The following should work:

let doSomethingAsync x =
    asyncResult {
        try    
            let! a = testSomethingAsync x
            return a * 2
        with ex ->
            return! AsyncResult.error "no no no"
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tom Moers