函数式编程里"副作用"(状态、IO、异常)无法用纯函数直接表达;单子(monad)把这类计算包装成"带结构的函子" T,使副作用仍可按纯函数方式组合——Haskell 的 Monad 类型类正源于此。它是伴随对的组合结构,也是伴随函子与极限的直接产物。
需先掌握函子(自函子、函子复合)、自然变换(单位与乘法)与伴随函子与极限(伴随产生单子)。
定义
范畴 C 上的单子是三元组 (T,η,μ):T:C→C 是自函子,η:IdC⇒T 与 μ:T2⇒T 是自然变换,满足
- 结合律:μ∘Tμ=μ∘μT(作为 T3⇒T)
- 单位律:μ∘ηT=μ∘Tη=idT
等价地:T 是自函子范畴 [C,C] 中的幺半群对象(幺元 η、乘法 μ)。
性质
- 伴随产生单子:若 F⊣G(F:C→D,G:D→C),则 T=G∘F 连同单位 η 与 μ=GεF 构成单子;反之每个单子都来自某伴随(Kleisli / Eilenberg–Moore)
- Kleisli 范畴 CT:对象同 C,态射 A→B 是 A→TB,复合用 μ 拼合——编程中"带副作用的函数"正是 Kleisli 态射
- 代数:T-代数 A 是对象 A 连同 α:TA→A 满足相容条件;Eilenberg–Moore 范畴 CT 的遗忘函子是 T 的"模范畴"
- 单子与伴随的双射:每个单子 T 唯一地对应 Kleisli 范畴与 Eilenberg–Moore 范畴这两个极端伴随
例子
- 幂集单子 T(A)=P(A):η(a)={a}、μ=⋃;其代数是完全格
- May-单子 T(A)=A+1(可选值):编程中的
Maybe,代数给出带基点集合 - Haskell 中
IO、State、List 都是单子:return 即 η,>>= 编码 Kleisli 复合
应用
单子是函数式编程副作用建模的标准工具(IO、状态、异常、解析器),也是代数理论(Lawvere 理论)、拓扑中的同伦单子(见同伦范畴)与余代数的对偶概念的公共框架。