根据 MSDN https://msdn.microsoft.com/en-us/library/dd233204.aspx, 冒号实际上不能用在操作符名称中。这似乎矛盾F# 规范 http://fsharp.org/specs/language-spec/3.1/FSharpSpec-3.1-working.docx来自 FSharp.org,我不确定那里发生了什么。但我们可以在 FSI 中验证:
> let ( >:> ) a b = a+b
Script.fsx(1,7): error FS0035: This construct is deprecated: ':' is not permitted as a character in operator names and is reserved for future use
如果你看how List<'T>被定义为 https://github.com/fsharp/fsharp/blob/0313094fa5d19fd871c83e7e45c35d1fad65daf9/src/fsharp/FSharp.Core/prim-types.fs#L3493,你会发现(::)
实际上不是一个运算符,而是一个案例构造函数:
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
果然,您可以使用它作为构造函数名称来定义自己的 DU 类型:
> type A =
> | ( :: ) of string * int
> | A of int
>
> let a = "abc" :: 5
val a : A = Cons ("abc",5)
现在,奇怪的是,如果我尝试使用另一个看起来像运算符的名称作为 case 构造函数,我会收到此错误:
> type A = | ( |> ) of string * int
Script.fsx(1,14): error FS0053: Discriminated union cases and exception labels must be uppercase identifiers
意思就是(::)
不知何故special(也是如此([])
, 顺便一提)。
所以底线似乎是——不,你不能那样做。
但为什么你需要这样做呢?也许您可以选择一个更可接受的运算符名称,它仍然可以表达“cons”的语义 - 例如,(<+>)
?