读编程与类型系统笔记11_高级类型及其他

1. 范畴论

1.1. 范畴论是数学的一个分支,研究的是由对象及这些对象之间的箭头组成的结构

1.2. 函子和单子的概念来自范畴论

1.3. Haskell是一种编程语言,从范畴论中汲取了许多灵感,所以它的语法和标准库很容易表达函子、单子和其他结构的概念。Haskell完全支持高阶类型

2. 函子(functor)

2.1. 函子是执行映射操作的函数的推广

2.2. 对于任何泛型类型,以Box‹T›为例,如果map()操作接受一个Box‹T›和一个从T到U的函数作为实参,并得到一个Box‹U›,那么该map()就是一个函子

2.3. 大部分主流语言都没有很好的方式来表达函子

2.4. 函子的常规定义依赖于高阶类型的概念

2.5. 函子能够在处理管道中传送最初的错误,但是如果管道中的每个步骤都可能失败,函子就无法工作

3. 高阶类型

3.1. 与高阶函数类似,代表具有另外一个类型参数的类型参数

3.2. T‹U›或Box‹T‹U››有一个类型参数T,后者又有一个类型参数U

3.3. 高阶类型是接受其他种类作为实参的种类(参数化的类型构造函数)

3.4. 理论上,我们可以深入任何级别,如T‹U‹V‹W›››

3.5. 在实际应用中,超过第一个T‹U›级别后,它就没那么有用了

3.6. TypeScript、C#或Java中没有一种好的方式来表达高阶类型,所以我们不能通过使用类型系统表达一个函子的方式来定义结构

3.7. Haskell和Idris等语言有更强大的类型系统,使得创建这种定义成为可能

4. 类型构造函数

4.1. 返回类型的一个函数

4.2. 每个类型都有一个构造函数

4.3. 类型number的构造函数看作不接受实参、返回number类型的一个函数,也就是() -› [number type]

5. bind()

5.1. 在Box‹T›上应用函数T =› Box‹U›,返回一个Box‹U›

6. map()

6.1. 在Box‹T›上应用函数T =› U,返回一个Box‹U›

7. 区别在于如何得到这个Box‹U›

8. 单子

8.1. 由bind()和return()或unit()的函数组成

8.2. return()或unit()

8.2.1. 接受一个类型T,并将其封装到泛型类型中,例如Box‹T›、T[]、Optional‹T›或Either‹Error, T›

8.3. 以泛型的方式编写程序,同时将程序逻辑所需的样板代码封装起来

8.3.1. 推广到各种列表:数组、链表和迭代器范围

8.3.2. 可以把一系列函数调用表达为一个管道,将数据管理、控制流或副作用抽象出去

8.3.3. 单子在错误传播、异步代码和序列处理的上下文中很有用

8.4. 如果一种编程语言不能表达高阶类型,就没有一种很好的方式来指定一个Monad接口

8.5. 大部分主流语言仍然把单子视为模式,而不是结构,但它们肯定是有用的结构,所以能够在不同的上下文中一再出现

8.6. 单子模式

8.6.1. 单子是一个泛型类型H‹T›。对于该类型,我们有一个函数(如unit())可接受类型T的一个值并返回类型H‹T›的一个值。还有一个函数(如bind())可接受类型H‹T›的一个值和一个从T到H‹U›的函数,并返回类型H‹U›的一个值

8.7. continuation单子

8.7.1. promise代表在将来某个时候发生的计算的结果

8.7.2. 链接promise是几乎所有主流编程语言都提供的一种API,它实际上就是单子性的

8.7.3. promise是封装了调度/异步执行的单子

8.8. 列表单子

8.8.1. 受一个T数组和从T到U数组的一个函数,并返回一个U数组

8.8.2. bind()接受一个T的序列和一个T =› U的序列的函数。其结果为一个压平的U列表

8.9. 状态单子

8.9.1. 封装一个状态,并把该状态与值一起传递

8.9.2. 在给定当前状态时,它将生成一个值和一个更新后的状态

8.10. IO单子

8.10.1. 封装了副作用

8.10.2. 允许我们实现能够读取用户输入或者写入文件或终端的纯粹函数,因为不纯粹的行为从函数中移除了出来,封装到了IO单子中

9. 函数式编程

9.1. 与面向对象编程区别很大的范式

9.1.1. 提供另外一种思考代码的视角

9.2. lambda和闭包、不可变的数据结构以及反应式编程都来自函数式编程语言

9.3. Haskell作为入门语言。它的语法相当简单,但类型系统十分强大,而且它有着牢固的理论基础

10. 泛型编程

10.1. 理论基础是抽象代码

11. 线性类型

11.1. 线性逻辑与处理资源的经典逻辑不同

11.2. 在经典逻辑中,如果一个演绎为true,就永远为true,但线性逻辑证明不符合这种演绎

11.3. 对于理解线性类型及其应用,Rust是一种很好的语言

12. 从属类型

12.1. 在泛型中,一个类型可以决定另外一个类型是什么(类型参数)

12.2. 从属类型则颠倒了这种情况:值决定了类型

12.3. 对于理解从属类型及其应用,Idris是一种很好的语言

posted @ 2023-01-19 09:15  躺柒  阅读(57)  评论(0编辑  收藏  举报