为什么你不能写出"(::) 1 [2]"你在F#中写"(+)1 2"的方式?

Joh*_*lds 5 f#

将F#中缀运算符放在括号中,它的行为类似于函数,

let foo = (*) 3 2  // foo = 6
let factorial n = [2..n] |> List.fold (*) 1  // n!
Run Code Online (Sandbox Code Playgroud)

但是,这不适用于:: operator(cons运算符),

let ls = (::) 1 [2..5]  // Error: Unexpected symbol '::' in binding.
Run Code Online (Sandbox Code Playgroud)

这是什么原因?

byt*_*ter 8

您可以使用静态方法:

let ls = List.Cons (1, [2..5])
Run Code Online (Sandbox Code Playgroud)

或运营商的详细名称:

let ls = op_ColonColon (1, [2..5])
Run Code Online (Sandbox Code Playgroud)

(使用F#3.0检查;旧版本可能表现不同.例如,MSDN建议op_Cons)

在这两种情况下,都没有办法在这里讨论这些论点.数字运算符定义如下:

let inline ( * ) (x:int) (y:int) = ...
Run Code Online (Sandbox Code Playgroud)

但是,列表连接需要一个元组,这也回答了你的问题,

这是什么原因?

实际上,(::)它不是通常的操作符(独立函数或类型成员),而是联合案例.以下List<'T>F#源中的定义方式:

type List<'T> =
    | ([])  : 'T list
    | (::)  : Head: 'T * Tail: 'T list -> 'T list
Run Code Online (Sandbox Code Playgroud)

因此,如果您的目的是部分应用参数,唯一不错的解决方案是编写一个包装函数,如@pad所建议的那样.


pad*_*pad 6

因为(::)(并且[]就此而言)是一个符号关键字,您不能指望将它用作中缀运算符.请参阅F#规范,第3.6节符号关键字.

在这种情况下,您必须定义一个额外的功能,例如

let cons x xs = x :: xs
let ls = cons 1 [2..5]
Run Code Online (Sandbox Code Playgroud)