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

时间:2014-08-25 21:46:13

标签: f#

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

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

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

let ls = (::) 1 [2..5]  // Error: Unexpected symbol '::' in binding.

原因是什么?

2 个答案:

答案 0 :(得分:8)

您可以使用静态方法:

let ls = List.Cons (1, [2..5])

或运营商的详细名称:

let ls = op_ColonColon (1, [2..5])

(使用F#3.0检查;旧版本可能会有不同的行为。例如,MSDN建议op_Cons

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

let inline ( * ) (x:int) (y:int) = ...

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

  

这是什么原因?

事实上,(::)不是通常的操作符(独立函数或类型成员),而是 union case 。以下是F# sourcesList<'T>的定义方式:

type List<'T> =
    | ([])  : 'T list
    | (::)  : Head: 'T * Tail: 'T list -> 'T list

因此,如果您的目的是部分应用参数,那么唯一的 nice 解决方案就是编写@pad建议的包装函数。

答案 1 :(得分:6)

由于(::)(以及[])是一个符号关键字,因此您无法将其用作中缀运算符。请参阅F# specification,第3.6节“符号关键字”。

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

let cons x xs = x :: xs
let ls = cons 1 [2..5]