I was playing with some F# code using this online compiler (I could not find the exact F# compiler version, this will be relevant later). I realized the following two functions were very different:
let f x y = x = y
let g x y = x != y
f
is completely generic, but to my surprise g
was not. Calling g 1 2
will cause a compilation error with the message:
A generic construct requires that the type 'int' have reference semantics, but it does not, i.e. it is a struct
I went and tried this on my own machine (using F# 3.0 on mono, but I get the same result in Visual Studio 2012) and received a completely different error when I tried to define g
:
error FS0332: Could not resolve the ambiguity inherent in the use of the operator '( != )' at or near this program point. Consider using type annotations to resolve the ambiguity.
Why is this use of !=
ambiguous and why is it an error? Also, why is this use of !=
considered ambiguous but use of =
in f
is not? The new error is helpful in alerting me to a case where automatic generalization did not work as I had expected. However, this does seem to be a breaking change between two different versions of the F# compiler. Searches for both of these error messages turned up empty. I did not see anything in the F# specification that seemed relevant. Any pointers to relevant sections would be helpful.
Note that !=
is not the name of the inequality operator in F#, <>
is.
http://msdn.microsoft.com/en-us/library/dd233228.aspx
Using <>
should be possible just the same as =
in your example.
The existing answer explains why the code does not behave as expected, so let me just add an explanation of what is the error message trying to say.
F# supports custom operators and you will get the same error message for any other (valid) operator symbol that you try to use in a function, for example the fish operator:
let fish x y = x <*>><< y
In this case, F# cannot define a generic function, because .NET does not have a way of specifying generic constraint saying that the type of one or the other argument support the <*>><<
operator (in .NET language, the constraint would have to say that one of the types needs a specific static method).
This is not the case for comparison or equality (because F# has a way to represent these). But if you use something like +
then you still won't get a generic function, but a function specialized to int
. In that case, you can use inline
and write a function that is generic (requires the +
operator):
let inline add x y = x + y
add 1 2
add 1.1 2.2
Similarly, you could define an inline function that requires any custom operator (like fish or !=
) but you would still not be able to call it with any standard types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With