1990:CAML 誕生#
事件#
1990 年,法國國家資訊與自動化研究所(INRIA)的 Gérard Huet、Guy Cousineau、Michel Mauny 等人發表了 CAML——名稱來自 Categorical Abstract Machine Language。CAML 把 Standard ML 的語言設計帶入工業級實作,是 ML 家族從學術原型走向生產環境的關鍵一步,也為 1996 年的 1996-OCaml誕生 鋪路。
語法/特性加入的理論與實用原因#
1. Categorical Abstract Machine(CAM)作為編譯目標#
- 理論原因:Cousineau、Curien 與 Mauny 在 1980 年代中期設計的 CAM,是一套以範疇論(category theory)為理論基礎的抽象機——lambda 項先編譯為範疇組合子(categorical combinators),再由簡單的堆疊機執行。理論上它提供了 lambda 演算的可執行語意,證明正確性可直接以範疇論論證。
- 實用原因:CAM 實作簡單、正確性有保證,適合快速打造出可用的 ML 編譯器。
- 彌補缺陷:當時 ML 實作(Edinburgh ML、LML)多為直譯或實驗性質,缺乏嚴謹又高效的編譯模型。
(* lambda 項 → 範疇組合子 → CAM 指令 *)
(* λx. x ⟶ id *)
(* λx. x x ⟶ dup ; app *)
(* CAM 機僅有 hd、tl、swap、cons、cur、app 等少數指令 *)
編譯流程示意:lambda 項先轉為範疇組合子,再由只有少數指令的堆疊機執行——正確性可純以範疇論論證:
原始式 (fun f x -> f x) 5
↓ 編譯(lambda 項 → 範疇組合子)
CAM 指令 cur(Snd ; App) ; Push 5 ; App
↓ CAM 堆疊機執行(state ⟶ C . S)
結果 5
2. 繼承 Standard ML 的型別與模組設計#
- 理論原因:CAML 採用完整化的 Hindley–Milner 型別推斷(見 1983-StandardML誕生)與 ML 的模式匹配、代數資料型別,並配備模組系統。
- 實用原因:Formel 計畫(Formel, 1983–1989)需要 ML 語言發展 Coq 定理證明器的前身(CoC 實作),型別安全與高階函數是形式化驗證的基礎。
- 彌補缺陷:Edinburgh ML 非正式、可攜性差;法國需要自己的 ML 實作做形式化與教學。
Caml Light 風格的基本函數與模式匹配——完整化 Hindley–Milner 型別推斷的展現:
let rec map f = function
[] -> []
| x::l -> f x :: map f l ;;
(* 型別:('a -> 'b) -> 'a list -> 'b,自動推斷 *)
map (function x -> x * x) [1; 2; 3] ;;
(* - : int list = [1; 4; 9] *)
代數資料型別與模式匹配——CAML 用它為 Coq 前身表示語法樹與證明項:
type expr =
Const of int
| Var of string
| Plus of expr * expr ;;
let rec eval env = function
Const n -> n
| Var name -> env name
| Plus (a, b) -> eval env a + eval env b ;;
eval (function "x" -> 5 | _ -> 0) (Plus (Const 3, Var "x")) ;;
(* - : int = 8 *)
列表遞迴是 CAML 的基本慣用法——高階函數與尾遞迴皆可自然表達:
let rec fact n = if n = 0 then 1 else n * fact (n - 1) ;;
(* 尾遞迴版本:不增長堆疊 *)
let fact n =
let rec loop acc n = if n = 0 then acc else loop (acc * n) (n - 1) in
loop 1 n ;;
fact 10 ;;
(* - : int = 3628800 *)
3. 工業級實作的可攜性#
- 理論原因:以 CAM 為中間語言,只要移植 CAM 直譯器即可把整個編譯器帶到新平台——理論上「一次設計、處處實作」。
- 實用原因:INRIA 的目標是讓 ML 實作能在當時各式工作站與迷你電腦上執行,服務教學與工程。
- 彌補缺陷:當時 ML 實作速度慢、可攜性差,難以走出學術實驗室。
「一次設計、處處實作」:編譯器只需產生 CAM(或後來的位元組碼)指令,移植時只要重寫那層薄薄的抽象機直譯器:
(* 編譯器架構層次示意 *)
(* Caml 原始程式 → CAM 位元組碼 → 各平台的 CAM 直譯器(數百行 C 即可) *)
(* 對照:直譯式實作需在每個平台重寫整個語意層 *)
後續發展#
- 1992 年 Caml Light:Xavier Leroy 以位元組碼(bytecode)重寫,捨棄 CAM 抽象機與重型模組系統,打造出輕量、快速、可攜的實作,可執行於一般 PC。
- 1996 年 OCaml:Didier Rémy 加入物件層,Caml Special Light 演化為 OCaml,成為 ML 家族最成功的工業級語言。
彌補了什麼缺陷#
CAML 彌補了 ML 實作速度慢、可攜性差的缺陷:以範疇論抽象機提供嚴謹而簡單的編譯模型,並由法國自主建立 ML 實作以支撐形式化驗證(Formel 計畫、Coq)與教學。其工業化路線最終結晶於 1996-OCaml誕生。