6

我正在使用这个在线编译器玩一些 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:无法解决在此程序点处或附近使用运算符“(!=)”所固有的歧义。考虑使用类型注释来解决歧义。

为什么这种使用!=模棱两可,为什么它是一个错误?另外,为什么这种使用被!=认为是模棱两可的,而=inf的使用却不是?新错误有助于提醒我自动泛化未按预期工作的情况。但是,这似乎是两个不同版本的 F# 编译器之间的重大变化。对这两个错误消息的搜索结果都是空的。我在F# 规范中没有看到任何相关的内容。任何指向相关部分的指针都会有所帮助。

4

2 回答 2

13

请注意,!=不是 F# 中不等式运算符的名称,<>而是。

http://msdn.microsoft.com/en-us/library/dd233228.aspx

使用<>应该与=您的示例相同。

于 2013-10-21T07:16:09.660 回答
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 或!=)的内联函数,但您仍然无法使用任何标准类型调用它。

于 2013-10-21T07:41:21.747 回答