2

Given the following function definition

let inline add<'X,'Y when 'X : (member Add : 'Y -> unit)> 
    (target:'X) (value:'Y) = target.Add value  

Why do I get this error?

  target.Add v
----^^^^^^^^^^
stdin(64,5): error FS0072: 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.

I am a bit perplexed to what other type annotation would be needed here. Can anybody explain?

robkuz
  • 9,488
  • 5
  • 29
  • 50

1 Answers1

5

I believe the proper way to do this is:

let inline add (target : ^X when ^X : (member Add : ^Y -> unit)) (value : ^Y) = 
    (^X : (member Add :  ^Y -> unit) target, value)

The answer and comments in this answer explains a bit as to why that syntax is necessary.

We can see it in action here:

let l = System.Collections.Generic.List<string>()
add l "Hello"

kvb also points out that given that the member constraint is now in the body, explicitly defining it in the arguments is not needed since the compiler can infer it, so we can clean it up a bit:

let inline add target value = 
    (^X : (member Add : ^Y -> unit) target, value)
Community
  • 1
  • 1
vcsjones
  • 138,677
  • 31
  • 291
  • 286
  • 3
    This is correct; note that given the member invocation expression in the function's body the compiler can infer the types of the arguments and the constraints. – kvb Apr 07 '15 at 15:24
  • thanks for the answers sofar even thou the syntax is indeed painful. On another note: Am I right to assume that I can't nest inline methods? – robkuz Apr 07 '15 at 16:44
  • @robkuz You can have an inlined method inside of an inlined method. If you are having issues with it, I would suggest [asking a new question](http://stackoverflow.com/questions/ask). – vcsjones Apr 07 '15 at 16:46