3

柯里化函数的结果是部分应用函数吗?我了解柯里化的工作原理,虽然我了解部分函数应用程序的工作原理,但我不清楚这些概念是否存在一些交叉。

我的困惑源于以下引自Learn you a Haskell for great good的引言,这与我之前基于John Skeet 的博客文章对这个概念的理解相冲突。

简单地说,如果我们调用一个参数太少的函数,我们会得到一个部分应用的函数,这意味着一个函数接受的参数与我们遗漏的参数一样多。

举个例子(在 F# 中,虽然问题一般是关于函数式编程)

> let add a b = a + b;;

val add : int -> int -> int

> let inc = add 1;;

val inc : (int -> int)

在这个例子中是inc一个部分应用的函数?

4

2 回答 2

3

一般来说,柯里化是指将一个双参数函数转换为一个接受一个参数并返回另一个单参数函数的函数,这样第一个参数调用柯里化函数的结果与第二个参数调用 this 的结果是等价的使用两个参数调用原始(未咖喱)函数。在具有闭包和动态类型(或类型推断)的伪 C 语言中,这看起来像这样:

// The original, uncurried function:
function f(a, b) { return 2 * a - b; }

// The curried function:
function g(a) {
    return function(b) {
        return f(a, b);
    }
}

// Now we can either call f directly:
printf("%i\n", f(23, 42));

// Or we can call the curried function g with one parameter, and then call the result
// with another:
printf("%i\n", (g(23))(42));

通过多次柯里化,我们可以将任何多参数函数简化为一组嵌套的单参数函数。

在 Haskell 中,所有函数都是单参数的;like 的构造f a b c实际上等价((f(a))(b))(c)于我们虚构的 C-with-closures。将多个参数真正传递给函数的唯一方法是通过元组,例如f (a, b, c)- 但由于柯里化函数的语法更简单,语义更灵活,因此很少使用此选项。

Haskell Prelude 定义了两个函数,curryuncurry在这两个表示之间进行转换:curryis of type ((a,b) -> c) -> a -> b -> c,即它接受一个接受元组(a, b)并返回 a的单参数函数,c并将其转换为 type 的函数a -> b -> c,即函数接受a 并返回一个接受 a并返回aa 的函数。做相反的事情。bcuncurry

部分应用并不是真正的事情。它只是给你有一个柯里化函数(例如f a b)的情况命名,而不是完全展开整个链(例如,f 23 42),你在途中的某个地方停下来,并进一步传递结果函数,例如let g = f 23。为了部分应用一个函数,它必须是柯里化的(你不能部分地应用f (a, b)as let g = f (a)),但是由于在 Haskell 中以柯里化的方式编写函数是默认的,部分应用是简单且常见的做法。

于 2012-06-03T12:24:00.527 回答
0

简短的回答:inc是通过部分应用获得的功能。

curried 函数的结果是目标语言(Haskell、F# 或其他)中某种类型的值,因此它可能是一个函数(但它也可能是一个整数、一个布尔值,...,具体取决于您的声明)。

关于部分应用程序......它只是给返回其他函数的函数应用程序的名称,但从技术上讲,它是一个和其他函数应用程序一样的函数应用程序。您返回的函数基于先前的参数甚至不是强制性的。举个\x -> id 例子:你总是得到恒等函数,独立于输入x

于 2012-06-03T12:19:03.027 回答