标准机器学习中函数声明 `f x y` 和 `f (x, y)` 有什么区别?

问题描述 投票:0回答:1

在标准ML中,以下声明有什么区别(我省略了以

=
开头的定义):

fun f x y;

fun f (x, y);

据我了解,第一个需要两个参数,第二个需要一个元组。如果是这样,那么使用其中一种与另一种的(实际)影响是什么?有人可以争论哪一种是最好的风格吗?假设,实际上并不需要使用整个元组,即只有

x
y
分别是相关的。

ml
1个回答
7
投票

是的,正如您所说,第一个采用“两个参数”,而第二个采用一个元组参数。然而,要了解到底发生了什么,您必须了解currying。在机器学习中,每个“函数”都只接受一个参数(不多也不少)。

第二种情况,这很容易理解,它需要一个参数,这是一个元组,它对元组中的东西做一些事情,并返回一个结果。在第一种情况下,您定义一个接受一个参数的函数,然后返回一个接受另一个参数的函数,然后返回结果。

例如,这是一个接受两个

int
并返回一个
int
的函数。查看这两个函数的类型很有启发性:第二个函数的类型是
(int * int) -> int
,即从 tuple 到 int 的函数。第一个函数的类型是
int -> int -> int
,由于
->
是右关联的,因此可以解析为
int -> (int -> int)
。所以你可以看到,它接受一个 int 并返回一个函数。语法
fun f x y = ...
是更详细的
val f = fn x => fn y => ...
的语法糖。当您应用此功能时,例如
f 3 4
,函数应用程序是左关联的,所以这实际上是
(f 3) 4
,所以你可以看到它是如何工作的:
f
接受一个
int
,返回一个函数,然后将其应用于另一个int。这就是柯里化的要点。 ML 的语法使其变得透明。

柯里化版本(第一个版本)允许您进行部分应用。这意味着,尽管您的函数在概念上接受两个参数,但您不必为其提供那么多的参数。因此,我们上面的

f 3 4
(即
(f 3) 4
),如果我们只采用
f 3
,而不是仅将其应用于
4
,而是保留它并将其存储在变量或其他内容中,会怎么样?通过“给函数提供比它想要的更少的参数”,我们会自动获得一个接受剩余参数的函数。例如,我们可以执行
map (f 3) someList
,它会为列表中的每个
f 3 x
计算
x
的列表,而无需我们编写一些复杂的语法。

在标准机器学习中,库函数大多采用非柯里化形式;而在 OCaml 和 Haskell 中,它们大多采用柯里化形式。 (请参阅这个问题。)但是,作为高阶函数的 SML 库函数(例如 map 和 Fold)倾向于将其函数参数放在单独的(柯里化)参数中。

© www.soinside.com 2019 - 2024. All rights reserved.