代表着lp
是一个带有 2 个参数的函数,第一个是curr
第二个是一个列表,从逻辑上讲,它可能是空的([]
) 或包含至少一个元素((a::l)
是一个列表的模式,其中a
位于头部,列表的其余部分是l
).
如果将 FP 代码翻译成某种众所周知的命令式语言,它看起来会像:
function lp(curr, lst) {
if (lst.length == 0) {
return curr;
} else {
var a = lst[0]; // first element
var l = lst.slice(1, lst.length); // the rest
if (gt(a, curr)) {
return lp(a, l);
} else {
return lp(curr, l)
}
}
}
虽然有点拗口,但翻译得很忠实。
函数式语言基于拉姆达演算,其中函数仅采用一个值并返回一个结果。虽然 SML 和其他 FP 语言基于此理论,但在实践中相当不方便,因此许多语言允许您通过所谓的方式来表达将多个参数传递给函数Currying.
所以,是的,在机器学习中,函数实际上只接受一个值,但柯里化可以让你模拟多个参数。
让我们创建一个名为的函数add
,将 2 个数字相加:
fun add a b = a + b
应该这样做,但我们定义了 2 个参数。是什么类型的add
?如果你看一下 REPL,它是val add = fn : int -> int -> int
。其中写道,“add 是一个函数,它接受一个 int 并返回另一个函数(它接受一个 int 并返回一个 int)”
所以我们也可以定义add
这边走:
fun add a =
fn b => a + b
你会发现他们很相似。事实上,在某种程度上可以肯定地说,
前者是后者的语法糖。
因此,您在 ML 中定义的所有函数,即使是具有多个参数的函数,实际上也是具有一个参数的函数,该函数返回接受第二个参数的函数,依此类推。一开始有点难以习惯,但它
很快就会成为第二天性。
fun add a b = a + b (* add is of type int -> int -> int *)
add 1 2 (* returns 3 as you expect *)
(* calling add with only one parameter *)
val add1 = add 1
What's add1
?它是一个function这将添加1
到您传递的单个参数!
add1 2 (* returns 3 *)
这是一个例子部分应用,您正在逐步调用函数,
一次一个参数,每次返回,另一个函数接受其余参数
的论点。
另外,还有另一种方法给出外观多个参数:元组:
(1, 2); (* evaluates to a tuple of (int,int) *)
fun add (a,b) = a + b;
add (1, 2) (* passing a SINGLE argument to a function that
expects only a single argument, a tuple of 2 numbers *)
在你的问题中,lp
可以有也被实施为lp (curr, someList)
:
fun max gt curr lst =
let fun lp (curr, []) = curr
| lp (curr, (a::l)) = if gt(a,curr) then lp (a, l)
else lp (curr, l)
in
lp (curr, lst)
end
请注意,在这种情况下,我们必须声明max
as max gt curr lst
!
在您发布的代码中,lp
显然是通过柯里化实现的。以及类型max
本身就是fn: ('a * 'a -> bool) -> 'a -> 'a list -> 'a
。拆开来看:
('a * 'a -> bool) -> (* passed to 'max' as 'gt' *)
'a -> (* passed to 'lp' as 'curr' *)
'a list -> (* passed to 'lp' as 'someList' *)
'a (* what 'lp' returns (same as what 'max' itself returns) *)
请注意type of gt
,第一个参数max
: fn : (('a * 'a) -> bool)
- 它是一个函数one争论('a * 'a)
, 两个元组'a
并返回一个'a
。所以这里没有柯里化。
使用哪一种取决于品味、惯例和实际考虑。
希望这可以帮助。