kagetoki
kagetoki

Reputation: 4787

F# inline function: instance member constraint fail

I try to use member constraint with my inline function like this:

    let inline extractMessageAsync 
        (envelope: ^env when ^env: 
            (member GetBodyAsync: unit-> Task<'a>)) =
    envelope.GetBodyAsync()

But I get the following error:

Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.

Although I understand that compiler needs more info about this type, I don't understand why, especially since it works just fine with static member constraints for operators like (+) or (*) etc.

Upvotes: 3

Views: 143

Answers (2)

TheQuickBrownFox
TheQuickBrownFox

Reputation: 10624

You can write a shorter and more generic version like this:

let inline GetBodyAsync x = (^a: (member GetBodyAsync: unit -> ^b) x)

Now writing GetBodyAsync is the equivalent of writing fun x -> x.GetBodyAsync() regardless of the return type of the method.

Usage:

open System.Threading.Tasks
type A() =
    member this.GetBodyAsync() = Task.FromResult 1

type B() =
    member this.GetBodyAsync() = async { return 2 }

A() |> GetBodyAsync |> fun x -> x.Result // 1
B() |> GetBodyAsync |> Async.RunSynchronously // 2

Upvotes: 2

Szer
Szer

Reputation: 3476

try this:

let inline extractMessageAsync<'a, ^env
         when ^env: (member GetBodyAsync: unit-> Task<'a>)>
        (envelope: ^env) =
    (^env: (member GetBodyAsync: unit-> Task<'a>) envelope)

Upvotes: 2

Related Questions