函数式编程的核心概念是什么?

时间:2021-11-14 20:03:04

In object-oriented programming, we might say the core concepts are:

在面向对象的编程中,我们可以说核心概念是:

  1. encapsulation
  2. inheritance,
  3. polymorphism

What would that be in functional programming?

函数式编程会是什么?

5 个解决方案

#1


There's no community consensus on what are the essential concepts in functional programming. In Why Functional Programming Matters (PDF), John Hughes argues that they are higher-order functions and lazy evaluation. In Wearing the Hair Shirt: A Retrospective on Haskell, Simon Peyton Jones says the real essential is not laziness but purity. Richard Bird would agree. But there's a whole crowd of Scheme and ML programmers who are perfectly happy to write programs with side effects.

关于函数式编程中的基本概念,没有社区共识。在为什么函数式编程很重要(PDF)中,John Hughes认为它们是高阶函数和惰性求值。在佩戴头发衬衫:对Haskell的回顾中,西蒙佩顿琼斯说真正重要的不是懒惰而是纯洁。理查德伯德会同意。但是有一大群Scheme和ML程序员非常乐意编写带副作用的程序。

As someone who has practiced and taught functional programming for twenty years, I can give you a few ideas that are widely believed to be at the core of functional programming:

作为一名已经练习和教授函数式编程二十年的人,我可以给你一些被广泛认为是函数式编程核心的想法:

  • Nested, first-class functions with proper lexical scoping are at the core. This means you can create an anonymous function at run time, whose free variables may be parameters or local variables of an enclosing function, and you get a value you can return, put into data structures, and so on. (This is the most important form of higher-order functions, but some higher-order functions (like qsort!) can be written in C, which is not a functional language.)

    具有适当词法范围的嵌套的一流函数是核心。这意味着您可以在运行时创建匿名函数,其*变量可以是封闭函数的参数或局部变量,并且您可以获得可以返回的值,放入数据结构中等等。 (这是高阶函数最重要的形式,但是一些高阶函数(如qsort!)可以用C编写,这不是一种函数式语言。)

  • Means of composing functions with other functions to solve problems. Nobody does this better than John Hughes.

    用其他函数组合函数来解决问题的方法。没有人比约翰休斯更好。

  • Many functional programmers believe purity (freedom from effects, including mutation, I/O, and exceptions) is at the core of functional programming. Many functional programmers do not.

    许多功能程序员认为纯度(不受影响,包括变异,I / O和异常)是函数式编程的核心。许多功能程序员没有。

  • Polymorphism, whether it is enforced by the compiler or not, is a core value of functional programmers. Confusingly, C++ programmers call this concept "generic programming." When polymorphism is enforced by the compiler it is generally a variant of Hindley-Milner, but the more powerful System F is also a powerful basis for functional languages. And with languages like Scheme, Erlang, and Lua, you can do functional programming without a static type system.

    多态性,无论是否由编译器强制执行,都是功能程序员的核心价值。令人困惑的是,C ++程序员将这一概念称为“通用编程”。当编译器强制执行多态时,它通常是Hindley-Milner的变体,但功能更强大的System F也是函数式语言的强大基础。使用Scheme,Erlang和Lua等语言,您可以在没有静态类型系统的情况下进行函数式编程。

  • Finally, a large majority of functional programmers believe in the value of inductively defined data types, sometimes called "recursive types". In languages with static type systems these are generally known as "algebraic data types", but you will find inductively defined data types even in material written for beginning Scheme programmers. Inductively defined types usually ship with a language feature called pattern matching, which supports a very general form of case analysis. Often the compiler can tell you if you have forgotten a case. I wouldn't want to program without this language feature (a luxury once sampled becomes a necessity).

    最后,绝大多数函数式程序员都相信归纳定义数据类型的价值,有时称为“递归类型”。在具有静态类型系统的语言中,这些通常被称为“代数数据类型”,但是即使在为初始Scheme程序员编写的材料中,您也会发现归纳定义的数据类型。归纳定义类型通常附带称为模式匹配的语言特征,它支持非常一般的案例分析形式。编译器通常会告诉您是否忘记了案例。如果没有这种语言功能,我不想编程(一旦采样成为必需品)。

#2


In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state. Functional programming has its roots in the lambda calculus, a formal system developed in the 1930s to investigate function definition, function application, and recursion. Many functional programming languages can be viewed as embellishments to the lambda calculus. - Wikipedia

在计算机科学中,函数式编程是一种编程范式,它将计算视为数学函数的评估,并避免状态和可变数据。它强调功能的应用,与强调状态变化的命令式编程风格形成对比。函数式编程的根源在于lambda演算,这是一个在20世纪30年代开发的用于研究函数定义,函数应用和递归的正式系统。许多函数式编程语言可以被视为lambda演算的装饰。 - *

In a nutshell,

简而言之,

  1. Lambda Calculus
  2. Higher Order Functions
  3. 高阶函数

  4. Immutability
  5. No side-effects

#3


Not directly an answer to your question, but I'd like to point out that "object-oriented" and functional programming aren't necessarily at odds. The "core concepts" you cite have more general counterparts which apply just as well to functional programming.

不是直接回答你的问题,但我想指出“面向对象”和函数式编程并不一定是不一致的。你引用的“核心概念”有更多的通用对应物,它们同样适用于函数式编程。

Encapsulation, more generally, is modularisation. All purely functional languages that I know of support modular programming. You might say that those languages implement encapsulation better than the typical "OO" variety, since side-effects break encapsulation, and pure functions have no side-effects.

更一般地,封装是模块化的。我所知道的所有纯功能语言都支持模块化编程。您可能会说这些语言比典型的“OO”类型更好地实现封装,因为副作用打破了封装,纯函数没有副作用。

Inheritance, more generally, is logical implication, which is what a function represents. The canonical subclass -> superclass relation is a kind of implicit function. In functional languages, this is expressed with type classes or implicits (I consider implicits to be the more general of these two).

更一般地说,继承是逻辑含义,这是函数所代表的含义。规范子类 - >超类关系是一种隐式函数。在函数式语言中,这用类型类或含义表示(我认为暗示是这两者中更普遍的)。

Polymorphism in the "OO" school is achieved by means of subtyping (inheritance). There is a more general kind of polymorphism known as parametric polymorphism (a.k.a. generics), which you will find to be supported by pure-functional programming languages. Additionally, some support "higher kinds", or higher-order generics (a.k.a. type constructor polymorphism).

“OO”学校的多态性是通过子类型(继承)实现的。有一种更普遍的多态性,称为参数多态性(a.k.a.generics),您会发现纯函数式编程语言支持这种多态性。另外,一些支持“更高种类”或更高阶的泛型(a.k.a.类型构造函数多态)。

What I'm trying to say is that your "core concepts of OO" aren't specific to OO in any way. I, for one, would argue that there aren't any core concepts of OO, in fact.

我想说的是,你的“OO的核心概念”并不以任何方式特定于OO。举个例子,我认为事实上并没有OO的任何核心概念。

#4


Let me repeat the answer I gave at one discussion in the Bangalore Functional Programming group:

让我重复我在班加罗尔功能编程小组的一次讨论中给出的答案:

A functional program consists only of functions. Functions compute values from their inputs. We can contrast this with imperative programming, where as the program executes, values of mutable locations change. In other words, in C or Java, a variable called X refers to a location whose value change. But in functional programming X is the name of a value (not a location). Any where that X is in scope, it has the same value (i.e, it is referentially transparent). In FP, functions are also values. They can be passed as arguments to other functions. This is known as higher-order functional programming. Higher-order functions let us model an amazing variety of patterns. For instance, look at the map function in Lisp. It represents a pattern where the programmer needs to do 'something' to every element of a list. That 'something' is encoded as a function and passed as an argument to map.

功能程序仅包含功能。函数根据输入计算值。我们可以将这与命令式编程进行对比,在程序执行时,可变位置的值会发生变化。换句话说,在C或Java中,名为X的变量指的是其值发生变化的位置。但在函数式编程中,X是值的名称(不是位置)。 X在范围内的任何地方,它具有相同的值(即,它是引用透明的)。在FP中,函数也是值。它们可以作为参数传递给其他函数。这被称为高阶函数编程。高阶函数让我们可以模拟各种各样的模式。例如,查看Lisp中的map函数。它代表了程序员需要对列表的每个元素做“某事”的模式。那个'某事'被编码为一个函数,并作为参数传递给map。

As we saw, the most notable feature of FP is it's side-effect freeness. If a function does something more than computing a value from it's input, then it is causing a side-effect. Such functions are not allowed in pure FP. It is easy to test side-effect free functions. There is no global state to set-up before running the test and there is no global state to check after running the test. Each function can be tested independently just by providing it's input and examining the return value. This makes it easy to write automated tests. Another advantage of side-effect freeness is that it gives you better control on parallelism.

正如我们所看到的,FP最显着的特征是它的副作用*度。如果一个函数做的不仅仅是从它的输入计算一个值,那么它会产生副作用。纯FP中不允许使用此类功能。很容易测试无副作用的功能。在运行测试之前没有设置全局状态,并且在运行测试后没有要检查的全局状态。只需提供输入并检查返回值,即可独立测试每个功能。这样可以轻松编写自动化测试。副作用*度的另一个优点是它可以更好地控制并行性。

Many FP languages treat recursion and iteration correctly. They does this by supporting something called tail-recursion. What tail-recursion is - if a function calls itself, and it is the last thing it does, it removes the current stack frame right away. In other words, if a function calls itself tail-recursively a 1000 times, it does not grow the stack a 1000 deep. This makes special looping constructs unnecessary in these languages.

许多FP语言正确地处理递归和迭代。他们通过支持称为尾递归的东西来做到这一点。什么是尾递归 - 如果一个函数调用自身,并且它是它做的最后一件事,它会立即删除当前的堆栈帧。换句话说,如果一个函数尾递归地调用自己1000次,它不会使堆栈增长1000深。这使得在这些语言中不需要特殊的循环结构。

Lambda Calculus is the most boiled down version of an FP language. Higher level FP languages like Haskell get compiled to Lambda Calculus. It has only three syntactic constructs but still it is expressive enough to represent any abstraction or algorithm.

Lambda Calculus是FP语言中最简化的版本。像Haskell这样的高级FP语言被编译为Lambda Calculus。它只有三个句法结构,但它仍然足以表达任何抽象或算法。

My opinion is that FP should be viewed as a meta-paradigm. We can write programs in any style, including OOP, using the simple functional abstractions provided by the Lambda Calculus.

我认为FP应该被视为一种元范式。我们可以使用Lambda Calculus提供的简单功能抽象,以任何风格编写程序,包括OOP。

Thanks, -- Vijay

谢谢, - 维杰

Original discussion link: http://groups.google.co.in/group/bangalore-fp/browse_thread/thread/4c2cfa7985d7eab3

原始讨论链接:http://groups.google.co.in/group/bangalore-fp/browse_thread/thread/4c2cfa7985d7eab3

#5


Abstraction, the process of making a function by parameterizing over some part of an expression.

抽象,通过参数化表达式的某些部分来创建函数的过程。

Application, the process of evaluating a function by replacing its parameters with specific values.

应用程序,通过用特定值替换其参数来评估函数的过程。

At some level, that's all there is to it.

在某种程度上,这就是它的全部。

#1


There's no community consensus on what are the essential concepts in functional programming. In Why Functional Programming Matters (PDF), John Hughes argues that they are higher-order functions and lazy evaluation. In Wearing the Hair Shirt: A Retrospective on Haskell, Simon Peyton Jones says the real essential is not laziness but purity. Richard Bird would agree. But there's a whole crowd of Scheme and ML programmers who are perfectly happy to write programs with side effects.

关于函数式编程中的基本概念,没有社区共识。在为什么函数式编程很重要(PDF)中,John Hughes认为它们是高阶函数和惰性求值。在佩戴头发衬衫:对Haskell的回顾中,西蒙佩顿琼斯说真正重要的不是懒惰而是纯洁。理查德伯德会同意。但是有一大群Scheme和ML程序员非常乐意编写带副作用的程序。

As someone who has practiced and taught functional programming for twenty years, I can give you a few ideas that are widely believed to be at the core of functional programming:

作为一名已经练习和教授函数式编程二十年的人,我可以给你一些被广泛认为是函数式编程核心的想法:

  • Nested, first-class functions with proper lexical scoping are at the core. This means you can create an anonymous function at run time, whose free variables may be parameters or local variables of an enclosing function, and you get a value you can return, put into data structures, and so on. (This is the most important form of higher-order functions, but some higher-order functions (like qsort!) can be written in C, which is not a functional language.)

    具有适当词法范围的嵌套的一流函数是核心。这意味着您可以在运行时创建匿名函数,其*变量可以是封闭函数的参数或局部变量,并且您可以获得可以返回的值,放入数据结构中等等。 (这是高阶函数最重要的形式,但是一些高阶函数(如qsort!)可以用C编写,这不是一种函数式语言。)

  • Means of composing functions with other functions to solve problems. Nobody does this better than John Hughes.

    用其他函数组合函数来解决问题的方法。没有人比约翰休斯更好。

  • Many functional programmers believe purity (freedom from effects, including mutation, I/O, and exceptions) is at the core of functional programming. Many functional programmers do not.

    许多功能程序员认为纯度(不受影响,包括变异,I / O和异常)是函数式编程的核心。许多功能程序员没有。

  • Polymorphism, whether it is enforced by the compiler or not, is a core value of functional programmers. Confusingly, C++ programmers call this concept "generic programming." When polymorphism is enforced by the compiler it is generally a variant of Hindley-Milner, but the more powerful System F is also a powerful basis for functional languages. And with languages like Scheme, Erlang, and Lua, you can do functional programming without a static type system.

    多态性,无论是否由编译器强制执行,都是功能程序员的核心价值。令人困惑的是,C ++程序员将这一概念称为“通用编程”。当编译器强制执行多态时,它通常是Hindley-Milner的变体,但功能更强大的System F也是函数式语言的强大基础。使用Scheme,Erlang和Lua等语言,您可以在没有静态类型系统的情况下进行函数式编程。

  • Finally, a large majority of functional programmers believe in the value of inductively defined data types, sometimes called "recursive types". In languages with static type systems these are generally known as "algebraic data types", but you will find inductively defined data types even in material written for beginning Scheme programmers. Inductively defined types usually ship with a language feature called pattern matching, which supports a very general form of case analysis. Often the compiler can tell you if you have forgotten a case. I wouldn't want to program without this language feature (a luxury once sampled becomes a necessity).

    最后,绝大多数函数式程序员都相信归纳定义数据类型的价值,有时称为“递归类型”。在具有静态类型系统的语言中,这些通常被称为“代数数据类型”,但是即使在为初始Scheme程序员编写的材料中,您也会发现归纳定义的数据类型。归纳定义类型通常附带称为模式匹配的语言特征,它支持非常一般的案例分析形式。编译器通常会告诉您是否忘记了案例。如果没有这种语言功能,我不想编程(一旦采样成为必需品)。

#2


In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data. It emphasizes the application of functions, in contrast to the imperative programming style, which emphasizes changes in state. Functional programming has its roots in the lambda calculus, a formal system developed in the 1930s to investigate function definition, function application, and recursion. Many functional programming languages can be viewed as embellishments to the lambda calculus. - Wikipedia

在计算机科学中,函数式编程是一种编程范式,它将计算视为数学函数的评估,并避免状态和可变数据。它强调功能的应用,与强调状态变化的命令式编程风格形成对比。函数式编程的根源在于lambda演算,这是一个在20世纪30年代开发的用于研究函数定义,函数应用和递归的正式系统。许多函数式编程语言可以被视为lambda演算的装饰。 - *

In a nutshell,

简而言之,

  1. Lambda Calculus
  2. Higher Order Functions
  3. 高阶函数

  4. Immutability
  5. No side-effects

#3


Not directly an answer to your question, but I'd like to point out that "object-oriented" and functional programming aren't necessarily at odds. The "core concepts" you cite have more general counterparts which apply just as well to functional programming.

不是直接回答你的问题,但我想指出“面向对象”和函数式编程并不一定是不一致的。你引用的“核心概念”有更多的通用对应物,它们同样适用于函数式编程。

Encapsulation, more generally, is modularisation. All purely functional languages that I know of support modular programming. You might say that those languages implement encapsulation better than the typical "OO" variety, since side-effects break encapsulation, and pure functions have no side-effects.

更一般地,封装是模块化的。我所知道的所有纯功能语言都支持模块化编程。您可能会说这些语言比典型的“OO”类型更好地实现封装,因为副作用打破了封装,纯函数没有副作用。

Inheritance, more generally, is logical implication, which is what a function represents. The canonical subclass -> superclass relation is a kind of implicit function. In functional languages, this is expressed with type classes or implicits (I consider implicits to be the more general of these two).

更一般地说,继承是逻辑含义,这是函数所代表的含义。规范子类 - >超类关系是一种隐式函数。在函数式语言中,这用类型类或含义表示(我认为暗示是这两者中更普遍的)。

Polymorphism in the "OO" school is achieved by means of subtyping (inheritance). There is a more general kind of polymorphism known as parametric polymorphism (a.k.a. generics), which you will find to be supported by pure-functional programming languages. Additionally, some support "higher kinds", or higher-order generics (a.k.a. type constructor polymorphism).

“OO”学校的多态性是通过子类型(继承)实现的。有一种更普遍的多态性,称为参数多态性(a.k.a.generics),您会发现纯函数式编程语言支持这种多态性。另外,一些支持“更高种类”或更高阶的泛型(a.k.a.类型构造函数多态)。

What I'm trying to say is that your "core concepts of OO" aren't specific to OO in any way. I, for one, would argue that there aren't any core concepts of OO, in fact.

我想说的是,你的“OO的核心概念”并不以任何方式特定于OO。举个例子,我认为事实上并没有OO的任何核心概念。

#4


Let me repeat the answer I gave at one discussion in the Bangalore Functional Programming group:

让我重复我在班加罗尔功能编程小组的一次讨论中给出的答案:

A functional program consists only of functions. Functions compute values from their inputs. We can contrast this with imperative programming, where as the program executes, values of mutable locations change. In other words, in C or Java, a variable called X refers to a location whose value change. But in functional programming X is the name of a value (not a location). Any where that X is in scope, it has the same value (i.e, it is referentially transparent). In FP, functions are also values. They can be passed as arguments to other functions. This is known as higher-order functional programming. Higher-order functions let us model an amazing variety of patterns. For instance, look at the map function in Lisp. It represents a pattern where the programmer needs to do 'something' to every element of a list. That 'something' is encoded as a function and passed as an argument to map.

功能程序仅包含功能。函数根据输入计算值。我们可以将这与命令式编程进行对比,在程序执行时,可变位置的值会发生变化。换句话说,在C或Java中,名为X的变量指的是其值发生变化的位置。但在函数式编程中,X是值的名称(不是位置)。 X在范围内的任何地方,它具有相同的值(即,它是引用透明的)。在FP中,函数也是值。它们可以作为参数传递给其他函数。这被称为高阶函数编程。高阶函数让我们可以模拟各种各样的模式。例如,查看Lisp中的map函数。它代表了程序员需要对列表的每个元素做“某事”的模式。那个'某事'被编码为一个函数,并作为参数传递给map。

As we saw, the most notable feature of FP is it's side-effect freeness. If a function does something more than computing a value from it's input, then it is causing a side-effect. Such functions are not allowed in pure FP. It is easy to test side-effect free functions. There is no global state to set-up before running the test and there is no global state to check after running the test. Each function can be tested independently just by providing it's input and examining the return value. This makes it easy to write automated tests. Another advantage of side-effect freeness is that it gives you better control on parallelism.

正如我们所看到的,FP最显着的特征是它的副作用*度。如果一个函数做的不仅仅是从它的输入计算一个值,那么它会产生副作用。纯FP中不允许使用此类功能。很容易测试无副作用的功能。在运行测试之前没有设置全局状态,并且在运行测试后没有要检查的全局状态。只需提供输入并检查返回值,即可独立测试每个功能。这样可以轻松编写自动化测试。副作用*度的另一个优点是它可以更好地控制并行性。

Many FP languages treat recursion and iteration correctly. They does this by supporting something called tail-recursion. What tail-recursion is - if a function calls itself, and it is the last thing it does, it removes the current stack frame right away. In other words, if a function calls itself tail-recursively a 1000 times, it does not grow the stack a 1000 deep. This makes special looping constructs unnecessary in these languages.

许多FP语言正确地处理递归和迭代。他们通过支持称为尾递归的东西来做到这一点。什么是尾递归 - 如果一个函数调用自身,并且它是它做的最后一件事,它会立即删除当前的堆栈帧。换句话说,如果一个函数尾递归地调用自己1000次,它不会使堆栈增长1000深。这使得在这些语言中不需要特殊的循环结构。

Lambda Calculus is the most boiled down version of an FP language. Higher level FP languages like Haskell get compiled to Lambda Calculus. It has only three syntactic constructs but still it is expressive enough to represent any abstraction or algorithm.

Lambda Calculus是FP语言中最简化的版本。像Haskell这样的高级FP语言被编译为Lambda Calculus。它只有三个句法结构,但它仍然足以表达任何抽象或算法。

My opinion is that FP should be viewed as a meta-paradigm. We can write programs in any style, including OOP, using the simple functional abstractions provided by the Lambda Calculus.

我认为FP应该被视为一种元范式。我们可以使用Lambda Calculus提供的简单功能抽象,以任何风格编写程序,包括OOP。

Thanks, -- Vijay

谢谢, - 维杰

Original discussion link: http://groups.google.co.in/group/bangalore-fp/browse_thread/thread/4c2cfa7985d7eab3

原始讨论链接:http://groups.google.co.in/group/bangalore-fp/browse_thread/thread/4c2cfa7985d7eab3

#5


Abstraction, the process of making a function by parameterizing over some part of an expression.

抽象,通过参数化表达式的某些部分来创建函数的过程。

Application, the process of evaluating a function by replacing its parameters with specific values.

应用程序,通过用特定值替换其参数来评估函数的过程。

At some level, that's all there is to it.

在某种程度上,这就是它的全部。