如何在Haskell中使用lambdas进行curry?

mah*_*nya 3 haskell currying

只是看着你学习Haskell(伟大的工作),并在curried函数部分下面有一个例子说明以下两个函数是相同的:

addThree x y z = x + y + z  
addThree = \x -> \y -> \z -> x + y + z  
Run Code Online (Sandbox Code Playgroud)

让我困惑的是如何将currying应用于lambda(s).随着功能的类型

addThree :: (Num a) => a -> a -> a -> a  
Run Code Online (Sandbox Code Playgroud)

当使用lambda时函数等于\x -> (\y -> (\z -> x + y + z))?如果是这种情况,那么x + y在最里面的lambda中被视为常数?也就是说,\z -> c + z这里cx + y

J. *_*son 9

在阅读类型签名时,addThree :: Num a => a -> a -> a -> a您应该在心理上添加相应的括号,如右箭头所示

addThree :: Num a => a ->  a ->  a -> a
addThree :: Num a => a -> (a -> (a -> a))
Run Code Online (Sandbox Code Playgroud)

这可能有助于描述单参数lambdas如何足以表示这样的函数.

在谈论咖喱羊肉时,你可以从几个方向看事物.我们来看一下这个内部片段

\z -> x + y + z
Run Code Online (Sandbox Code Playgroud)

如果这就是你被给予并被要求解释它的全部内容,那么你必须沮丧地举起双手 - 根本没有任何关于什么xy应该意味着什么的定义.它们被称为"自由"变量,因为它们不受lambda的约束.

为了给它们定义,我们必须包含更多意义x与... 结合的 lambda y.

\x -> \y ->     \z -> x + y + z       -- ok!
Run Code Online (Sandbox Code Playgroud)

所以,从内到外看,没有那些外在的lambda,表达就毫无意义.

但是,当您开始评估应用程序下的表达式时

(\x -> \y -> \z -> x + y + z) 1 2 3
Run Code Online (Sandbox Code Playgroud)

然后出现了另一个故事.现在,您必须完全依靠自己处理每个lambda绑定.规则是,为了评估应用于值的lambda,您可以将绑定变量替换为该值内的任何值.

(\x -> \y -> \z -> x + y + z) 1 2
(      \y -> \z -> 1 + y + z)   2
(            \z -> 1 + 2 + z)    
Run Code Online (Sandbox Code Playgroud)

因此,从外部来看,表达\z -> x + y + z永远不会存在,x并且y在我们走得那么远之前被淘汰了.

然而,值得注意的是,这与现在还不完全相同c + z!在绑定第三个参数之前,我们不评估内部lambda的主体.从某种意义上说,除非我们给它一些价值,否则无法知道lambda中的内容.(\z -> 1 + 2 + z)是完全不透明的.只有在应用了最终参数后,我们才能开始评估体内的添加.

从广义上讲,这就是所谓的"在活页夹下"工作的难度.