gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 14:41:52 26 4
gpt4 key购买 nike

我是 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com