令人困惑的匿名函数构造

时间:2016-11-15 18:04:08

标签: f#

我正在阅读F#教程,并遇到了一个我不理解的语法示例。我正在阅读的页面链接位于底部。以下是该页面的示例:

let rec quicksort2 = function
   | [] -> []                         
   | first::rest -> 
        let smaller,larger = List.partition ((>=) first) rest 
        List.concat [quicksort2 smaller; [first]; quicksort2 larger]

// test code        
printfn "%A" (quicksort2 [1;5;23;18;9;1;3])

我不明白的部分是:((>=) first)。究竟是什么?相比之下,这是来自List.partition的{​​{3}}的示例:

let list1 = [ 1 .. 10 ]
let listEven, listOdd = List.partition (fun elem -> elem % 2 = 0) list1
printfn "Evens: %A\nOdds: %A" listEven listOdd

List.partition的第一个参数(这是正确的术语吗?)显然是一个匿名函数。我重写了这条线:

let smaller,larger = List.partition (fun e -> first >= e) rest 

,它的工作原理与上面的例子相同。我只是不明白这个结构如何完成同样的事情:((>=) first)

MSDN documentation

2 个答案:

答案 0 :(得分:5)

这与中缀符号与前缀符号大致相同 运算符也是函数,遵循相同的规则(即可以部分应用它们)

所以这里(>=) first是运算符> = first已经应用为“第一”操作数,并且在重写该行时注意到了一个等待运算符的第二个操作数的函数

答案 1 :(得分:3)

此构造结合了两个功能:带前缀表示的操作符调用和部分功能应用程序。

首先,让我们看看使用前缀表示法调用运算符

let x = a + b

上面的代码使用两个参数+a调用运算符b。由于这是一种函数式语言,因此一切都是函数,包括运算符,包括运算符+。这只是运算符有这个有趣的调用语法,你将函数放在之间而不是在它们之前。但你仍然可以像操作任何其他常规函数一样对待操作符。为此,您需要将其括在括号中:

let x = (+) a b     // same thing as a + b.

当我说“和其他任何功能一样”时,我完全是这样说的:

let f = (+)
let x = f a b     // still same thing.

接下来,让我们看一下部分功能应用。考虑这个功能:

let f x y = x + y

我们可以打电话给他并获得一个号码作为回报:

let a = f 5 6    // a = 11

但我们也可以通过仅提供两个参数中的一个来“几乎”调用它:

let a = f 5    // a is a function
let b = a 6   // b = 11

这种“几乎调用”(技术上称为“部分应用程序”)的结果是另一个仍然需要剩余参数的函数。

现在,让我们结合两个

let a = (+) 5    // a is a function
let b = a 6      // b = 11

一般来说,可以写出以下等价物:

(+) x    ===    fun y -> x + y

或者,类似地,对于您的具体情况:

(>=) first     ===     fun y -> first >= y