第1章 入门 - 深度伴读

本章定位

第1章是”破冰”章节,不涉及真正的证明技巧。核心目标是建立三个心智模型:

  1. Lean 是什么(类型论证明助手)
  2. 证明即程序(Prop → 证明项 → tactic)
  3. 工作流(VS Code + Goal 窗口 + 交互式反馈)

1.1 Getting Started

核心要点

本节讲的是”怎么开始用”,技术性内容不多,但有几个概念需要建立:

形式化 ≈ 编程

Lean 的核心洞见:写证明就像写程序

  • 普通程序:输入数据 → 处理 → 输出数据
  • Lean 证明:给定命题(类型)→ 构造证据(项)→ Lean 验证类型正确

这个类比贯穿整个学习过程。如果你有编程基础,会更容易理解 Lean 的思维方式。

工作流

VS Code 编辑 .lean 文件
        ↓
Lean 服务器实时检查
        ↓
Goal 窗口显示证明状态
        ↓
鼠标悬停查看反馈

关键习惯

永远盯着 Goal 窗口。它告诉你:

  • 当前有哪些假设(context)
  • 还需要证明什么(target)

这是你在 Lean 中唯一的”导航仪”。

常见困惑

困惑解答
#check#eval 有什么区别?#check 查看类型,#eval 计算值
为什么要复制 MIL 文件夹?保留原始文件便于 git pull 更新
\R 怎么打出 ℝ?输入 \R 后按空格或 Tab

1.2 Overview

本节是全书最重要的概念基础

理解本节的三层结构,后面所有章节都是在这个框架下展开的。

核心概念:三层类型系统

Lean 的世界只有三类东西,用 #check 一看便知:

┌─────────────────────────────────────────────────────────┐
│  第1层:数据(数学对象)                                  │
│  类型:ℕ, ℝ, ℕ → ℕ, List ℝ ...                         │
│  例子:2 + 2, f(x) = x + 3                              │
├─────────────────────────────────────────────────────────┤
│  第2层:命题(数学陈述)                                  │
│  类型:Prop                                              │
│  例子:2 + 2 = 4, FermatLastTheorem, ∀ x, x² ≥ 0       │
├─────────────────────────────────────────────────────────┤
│  第3层:证明(命题的证据)                                │
│  类型:P,其中 P : Prop                                  │
│  例子:rfl : 2 + 2 = 4, sorry : 任何命题(作弊)         │
└─────────────────────────────────────────────────────────┘

关键洞见:在 Lean 中,“证明一个命题 P” = “构造一个类型为 P 的项”。

-- 这不是"声明",这是在"构造证据"
theorem easy : 2 + 2 = 4 := rfl
-- easy 的类型是 "2 + 2 = 4",它是一个 Prop
-- rfl 是构造这个证据的方法

sorry 是什么?

sorry 是 Lean 内置的”万能证据”,可以假装证明任何命题。 它的存在是为了让你先搭框架再填充细节。 Lean 知道你在作弊,会在 Goal 窗口用黄色警告。

两种证明风格

这是本章第二个核心概念:

风格1:证明项(Proof Term)

直接写出”证据长什么样”:

-- Even n 表示"n 是偶数",定义为 ∃ k, n = k + k(即 n = 2k)
-- 所以 Even n 的值是一个对 ⟨k, hk⟩,其中 k 是 witness,hk 是证明 n = k + k
 
example : ∀ m n : Nat, Even n → Even (m * n) :=
  fun m n ⟨k, hk⟩ ↦ ⟨m * k, by rw [hk, mul_add]⟩
--  ↑ 给定 n = k + k,构造 m*n = m*k + m*k,所以 m*n 也是偶数
--  ↑ mul_add : m * (k + k) = m * k + m * k

优点:紧凑、精确 缺点:难写、难读

风格2:Tactic 证明

给 Lean 一步步指令来构造证据:

example : ∀ m n : Nat, Even n → Even (m * n) := by
  -- rintro = intro + rcases,同时引入变量和解包假设
  rintro m n ⟨k, hk⟩      -- m,n : Nat; k : Nat; hk : n = k + k
  use m * k               -- 提供偶数 witness:m*n = m*k + m*k
  rw [hk]                 -- 把 n 换成 k + k:目标变成 m*(k+k) = m*k + m*k
  ring                    -- 自动用分配律证明

优点:交互式、有反馈、易调试 缺点:稍冗长

本书的选择

主要用 Tactic 风格。原因:

  1. 有即时反馈(Goal 窗口)
  2. 更接近人类思考方式
  3. 可以逐步构建,边写边看

Tactic 证明的状态变化

这是你需要建立的核心直觉。每执行一个 tactic,Goal 窗口会变化:

example : ∀ m n : Nat, Even n → Even (m * n) := by
  -- 初始状态:
  -- ⊢ ∀ (m n : Nat), Even n → Even (m * n)
  
  rintro m n ⟨k, hk⟩
  -- 状态变为:
  -- m n k : Nat
  -- hk : n = k + k
  -- ⊢ Even (m * n)
  
  use m * k
  -- 状态变为:
  -- ⊢ m * n = m * k + m * k
  
  rw [hk]
  -- 状态变为:
  -- ⊢ m * (k + k) = m * k + m * k
  
  ring
  -- 目标解决!

学习建议

把光标放在每个 tactic 后面,观察 Goal 窗口的变化。 这是学习 Lean 最重要的练习

证明项 vs Tactic 的关系

证明项:直接描述"证据是什么"
   ↕ 可以互相嵌套
Tactic:描述"怎么构造证据"

by 关键字:从 tactic 世界切换到证明项世界
  例:⟨m * k, by rw [hk, mul_add]⟩
      ↑ 证明项中嵌入了一个 tactic 块

自动化的力量

本节展示了 simp 的威力:

example : ∀ m n : Nat, Even n → Even (m * n) := by
  intros; simp [*, parity_simps]
--  ↑ 一行搞定!

何时用 simp

  • simp 会尝试所有已知的简化规则
  • simp [*, parity_simps] 中:* 表示使用所有局部假设,parity_simps 是 Mathlib 中关于奇偶性的简化规则集合
  • 适合”显然”的证明,但有时会过度简化导致意外结果
  • 对于学习阶段,建议先用 rw 手动证明,理解原理后再用 simp

本章练习指导

必做练习

  1. #eval "Hello, World!" - 确保环境正常
  2. 类型检查 - 对各种表达式使用 #check,理解类型
  3. Even 证明 - 手动写一遍 tactic 证明,观察状态变化

可跳过内容

  • Acknowledgments 部分(纯致谢)
  • Gitpod/Codespaces 部分(如果你本地安装了 Lean)

本章核心概念总结

概念含义关键字
类型 (Type)Lean 中一切皆有类型#check
Prop命题的类型Prop
证明项类型为 Prop 的项theorem, example
Tactic构造证明的指令by, rw, ring
Goal 窗口显示当前证明状态 符号
sorry占位符,假装证明sorry

预告:第2章会学到什么

第2章开始真正的数学证明,核心 tactic:

  • rw - 重写(替换等式一边)
  • ring - 自动证明代数恒等式
  • calc - 写计算链
  • apply - 应用定理

自测问题

  1. 2 + 2 的类型是什么?2 + 2 = 4 的类型是什么?
  2. sorry 能证明 False 吗?为什么这很危险?
  3. tactic 证明中的 by 关键字起什么作用?

伴读文档 - 第1章完