haskell - Haskell 中何时需要 lambda 形式?

标签 haskell scheme closures higher-order-functions

我是 Haskell 的新手,也是函数式编程的新手。 在其他(除了 Haskell)语言中,lambda 形式通常非常有用。

例如,在方案中:

(define (deriv-approx f)
  (lambda (h x)
    (/ (- (f (+ x h)
          (f x)
       h)))

将创建一个闭包(在函数 f 上)来近似导数(在值 x 处,间隔为 h)。 然而,由于 lambda 形式的部分应用,这种用法在 Haskell 中似乎没有必要:

deriv-approx f h x = ( (f (x + h)) - (f x) ) / h

Haskell 中需要 lambda 形式的示例有哪些?

编辑:将“闭包”替换为“lambda 形式”

最佳答案

我将给出两个稍微间接的答案。

首先,考虑以下代码:

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,它还向主函数传递两个参数,更重要的是,将 foldr 应用于所有这些参数。将 foldr 的类型 (a -> b -> b) -> b -> [a] -> b 与上面的进行比较;显然它需要三个参数,但上面我们已将其应用到四个!更不用说累加器函数需要两个参数,但我们这里有一个三参数 lambda。当然,诀窍在于两者都返回一个带有单个参数的函数;我们只是当场应用该参数,而不是摆弄 lambda。

所有这些,希望能让您相信这两种形式是等效的。 Lambda 形式从来都不是必需的,或者也许总是必需的,因为谁能区分其中的区别?

关于haskell - Haskell 中何时需要 lambda 形式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7114533/

相关文章:

javascript - 使用闭包模拟私有(private)方法与对象中的公共(public)方法

javascript - 如何将此 javascript 代码重写为 C++11?

haskell - Haskell 中的递归排列

haskell - 对列表列表的操作 |如何

haskell - "module [...] is defined in multiple files"Haskell 编译错误

scheme - 在Scheme中严格声明变量

list - 你如何在 Haskell 中编写函数 'pairs'?

loops - Racket 中的 While 循环

scheme - 方案/内存中的数组

swift - 设置函数范围变量以避免使用捕获列表