工人组合器的解释

发布于 2024-12-06 05:56:13 字数 1311 浏览 3 评论 0原文

什么是组合器?

它是“没有自由变量的函数或定义”(如SO中所定义)?

或者这样怎么样:根据 John Hughes 在他关于 Arrows 的著名论文中, “组合器是一种从程序片段构建程序片段的函数”,这是有利的,因为“......使用组合器的程序员构建了大部分所需的程序自动地,而不是手工写下每个细节”。他接着说 mapfilter 是此类组合器的两个常见示例。

一些与第一个定义匹配的组合器:

一些与第二个定义匹配的组合器:

  • 映射
  • 过滤器
  • 折叠/减少(大概)
  • 任何>> =,compose,fmap ??????

我对第一个定义不感兴趣——那些不会帮助我编写一个真正的程序(如果你说服我我错了,+1)。 请帮我理解第二个定义。我认为map、filter和reduce很有用:它们让我能够在更高的水平上编程——更少的错误、更短、更清晰的代码。以下是我关于组合器的一些具体问题:

  1. 还有哪些组合器的更多示例,例如映射、过滤器?
  2. 编程语言经常实现哪些组合器?
  3. 组合器如何帮助我设计更好的 API?
  4. 如何设计有效的组合器?
  5. 组合器与非函数式语言(例如 Java)中的组合器有何相似之处,或者这些语言使用什么来代替组合器?

更新

感谢@CA McCann,我现在对组合器有了更好的理解。但有一个问题对我来说仍然是一个症结:

大量使用组合器编写的函数式程序和不使用组合器编写的函数式程序有什么区别?

我怀疑答案是大量使用组合器的版本更短、更清晰、更笼统,但如果可能的话,我希望能进行更深入的讨论。

我还在寻找常见编程语言中复杂组合器(即比 fold 更复杂)的更多示例和解释。

What is a combinator??

Is it "a function or definition with no free variables" (as defined on SO)?

Or how about this: according to John Hughes in his well-known paper on Arrows, "a combinator is a function which builds program fragments from program fragments", which is advantageous because "... the programmer using combinators constructs much of the desired program automatically, rather than writing every detail by hand". He goes on to say that map and filter are two common examples of such combinators.

Some combinators which match the first definition:

Some combinators which match the second definition:

  • map
  • filter
  • fold/reduce (presumably)
  • any of >>=, compose, fmap ?????

I'm not interested in the first definition -- those would not help me to write a real program (+1 if you convince me I'm wrong). Please help me understand the second definition. I think map, filter, and reduce are useful: they allow me to program at a higher level -- fewer mistakes, shorter and clearer code. Here are some of my specific questions about combinators:

  1. What are more examples of combinators such as map, filter?
  2. What combinators do programming languages often implement?
  3. How can combinators help me design a better API?
  4. How do I design effective combinators?
  5. What are combinators similar to in a non-functional language (say, Java), or what do these languages use in place of combinators?

Update

Thanks to @C. A. McCann, I now have a somewhat better understanding of combinators. But one question is still a sticking point for me:

What is the difference between a functional program written with, and one written without, heavy use of combinators?

I suspect the answer is that the combinator-heavy version is shorter, clearer, more general, but I would appreciate a more in-depth discussion, if possible.

I'm also looking for more examples and explanations of complex combinators (i.e. more complex than fold) in common programming languages.

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

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

发布评论

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

评论(1

眼眸里的快感 2024-12-13 05:56:13

我对第一个定义不感兴趣——那些不会帮助我编写一个真正的程序(如果你说服我我错了,+1)。请帮我理解第二个定义。我认为map、filter和reduce很有用:它们让我能够在更高的水平上编程——更少的错误、更短、更清晰的代码。

这两个定义基本上是相同的。第一个基于正式定义,您给出的示例是原始组合器 - 可能的最小构建块。它们可以帮助您编写真正的程序,因为使用它们您可以构建更复杂的组合器。将像 S 和 K 这样的组合器视为假设的“组合计算机”的机器语言。当然,实际的计算机并不是这样工作的,因此在实践中,您通常会以其他方式在幕后实现更高级别的操作,但概念基础仍然是理解含义的有用工具 em> 那些更高级别的操作。

您给出的第二个定义更加非正式,涉及使用更复杂的组合器,以高阶函数的形式以各种方式组合其他函数。请注意,如果基本构建块是上面的原始组合器,那么由它们构建的所有内容都是高阶函数和组合器。然而,在存在其他原语的语言中,您可以区分函数或非函数,在这种情况下,组合器通常被定义为以通用方式操作其他函数的函数,而不是对任何非函数进行操作。直接发挥作用。

还有哪些组合器的示例,例如映射、过滤器?

太多了,无法一一列出!这两者都将描述单个值行为的函数转换为描述整个集合行为的函数。您还可以使用仅转换其他函数的函数,例如端到端组合它们,或者拆分和重新组合参数。您可以使用组合器将单步操作转换为生成或使用集合的递归操作。或者其他各种事情,真的。

编程语言通常实现哪些组合器?

这将会有很大的不同。完全通用的组合器相对较少——主要是上面提到的原始组合器——所以在大多数情况下,组合器会对正在使用的任何数据结构有一定的了解(即使这些数据结构无论如何都是由其他组合器构建的),其中在这种情况下,通常有一些“完全通用”的组合器,然后有人决定提供任何各种专门的形式。在许多荒谬的情况下,地图、折叠和展开(适当的通用版本)足以完成您可能想要的几乎所有操作。

组合器如何帮助我设计更好的 API?

正如您所说,通过考虑高级操作以及它们交互的方式,而不是低级细节。

想一想“foreach”式循环在集合上的流行程度,它可以让您抽象出枚举集合的细节。在大多数情况下,这些只是映射/折叠操作,通过将其作为组合器(而不是内置语法),您可以执行一些操作,例如采用两个现有循环并以多种方式直接组合它们 - 将一个嵌套在另一个中,一个接一个地执行,依此类推——只需应用组合器,而不是处理一大堆代码。

如何设计有效的组合器?

首先,考虑哪些操作对程序使用的任何数据有意义。然后考虑如何以通用方式有意义地组合这些操作,以及如何将操作分解为更小的部分并重新连接在一起。主要是使用转换操作,而不是直接操作。当您的函数只是以不透明的方式执行一些复杂的功能并且仅输出某种预先消化的结果时,您对此无能为力。将最终结果留给使用组合器的代码——您想要的是从 A 点到 B 点的东西,而不是期望成为过程的开始或结束的东西。

组合器与非函数式语言(例如 Java)中的组合器有何相似之处,或者这些语言使用什么来代替组合器?

啊哈哈哈哈。有趣的是,你应该问,因为对象首先确实是高阶的东西——它们有一些数据,但它们也携带一堆操作,并且很多构成良好 OOP 设计的内容都可以归结为“对象应该通常表现得像组合器,而不是数据结构”。

因此,这里最好的答案可能是,他们使用具有大量 getter 和 setter 方法或公共字段的类,以及主要由执行一些不透明的预定义操作组成的逻辑,而不是类似组合器的东西。

I'm not interested in the first definition -- those would not help me to write a real program (+1 if you convince me I'm wrong). Please help me understand the second definition. I think map, filter, and reduce are useful: they allow me to program at a higher level -- fewer mistakes, shorter and clearer code.

The two definitions are basically the same thing. The first is based on the formal definition and the examples you give are primitive combinators--the smallest building blocks possible. They can help you to write a real program insofar as, with them, you can build more sophisticated combinators. Think of combinators like S and K as the machine language of a hypothetical "combinatory computer". Actual computers don't work that way, of course, so in practice you'll usually have higher-level operations implemented behind the scenes in other ways, but the conceptual foundation is still a useful tool for understanding the meaning of those higher-level operations.

The second definition you give is more informal and about using more sophisticated combinators, in the form of higher-order functions that combine other functions in various ways. Note that if the basic building blocks are the primitive combinators above, everything built from them is a higher-order function and a combinator as well. In a language where other primitives exist, however, you have a distinction between things that are or are not functions, in which case a combinator is typically defined as a function that manipulates other functions in a general way, rather than operating on any non-function things directly.

What are more examples of combinators such as map, filter?

Far too many to list! Both of those transform a function that describes behavior on a single value into a function that describes behavior on an entire collection. You can also have functions that transform only other functions, such as composing them end-to-end, or splitting and recombining arguments. You can have combinators that turn single-step operations into recursive operations that produce or consume collections. Or all kinds of other things, really.

What combinators do programming languages often implement?

That's going to vary quite a bit. There're relatively few completely generic combinators--mostly the primitive ones mentioned above--so in most cases combinators will have some awareness of any data structures being used (even if those data structures are built out of other combinators anyway), in which case there are typically a handful of "fully generic" combinators and then whatever various specialized forms someone decided to provide. There are a ridiculous number of cases where (suitably generalized versions of) map, fold, and unfold are enough to do almost everything you might want.

How can combinators help me design a better API?

Exactly as you said, by thinking in terms of high-level operations, and the way those interact, instead of low-level details.

Think about the popularity of "for each"-style loops over collections, which let you abstract over the details of enumerating a collection. These are just map/fold operations in most cases, and by making that a combinator (rather than built-in syntax) you can do things such as take two existing loops and directly combine them in multiple ways--nest one inside the other, do one after the other, and so on--by just applying a combinator, rather than juggling a whole bunch of code around.

How do I design effective combinators?

First, think about what operations make sense on whatever data your program uses. Then think about how those operations can be meaningfully combined in generic ways, as well as how operations can be broken down into smaller pieces that are connected back together. The main thing is to work with transformations and operations, not direct actions. When you have a function that just does some complicated bit of functionality in an opaque way and only spits out some sort of pre-digested result, there's not much you can do with that. Leave the final results to the code that uses the combinators--you want things that take you from point A to point B, not things that expect to be the beginning or end of a process.

What are combinators similar to in a non-functional language (say, Java), or what do these languages use in place of combinators?

Ahahahaha. Funny you should ask, because objects are really higher-order thingies in the first place--they have some data, but they also carry around a bunch of operations, and quite a lot of what constitutes good OOP design boils down to "objects should usually act like combinators, not data structures".

So probably the best answer here is that instead of combinator-like things, they use classes with lots of getter and setter methods or public fields, and logic that mostly consists of doing some opaque, predefined action.

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