我将给出两个稍微间接的答案。
首先,考虑以下代码:
module Lambda where
derivApprox f h x = ( (f (x + h)) - (f x) ) / h
我已经编译了这个,同时告诉 GHC 转储一个中间表示,它大致是作为编译过程的一部分使用的 Haskell 的简化版本,以获得这个:
Lambda.derivApprox
:: forall a. GHC.Real.Fractional a => (a -> a) -> a -> a -> a
[LclIdX]
Lambda.derivApprox =
\ (@ a) ($dFractional :: GHC.Real.Fractional a) ->
let {
$dNum :: GHC.Num.Num a
[LclId]
$dNum = GHC.Real.$p1Fractional @ a $dFractional } in
\ (f :: a -> a) (h :: a) (x :: a) ->
GHC.Real./
@ a
$dFractional
(GHC.Num.- @ a $dNum (f (GHC.Num.+ @ a $dNum x h)) (f x))
h
如果您看过去杂乱无章的注释和冗长,您应该能够看到编译器已将所有内容都转换为 lambda 表达式。我们可以认为这表明您可能不需要手动执行此操作。
相反,让我们考虑一下您可能需要 lambda 的情况。这是一个使用折叠来组成函数列表的函数:
composeAll :: [a -> a] -> a -> a
composeAll = foldr (.) id
那是什么?看不到 lambda!事实上,我们也可以走另一条路:
composeAll' :: [a -> a] -> a -> a
composeAll' xs x = foldr (\f g x -> f (g x)) id xs x
这不仅充满了 lambda,它还为 main 函数提供了两个参数,更重要的是,它适用foldr
于所有参数。foldr
将, ,的类型(a -> b -> b) -> b -> [a] -> b
与上述比较;显然它需要三个参数,但上面我们已经将它应用于四个!更不用说累加器函数有两个参数,但我们这里有一个三参数 lambda。当然,诀窍在于两者都返回一个带有单个参数的函数。我们只是在现场应用这个论点,而不是在周围玩弄 lambdas。
希望所有这些都让您相信这两种形式是等价的。Lambda 形式从来都不是必需的,或者可能总是必需的,因为谁能分辨?