我正在使用this在线编译器玩一些F#代码(我找不到确切的F#编译器版本,这将在以后相关)。我意识到以下两个功能非常不同:
let f x y = x = y
let g x y = x != y
f
完全是通用的,但令我惊讶的是g
并非如此。调用g 1 2
将导致编译错误消息:
泛型构造要求类型'int'具有引用语义,但它没有,即它是结构
我去了我自己的机器上尝试过这个(在单声道上使用F#3.0,但我在Visual Studio 2012中得到了相同的结果)并在我尝试定义g
时收到完全不同的错误:
错误FS0332:无法解决在此程序点或附近使用运算符'(!=)'所固有的歧义。考虑使用类型注释来解决歧义。
为什么!=
使用含糊不清,为什么会出错呢?另外,为什么!=
的使用被认为含糊不清,但在=
中使用f
不是?新错误有助于提醒我一个自动泛化无法按预期工作的情况。但是,这似乎是两个不同版本的F#编译器之间的重大变化。搜索这两个错误消息都显示为空。我没有在F# specification中看到任何看似相关的内容。任何指向相关部分的指针都会有所帮助。
答案 0 :(得分:13)
答案 1 :(得分:9)
现有的答案解释了为什么代码没有按预期运行,所以让我简单地添加一个解释错误消息的解释。
F#支持自定义运算符,您将尝试在函数中使用的任何其他(有效)运算符符号获得相同的错误消息,例如fish运算符:
let fish x y = x <*>><< y
在这种情况下,F#无法定义泛型函数,因为.NET没有指定泛型约束的方法,说明一个或另一个参数的类型支持<*>><<
运算符(在.NET语言中,约束必须说其中一种类型需要特定的静态方法)。
这不是比较或相等的情况(因为F#有一种表示这些的方法)。但是如果你使用+
这样的东西,你仍然不会得到一个泛型函数,而是一个专门用于int
的函数。在这种情况下,您可以使用inline
并编写一个通用的函数(需要+
运算符):
let inline add x y = x + y
add 1 2
add 1.1 2.2
同样,您可以定义一个内联函数,该函数需要任何自定义运算符(如fish或!=
),但您仍然无法使用任何标准类型调用它。