Let's say I want to extend xUnit's Assert.Throws to support F# async in this way:
Assert.AsyncThrows<InvalidOperationException>(fun () -> async { return "" })
The implentation is as such:
module Xunit.Assert
let AsyncThrows<'TException when 'TException :> exn> asyncFunc = async {
let mutable actualException = None
try
let! r = asyncFunc()
return ()
with
| :? 'TException as e -> actualException <- Some e
| _ -> ()
return Assert.Throws(
(fun () ->
match actualException with
| Some ex -> raise ex
| None -> ()))
}
The type of asyncFunc is inferred to be unit -> Async<obj>. This is needlessly restrictive on callers; it should be unit -> Async<'a>. I have tried the following:
let AsyncThrows<'TException when 'TException :> exn> (asyncTask:unit->Async<'a>)
This doesn't work and still compiles as Async<obj> with a cryptic warning ("...causes the code to be less generic than indicated...").
let AsyncThrows<'TException, 'a when 'TException :> exn> (asyncTask:unit->Async<'a>)
This works, but forces callers to explicitely supply the return type of the async function, e.g.
Assert.AsyncThrows<InvalidOperationException, string>(fun () -> async { return "" } )
Is there a way to only have to supply the type of the exception but not of the async function?
(Note: my actual use case doesn't use async but a another similar computation expression; I used async for illustration purposes).