只是看着你学习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
,其中c
是x + y
?
答案 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包装到y
和x
。
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 + z
和x
在我们走到那么远之前被消除了。
y
不完全相同!在绑定第三个参数之前,我们不评估内部lambda的主体。从某种意义上说,除非我们给它一些价值,否则无法知道lambda中的内容。 c + z
完全不透明。只有在应用了最终参数后,我们才能开始评估体内的添加。
从广义上讲,这就是所谓的工作难度"在一个活页夹下面#34;