可能存在事实性错误,暂时没有排查错误,一口气写完的

我们即将开展学习的这门语言:OCaml,是一种函数式编程语言,但它不仅仅支持函数式编程,还支持多范式编程,涵盖了命令式编程、面向对象编程和并发编程等多种范式。OCaml 作为 ML(Meta Language)家族的一员,继承了 ML 语言的函数式编程特性,同时也添加了对其他编程风格的支持。

CS61A 中也有这个概念,使用的是 Scheme,最后的 Project 是在 Python 中构建 Scheme 的 Interpreter,《Fluent Python 2nd》 有简单实现一个类似的解释器,参照 lispy

函数式编程作为编程语言的一种范式流传至今,从 Lisp 这位元祖开始,发展出许多编程语言,如 Scheme, Racket, OCaml, Haskell, Moonbit... 整个社区时常产生类似 Vim 还是 Emacs 好的争论。是纯函数式好还是多范式编程更好?这类问题放在不同人上只会有无意义的争锋相对,各执己见,咱学完也别淌这趟浑水,打个太极☯️,喜欢啥就用啥。学完这些语言,你也很难在国内找到一份“语言对口”的工作。很多国际大厂在内部都有在使用这类语言实现项目。Jane Street 几乎纯使用 OCaml 构建了整个公司的系统框架,也为整个 OCaml 社区做出极大贡献。

画风切换回来,什么是 Meta Language?早期人们希望通过一种共同语言来描述、定义其他语言的语法结构与行为,以我的理解,这时的元语言是想提供一种创造或使用其他语言的框架。我们在学习 CLRS 碰到的算法伪代码,并不直接用于编写最终的代码,而是作为定义、分析整体算法的工具为我们使用。元语言本身并不直接用于编写最终的应用程序,而是作为定义、分析、编译、解释或处理其他编程语言的工具。随着时间的推移,ML 发展成了一种功能强大的编程语言,具有类型推导、模式匹配和强类型系统等特性。

从现实看,函数式编程的教育在国内是极大忽视的,而这门课在国外几乎是“必需品”。函数式编程的理念也深深嵌在现代流行的编程语言中。至于为什么选择 OCaml 作为本轮学习的主要编程语言,纯属我个人强买强卖(其实是好的资源比较多,图标也很好看👍

我个人很中意 Pattern Matching 这个概念,举个例子

在 OCaml 中,

(* 定义几何形状类型 *)
type shape =
  | Circle of float   (* 圆形,包含半径 *)
  | Rectangle of float * float  (* 矩形,包含宽和高 *)
  | Triangle of float * float * float  (* 三角形,包含三边 *)

(* 计算面积的函数 *)
let area s =
  match s with
  | Circle r -> 3.1415 *. r *. r  (* 圆形的面积公式:πr² *)
  | Rectangle (w, h) -> w *. h   (* 矩形的面积公式:宽 × 高 *)
  | Triangle (a, b, c) ->
      (* 海伦公式:sqrt(p * (p - a) * (p - b) * (p - c)),其中 p 是半周长 *)
      let p = (a +. b +. c) /. 2.0 in
      sqrt (p *. (p -. a) *. (p -. b) *. (p -. c))

(* 测试 *)
let _ = 
  Printf.printf "Circle area: %f\n" (area (Circle 5.0));
  Printf.printf "Rectangle area: %f\n" (area (Rectangle (3.0, 4.0)));
  Printf.printf "Triangle area: %f\n" (area (Triangle (3.0, 4.0, 5.0)));

在 Python 中(好像没办法简单写)

import math

class Circle:
    def __init__(self, radius):
        self.radius = radius

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

class Triangle:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

def calculate_area(shape):
    match shape:
        case Circle(r):
            return math.pi * r * r
        case Rectangle(w, h):
            return w * h
        case Triangle(a, b, c):
            p = (a + b + c) / 2
            return math.sqrt(p * (p - a) * (p - b) * (p - c))

circle = Circle(5.0)
rectangle = Rectangle(3.0, 4.0)
triangle = Triangle(3.0, 4.0, 5.0)

print(f"Circle area: {calculate_area(circle)}") 
print(f"Rectangle area: {calculate_area(rectangle)}")
print(f"Triangle area: {calculate_area(triangle)}")

看上去也没啥好坏之分,确实如此,但我再摆出红黑树呢!魅力一下就显现了=》

在构建红黑树时,我们会遇到一些构造起来十分头疼的 case,转化到实际的代码编写又是一门苦差事,这里我摆出 balance 操作在 OCaml 的实现,读者可以在未来实现过红黑树后再来看看。

# 摘自 https://cs3110.github.io/textbook/chapters/ds/rb.html#balance
type color = Red | Black
type 'a rbtree = Leaf | Node of color * 'a * 'a rbtree * 'a rbtree

let balance = function
  | Black, z, Node (Red, y, Node (Red, x, a, b), c), d
  | Black, z, Node (Red, x, a, Node (Red, y, b, c)), d
  | Black, x, a, Node (Red, z, Node (Red, y, b, c), d)
  | Black, x, a, Node (Red, y, b, Node (Red, z, c, d)) ->
    Node (Red, y, Node (Black, x, a, b), Node (Black, z, c, d))
  | a, b, c, d -> Node (a, b, c, d)

OCaml 还支持其他编程范式,比如:

  • 命令式编程:实现了引用、可变数据结构和控制流语句(如 for 和 while 循环)

  • 面向对象编程:提供了类、对象、继承等基本特性,并且能够与函数式编程无缝结合。

  • 并发编程:拥有多种并发编程的方式,支持轻量级线程和并发数据结构。


说太多历史也不大好,本篇的主线是指导环境配置的工作。

请参照:https://cs3110.github.io/textbook/chapters/preface/install.html

我们的学习也会围绕 CS3110 的教材展开,根据内容进行配置即可。

(这个师兄老是丢链接然后就不管了,好坏啊!)会有实际演示和答疑的,别担心!


本轮学习将与华师 24 级图灵班的学习同步(其实是飞速)开展,面向所有愿意共同学习的朋友,预期是在本学期中学习完 CS3110。本教材会同步学习一些算法与数据结构,与 CLRS 的学习并无冲突,前者偏向实践,另一则更希望读者掌握数学和分析算法的工具。

个人学习 OCaml 的经验尚浅,此次学习也是希望能够巩固自身,顺便将之前觉得重要的概念分享出来。在毕业之前最后抖几下🥲

俊坚师兄也分享了自己的学习经验,可移步至 CS-Plan 查看

有关形式化证明的学习,会参照 Software Foundation 学习,日后再议!

我会尽量将视频上传至论坛 B 站,本贴也会跟踪相关信息。开学后,我会首先填坑,带着各位一起看看如何用 OCaml 实现一种语言的编译器。

  • 2024.2.9 02:20, v0
15 天 后

内容:函数式编程初导
时间:2025 年 2 月 23 日

视频链接:B站
所有文字资料已同步至 Notion,地址为 program.cs-plan.com

Type Define 的时候没有大写开头,闹了点乌龙(
PS:录制的时候没发现还开着视频,如果挡住了屏幕,十分抱歉

12 天 后

我们将使用 Github ClassRoom 作为 Exercise 布置的平台

以上作业部分基于 UMD 330, https://bakalian.cs.umd.edu/330,这门课也很适合拿来学习 OCaml 这门语言,剩余未讲授/布置的内容欢迎自学完成!(我做的是好久前的版本了 lol)

16 天 后

© 2018-2025 0xFFFF