Question

I have the following code in F#:

   let CreateSampleDataFromJson<'T>(path) = 
      let uri = new Uri(path)
      async {
         let file = StorageFile.GetFileFromApplicationUriAsync(uri)
         let jsonText = FileIO.ReadTextAsync(file)
         return JsonObject<'T>.Parse(jsonText)
      }

The problem I'm having is that file is an IAsyncOperation<StorageFile> and not a StorageFile as ReadTextAsync expects.

In C# you can do something similar to this:

var file = await StorageFile.GetFileFromApplicationUriAsync(uri) 

i.e.

public async Task<T> CreateSampleDataFromUrl<T>(string path)
{
  var uri = new Uri(path);
  var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
  var jsonText = await FileIO.ReadTextAsync(file);
  return JsonObject<T>.Parse(jsonText);
}

The problem is that I don't know how to await an IAsyncOperation in F#. The usual let! doesn't work. i.e. the following fails to compile:

async {
   let! file = StorageFile.GetFileFromApplicationUriAsync(uri)

With the compiler error:

error FS0001: This expression was expected to have type    Async<'a>    but here has type    IAsyncOperation<StorageFile>

I found a document that said there's an AsTask() extension method defined in the System.WindowsRuntimeSystemExtensions class which I can use as follows:

 let! file = StorageFile.GetFileFromApplicationUriAsync(uri).AsTask() |> Async.AwaitTask

Is there a standard way of doing this or something available in an F# library somewhere that makes this a bit nicer?

Was it helpful?

Solution

Your solution seems fine by me. If you're looking for a nicer syntax, how about rolling it into a function like this (without the possibly gratuitous type annotations):

let await<'a> (op: IAsyncOperation<'a>) : Async<'a> =
   op.AsTask() |> Async.AwaitTask

This will give you the almost exact same syntax you'd see in c#:

async {
   let! file = await <| StorageFile.GetFileFromApplicationUriAsync(uri)
   ...
}

The compiler errors you were getting with your previous approaches are to be expected. All async workflow cares about is the F#-specific Async type. This type gives you a way to interop with the rest of .NET world through Tasks, but that's it. IAsyncOperation is from a 'different part of the world', I wouldn't expect F# core libraries to support it anytime soon.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top