这是Bartosz Milewski关于范畴论的博客的第二部分,第一部分已经由garfileo翻译完成,建议大家先看第一部分。第一部分导言的地址是写给程序员的范畴论

第二部分的导言

在本书的第一部分我曾说范畴论和编程都与可复合性相关。在编程时,你总会不断地把问题分解到一个你能处理其细节的程度,然后一个个地解决每个子问题,最后把它们自底向上地重新组合起来。大致来说,这有两种实现的方法:告诉计算机要做什么(what to do),或者告诉它如何去做(how to do it)。也就分别是声明式(编程)和命令式(编程)。

你甚至可以从最底层的地方来理解这件事。复合本身可以被声明式地定义,例如h是f与g的一个复合:

h = g . f

或者命令式地定义,这时,先调用f,保留计算结果,再对该结果调用g:

h x = let y = f x

in g y

一个程序的这种命令式版本通常被描述成按照时间顺序执行的一个指令序列。特别是,对g的调用不能发生在f执行完成之前。至少这是一种概念上的想象————不过,在一个参数传递方式为按需调用的惰性语言中,实际的执行顺序可能完全不同。

实际上,声明式代码和命令式代码的执行过程只会有一点差异,甚至没有,这取决于编译器有多聪明。但这两种方法论毕竟不同,尤其在我们寻找问题的解决方案时和考虑代码的可维护性和可调试性时,它们会完全不同。

这里有一个重大问题:当面对一个具体问题时,我们是否总是可以在声明式和命令式的方法中选择一个?进一步,如果有一个声明式的的解决方案,是否一定可以转化为计算机代码?这个问题的答案远非显然,并且,如果我们能够找到这个问题的答案,我们对宇宙的理解可能就会迎来一场革命。

让我来详细说说。物理中有一个类似的二元性,它要么会是一些潜在的深刻原则的一个重要部分,要么会告诉我们一些有关大脑如何工作的事。理查德·费曼曾经提到,这个对应启发了他在量子电动力学领域的工作。

大部分的物理定律有两种表达形式。一种使用局部(local)或无穷小(infinitesimal)的思维。我们会在一个小邻域内观察系统的状态,并且预测它在下一时刻如何演变。这种想法通常透过一组的微分方程组的形式表达,并且我们会在一个周期时间里对它们做积分或求和。

让我们看看这种形式和命令式思维有多像:我们通过一系列的“小碎步”达到最终解,而每一个碎步取决于前一步的结果。事实上,物理系统的计算机仿真也是按部就班地把微分方程组重写为差分方程组,然后迭代它们。这也是行星游戏中宇宙飞船的运动方式。在每一个时间步长里,飞船的位置通过一个小的增量改变,它就是速度乘以时间间隔。而速度呢,也是如此迭代计算,它的小增量正比于加速度,也就是力除以质量。

牛顿运动定律所对应的微分方程组是有明确写法的:

F = m dv/dt

v = dx/dt

同样的方法可以用来处理更复杂的问题,比如用麦克斯韦方程组来描述电磁场的传播,或者甚至是用格点量子色动力学来描述一个质子中的夸克和胶子的行为。

数字计算机的使用促进了这种与时空离散化相结合的局域思维,史蒂芬·霍夫曼曾试图将整个宇宙的复杂性约减为一个元胞自动机系统,这种思维在这个伟大尝试中体现到了极致。

另一种是全局的方法。我们观察系统的初始状态和终止状态,然后通过最小化某个函数计算出两者之间的轨迹。最简单的例子就是费马的最小时间原理。它声称光线会沿着时间最小的路径传播。特别地,当没有反射物或折射物时,光线会沿着最短的路径传播,也就是一条直线。但是,光在厚实(透明)的材料中会传播的更慢,比如水或玻璃。所以如果你选择的起点在空气中,终点在水里,那么光就会在空气中传播更长一点以获得水中路线的缩减。这个最小时间所对应的路径使得光在空气和水的界面处发生折射,这导出了斯涅尔折射定律:

sin θ_1 / sin θ_2 = v_1 / v_2

其中,v_1是光在空气中的传播速度。v_2是光在水中的传播速度。

和翻译第一部分的garfileo一样,我也遇到了不能在代码块中写下标的问题,同时思否的LaTeX也不能写行内公式。于是这里采取了和他一样的约定方式:_表示下标,^表示上标。

所有的经典力学(结论)都能从最小作用量原理推出。该作用量就是拉格朗日量沿路径的积分(对时间),而拉格朗日量则是动能与势能之差(注意是差而不是和,和是总能量)[因此这个所谓的“作用量”是一个关于路径的函数,而路径是一个坐标关于时间的函数,所以作用量是一个泛函,而经典力学下粒子的路径就是这个泛函取最小值的那个路径。想要更具体了解该推导过程,还需要了解变分法的相关内容。译者注]。当你朝一个目标发射一个迫击炮时,炮弹会先上升,这时重力势能变大,从而,对作用量积累负向的贡献。同时炮弹会变慢,在抛物线的顶点达到动能的最小值。然后它会加速以更快地通过接下来的低势能区域。

费曼地最大贡献就是意识到了最小作用量原理可以推广到量子力学。再一次,这个问题被表达成了已知初始状态和终止状态的形式。两个状态间的费曼路径积分被用作计算转移概率。

我们的重点是,在描述物理的定律时有一个奇特的难以解释的二元性。我们既可以用局部的观念,于是万物都按照一个小增量的序列行进;我们也可以用全局的观念,一旦我们声明了初始和终止条件,那么这两者中的过程也就确定了。

全局的手段也可以用在编程中,例如在实现射线跟踪时。我们声明(观察的)眼睛位置和光源位置,需要做的是指出这两者间所有可能的光路。我们不需要精确的最小化每条射线的飞行时间,我们会利用斯涅耳定律和反射定律来达到同样的效果。

局部和全局的手段最大的不同就是在于它们对于时空的处理上,尤其是时间。局部的手段永远对这里和当下感兴趣,而全局的手段会做一个长程的静态的观察,就好像未来早就注定了,我们只不过实在分析某个永恒的宇宙的属性罢了。

没有什么比用函数式响应式编程(the Functional Reactive Programming, FRP)来实现用户交互更能说明问题的了。FRP不是针对所有的可能的用户动作写一个又一个的独立的接口,并让所有人都有那些共享的可变状态的权限,而是把外部事件看作一个无限长的列表,然后对这个列表做一系列的操作。观念上来讲,这个包含所有未来动作的列表就已经在那儿了,就像程序的输入数据一样可以使用。一个数字π的列表和一个伪随机数的列表,又或是一个包含了来自电脑硬件的鼠标位置的列表,在一个程序看来没有任何不同。不论是哪种情况,如果你想要获得(列表的)第n项,那你就必须先获得前n-1项。当这个性质用到瞬时事件里时,我们就称之为因果律。

可这和范畴论有什么必然关系呢?我会说明范畴论契合了一种全局的手段并且因此支持了声明式编程。首先,不像微积分,范畴论没有内置的距离或领域的概念,或者时间的概念。我们有的是抽象的对象和他们之间的抽象的连接。如果你能通过一系列的步骤从A得到B,那么你只用一步也可以。此外,范畴论的主要武器是泛构造,而这本身就是全局手段的象征。我们已经在实践中见识过它了,比如,在范畴积的定义中。积定义的方式,就是指明它的性质——一种极其声明式的手段。积是一个具有两个投影的对象,并且是最好的那一个——它优化出了某个性质:能够因式化其他(也满足这种条件的)对象的投影的性质。

注意把它和费马的最小时间原理或最小作用量原理比较。

相反,让我们把它和更加命令式的传统的笛卡儿积定义作比较。你在描述如何生成一个积的元素时,会先从一个集合中挑一个元素,再从另一个集合中挑一个。这是生成一个序对的方式,然后也会有一个拆解序对的方式。

几乎在每一种编程语言中,包括函数式语言,例如Haskell,积类型、余积类型和函数类型都是内置的,而不是通过泛构造定义的;即使已经存在一些创造范畴式的编程语言的努力(例如,参见参考文献中Tatsuya Hagino的论文)

不论是否被直接使用,范畴化的定义支撑了已有的编程结构,并且会引导出一些新的结构。更重要的是,范畴论在声明式的层面上提供了一种可以生成计算机程序的元语言。这也鼓励我们在实现代码之前就能够导出问题的范式。

致谢

感谢Gershom Bazerman检查我的数学和逻辑,和André van Meulebrouck在编辑上的帮助。

参考文献

java 声明式编程_声明式编程 - SegmentFault 思否相关推荐

  1. 老九java线上,老九 - SegmentFault 思否

    我们接着上面一篇继续学习JVM的基本知识. 对象存活判断 上篇中我们介绍过JVM垃圾回收综述中说过一次垃圾回收之后会有一些对象存活.这节我们介绍两个判断对象存活的算法. 判断对象存活有引用计数算法和可 ...

  2. mysql中的leading用法_登录 - SegmentFault 思否

    前面我们主要分享了MySQL中的常见知识与使用.这里我们主要分享一下MySQL中的高阶使用,主要包括:函数.存储过程和存储引擎. 对于MySQL中的基础知识,可以参见 1 函数 函数可以返回任意类型的 ...

  3. 网易云信入选《SegmentFault 思否 2019 中国技术品牌影响力企业榜单》!

    近日,SegmentFault 思否作为中国最大的新一代开发者社区,依托数百万开发者用户行为数据,及科技企业技术品牌在国内市场的大数据分析,评选出 30 家在开发者领域最具影响力的科技企业,权威发布& ...

  4. 极客广州——EOS Asia郭达峰担任SegmentFault思否黑客马拉松技术顾问

    近日备受关注的 EOS 投票率超过 15%,主网激活,已正式上线.EOS Asia 联合创始人郭达峰将担任 SegmentFault 思否区块链黑客马拉松广州站技术顾问,为大赛项目提供技术咨询支持.届 ...

  5. SegmentFault 思否发布开源问答社区软件 Answer

    ONES 旗下技术问答社区 SegmentFault 思否(下称"思否")今日宣布,正式对外开源其问答社区软件 Answer. 作为国内领先的新一代技术问答社区,思否始于「聚集体智 ...

  6. 安势信息入选 SegmentFault思否「2022 中国新锐技术先锋企业」

    2023 年 1 月 4 日,中国技术先锋年度评选 | 2022 中国新锐技术先锋企业榜单正式发布.作为中国领先的新一代开发者社区,SegmentFault 思否依托数百万开发者用户数据分析,各科技企 ...

  7. 对比CSDN与开源中国、segmentFault思否

    前言:作为一个IT行业学生我遇到问题一般会通过搜索几个权威性论坛得到的结果,通常是CSDN.SegmentFault.开源中国. 1.需求测评以及对比 首先对于一个学生或者一个IT从业人员而言,相关I ...

  8. SegmentFault 思否社区被收购了!

    SegmentFault 思否被 ONES 收购了,而今年也刚好是思否的十周年,思否的创始人兼 CTO 祁宁在社区发布了一封致开发者的信 -- <10>,回顾了思否社区成立10年来的理想与 ...

  9. 开源社拍了拍 SegmentFault 思否,6 月杭州见

    5 月 19 日,OpenAI 突然官宣 ChatGPT 正式推出 iOS APP,迎来真 · iPhone 时刻.同日,国家超算天津中心发布国产中文语言大模型天河天元,并在此基础上启动了深度训练面向 ...

  10. 亚马逊云科技云创计划携手 SegmentFault 思否,成就 AI 探路者

    ‍‍ AI 无疑是这个夏天最"出圈"的话题. ChatGPT 的爆红向 AI 产业释放了"走出实验室"的信号,并提供了"从通用范式落地到具体场景&qu ...

最新文章

  1. R语言使用latticeExtra包可视化双Y轴线图实战(Dual Y axis):单y轴线图、双y轴图线图、双y轴图线图(添加图例)
  2. ole db 访问接口 sqlncli 无法启动分布式事务_阿里终面:分布式事务原理
  3. Elasticsearch(一)架构及一般性应用
  4. node.js学习笔记14—微型社交网站
  5. 邮件列表统计(网站推广)
  6. Object 及toString() 方法的重写
  7. BZOJ 1026 [SCOI2009]windy数
  8. launchMode
  9. 设置同时上内外网+文件共享
  10. JSP 九大内置对象详解
  11. 更改hadoop集群yarn的webui中的开始时间和结束时间为本地时间
  12. 计算机组成原理(三)--存储器的层次结构
  13. vba判断是否为数字的方法小集
  14. C++ Primer Plus学习(四)—— string类实践
  15. android取消自动获取焦点,Android 如何让EditText不自动获取焦点 (转)(示例代码)...
  16. 《Redis开发与运维》学习第一章
  17. MATLAB 非对称矩阵求逆
  18. PostgreSQL 数据库导入导出
  19. design pattern scard
  20. “管中窥豹”,MyCAT的基因缺陷

热门文章

  1. 【LaTeX教程】七.LaTeX数学公式初步
  2. 【编写if时尽量不要带else】
  3. 15 EXCEL仪表盘创建2
  4. php服务器文件直链,比较简单的百度网盘文件直链PHP代码
  5. Android安装apk应用的时候出现INSTALL_FAILED_SHARED_USER_INCOMPATIBLE如何解决
  6. centos 7 更新时间和更新时区
  7. 手把手带你安装PyTorch指定版本嘿!
  8. qq三国挂机云服务器,云服务器挂机QQ三国游戏的流程和实际操作概况记录
  9. html如何添加音乐火狐,电脑如何将HTML书签导入进火狐浏览器中
  10. 利用openCV(C++)实现Halcon中的min_max_gray函数的功能