Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 这个函数签名在sml中是什么意思?_Function_Sml_Smlnj - Fatal编程技术网

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

Function 这个函数签名在sml中是什么意思?,function,sml,smlnj,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 有人能解释一下这是怎么回事吗?我最困惑的是这句话:

我正在浏览教授关于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
是一个包含两个参数的函数,第一个参数是
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语言都是基于这一理论的,但在实践中相当不方便,因此这些语言中的许多语言都允许您通过所谓的函数来表示向函数传递多个参数

是的,在ML中,函数实际上只接受一个值,但curry允许您模拟多个参数

让我们创建一个名为
add
的函数,它添加了两个数字:

fun add a b = a + b
应该这样做,但我们定义了两个参数。添加的
类型是什么?如果您查看REPL,它是
valadd=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)

注意,在这种情况下,我们必须将
max
声明为
max gt curr lst

在你发布的代码中,
lp
显然是用currying实现的。以及
max
本身是
fn:('a*'a->bool)->'a->'a列表->'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)
-它是一个one参数
('a*'a)
,两个
'a
元组的函数,返回一个
'a
。所以这里没有咖喱

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


希望这能有所帮助。

从Faiz出色的回答中,我只想澄清一点关于咖喱的问题

如前所述,SML只允许函数接受1个参数。这是因为函数实际上是(语法糖)的派生形式。事实上这并不完全正确,但让我们简单地说一下

现在以这个幂函数为例。这里我们将函数声明为“接受两个参数”

如上所述,
fun…
是一种派生形式,因此幂函数的等价形式为

val rec pow = fn n => fn k => ...
正如您在这里可能看到的,我们在表达原始函数声明的两个不同模式匹配时遇到了问题,因此我们不能再保持它的“简单”,而
fun
声明的真正等价形式是

val rec pow = fn n => fn k =>
    case (n, k) of 
      (n, 0) => 1
    | (n, k) => n * pow n (k-1)
为了完整性起见,cases实际上也是一种派生形式,以匿名函数作为等价形式

val rec pow = fn n => fn k => 
    (fn (n,0) => 1
      | (n,k) => n * pow n (k-1)) (n,k)

请注意,
(n,k)
直接应用于最内部的匿名函数。

这是一种函数定义形式,您将在基于ML的语言、haskell、lisp中反复看到:如果您点击了空列表,函数就完成了,否则,处理列表头和递归。您能再解释一下函数
lp
采用的参数以及
curr
是什么吗?参数是元组
(curr,someList)
?如果不是太多工作,您能告诉我如果将
lp
实现为
lp(curr,someList)
会是什么样子吗?谢谢你?刚刚加上去的。希望这会有所帮助。@Faiz“事实上,可以肯定地说,在某种程度上,前者是后者的语法糖分”。它确实是一种派生形式,尽管您所介绍的形式没有完全扩展到它的等价形式。啊,您的意思是
val add=fn a=>fn b=>a+b
?是的,为了完整起见,我应该加上这个!谢谢
val rec pow = fn n => fn k =>
    case (n, k) of 
      (n, 0) => 1
    | (n, k) => n * pow n (k-1)
val rec pow = fn n => fn k => 
    (fn (n,0) => 1
      | (n,k) => n * pow n (k-1)) (n,k)