了解功能降低
此功能编程书关于不同函数之间的等效性。例如,如果我的理解是正确的,则意味着:
func(param => otherFunc(param))
func(otherFunc) // simplified
,如果我能以我的能力表达它,我会说:
一个获取一定数量参数的函数,然后仅 返回将这些参数称为参数的第二个函数 与仅将第二个函数作为单个参数的函数相同。
这是正确的理解吗?有什么例子表明这将如何工作?到目前为止,我唯一能想到自己的人是很琐碎的,所以我想看看是否可以看到更多的例子来加深对此应用的理解。
There are a few examples in this functional programing book about equivalency between different functions. For example, if my understanding is correct it means:
func(param => otherFunc(param))
func(otherFunc) // simplified
And, if I can articulate it in words to the best of my ability, I would say:
A function that takes a certain number of parameters and then only
returns a second function called with those parameters as arguments
is the same as a function that just takes the second function as a single parameter.
Is this a correct understanding? What would be some examples that would show how this would work? The only ones I can think of myself so far are quite trivial, so I'd like to see if I can see more examples to deepen my understanding of some applications of this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在Lambda微积分(是许多功能编程概念的基础)中,这称为ETA降低,是系统中为数不多的基本减少操作之一。
η-还原
LC:
λx.fx= f
JavaScript:
(x => f(x))= f
向自己证明这有效是非常微不足道的。 “包装” lambda中的函数明确地提供了下一个参数,该参数无论如何都会应用。
为了简洁起见,假设我们在教堂编码中有一个增量函数公司和LC编号。
LC:
(λx.incx)3 - > Inc 3 - > 4
=inc 3 - > 4
JavaScript:
(X => Inc(X))(3) - > Inc(3) - > 4
=inc(3) - > 4
如果您具有多重题目功能,这会分解一点。由于纯lambda微积分仅具有一元函数,因此减少ETA是如此简单,但是在JS中,我们可以使用窍门来捕获任何数量的参数。
JS“ ETA”等效
((... x)=> f(... x))= f
至于应用程序,您可以使用此事实简化表达式。除此之外,实际上没有理由以这种方式扩展表达式,只是为了表现和可读性而减少它们。
是的,这些都是等效的,这实际上是您发现的核心功能编程原理。
In the lambda calculus, which is the foundation for a lot of functional programming concepts, this is called Eta reduction and is one of the few fundamental reduction operations in the system.
η-Reduction
LC:
λx.f x = f
Javascript:
(x => f(x)) = f
It is quite trivial to prove to yourself that this works. "Wrapping" the function in a lambda just explicitly provides the next argument which is applied anyway.
For the sake of brevity assume we have an increment function INC and LC numbers in the church encoding.
LC:
(λx.INC x) 3 -> INC 3 -> 4
=INC 3 -> 4
Javascript:
(x => INC(x))(3) -> INC(3) -> 4
=INC(3) -> 4
This breaks down a little bit if you have a multi-argument function. Since pure lambda calculus only has unary functions, eta reduction is this simple, but in JS we can use a trick to capture any number of arguments.
JS "Eta" Equvilancy
((...x) => f(...x)) = f
As for applications, you can use this fact to simplify expressions. Other than that there isn't really a reason to expand expressions this way, only reducing them for sake of performance and readability.
Yes, these are equivalent, and this is actually a core functional programming principle that you have discovered.
我将尝试逐步做出最好的解释。
步骤1
您可以用2种不同的语法定义一个函数
,或者
这些2个语法或多或少是等效的,但是第二个语法是您拥有一个名为Inc的常数(如此变量),该函数的指向是指向一段记忆的指针包含一个函数。
因此,
inc
是一个包含(值)功能有效负载的变量。步骤2
,并且我们希望将每个元素递增到可以使用函数映射的新数组中。
地图是一个创建一个新数组的函数,该数组填充了调用调用数组中每个元素的提供的函数的结果。
步骤3
,我们拥有
inc
功能,我们想在map
中使用该功能。我们可以做一个非常简单的事情。
步骤4
暂时暂时尝试使用
inc
函数,我们在步骤3上所做的事情。我们将尝试另一个批准。在步骤1,我们已经看到一个函数定义如下。
平等标志周围的语义非常强大,并且说:
我们可以采用
inc
功能定义和步骤2代码。在两行的右侧,我们都有一个重复的表达式:
第一行说等效的表达式为
inc
。试图采用这种方法的结果是:当您尝试以这种方式读取代码时,您可以想象到Inline
inc
标签具有自己的表达式。奖金
试图将此方法应用于2个参数函数,我们需要另一个用户酶。给定数字数组,我们需要每个数字的总和。
为此,我们将使用标准
RELAD
功能。现在,我们可以提取总和函数并用其标签替换表达式。
I'll try to do my best explanation by step by step examples.
Step 1
In javacript you can define a function with 2 different syntax
or
Those 2 syntax are more or less equivalent but the second one is stays that you have a constant called inc (so a variable) that have a pointer to a piece of memory that contains a function.
So,
inc
is a variable that contains (as value) the function payload.Step 2
Supposing that we have an array and we want to increment each element into a new array we can use the function map.
Map is a function that creates a new array populated with the results of calling a provided function on every element in the calling array.
Mozilla Reference
Step 3
We have have a
inc
function and we want to use that function in ourmap
.We can do a very simple things.
Step 4
Forget for a moment what we have done on step 3, trying using our
inc
function. We will try another approac.At step 1 we have seen that a function is defined as follows.
The semantics around the equal sign is quite powerful and is saying:
We can take our
inc
function definition and the Step 2 code.On the right side of both lines we have a duplicated expression:
And first line says that an equivalent expression is
inc
. Trying to apply this approach the results is:when you are trying to read a code written in this way you can imagine to inline
inc
label with its own expression.Bonus
Trying to apply this approach for 2 parameter function we need another usecase. Given an array of numbers we want the sum of each number.
To achieve that we'll use the standard
reduce
function.Mozilla Reference
now we can extract a sum function and replace the expression with it's label.
这两个
并不完全相同,原因是这些的两个并不完全相同,
确实看到了这个示例:
它们与众不同的原因是
x => f(x)
是一个仅采用1个参数的函数,即使函数f
期望2,因此,当您将f2
用2个参数馈送时,它会添加INGNORES第二个参数,然后仅使用1个参数调用f
,该参数导致第二个参数(f
)为undefined
。显然,您可以将
f2
作为(x,y)=> f(x,y)
,但是如果f
是ternary,则会遇到麻烦。因此,如果您不想阐明包装器函数的所有参数以使其与
f
一致,则必须像这样编写包装器函数,以表达
f2Correct的想法
可以采用任何数量的参数,并且将它们全部转发到f
。实际上,f2Correct
等效于f
。关于您对此的理解,我认为您接近了,但可能会错误地介绍它。
These two
are not exactly the same, the reason being that these two are not exactly the same
Indeed look at this example:
The reason they are not the same is that
x => f(x)
is a function that only takes 1 argument, even though the functionf
expects 2, so when you feedf2
with 2 arguments, it ingnores the second argument, and then callsf
with 1 argument only, which results in the second argument (off
) beingundefined
.Clearly, you could have written
f2
as(x, y) => f(x, y)
, but then you'd be in trouble iff
was ternary.So, if you don't want to spell out all the arguments of the wrapper function to make it agree with
f
, you have to write the wrapper function like thiswhich expresses the idea that
f2correct
can take any number of arguments, and it forwards them all tof
. In fact,f2correct
is equivalent tof
.As regards your understanding of that, I think you got close, but probably misworded it.
当您评估表达式时,可能会“容易”(YMMV)。
让我们从简单的东西开始:
让我们定义
inc
并对其进行评估:因此:
重要位在这里:
(inc)
。该表达式评估该函数并简单地返回它。因此,当您做
(INC)(41)
时,您最终会进行inc(41)
。让我们在右操作数中内联
inc
:现在,让我们添加一个不必要的包装器:
让我们简化一点:
或仅仅:
也有助于知道如何读取内容:
expression
n => Inc(n)
(这是一个函数)被应用于41
。 (此时,n
等于41
。)然后,inc
将其应用于n
。因此,您不妨直接将
inc
直接应用于 41 ,然后跳过第一个表达式,即:It is probably "easier" (YMMV) to see when you evaluate expressions.
Let's start with something simple:
Let's define
inc
and evaluate it:And so:
Important bit is here:
(inc)
.The expression evaluates the function and simply returns it. So when you do
(inc)(41)
you end up doinginc(41)
.Let's inline
inc
in the right operand:Now let's add an unnecessary wrapper:
Let's simplify a little bit:
Or just:
It also helps to know how to read things:
The expression
n => inc(n)
(which is a function) is applied to41
. (At this pointn
is equal to41
.) Theninc
is applied ton
.So you might as well just apply
inc
to41
directly and skip the first expression, i.e.:在JavaScript中,如果您不使用括号,则只需恢复一个函数(指针)即可。
看看之间的区别。
第一个调用执行函数
func
并返回结果并将其保存到a
中。第二个呼叫(无括号)返回AS-IS的函数,并将其绑定到
b
。之后,做一个。只要没有副作用,就应该与
a
相同。现在看一下lambda功能。
在这里,您只需创建一个函数
d
调用func
,然后将其参数传递到func
。你顺便说一句。也可以这样写。
并且可以重新编写此代码。
就像您现在看到的那样。
d
与func
相同。再次可以重新编写此代码。两个功能都是相同的。
这就是为什么您可以在示例中直接传递
其他func
。您只需传递函数,而无需创建另一个新功能。In JavaScript if you don't use parenthesis, you just get back a function (pointer).
Look at the difference between.
The first call executes the function
func
and returns the result and saves it intoa
.The second call (without the parenthesis) returns the function as-is, and just binds it to
b
. After this, doing a.should be the same as
a
, as long there are no side-effects.Now look at the lambda-function.
Here you just create a function
d
that callsfunc
and passes it arguments along tofunc
.You btw. also can write it this way.
and this piece of code can be re-written.
as you now maybe see.
d
is the same asfunc
. And again to the loop, this piece of code can be re-written.Both function are the same.
That's why you can pass
otherFunc
in your example directly. You just pass the function as-is, without the need to create another new function.