这些返回类型有什么不同?
val fn1 : int −> (int −> (int −> int))
val fn2: (int −> int) −> (int −> int)
这创建了一个类型为
的函数int -> int -> int meaning int -> (int -> int)
是吗?不带括号它们的意思是一样的!
正如你所说,
fn1
的函数类型相当于int -> int -> int -> int
。
当您有多个像 fn1 a b c
这样的
curried参数时,那么
fn1 a
是 int -> int -> int
类型的函数,而 fn1 a b
是 int -> int
类型的函数。因此 fn1
也可以被视为一个返回函数的函数,该函数返回一个返回 int
的函数。添加像 int -> (int -> (int -> int))
这样的括号会突出显示该解释。
函数
fn2
有所不同:它采用 int -> int
类型的函数作为参数,并返回另一个 int -> int
类型的函数。
SML 中的函数采用一个参数并返回一个值。 故事结束。
嗯,不完全是。
当我们需要向函数传递多个参数时,有两种方法可以做到这一点。您可以将元组或记录或其他聚合数据结构传递给函数。这是一个单一的值,但却是由多条数据组成的。
fun f (x, y) = x * 3 + y
柯里化的来源是函数也是值,并且函数返回单个值。该值可以是一个函数。所以我们可以写:
val f = fn x => fun y => x * 3 + y
这很乏味,所以我们可以写成:
fun f x y = x * 3 + y
这非常适合部分应用:将通过将一个参数应用于
f
返回的函数绑定到一个新名称,然后在其余参数上调用它。
val g = f 3;
val h = g 1; (* 10 *)
像
f
这样的函数可以被赋予类型 int -> (int -> int)
,因为它描述了它的作用:给定 int
值,返回一个接受 int
并返回 int
的函数。但是 int -> int -> int
等效地描述了这一点。
现在,如果您看到
(int -> int) -> int
,则描述的是不同的东西。这意味着该函数接受一个函数作为参数并返回一个 int
。
执行此操作的函数示例:
fun g f = 1 + f 5
由于
int -> int
函数表示作为参数传入的一个值,因此无法从类型签名 (int -> int) -> int
中删除括号。
让我们分解一下
fn1
和 fn2
的返回类型来了解它们的区别:
1.
fn1: int -> (int -> (int -> int))
fn2: (int -> int) -> (int -> int)
现在,让我们看看这些类型在应用时如何发挥作用:
fn1
,你可以这样称呼它:
val result = fn1(5)(10)(15)
这意味着
fn1
被赋予 5
作为其初始参数,从而导致另一个函数的返回。随后,该函数被赋予 10
作为参数,并返回一个不同的函数。最后,最里面的函数接收 15
并返回结果。
fn2
,你可以这样称呼它:
val result = fn2(x => x * 2)(10)
这里,fn2
采用函数x => x * 2
作为其第一个参数,该函数本身就是一个将其输入加倍的函数。然后,外部函数返回一个新函数,该函数将 10
作为输入,从而得到 20
。所以,总结一下:
fn1
返回一个嵌套函数,该函数依次接受多个参数。
fn2
生成一个函数,该函数接收另一个函数作为其输入,后跟其自身的参数。
当您最初查看它们时,它们可能看起来很相似,但区别在于它们的返回类型的结构和实现方式。返回类型中的括号对于理解函数的行为和应用至关重要。