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

时间:2013-12-26 20:44:44

标签: haskell currying

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

addThree x y z = x + y + z  
addThree = \x -> \y -> \z -> x + y + z  

这里让我感到困惑的是如何将currying应用于lambda(s)。 功能类型为

addThree :: (Num a) => a -> a -> a -> a  

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

1 个答案:

答案 0 :(得分:9)

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

addThree :: Num a => a ->  a ->  a -> a
addThree :: Num a => a -> (a -> (a -> a))

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

谈到咖喱羊羔时,你可以从几个方向看东西。让我们检查一下内部片段,例如

\z -> x + y + z

如果这就是你被给予并被要求解释的全部内容,那么你必须沮丧地举起双手 - 根本没有x和{{1}的定义应该意味着。他们被称为"免费"变量,因为它们不受lambda约束。

为了给他们定义,我们必须将更多 bind 含义的lambdas包装到yx

y

所以,从内到外看,没有那些外面的羔羊,这个表达就毫无意义。

但是,当您开始评估应用程序

下的表达式时
\x -> \y ->     \z -> x + y + z       -- ok!
然后出现了一个不同的故事。现在,您必须完全依靠自己处理每个lambda绑定。规则是,为了评估应用于值的lambda,您可以在其中的任何位置将该值替换为该值。

(\x -> \y -> \z -> x + y + z) 1 2 3

因此,从外部来看,表达式(\x -> \y -> \z -> x + y + z) 1 2 ( \y -> \z -> 1 + y + z) 2 ( \z -> 1 + 2 + z) 永远不存在,\z -> x + y + zx在我们走到那么远之前被消除了。

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

从广义上讲,这就是所谓的工作难度"在一个活页夹下面#34;