F# 柯里化函数
任何人都有一个不错的例子,最好是实用/有用的,他们可以发布演示这个概念?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
任何人都有一个不错的例子,最好是实用/有用的,他们可以发布演示这个概念?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(6)
我给出了一个在 C# 中模拟柯里化的好例子 在我的博客上。 要点是,您可以从现有的多参数函数中创建一个对参数封闭的函数(在我的示例中,创建一个用于计算对给定市镇的值封闭的销售税的函数)。
这里吸引人的是,您不必专门创建一个单独的函数来计算库克县的销售税,您可以在运行时动态创建(和重用)该函数。
I gave a good example of simulating currying in C# on my blog. The gist is that you can create a function that is closed over a parameter (in my example create a function for calculating the sales tax closed over the value of a given municipality)out of an existing multi-parameter function.
What is appealing here is instead of having to make a separate function specifically for calculating sales tax in Cook County, you can create (and reuse) the function dynamically at runtime.
这是一个相当简单的过程。 获取一个函数,绑定其参数之一并返回一个新函数。 例如:
现在通过柯里化简单的 concatStrings 函数,您可以轻松地将 DOS 风格的命令提示符添加到任何字符串的前面! 真的很有用!
好吧,其实不是。 我发现一个更有用的情况是当我想要一个函数以类似流的方式返回数据时。
它的方便之处在于,您不必为此类事情创建整个类、调用构造函数、调用 obj.readDWORD(),而只需拥有一个无法从您手下进行变异的函数。
It's a fairly simple process. Take a function, bind one of its arguments and return a new function. For example:
Now by currying the simple concatStrings function, you can easily add a DOS style command prompt to the front of any string! Really useful!
Okay, not really. A more useful case I find is when I want to have a make a function that returns me data in a stream like manner.
The convenient part about it is that rather than creating an entire class for this sort of thing, calling the constructor, calling obj.readDWORD(), you just have a function that can't be mutated out from under you.
虽然前面的示例回答了这个问题,但这里有两个更简单的示例,说明柯里化如何有利于 F# 编程。
并且不要忘记您可以柯里化 Printf 系列函数! 在柯里化版本中,请注意明显缺少 lambda。
While the previous examples answered the question, here are two simpler examples of how Currying can be beneficial for F# programming.
And don't forget you can curry the Printf family of function! In the curried version, notice the distinct lack of a lambda.
您知道可以将函数映射到列表上吗? 例如,映射一个函数以向列表的每个元素加一:
这实际上已经使用了柯里化,因为
(+)
运算符用于创建一个函数以向其参数加一,但您可以通过更改该示例以映射列表列表的相同函数,可以从该示例中挤出更多内容:如果没有柯里化,您将无法部分应用这些函数,而必须编写如下所示的内容:
You know you can map a function over a list? For example, mapping a function to add one to each element of a list:
This is actually already using currying because the
(+)
operator was used to create a function to add one to its argument but you can squeeze a little more out of this example by altering it to map the same function of a list of lists:Without currying you could not partially apply these functions and would have to write something like this instead:
我的示例将介绍如何使用它来重用和封装代码。 一旦您查看这些内容,就会发现这一点相当明显,并且应该为您提供一个具体、简单的示例,您可以考虑将其应用于多种情况。
我们想要在树上绘制地图。 如果该函数需要多个参数,则可以对该函数进行柯里化并应用于每个节点——因为我们将在节点上应用该参数作为它的最终参数。 它不必进行柯里化,但编写另一个函数(假设该函数在其他实例中与其他变量一起使用)将是一种浪费。
但这与:
所以这个简单的例子并不令人信服。 但它确实如此,一旦你更多地使用该语言并自然地遇到这些情况,它就会变得强大。 另一个示例将一些代码重用为柯里化。 创建素数的递归关系。 那里有很多相似之处:
好吧,现在 rowland 和 cloitre 是柯里化函数,因为它们有自由变量,我们可以获取它的序列的任何索引,而无需知道或担心 f_recurrence。
My examples will cover using it for the reuse and encapsulation of code. This is fairly obvious once you look at these and should give you a concrete, simple example that you can think of applying in numerous situations.
We want to do a map over a tree. This function could be curried and applied to each node if it needs more then one argument -- since we'd be applying the one at the node as it's final argument. It doesn't have to be curried, but writing another function (assuming this function is being used in other instances with other variables) would be a waste.
but this is the same as:
So this simple case isn't convincing. It really is though, and powerful once you use the language more and naturally come across these situations. The other example with some code reuse as currying. A recurrence relation to create prime numbers. Awful lot of similarity in there:
Ok, now rowland and cloitre are curried functions, since they have free variables, and we can get any index of it's sequence without knowing or worrying about f_recurrence.
柯里化描述了将具有多个参数的函数转换为单参数函数链的过程。 C# 中的示例,对于三参数函数:
现在,布尔参数可能不是您最可能希望在部分应用程序中保持打开状态的参数。 这就是为什么 F# 函数中的参数顺序一开始看起来有点奇怪的原因之一。 让我们定义一个不同的 C# curry 函数:
现在,我们可以做一些更有用的事情:
为什么这些示例是 C# 中的? 因为在 F# 中,函数声明默认是柯里化的。 通常不需要柯里化函数; 他们已经被咖喱了。 主要的例外是框架方法和其他重载函数,它们采用包含多个参数的元组。 因此,您可能想要柯里化这样的函数,事实上,当我寻找一个可以执行此操作的库函数时,我遇到了这个问题。 我想它丢失了(如果确实如此),因为实现起来非常简单:
要解决 String.Compare 的失败问题,因为据我所知,没有办法指定要选择哪个 3 参数重载,您可以使用非通用解决方案:
我不会详细介绍 F# 中部分函数应用程序的使用,因为其他答案已经涵盖了这一点。
Currying describes the process of transforming a function with multiple arguments into a chain of single-argument functions. Example in C#, for a three-argument function:
Now, the boolean argument is probably not the argument you'd most likely want to leave open with a partial application. This is one reason why the order of arguments in F# functions can seem a little odd at first. Let's define a different C# curry function:
Now, we can do something a little more useful:
Why are these examples in C#? Because in F#, function declarations are curried by default. You don't usually need to curry functions; they're already curried. The major exception to this is framework methods and other overloaded functions, which take a tuple containing their multiple arguments. You therefore might want to curry such functions, and, in fact, I came upon this question when I was looking for a library function that would do this. I suppose it is missing (if indeed it is) because it's pretty trivial to implement:
To get around the failure with String.Compare, since as far as I can tell there's no way to specify which 3-argument overload to pick, you can use a non-general solution:
I won't go into detail about the uses of partial function application in F# because the other answers have covered that already.