我是Haskell和函数式编程的新手。我正在阅读《Real World Haskell》,但我发现我对一些示例感到困惑。
具体来说,在第9章的“用于谓词的特定领域语言”一节中,有带有w x y z参数的示例。
我把它简化成了这样:
为什么这段代码可以编译?
f :: Int -> (Int -> Int)
f x y = x+y
main = do
let q = f 4 5
putStr (show (q))
根据类型签名,
f
明显接受一个参数并返回一个函数。但是,我可以编写函数方程使其接受两个参数并返回一个 int。为什么会这样?这是否意味着类型签名被忽略了?这是柯里化吗?这是某种闭包吗? 如果我正确理解了 http://www.haskell.org/haskellwiki/Currying,那么它似乎与那里定义的柯里化相反 - 我的
f
函数正在接受多个参数而不是单个参数!此外,任何回答的人都可以提供一个指向某种 Haskell 文档的链接,其中说明了这种能力(如果可能的话)。
编辑:
思考了一段时间之后,你们两个似乎在暗示:
1)这种语法是语法糖,f 总是只有一个参数,无论方程中写了多少个参数
2)应用 f 时,函数体将(总是?)转换为存根(实际上是返回的函数),其中 x 固定为给定的参数(4),y 是一个参数。
3)然后将这个新函数应用于 5,替换 y,然后评估 + 函数。
我真正感兴趣的是,在哪里可以找到类似“在函数方程中,如果你写了多个参数,它实际上是语法糖,并且会发生以下情况...”这样的内容。或者这对每个人都是如此显而易见,除了我?
编辑 II:
真正的启发性答案在下面的@luqui评论中,不幸的是,我不认为我可以将评论标记为答案。
事实上,f x y = ... 实际上是以下语法糖:f = \x -> \y -> ...
对我来说,每个人都在下面说的其他一切都是由此而来的。
我在Haskell入门指南中找到了这方面的资料,链接如下:http://haskell.cs.yale.edu/tutorial/functions.html,位于第3.1节,称为Lambda抽象。
事实上,等式:
inc x = x+1 add x y = x+y
实际上是简写为:
inc = \x -> x+1 add = \x y -> x+y
虽然它没有使用“语法糖”这个词组,而是使用了更加数学化的“简写”这个词,但作为一个程序员,我读到这里时就会想到“糖” :-)
f 4 5
,这相当于解析为(f 4) 5
,因此f
将以4
作为参数被调用并返回\y -> 4 + y
的函数。然后你有(\y -> 4 + y) 5
,它变成了4 + 5
,然后是9
。诀窍在于函数类型和函数定义是右结合的,而函数应用是左结合的,因此它们可以很好地对齐。 - Antal Spector-Zabusky