4

我对 F# 很陌生。我注意到的第一件事是集合操作被定义为函数而不是方法。

作为一个实验,我定义了几个方法list

type List<'a> with
    member this.map f = List.map f this
    member this.filter f = List.filter f this

然后,给定这些助手:

let square x = x * x

let isEven n = n % 2 = 0

这是使用这些方法的示例:

[1 .. 10].filter(isEven).map(square)

这是传统的方式:

[1 .. 10] |> List.filter isEven |> List.map square

所以简洁显然不是选择函数而不是方法的理由。:-)

从库设计的角度来看,为什么选择函数而不是方法?

我的猜测是,这是因为您可以传递List.filter,但不能真正传递该filter方法,除非它“绑定”到列表或包装在匿名函数中(即(fun (ls : 'a list) -> ls.filter)有效地将filter方法转换回函数 on list)。

然而,即使有这个原因,直接调用操作的最常见情况似乎会偏爱方法,因为它们更简洁。所以我想知道是否还有其他原因。

编辑:

我的第二个猜测是功能专业化。即专业化很简单List.filter(例如let evens List.filter isEven)。evens必须定义一个方法似乎更冗长。

4

2 回答 2

6

函数比方法更重要的是函数专业化和它实现的简单分解。

这是涉及函数的示例表达式:

let square x = x * x

let isEven n = n % 2 = 0

[1 .. 10] |> List.filter isEven |> List.map square

让我们分解出一个称为evens过滤偶数的函数:

let evens = List.filter isEven

现在让我们分解出一个对整数列表求平方的函数:

let squarify = List.map square

我们原来的表达现在是:

[1 .. 10] |> evens |> squarify

现在让我们回到原来的基于方法的表达式:

[1 .. 10].filter(isEven).map(square)

在这种情况下,对偶数进行过滤并不是那么简单。

于 2013-02-27T14:13:35.663 回答
4

我认为你的猜测是正确的。撇开简洁不谈,能够将其List.filter视为可以传递(您的第一个猜测)和部分应用(您的第二个猜测)的一流事物是关键。这是一种以动词而非名词为导向的看待世界的方式。我认为史蒂夫·耶格说得最好:)

于 2013-02-27T18:26:17.193 回答