function - 这个函数签名在sml中是什么意思?

标签 function sml smlnj

我正在查看我的教授关于 SML 语言的一些注释,其中一个函数如下所示:

fun max gt = 
    let fun lp curr [] = curr
           | lp curr (a::l) = if gt(a,curr)
                             then lp a l
                             else lp curr l
in
    lp
end

有人可以帮忙解释一下这是在做什么吗?我最困惑的是这行:

    let fun lp curr [] = curr

这到底是什么意思?据我所知,有一个名为 lp 的函数,但是 curr [] 是什么意思?这些是论据吗?如果是的话,sml中不是只允许有一个参数吗?

最佳答案

这意味着 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)
    }
  }
}

虽然拗口,但翻译很忠实。

函数式语言基于 Lambda Calculus ,其中函数仅采用一个值并返回一个结果。虽然 SML 和其他 FP 语言基于此理论,但在实践中相当不方便,因此许多这些语言允许您通过所谓的 Currying 来表达将多个参数传递给函数。 .

所以,是的,在 ML 函数中实际上只采用一个值,但柯里化(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

什么是add1?这是一个函数,它将向您传递的单个参数添加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 声明为 max gt curr lst!

在您发布的代码中,lp 显然是通过柯里化(Currying)实现的。以及类型 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) *)

注意 gt类型,即 max 的第一个参数:fn : (('a * 'a) -> bool) - 它是一个参数('a * 'a)的函数,两个'a的元组's 并且它返回一个 'a。所以这里没有柯里化(Currying)。

使用哪个是品味、惯例和实际考虑的问题。

希望这有帮助。

关于function - 这个函数签名在sml中是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14432696/

相关文章:

objective-c - header 中的 Obj-C 函数声明

c++ - 内联函数联动

python - 在函数中绑定(bind)对象值(闭包)

user-interface - 标准 ML 的 GUI?

compiler-construction - 在 "Real-World"应用程序中使用 ML

sml - 在 sml 中匹配非穷举

sml - 为什么 SML 中的以下延续函数不起作用?

javascript - NodeJS buffer.slice() 不是一个函数?

functional-programming - 尝试理解 SML 选项结构

javascript - 如何将对象添加到数组