|
@@ -3,32 +3,32 @@
|
|
|
|
|
|
### 函数式编程笔记
|
|
|
|
|
|
-- 函数式编程主要解决两个问题
|
|
|
+- 函数式编程主要解决的问题(通过历史预测未来)
|
|
|
|
|
|
- - 分布式计算颗粒度
|
|
|
- 代码复杂度
|
|
|
+ - 线程管理
|
|
|
+ - 迭代
|
|
|
+ - 分布式计算颗粒度
|
|
|
|
|
|
- 编程语言是工具(简化程序复杂度)
|
|
|
|
|
|
- - 软件开发的工具
|
|
|
- - 团队协作软件开发的工具
|
|
|
- - 使用工具到顶了,功能复杂度hold人脑不住了,就要换工具(人脑几十年的时间不会有什么进化)
|
|
|
- - 结构化编程 -> 面向对象 -> 函数式编程;可以看到这个路线就是对“状态”的限制使用之路
|
|
|
-
|
|
|
+ - 软件开发的工具,团队协作软件开发的工具
|
|
|
+ - 使用工具到顶了,功能复杂度hold人脑不住了,就要换新工具(人脑几十年的时间不会有什么进化)
|
|
|
+ - 应用软件开发:结构化编程 -> 面向对象 -> 函数式编程;可以看到这个路线就是对“**状态**”的限制使用之路
|
|
|
+
|
|
|
+
|
|
|
|
|
|
-
|
|
|
- **莱布尼兹**(与**牛顿**)曾经有两个梦想:
|
|
|
- 创建一种“普遍语言”(universal language)使得任何问题都可以用这种语言表述;
|
|
|
- 对前一个问题的回答就是自弗雷格、罗素开始,经公理集合论运动的最终结果:以一阶谓词逻辑为语言所形式化阐述的集合论,现在已经成为数学的普遍语言,现代逻辑学、特别是将符号逻辑应用于数学领域所产生的数理逻辑,其最重要的目标就是为整个数学提供一个严格精确的语言。这是我们在学习**数理逻辑**时应当把握的方向。
|
|
|
- 找到一种"判定方法"(decision method)以解决所有可以在“普遍语言”中所表述的问题
|
|
|
- 第二个问题则是现代哲学和**计算机科学**最关注的问题
|
|
|
- - 1928年提出的一个重要的数学问题:“判定性问题” (decision problem),所有计算问题都可以规约到相应的一个判定性问题。
|
|
|
- - “任意正整数是不是素数”这个问题就是可判定的。不可判定问题:“停机问题”、“理发师悖论”-理发师不帮自己理发的人理发,那他该不该帮自己理发?
|
|
|
- - 可计算理论的研究对象有三个 : ( 1) 判定问题; ( 2) 可计算函数;( 3) 计算复杂性(P=?NP)。
|
|
|
- - 1936年,阿隆佐邱奇**Alonzo Church** 和 阿兰图灵**Alan Turing** 证明了:为“判定性问题”设计一个通用算法这件事是不可能的,“可判定”,“不可判定”。
|
|
|
+ - 1928年提出的一个重要的数学问题:“**判定性问题**” (decision problem),所有计算问题都可以规约到相应的一个判定性问题。“任意正整数是不是素数”这个问题就是可判定的。不可判定问题:“停机问题”、“理发师悖论”-理发师不帮自己理发的人理发,那他该不该帮自己理发?
|
|
|
+ - 可计算理论的研究对象有三个 : ( 1) 判定问题; ( 2) 可计算性;( 3) 计算复杂性(P=?NP)。
|
|
|
+ - 1936年,阿隆佐邱奇**Alonzo Church** 和 阿兰图灵**Alan Turing** 证明了:为“判定性问题”设计一个通用算法这件事是不可能的。
|
|
|
- 与此同时,对于“可判定”,他们各自详细阐述了两个计算模型:Alonzo Church的**Lambda演算(λ演算)**,Alan Turing的理论机器(之后被称作**图灵机**)
|
|
|
- ![](./img_readbook/p55783884.jpg)
|
|
|
-
|
|
|
+
|
|
|
- 图灵机
|
|
|
|
|
|
- 一切可计算的问题都能计算,这样的处理器或者编程语言就叫图灵完备的。
|
|
@@ -58,7 +58,7 @@
|
|
|
- **变量(Variable)**:形式:**x** 变量名可能是一个字符或字符串,它**表示一个参数**(形参)或者**一个值**(实参)
|
|
|
- **抽象体(Abstraction)**: 形式:**λx.M** 它表示获取一个参数x并返回M的lambda函数,M是一个合法lambda表达式,且符号λ和.表示绑定变量x于该函数抽象的函数体M。简单来说就是**表示一个形参为x的函数M**
|
|
|
- **应用(Application)** 形式:**M N** 它表示将函数M应用于参数N,其中M、N均为合法lambda表达式。简单来说就是**给函数M输入实参N**
|
|
|
- - Alpha「转换」(α 转换): 一个lambda函数抽象在更名绑定变量前后是等价的。**α: λx.x ≡ λy.y**
|
|
|
+ - Alpha「转换」(α 转换): 一个lambda函数抽象在更名绑定变量前后是等价的。**λx.x ≡ λy.y**
|
|
|
- Beta「规约」(β-Reduction):是把标识符用参数值替换;执行任何可以由机器来完成的计算。
|
|
|
|
|
|
```lambda
|
|
@@ -132,7 +132,7 @@
|
|
|
- 函数式编程的要求:
|
|
|
- 一等函数/高阶函数
|
|
|
- 闭包
|
|
|
- - 泛型
|
|
|
+ - **泛型**(go1.18)
|
|
|
- 尾递归优化
|
|
|
- 可变个数参数的函数+可变类型参数
|
|
|
- “柯里化”(Currying)
|
|
@@ -152,7 +152,7 @@
|
|
|
|
|
|
- 范畴(category) ;随便什么东西,只要能找出它们之间的关系,就能定义一个"范畴"
|
|
|
|
|
|
- - ![bg2017022210](img_readbook/bg2017022210.jpg)
|
|
|
+ - ![bg2017022210](./img_readbook/bg2017022210.jpg)
|
|
|
|
|
|
- 对象/点:object
|
|
|
|
|
@@ -160,9 +160,9 @@
|
|
|
|
|
|
- 满足结合律:f:a→b,g:b→c 的组合是 g∘f ; 结合律:(h∘g)∘f = h∘(g∘f)
|
|
|
|
|
|
- ![bg2017022204](/work/book/xq_study/img_readbook/bg2017022204.png)
|
|
|
+ ![bg2017022204](./img_readbook/bg2017022204.png)
|
|
|
|
|
|
- ![bg2017022209](/work/book/xq_study/img_readbook/bg2017022209.png)
|
|
|
+ ![bg2017022209](./img_readbook/bg2017022209.png)
|
|
|
|
|
|
```javascript
|
|
|
const compose = function (f, g) {
|
|
@@ -174,7 +174,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
- - 存在恒等态射(identity):单位元;
|
|
|
+ - 存在恒等态射(identity):
|
|
|
|
|
|
- 对于任何态射f:a→b,有1b∘f=f=f∘1a ;可以简单的认为是;f(x)=x
|
|
|
|
|
@@ -219,7 +219,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
-- - 态射的种类:
|
|
|
+ - 态射的种类:
|
|
|
|
|
|
- 单态射:不存在两个a中元素 map 到同一个b中的元素。
|
|
|
- 满态射:每一个b中的元素,都在a中有至少一个 source mapper。
|
|
@@ -234,15 +234,15 @@
|
|
|
- 同一种操作在不同的数学结构上定义可以不同。
|
|
|
- 比如:指数函数是一个同态。e(x+y)=exey→f(x∗y)=f(x)∗f(y)
|
|
|
|
|
|
- - 函子(functor)
|
|
|
+ - **函子(functor)**
|
|
|
|
|
|
- - 函子是函数式编程里面最重要的数据类型,也是基本的运算单位和功能单位。
|
|
|
+ - 函子是函数式编程里面最重要的,也是基本的运算单位和功能单位。
|
|
|
|
|
|
- 函子是范畴之间的map关系。可以理解为范畴之间的态射。
|
|
|
|
|
|
- 图中,函数`f`完成值的转换(`a`到`b`),将它传入函子,就可以实现范畴的转换(`Fa`到`Fb`)。
|
|
|
|
|
|
- - ![bg2017022211](img_readbook/bg2017022211.jpg)
|
|
|
+ - ![bg2017022211](./img_readbook/bg2017022211.jpg)
|
|
|
|
|
|
- 具有`map`方法的数据结构,都可以当作函子的实现。代码中,`Functor`是一个函子,它的`map`方法接受函数`f`作为参数,然后返回一个新的函子,里面包含的值是被`f`处理过的(`f(this.val)`)。
|
|
|
|
|
@@ -258,7 +258,7 @@
|
|
|
}
|
|
|
```
|
|
|
|
|
|
- - 例子说明,函数式编程里面的运算,都是通过函子完成,即运算不直接针对值,而是针对这个值的容器----函子。函子本身具有对外接口(`map`方法),各种函数就是运算符,通过接口接入容器,引发容器里面的值的变形。因此,**学习函数式编程,实际上就是学习函子的各种运算。**由于可以把运算方法封装在函子里面,所以又衍生出各种不同类型的函子,有多少种运算,就有多少种函子。函数式编程就变成了运用不同的函子,解决实际问题。
|
|
|
+ - 函数式编程里面的运算,都是通过函子完成,即运算不直接针对值,而是针对这个值的容器----函子。函子本身具有对外接口(`map`方法),各种函数就是运算符,通过接口接入容器,引发容器里面的值的变形。因此,**学习函数式编程,实际上就是学习函子的各种运算。**由于可以把运算方法封装在函子里面,所以又衍生出各种不同类型的函子,有多少种运算,就有多少种函子。函数式编程就变成了运用不同的函子,解决实际问题。
|
|
|
|
|
|
- Maybe 函子
|
|
|
|