错误:表达式中的意外中缀运算符,关于成功编译的前缀运算符

时间:2016-09-06 01:11:26

标签: f# operator-overloading prefix-operator infix-operator

与中缀运营商一起玩一下,我对以下内容感到惊讶:

let (>~~~) = function null -> String.Empty | s -> s  // compiles fine, see screenshot
match >~~~ input with .... // error: Unexpected infix operator in expression

val (>~~~) : string -> string)

Unexpected infix operator

更改前缀运算符的第一个字符(例如!~~~)可以修复它。我得到 infix 运算符意外的错误是相当奇怪的。悬停显示定义为string -> string

我对错误并不太感到惊讶,F#要求(iirc)前缀运算符的第一个字符本身必须是预定义的前缀运算符之一。但为什么它编译得很好,当我使用它时,编译器会抱怨?

更新:当我在运算符定义中使用无效字符时,F#编译器在其他情况下似乎知道就好了,它说“无效的运算符定义。前缀运算符定义必须使用有效的前缀运算符名称。”< / em>的

Invalid operator definition.

1 个答案:

答案 0 :(得分:3)

F#中自定义运算符的规则非常紧张 - 因此,即使您可以定义自定义运算符,也会有很多关于它们如何运行的规则,并且您无法更改这些规则。特别是:

  • 只有一些运营商(主要是!~的运营商)可以用作前缀运营商。使用~,您还可以重载一元运算符+-~~~,因此如果您定义了名为~+.的运算符,然后可以用它作为例如+. 42
  • 其他运算符(包括以>开头的运算符)只能用作中缀。您可以使用括号将任何运算符转换为普通函数,这就是为什么(+) 1 2有效。
  • ?符号是特殊的(用于动态调用),不能作为自定义运算符的第一个符号出现。

我认为最直观的思考方式是自定义运算符的行为类似于标准的F#运算符,但您可以在标准运算符名称之后添加其他符号。