在Haskell中,(+)是一个函数,((+)2)是一个函数,((+)2 3)是5.那究竟是什么?

Mai*_*tor 12 haskell programming-languages functional-programming function partial-application

  1. 这怎么可能,那里发生了什么?

  2. 这有名字吗?

  3. 还有哪些其他语言具有相同的行为?

  4. 没有强大的打字系统?

Ben*_*Ben 42

如果查看类型,这种行为非常简单直观.为了避免中缀运算符的复杂性+,我将使用该函数plus.我也将专注plus于工作Int,以减少类型线噪声.

假设我们有一个plus类型的函数Int -> Int -> Int.读取它的一种方法是" Int返回两个s 的函数Int".但那个符号对于那个阅读来说有点笨拙,不是吗?返回类型不会在任何地方特别挑选出来.为什么我们这样写函数类型签名?因为它->是右关联的,所以是等价的类型Int -> (Int -> Int).这看起来更像是它在说"从功能Int到(一个从功能IntInt)".但这两种类型实际上是完全相同的,而后一种解释是理解这种行为如何运作的关键.

Haskell将所有函数视为从单个参数到单个结果.可能存在计算,计算结果取决于两个或多个输入(例如plus).Haskell说该函数 plus是一个函数,它接受一个输入,并产生一个输出,这是另一个函数.第二个函数接受一个输入并产生一个数字输出.因为第一个函数是由第一个计算的(并且对于第一个函数的不同输入将是不同的),所以"最终"输出可以取决于两个输入,因此我们可以使用这些仅使用单个输入的函数实现具有多个输入的计算.

我保证,如果你看一下类型,这将很容易理解.这是一些示例表达式,其类型明确注释:

plus       :: Int -> Int -> Int
plus 2     ::        Int -> Int
plus 2 3   ::               Int
Run Code Online (Sandbox Code Playgroud)

如果某个函数是一个函数并将其应用于参数,那么要获取该应用程序的结果类型,您需要做的就是从函数类型中删除第一个箭头的所有内容.如果留下一个有更多箭头的类型,那么你仍然有一个功能!在表达式右侧添加参数时,可以从其类型的左侧删除参数类型.该类型使其立即清楚所有中间结果的类型是什么,以及为什么plus 2可以进一步应用的函数(其类型具有箭头)而plus 2 3不是(其类型没有箭头).

"Currying"是将两个参数的函数转换为一个参数的函数的过程,该函数返回另一个参数的函数,该函数返回原始函数返回的内容.它也用于引用像Haskell这样的语言的属性,它自动使所有函数都以这种方式工作; 人们会说Haskell"是一种讨厌的语言"或"已经过时",或者"已经过去了".

请注意,这非常优雅,因为Haskell的函数应用语法是简单的令牌邻接.你可以自由地阅读plus 2 3作为plus2个参数的应用,或者应用plus2然后应用结果3; 你可以在精神上建模它,无论你最适合你当时做什么.

在带有括号参数列表的类C函数应用程序的语言中,这有点分解.与此语法的语言plus(2, 3)非常不同plus(2)(3),所plus涉及的两个版本可能具有不同的类型.因此,具有这种语法的语言往往不会一直使用所有函数,甚至不能自动调整您喜欢的任何函数.但是这些语言在历史上也倾向于不具备作为一等价值的功能,这使得缺乏讨论成为现实.


Dan*_*ton 9

在Haskell中,所有函数都只需1个输入,并产生1个输出.有时,函数的输入或输出可以是另一个函数.函数的输入或输出也可以是元组.您可以通过以下两种方式之一模拟具有多个输入的函数:

  • 使用元组作为输入
    (in1, in2) -> out

  • 使用函数作为输出*
    in1 -> (in2 -> out)

同样,您可以通过以下两种方式之一模拟具有多个输出的函数:

  • 使用元组作为输出*
    in -> (out1, out2)

  • 使用函数作为"第二个输入"(la函数作为输出)
    in -> ((out1 -> (out2 -> a)) -> a)

*这种方式通常受到Haskellers的青睐

(+)函数模拟以典型的Haskell方式生成函数作为输出的2个输入.(专Int为方便沟通:)
(+) :: Int -> (Int -> Int)

为方便起见,它->是右关联的,因此(+)也可以编写类型签名
(+) :: Int -> Int -> Int


(+) 是一个函数,它接收一个数字,并从数字到数字产生另一个函数.

(+) 5是应用于(+)参数的结果5,因此,它是从数字到数字的函数.

(5 +) 是另一种写作方式 (+) 5

2 + 3是另一种写作方式(+) 2 3.函数应用程序是左关联的,所以这是另一种写作方式(((+) 2) 3).换句话说:将函数(+)应用于输入2.结果将是一个功能.使用功能,并将其应用于输入3.结果是一个数字.

因此,(+)是一个函数,(5 +)是一个函数,并且(+) 2 3是一个数字.


Ned*_*der 6

在Haskell中,您可以使用两个参数的函数,将其应用于一个参数,并获取一个参数的函数.事实上,严格来说,+不是两个参数的函数,它是一个参数的函数,它返回一个参数的函数.