mattgately
mattgately

Reputation: 1032

simple F# run-time generic function with type constraint can't be resolved

I have a basic function with one generic parameter:

let func<'T> (x:'T when 'T : (static member op_Explicit: 'T -> float) ) =
   float x

Why am I getting the error: "The declared type paramater 'T cannot be used here since the type parameter cannot be resolved at compile time"

In this example, I've provided one generic paramater and constrained it to be able to explicitly cast to float, and all the function does is cast to float, so what is the problem? I've read all of the MSDN documents relating to generics in F# yet they seem to just go in circles, and don't correspond to the behavior I see in Visual Studio. From my understanding, using the single quote syntax 'T is for run-time generics, not compile-time generics.

This brings me to another question. I often see the syntaxes 'T and ^T intermingled, both with and without inline. This goes against the MSDN documentation regarding these syntactical definitions. Am I missing something?

Furthermore, from the documentation, it seems that the op_Explicit constraint on type 'T should be able to be inferred automatically without any type annotation from:

let func x =
   float x

but the type of x is inferred to be int in this case.

Upvotes: 2

Views: 1249

Answers (2)

Brian
Brian

Reputation: 118865

Here's a quickie-summary that may help out.

You use inline and ^T and member constraints to author weird code 'for all types T that have this ad-hoc API set'; this is code that cannot be authored directly in .NET (e.g. you can't write it in C#), and it must be inline because the F# compiler can inline/hard-code the specific type at each individual call site. This is a very advanced feature, and so you're unlikely to find too many docs/samples about it (and the error diagnostics are not always great).

You use 'T for normal generics, e.g. the usual generic stuff you do in C#. This is a mainline scenario.

Note that in both cases, it is often possible(/better/easier) to let F# infer types and genericity for you, rather than spelling it out. E.g.

let inline f x = float x

and the hover-tip in Visual Studio over f shows that the appropriate constraint has been inferred.

Upvotes: 4

mattgately
mattgately

Reputation: 1032

Thanks to @ildjarn, I found the answer:

From http://msdn.microsoft.com/en-us/library/dd548046:

Statically resolved type parameters are primarily useful in conjunction with member constraints, which are constraints that allow you to specify that a type argument must have a particular member or members in order to be used. There is no way to create this kind of constraint by using a regular generic type parameter.

It seems that Visual Studio should give a different error, then, such as: "Member constraints cannot be used here since 'T is not a statically resolved type" or "Member constraints can only be used in conjunction with statically-resolved type parameters."

Upvotes: 0

Related Questions