我一直在尝试理解SML中的高阶函数。我知道如何编写简单的高阶函数并理解签名。一个例子是:
fun increment list = map (fn x=> x + 1) list;
val it = fn: int list -> int list
但是,我无法理解以下高阶函数的签名:
fun add x y = x + y;
val add = fn: int -> int -> int
该功能可写为:
fun add (x,y) = x+y;
val add: fn : (int * int) -> int
我明白了。但是在上一个函数中,我无法理解操作顺序是如何工作的。该函数是一次采用两个参数,还是一次生成一个新函数,然后产生所需的结果?它如何适用于任何其他更高阶函数?
我需要为我的作业建立关于高阶函数签名的概念,以及几周后我的考试。
答案 0 :(得分:1)
要记住的一件事是所有 SML函数只接受一个参数。该参数可以是一对,如第二个{{1}}函数,或者一个int,就像在您的第一个add
函数中一样。你是正确的,第一个add
返回类型为add
的函数。你也可以写
int -> int
这使得它更清楚它需要一个参数。甚至
fun add1 x = fn y => x + y
(FWIW,你的val add1 = fn x => fn y => x + y
函数看起来有点奇怪。它忽略了它的参数,每次都返回相同的结果。
double
可能就是你的意思。)
答案 1 :(得分:1)
在SML中,可以使用函数。
- fun add x y = x + y
val add = fn : int -> int -> int
是咖喱。这意味着它可以部分应用,如下所示:
- fun add2 x = add 2 x;
val add2 = fn: int -> int
- add2 3;
val it = 5 : int
如果我们将函数编写为:
- fun add2tuple(x,y) = x + y;
val add2tuple = fn : (int * int) -> int
我们实际上并没有传递两个参数,而是传递一个元组。元组包含两个整数是元组类型的描述。
如果我们以咖喱形式编写函数,那么函数参数不会放在元组中。
在curry形式中,可以通过在1和n-1个参数之间传递来部分应用函数fun f p1 p2 ... pn = ...
。
但是不能部分应用参数为单个元组的函数。
- fun addordered x y = x + (2 * y);
val addordered = fn : int -> int -> int
- addordered 2 3;
val it = 8 : int
- fun addordered2 x = addordered x 2;
val addordered2 = fn : int -> int
- addordered2 3;
val it = 7 : int
这个例子可能会澄清元组是一回事:
- fun add3tuple(x,y,z) = x + y;
val add3tuple = fn : int * int * 'a -> int
- add3tuple(3,4,5);
val it = 7 : int
- add3tuple(3,4,"Hello World");
val it = 7 : int
希望你喜欢Dan Grossman的课程。