练习部分 lambda 抽象

发布于 2024-10-22 03:28:14 字数 244 浏览 6 评论 0原文

我是 Haskell 编程新手。现在我正在学习 lambda 函数和 lambda 抽象。我想,lambda 函数的实践部分是什么?例如我们有:

map(\x -> x * 2) [1,2,3,4,5]
[2,4,6,8,10]

这个练习部分是什么?我们可以创建普通函数并将其设置在映射函数参数中。只是为了减少代码?那为什么会出现这个抽象呢?代码减少并不是什么大问题。为什么?

谢谢。

I'm new in Haskell programming. Now i'm learn lambda function and lambda abstractions. And i thought, what's the practice part of lambda functions. For example we have:

map(\x -> x * 2) [1,2,3,4,5]
[2,4,6,8,10]

What's of this practice part? We can create normal function and set it in map function argument. Only for code reduction? Then why was coming up this abstraction. Code reduction is not big point. Why?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

呆萌少年 2024-10-29 03:28:14

有两种方法可以解释这个问题。第一个是为什么要写 map (\x -> x * x) 当我们可以写

doubleIt x = x * x
... map doubleIt ...

答案时,你可能会遇到以下情况:

foo y zs = map (\x -> x^y) zs

然后没有完全直接的转换可以让你将匿名函数完全浮动到顶层。

我们可以这样写

foo y zs = map (powerIt y) xs
powerIt y = ?

,然后我们发现 powerIt y = \x -> x^y ! (当然,你可以将 x 浮回到外部定义,但在这种情况下,你实际上想要(尽管语法上 Haskell 不允许你)将 (powerIt y) 写为 (\x -> powerIt yx)

当您拥有一流函数时,它们需要关闭其环境,这意味着您需要一些。 > 引入一个可以引用它所声明的词法作用域中的事物的方法,这就是 lambda 的力量!

现在,另一个问题是为什么不将匿名函数浮动到不是顶部的适当级别,从而得到,例如

foo y zs = let powerIt x = x^z
           in map powerIt zs

,在这种情况下,请再次仔细考虑一下 let 的真正含义。事实上,我们可以通过以下方式将 let 转换为几个 lambda: foo ys zs = (\powerIt -> map powerIt zs) (\ x -> x^y)

现在,在实际实现中,这些脱糖并不完全按照这种方式发生,有时出于效率方面的原因,编译器会以不同的方式处理不同的子句。但核心的东西仍然存在——lambda 非常强大和昂贵,并且可以为我们提供一种简单且易于推理的核心语言,尽管我们在它们之上分层的绑定形式多种多样。

如果没有 lambda,我们就有了一种可以定义变量、定义函数的语言,有时我们还可以用函数做某些事情。有了 lambda,我们就有了一种语言,其中函数是值,就像任何其他值一样,并且我们有一组统一的方法来为任何东西分配名称。

视角的反转是将 lambda 视为一般情况,而不是特殊情况,并将我们所有其他各种名称绑定机制视为它们的糖。

There's two ways to interpret this question. The first is why write map (\x -> x * x) when we can write

doubleIt x = x * x
... map doubleIt ...

The answer there is that you may have the following:

foo y zs = map (\x -> x^y) zs

and then there is no fully straightfoward transformation that allows you to float the anonymous function fully to the top level.

We could write

foo y zs = map (powerIt y) xs
powerIt y = ?

and then we discover that powerIt y = \x -> x^y ! (sure, you could float the x back to the outer definition, but in that case, you'd actually want to (although syntactically Haskell doesn't make you) write (powerIt y) as (\x -> powerIt y x).

When you have first class functions, they need to close over their environment, and that means that you need some way to introduce a function which can refer to things in the lexical scope where it is declared. That's the power of lambdas!

Now, the other question is why not float the anonymous functions to the appropriate level that's not the top and thus get, e.g.

foo y zs = let powerIt x = x^z
           in map powerIt zs

In that case, think carefully about what let really means again. In fact, we can transform the let into a few lambdas in the following way: foo ys zs = (\powerIt -> map powerIt zs) (\x -> x^y)

Now, in real implementations, these desugarings don't all happen exactly this way, and sometimes different clauses get treated differently by compilers for reasons involving efficiency. But the core thing remains -- lambdas are very powerful and expessive, and can give us a core language that is simple and easy to reason about despite the variety of binding forms that we layer on top of them.

Without lambdas we have a language where we can define variables and we can define functions and then we can sometimes do certain things with functions. With lambdas we have a language where functions are values just like any other value, and we have one set of uniform ways to assign names to anything.

The inversion of perspective is to see lambdas not as a special-case, but as the general case, and all our other various name binding mechanisms as sugar for them.

逆光飞翔i 2024-10-29 03:28:14

并非所有函数的使用都足够广泛,以至于“值得”命名。例如,如果您仅使用此函数一次,对于此特定地图,您可能不想为其指定名称,因为您将永远不会再次使用它。

Not all functions are used widely enough to "deserve" a name. For example, if you're only using this function once, for this specific map, you probably don't want to assign it a name because you'll never use it again.

感受沵的脚步 2024-10-29 03:28:14

您经常面临这样的情况:您需要一个非常专业的功能。它仅在软件的这一部分中使用。因此,给它一个具体的名称是没有任何意义的。

you often face the situation, that you need a pretty specialized function. It is used in this part of your software and only there. Therefore it doesn't make any sense, to give it a concrete name.

熟人话多 2024-10-29 03:28:14

可读性;你可以有(牵强,但为了说明这一点)

map (\x -> x * 2) . anotherfunction . anotheragain . itgoesonandon $
[ a lont list ]

vs

map f . anotherfunction . anotheragain . itgoesonandon $
[ a lont list ]
  where f x = x * 2

这是品味问题,但在第一种情况下,你立即知道你正在映射什么函数,在第二种情况下,你必须在源代码中找到 f ,它可能距离几行。

顺便说一句,我会写 map (*2) .... 无论如何

另一个例子是脱糖一元表示法。

例如,

do a <- action1
   b <- action2
   action3
   c <- action4 a b
   action5 c

变成:

action1 >>= \a -> action2 >>= \b -> action3 >> action4 a b >>= \c -> action5 c

vs

action1 >>= a2
  where a2 a = action2 >>= a3
           where a3 b = action3 >> action4 a b >>= a4
                   where a4 c = action5 c

(该代码中可能有错误,但我永远不会这样写)

Readability; you can have ( far fetched, but to illustrate the point )

map (\x -> x * 2) . anotherfunction . anotheragain . itgoesonandon $
[ a lont list ]

vs

map f . anotherfunction . anotheragain . itgoesonandon $
[ a lont list ]
  where f x = x * 2

It's matter of taste but in the first case you know right away what function you are mapping, in the second one you have to locate f in the source code, and it might be a few lines away.

By the way, I would write map (*2) .... anyway

Another example is desugared monadic notation.

For example,

do a <- action1
   b <- action2
   action3
   c <- action4 a b
   action5 c

becomes :

action1 >>= \a -> action2 >>= \b -> action3 >> action4 a b >>= \c -> action5 c

vs

action1 >>= a2
  where a2 a = action2 >>= a3
           where a3 b = action3 >> action4 a b >>= a4
                   where a4 c = action5 c

(there might be an error in that code, but I would never write that anyways )

归属感 2024-10-29 03:28:14

如果我正确理解你的问题,你会问为什么有人会在特定编程语言的范围之外提出 Lambda 函数的抽象,对吗?

那么,编程语言中的 Lambda 函数源自 Lambda 演算,这是一种函数定义的形式系统。正如维基百科所说,Lambda 演算是由 Alonzo Church 在 20 世纪 30 年代作为数学基础研究的一部分引入的。它有广泛的应用,不仅仅是在计算机科学领域。

正如上面的评论者所指出的,函数式编程源于 Lambda 演算。我只能建议你阅读维基百科中的相关条目,那里有一些非常有趣的信息;-)。

If I understand your question correctly you are asking why someone would come up with the abstraction of Lambda functions outside of the scope of a specific programming language, correct?

Well, Lambda functions in programming languages are derived from Lambda calculus, which is a formal system for function definition. As Wikipedia says, Lambda calculus was introduced by Alonzo Church in the 1930s as part of an investigation into the foundations of mathematics. It has a wide range of applications, not just in Computer Science.

As noted by a commenter above, Functional programming has it's roots in Lambda calculus. I can only advise you to read the relevant entries in Wikipedia, there's some very interesting info in there ;-).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文