部分是柯里化的结果吗?

Is a section the result of currying?

Hutton 在 Haskell 中的编程

In general, if # is an operator, then expressions of the form (#), (x #), and (# y) for arguments x and y are called sections, whose meaning as functions can be formalised using lambda expressions as follows:

(#)   =   \x  ->  (\y ->  x   #   y)
(x    #)  =   \y  ->  x   #   y
(#    y)  =   \x  ->  x   #   y

"section"和"currying"有什么区别和联系?

节是对多参数函数应用柯里化操作的结果吗?

谢谢。

节只是将中缀运算符应用于单个参数的特殊语法。 (# y) 是两者中更有用的一个,因为 (x #) 等同于 (#) x(它只是以通常的方式将中缀运算符作为函数应用于单个参数)。

左侧部分和右侧部分是用于将中缀运算符部分应用于单个参数的语法设备(另请参阅 )。为了准确起见,我们应该注意柯里化与部分应用不是一回事:

  • 柯里化正在将一个接受 N 个参数的函数转换为一个接受单个参数的函数,returns 一个接受 [=51] 个参数的函数=]N-1 个参数。

  • Partial application 正在制作一个函数,该函数采用 N-1 个参数,而该函数采用 N 个参数通过提供参数之一。

在Haskell中,碰巧一切都是柯里化的;所有函数都只接受一个参数(甚至 Haskell 中的非科里化函数也接受一个元组,严格来说,这是一个单一的参数——你可能想玩玩 curryuncurry 函数看看它是如何工作的)。尽管如此,我们还是经常非正式地将 return 函数视为具有多个参数的函数。从这个有利的角度来看,默认柯里化的一个很好的结果是函数对其第一个参数的部分应用变得微不足道:而例如,elem 接受一个值和一个容器并测试该值是否是一个元素在容器中,elem "apple" 获取一个容器(字符串)并测试 "apple" 是否是其中的一个元素。

至于运算符,当我们写的时候,比如...

5 / 2

...我们将运算符 / 应用于参数 52。运算符也可以以前缀形式使用,而不是中缀:

(/) 5 2

在前缀形式中,运算符可以按通常的方式部分应用:

(/) 5

然而,可以说这看起来有点尴尬——毕竟,5 这里是分子,而不是分母。在这种情况下,我会说左侧部分语法更容易理解:

(5 /)

此外,部分应用到第二个参数 is not quite as straightforward to write,需要 lambda,或 flip。对于运算符,右侧部分可以提供帮助:

(/ 2)

请注意,部分也适用于通过反引号语法制成运算符的函数,所以这...

(`elem` ["apple", "grape", "orange"])

... 获取一个字符串并测试它是否可以在 ["apple", "grape", "orange"].

中找到

curry f x y = f (x,y)uncurry g (x,y) = g x y

(+ 3) 4 = (+) 4 3 = 4 + 3(4 +) 3 = (+) 4 3 = 4 + 3

一个部分是部分应用 curried 函数的结果:(+ 3) = flip (+) 3(4 +) = (+) 4

柯里化函数(如 g(+))一次需要一个参数。一个未柯里化的函数(比如 f)期望它的参数在一个元组中。

要部分应用一个未柯里化的函数,我们必须首先将其转换为一个柯里化函数,curry。要部分应用柯里化函数,我们不需要做任何事情,只需将其应用到一个参数即可。

curry   :: ((a, b)  -> c ) -> ( a -> (b -> c))
uncurry :: (a -> (b -> c)) -> ((a, b)   -> c )

 x :: a
 g :: a -> (b -> c)       
--------------------
 g    x ::  b -> c  

 x       ::  a
 f       :: (a, b)   -> c
---------------------------
 curry f ::  a -> (b -> c)
 curry f     x ::  b -> c