Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the use of '!=' considered ambiguous but a similar use of '=' is not?

Tags:

generics

f#

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.

like image 596
Mike Zboray Avatar asked Oct 21 '13 07:10

Mike Zboray


2 Answers

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.

like image 187
DuckMaestro Avatar answered Nov 12 '22 04:11

DuckMaestro


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.

like image 30
Tomas Petricek Avatar answered Nov 12 '22 03:11

Tomas Petricek