#check Point.ext -- 自动生成的扩展性定理example (a b : Point) (hx : a.x = b.x) (hy : a.y = b.y) (hz : a.z = b.z) : a = b := by ext -- 扩展性:要证 a = b,只需证各字段相等 repeat' assumption
的作用
没有 @[ext],证明 a = b 会很麻烦。有了它,只需 ext 即可分解为字段相等。
三种构造方式
-- 方式1:命名字段(最清晰)def myPoint1 : Point where x := 2 y := -1 z := 4-- 方式2:匿名构造器 ⟨⟩(最简洁)def myPoint2 : Point := ⟨2, -1, 4⟩-- 方式3:显式构造函数#check Point.mk 2 (-1) 4
也可以自定义构造函数名:
structure Point' where build :: x : ℝ y : ℝ#check Point'.build 2 3
定义函数和操作
namespace Pointdef add (a b : Point) : Point := ⟨a.x + b.x, a.y + b.y, a.z + b.z⟩-- 匿名投影符号:a.add b 等价于 Point.add a b#check myPoint1.add myPoint2-- 证明性质protected theorem add_comm (a b : Point) : add a b = add b a := by rw [add, add] ext <;> dsimp -- <;> 对 ext 生成的所有子目标应用 dsimp repeat' apply add_comm-- 有时等式是定义上成立的(definitional equality)theorem add_x (a b : Point) : (a.add b).x = a.x + b.x := rflend Point
def addAlt : Point → Point → Point | Point.mk x₁ y₁ z₁, Point.mk x₂ y₂ z₂ => ⟨x₁ + x₂, y₁ + y₂, z₁ + z₂⟩-- 更简洁的版本(匿名构造器)def addAlt' : Point → Point → Point | ⟨x₁, y₁, z₁⟩, ⟨x₂, y₂, z₂⟩ => ⟨x₁ + x₂, y₁ + y₂, z₁ + z₂⟩
模式匹配的缺点
rw [addAlt] 后 Goal 窗口会显示 match 语句,可读性较差。推荐使用 where 或 := ⟨...⟩ 风格。
带约束的结构体
结构体不仅可以包含数据,还可以包含 Prop 类型的约束字段:
structure StandardTwoSimplex where x : ℝ y : ℝ z : ℝ x_nonneg : 0 ≤ x y_nonneg : 0 ≤ y z_nonneg : 0 ≤ z sum_eq : x + y + z = 1
这是数学中常见的”带约束的对象”。证明构造时需要提供数据和约束证明:
def swapXy (a : StandardTwoSimplex) : StandardTwoSimplex where x := a.y y := a.x z := a.z x_nonneg := a.y_nonneg -- 传递约束 y_nonneg := a.x_nonneg z_nonneg := a.z_nonneg sum_eq := by rw [add_comm a.y a.x, a.sum_eq]
参数化结构体
结构体可以依赖参数:
open BigOperatorsstructure StandardSimplex (n : ℕ) where V : Fin n → ℝ NonNeg : ∀ i : Fin n, 0 ≤ V i sum_eq_one : (∑ i, V i) = 1
Fin n 是一个有 n 个元素的类型。这使得我们可以定义任意维度的标准单形。
结构体 vs 其他类型构造
-- 乘积类型(等价于 Point,但字段无名称)def Point'' := ℝ × ℝ × ℝ-- 只包含约束的结构体(无数据)structure IsLinear (f : ℝ → ℝ) where is_additive : ∀ x y, f (x + y) = f x + f y preserves_mul : ∀ x c, f (c * x) = c * f x-- 用简单合取也可以,但结构体更好 def IsLinear' (f : ℝ → ℝ) := (∀ x y, f (x + y) = f x + f y) ∧ ∀ x c, f (c * x) = c * f x
def StdSimplex := Σ n : ℕ, StandardSimplex nsectionvariable (s : StdSimplex)#check s.fst -- ℕ:维度#check s.snd -- StandardSimplex s.fst:该维度的单形end
Sigma 类型与 Subtype 的区别:
Subtype:第二分量是 Prop(证明)
Sigma:第二分量是任意 Type(数据)
7.2 Algebraic Structures
核心洞见
代数结构 = 数据 + 公理。Lean 用 class 定义,instance 注册。
为什么要用代数结构?
原文列举了7个例子(偏序集、群、格、环、有序环、度量空间、拓扑空间)。核心需求:
泛化推理:证明一个定理,自动适用于所有实例
统一符号:+、* 在所有实例中通用
继承:交换环也是环,所有环定理对交换环成立
定义群结构
structure Group₁ (α : Type*) where mul : α → α → α one : α inv : α → α mul_assoc : ∀ x y z : α, mul (mul x y) z = mul x (mul y z) mul_one : ∀ x : α, mul x one = x one_mul : ∀ x : α, mul one x = x inv_mul_cancel : ∀ x : α, mul (inv x) x = one
def permGroup {α : Type*} : Group₁ (Equiv.Perm α) where mul f g := Equiv.trans g f -- 注意:mul f g = g ∘ f one := Equiv.refl α inv := Equiv.symm mul_assoc f g h := (Equiv.trans_assoc _ _ _).symm one_mul := Equiv.trans_refl mul_one := Equiv.refl_trans inv_mul_cancel := Equiv.self_trans_symm
乘法方向
mul f g = g.trans f 意味着 mul f g 的 forward 函数是 f ∘ g(先 g 后 f)。这与数学中常见的群乘法方向一致。
class Group₂ (α : Type*) where mul : α → α → α one : α inv : α → α mul_assoc : ∀ x y z : α, mul (mul x y) z = mul x (mul y z) mul_one : ∀ x : α, mul x one = x one_mul : ∀ x : α, mul one x = x inv_mul_cancel : ∀ x : α, mul (inv x) x = one-- 注册实例:Lean 会自动找到instance {α : Type*} : Group₂ (Equiv.Perm α) where mul f g := Equiv.trans g f one := Equiv.refl α inv := Equiv.symm mul_assoc f g h := (Equiv.trans_assoc _ _ _).symm one_mul := Equiv.trans_refl mul_one := Equiv.refl_trans inv_mul_cancel := Equiv.self_trans_symm
class 和 instance 的组合让 Lean 自动推断结构:
#check Group₂.mul -- 有隐式的 [Group₂ α] 参数def mySquare {α : Type*} [Group₂ α] (x : α) := Group₂.mul x x-- 使用:Lean 自动找到 Equiv.Perm β 的 Group₂ 实例example {β : Type*} (f g : Equiv.Perm β) : Group₂.mul f g = g.trans f := rfl
Coercion:自动转换
Lean 可以自动将 Equiv α β 强制转换为函数 α → β:
example (x : α) : (f.trans g) x = g (f x) := rflexample : (f.trans g : α → γ) = g ∘ f := rfl
这是通过 CoeFun 类型类实现的。类似地,你可以定义自己的 coercion:
instance : Add Point where add := Point.addsectionvariable (x y : Point)#check x + y -- 现在 Point 支持 + 运算example : x + y = Point.add x y := rflend
def div' (a b : ℤ) := (a + b / 2) / bdef mod' (a b : ℤ) := (a + b / 2) % b - b / 2-- 关键性质:|mod' a b| ≤ b/2theorem abs_mod'_le (a b : ℤ) (h : 0 < b) : |mod' a b| ≤ b / 2 := by sorry
用这些定义高斯整数的除法:
instance : Div GaussInt := ⟨fun x y ↦ ⟨Int.div' (x * conj y).re (norm y), Int.div' (x * conj y).im (norm y)⟩⟩instance : Mod GaussInt := ⟨fun x y ↦ x - y * (x / y)⟩