{"name":"函数式编程","id":"编程语言-编程范式-函数式编程","content":"# 函数式编程（Functional Programming）\n\n> 函数式编程是一种**以数学函数为核心抽象**、以**不可变数据**和**无副作用计算**为基础的编程范式。\n> 它将程序视为表达式之间的组合，而非一系列修改状态的命令。\n\n---\n\n## 一、命令式 vs 函数式：两种思维模型\n\n* **命令式编程（Imperative Programming）**\n  按照“程序是一系列改变状态的命令”来建模。\n  核心是 **“怎么做”** —— 你一步步告诉计算机执行什么操作。\n\n* **函数式编程（Functional Programming）**\n  将程序描述为**表达式的组合**和**数据的变换**。\n  核心是 **“是什么”** —— 定义数据之间的映射关系，而非操作过程。\n\n> 换句话说，命令式编程像是“指挥演员演戏”，\n> 函数式编程更像是“定义剧情规则，让演员自然演绎”。\n\n---\n\n## 二、核心思想：表达式与不可变性\n\n函数式编程鼓励：\n\n* 使用表达式（expression）而非语句（statement）；\n* 数据不可变（immutable data）；\n* 无副作用（pure function）；\n* 函数为“一等公民”（First-class Function）。\n\n它把底层细节（如内存管理、状态更新）交给运行时去优化，\n开发者只需专注于描述**输入与输出的关系**。\n\n这种思维带来的最大好处是：\n\n> 控制权的上移 —— 从控制“怎么执行”，变成控制“怎么定义逻辑”。\n\n---\n\n## 三、函数式编程的三大核心操作\n\n函数式编程往往围绕几种基础操作展开（以 List / Set / Map 为核心数据结构）：\n\n### 1️⃣ filter（过滤）\n\n保留满足条件的元素：\n\n```js\n[1, 2, 3, 4, 5].filter(x => x % 2 === 0)\n// → [2, 4]\n```\n\n### 2️⃣ map（映射）\n\n将集合中的每个元素“映射”为新的值：\n\n```js\n[1, 2, 3].map(x => x * 2)\n// → [2, 4, 6]\n```\n\n### 3️⃣ reduce / fold（规约 / 折叠）\n\n通过累加器把集合折叠为单个值：\n\n```js\n[1, 2, 3, 4].reduce((acc, x) => acc + x, 0)\n// → 10\n```\n\n> filter / map / reduce 是函数式世界的“for 循环 + if + sum”三件套，\n> 用声明式的方式表达数据转换。\n\n---\n\n## 四、函数式语言的权责转移\n\n在函数式语言中，许多“命令式责任”被转移到语言运行时：\n\n1. **底层迭代 → 高阶函数**\n\n   * 用 `map`、`filter`、`reduce` 替代显式 for 循环。\n\n2. **状态管理 → 闭包与不可变变量**\n\n   * 不再维护共享变量，而是通过闭包捕获作用域。\n\n3. **参数控制 → 柯里化（Currying）**\n\n   * `process(x, y, z)` 变为 `process(x)(y)(z)`。\n     每次调用返回一个新函数，就像“逐层工厂”。\n\n4. **灵活复用 → 部分施用（Partial Application）**\n\n   * 给函数固定一部分参数，得到一个“定制版函数”：\n     `sum = add(5)` → `sum(3) = 8`。\n\n---\n\n## 五、从迭代到递归：让逻辑自洽\n\n函数式编程不鼓励显式循环，而使用递归表达重复。\n\n### 传统迭代：\n\n```js\nlet sum = 0;\nfor (let i = 1; i <= 3; i++) sum += i;\n```\n\n### 函数式递归：\n\n```js\nfunction sum(n) {\n  return n === 0 ? 0 : n + sum(n - 1);\n}\n```\n\n### 尾递归优化（Tail Recursion）\n\n尾递归允许编译器复用调用栈，避免堆栈溢出：\n\n```js\nfunction story() {\n  // 尾递归：下一次调用不依赖当前栈\n  return story(); \n}\n```\n\n与非尾递归的区别在于：\n\n> 尾递归调用后没有额外逻辑 → 可直接返回结果。\n\n---\n\n## 六、函数式语言常见特性\n\n### 1️⃣ 记忆（Memoization）\n\n缓存函数结果以避免重复计算。\n仅适用于**纯函数（Pure Function）**——即同输入、同输出、无副作用。\n\n```js\nfunction memoize(fn) {\n  const cache = {};\n  return (...args) => {\n    const key = JSON.stringify(args);\n    return cache[key] ?? (cache[key] = fn(...args));\n  };\n}\n```\n\n函数式语言通常能天然支持记忆化，如：\n\n```lisp\n(memoize (hash \"homer\"))\n```\n\n> 纯函数 + 不可变性 = 缓存安全。\n\n---\n\n### 2️⃣ 惰性求值（Lazy Evaluation）\n\n表达式不会立即求值，而是**在需要时才计算**。\n优点是节省资源、支持无限数据结构。\n\n在 Java 中，可用 `Stream` 实现：\n\n```java\nStream.of(1, 2, 3)\n      .filter(x -> x > 1)\n      .map(x -> x * 2);\n```\n\n直到 `.collect()` 执行前，上述操作都不会真正运行。\n\n---\n\n## 七、函数式的重用机制\n\n在 OOP 中，**复用的单元是类或对象**。\n在 FP 中，**复用的单元是函数**。\n\n由于函数式语言的核心数据结构少（多为 List / Map），\n重用往往通过“函数组合”完成。\n\n例如：\n\n```js\nconst pipeline = compose(\n  filter(isValid),\n  map(parse),\n  reduce(sum)\n);\n```\n\n> 这种组合模式比继承更轻量、更安全。\n\n---\n\n## 八、设计模式在函数式世界的变形\n\n在函数式语言中，许多 OOP 设计模式变得不再必要，\n因为语言特性本身已经提供了解决方案。\n\n| 面向对象模式                | 在函数式中的替代                    |\n| --------------------- | --------------------------- |\n| 模板方法（Template Method） | 高阶函数（Higher-order Function） |\n| 工厂方法（Factory）         | 部分施用 / 柯里化                  |\n| 策略模式（Strategy）        | 函数作为参数传入                    |\n| 观察者模式（Observer）       | 响应式流（Reactive Stream）       |\n\n示例：\n\n```groovy\nclass CustomerBlocks {\n  def checkCredit, checkInventory, ship\n  def process() {\n    checkCredit()\n    checkInventory()\n    ship()\n  }\n}\n```\n\n在函数式中，这等价于：\n\n```js\nconst process = compose(checkCredit, checkInventory, ship);\n```\n\n> OOP 通过“封装不确定因素”让代码易懂，\n> FP 则通过“消除不确定因素”让代码易懂。\n\n---\n\n## 九、从函数式编程到函数式基础设施\n\n函数式编程的哲学已渗透到现代架构中：\n\n| 领域                            | 函数式思想体现      |\n| ----------------------------- | ------------ |\n| **不可变值（Immutable Value）**     | 函数式的基础假设     |\n| **CQRS / Event Sourcing**     | 状态不可变、通过事件推导 |\n| **函数式 Web 编程（WebFlux, Akka）** | 无共享状态的并发     |\n| **日志数据库（如 Kafka）**            | 事件流即系统真相     |\n| **Serverless 架构**             | 函数即服务（FaaS）  |\n\n> 从“函数式编程”到“函数式基础设施”，\n> 是软件工程抽象层次的一次跃迁。\n\n---\n\n## 🔚 十、总结\n\n| 关键特性                            | 说明               |\n| ------------------------------- | ---------------- |\n| **纯函数（Pure Function）**          | 相同输入 → 相同输出，无副作用 |\n| **不可变性（Immutability）**          | 数据不可修改，只能创建新版本   |\n| **高阶函数（Higher-order Function）** | 函数可作为参数或返回值      |\n| **组合（Composition）**             | 函数间可像积木一样拼接      |\n| **惰性与记忆（Lazy + Memoization）**   | 高性能与确定性          |\n\n> 函数式编程不只是“另一种写法”，\n> 而是一种**从状态到变换**、从**控制到描述**的思想转变。\n> 它让我们更接近“数学意义上的确定性程序”。\n\n### **十一、Haskell：函数式编程的纯正实现**\n\n> 如果说函数式编程是一种思想，那么 Haskell 就是这思想的实验场与结晶。\n> 它不是“支持函数式”的语言，而是“由函数式原则构建”的语言。\n\n#### 1️⃣ Haskell 的设计哲学\n\n* **纯度（Purity）**：\n  所有函数都是纯函数，不能产生副作用。\n  与外部交互（如 I/O）必须通过 **Monad** 显式表示。\n* **不可变性（Immutability）**：\n  所有值都是常量，无法修改。\n  这让并发与推理变得安全。\n* **惰性求值（Lazy Evaluation）**：\n  表达式不会立即计算，而是在需要时求值。\n  支持无限序列与高性能管道。\n* **强类型与类型推导（Strong & Inferred Typing）**：\n  类型是函数式世界的“契约”，编译器可自动推导，保证安全。\n* **函数即一等公民（First-Class Function）**：\n  函数可以被当作参数、返回值、变量或数据结构成员。\n\n> 这些设计，使 Haskell 成为“数学函数语义”最纯粹的语言。\n\n---\n\n#### 2️⃣ 函数式核心概念在 Haskell 中的体现\n\n| 函数式概念    | Haskell 实现 | 示例                                   |\n| -------- | ---------- | ------------------------------------ |\n| **纯函数**  | 所有函数都是纯的   | `add x y = x + y`                    |\n| **不可变性** | 无变量可变赋值    | `let name = \"cxk\"`                   |\n| **高阶函数** | 函数可作为参数    | `map (*2) [1..5]`                    |\n| **函数组合** | `(.)` 操作符  | `(f . g) x = f (g x)`                |\n| **柯里化**  | 所有函数天然柯里化  | `add x y` 等价于 `(add x) y`            |\n| **模式匹配** | 基于值结构的函数分支 | `myNot True = False; myNot _ = True` |\n| **惰性求值** | 延迟执行直到需要   | `take 10 [1..]` 返回前10个自然数            |\n| **类型安全** | 强静态类型系统    | `:type (1, \"cxk\") → (Int, String)`   |\n\n> 换句话说，**Haskell 把函数式编程的“理想”变成了语言约束。**\n\n---\n\n#### 3️⃣ 从命令式到函数式的对比：Haskell 的表达优势\n\n| 命令式思维      | 函数式思维（Haskell）        |\n| ---------- | --------------------- |\n| 使用循环 `for` | 使用递归或高阶函数             |\n| 依赖变量更新     | 使用不可变数据流              |\n| 注重过程（怎么做）  | 注重表达（是什么）             |\n| 错误在运行期发现   | 错误在类型检查期发现            |\n| 有副作用       | 副作用必须显式管理（如 IO Monad） |\n\n---\n\n#### 4️⃣ Haskell 示例：从理念到实践\n\n**例 1：纯函数与类型声明**\n\n```haskell\nadd :: Int -> Int -> Int\nadd x y = x + y\n```\n\n> 函数类型即契约：输入两个整数 → 输出一个整数\n> 无副作用、可替换、可测试。\n\n---\n\n**例 2：高阶函数与映射**\n\n```haskell\nmap (*2) [1..5]\n-- [2,4,6,8,10]\n```\n\n> `map` 体现了“以函数为参数”的思想，\n> 消除了显式循环与状态。\n\n---\n\n**例 3：惰性求值与无限列表**\n\n```haskell\ntake 5 [1..]\n-- [1,2,3,4,5]\n```\n\n> `[1..]` 是无限列表，但不会立即生成，\n> `take 5` 才触发部分计算。\n\n---\n\n**例 4：模式匹配与递归**\n\n```haskell\nfactorial 0 = 1\nfactorial n = n * factorial (n - 1)\n```\n\n> 递归表达“定义本身”，而不是命令式的循环。\n\n---\n\n**例 5：代数数据类型与类型安全**\n\n```haskell\ndata Color = Red | Blue | Yellow\nmix Red Blue = \"Purple\"\n```\n\n> 通过类型系统捕获语义错误，\n> 每种可能性都被编译器穷尽检查（Exhaustive Checking）。\n\n---\n\n#### 5️⃣ 哲学总结：Haskell 的函数式纯度之路\n\nHaskell 的核心价值不只是“函数式语法”，\n而是通过语言机制强制开发者：\n\n* 思考 **函数之间的关系**，而非过程；\n* 明确 **副作用的边界**；\n* 借助 **类型系统确保确定性**；\n* 让代码更接近 **数学表达式的可推理性**。\n\n> 在这个意义上，Haskell 就像是“函数式编程的实验物理实验室”：\n> 它让抽象思想以语言形式被验证、约束、实践。\n\n## 关联内容（自动生成）\n\n- [/编程语言/JavaScript/React.md](/编程语言/JavaScript/React.md) React 的设计理念深受函数式编程影响，特别是不可变数据和纯函数的概念在 Hooks 和组件设计中得到了广泛应用\n- [/编程语言/JAVA/高级/Stream流.md](/编程语言/JAVA/高级/Stream流.md) 函数式编程是 Java Stream 的理论基础，Stream 体现了函数式编程的核心思想，如不可变性、高阶函数、闭包等概念，体现了不同的计算模型和控制流方式\n- [/编程语言/JAVA/高级/Lambda表达式.md](/编程语言/JAVA/高级/Lambda表达式.md) 函数式编程是 Lambda 表达式的理论基础，Lambda 体现了函数式编程的核心思想，如高阶函数、不可变性、无副作用计算等\n- [/编程语言/编程范式/响应式编程.md](/编程语言/编程范式/响应式编程.md) 响应式编程的操作符与函数式编程的 map、filter、reduce 类似，都强调数据变换和函数组合\n- [/编程语言/编程语言.md](/编程语言/编程语言.md) 探讨了函数式编程作为重要抽象机制的核心思想，包括不可变性、高阶函数、闭包等概念，体现了不同的计算模型和控制流方式\n- [/编程语言/编程范式/编程范式.md](/编程语言/编程范式/编程范式.md) 详细探讨了函数式编程的概念、特点和应用，与本文中提到的函数式编程范式相呼应\n- [/编程语言/python.md](/编程语言/python.md) Python支持函数式编程范式，该文档详细介绍了函数式编程的核心概念，与Python的函数式编程能力密切相关\n- [/软件工程/设计模式/行为模式.md](/软件工程/设计模式/行为模式.md) 函数式编程中的高阶函数、函数作为参数等概念与行为模式中的策略模式、模板方法模式等有对应关系\n- [/编程语言/并发模型.md](/编程语言/并发模型.md) 函数式编程的不可变性与无副作用特性有助于解决并发编程中的状态同步问题\n- [/软件工程/架构/数据系统.md](/软件工程/架构/数据系统.md) 从函数式编程到数据系统架构，Stream 体现了声明式数据处理在系统架构中的重要性\n","metadata":"tags: ['编程语言']","hasMoreCommit":false,"totalCommits":10,"commitList":[{"date":"2026-02-12T14:07:03+08:00","author":"MY","message":"doc: 整理标签","hash":"290b3e8ad18f48832ac282290238d020fc030a88"},{"date":"2026-02-10T14:42:15+08:00","author":"MY","message":"docs(函数式编程): 添加标签和关联内容链接","hash":"451b870dfb787c2a7a1bfc4c8092fb42db6d7a45"},{"date":"2025-11-07T17:42:13+08:00","author":"MY","message":"docs(programming-paradigm): 添加 Haskell 函数式编程详解","hash":"975a7e34925aabf42647a04906b2dda78f14b4f3"},{"date":"2025-10-23T11:39:49+08:00","author":"MY","message":"docs(fp): 重构函数式编程文档内容与结构","hash":"8593355dc2d82450eaf5f89dddc9814b1ff53656"},{"date":"2021-08-05T21:37:17+08:00","author":"MY","message":"📦整理 编程范式","hash":"5797e4e654e615ab9b65412c48ac2132b116e651"},{"date":"2021-05-14T16:44:44+08:00","author":"cjiping","message":"✏更新 函数式编程","hash":"fa202ca250d6cab39026176f7f3b5265e3d81306"},{"date":"2021-05-13T16:06:46+08:00","author":"cjiping","message":"✏更新 函数式编程","hash":"61302a75ec31c35ae850e3305c50390f4b6fbd28"},{"date":"2021-05-12T15:06:41+08:00","author":"cjiping","message":"✏更新 函数式编程","hash":"ce8247bff530cd83c0b830828c6a3cbd463bf834"},{"date":"2021-05-11T10:52:34+08:00","author":"cjiping","message":"✏更新 函数式编程","hash":"7ca7bdf505b894501d261e4476a706d0610f26ab"},{"date":"2021-05-10T15:33:52+08:00","author":"cjiping","message":"➕增加 函数式编程","hash":"11e6821f84840879956426357255adf184c77ee8"}],"createTime":"2021-05-10T15:33:52+08:00"}