LEAN
类
structure:类
inductive:递归定义类
class:类型类:方法
构造主义
Lean(以及 Coq 等)本身只是“形式化数学的工具/平台”,它的底层逻辑“天然支持”构造性逻辑,但——
- Lean 内部确实默认使用构造主义(你写出来的函数、证明都要求是具体的/可以检查的对象)。
- Lean 也可以引入经典公理(如排中律),此时系统本身逻辑就“升格”为经典逻辑环境,且用户可以自由选择是否采用构造/经典逻辑。
- mathlib(Lean 的数学库)专注于数学实际工作,往往默认会局部引入排中律等经典公理,以便和大多数数学文献一致。
- 你可以在 Lean 里使用
open classical或加公理axiom em : ∀ P : Prop, P ∨ ¬P
因此,Lean 是构造性基础的,但对经典逻辑“兼容并蓄”,可以按需切换。
类型论
degree & universe
| sort | type | term |
|---|---|---|
| Prop (Sort 0) | True | True.intro |
| Type (Sort 1) | Bool | true |
| Type 1 (Sort 2) | Nat → Type | fun n => Fin n |
| Type 2 (Sort 3) | Type → Type 1 | fun (_ : Type) => Type |
| … | … | … |
| →度(degree)上升 | ||
| ↓宇宙(universe)的变化 |
polymorphic
1 | |
实际上这里的u不是目标语言的项,应该把 Type u 看成一个整体
dependent
types can depend on parameters
如果类型签名写Type → α → List α → List α α的指代不清晰
建议写cons (α : Type) (a : α) (as : List α) : List α
/fu_language cons α : Type : α → List α → List α
在 Haskell 中,cons 的类型是隐式多态的:cons :: α -> [α] -> [α]: 类型变量 α 由类型推断自动填充,无需显式传递 Type 参数。
dependent function type, or dependent arrow type, Pi-type:α : Type and β : α → Type i.e. β: (a : α) → β a also writen as $\prod _{a :\alpha} ~\beta ~a$
dependent Cartesian product types (a : α) × β a also writen as $\sum _{a :\alpha} ~\beta ~a$
eg.godown := Sigma (λ n : Nat => Fin n) <2,1>:godown
Implicit Arguments
def bs : Lst Nat := Lst.cons _ 5 (Lst.nil _)def Lst.cons {α : Type u} (a : α) (as : Lst α) : Lst α := List.cons a as
Lean 为了类型推断和后续泛化方便,在你没有指定具体类型参数时,用 ?m.n 这种形式“占位”。
1 | |
括号减少 “signature 损耗/粉饰” i.e. (ident) 的括号阻止了 Lean 自动展开 ident 的定义,因此只显示其未实例化的类型, Lean 仅检查 部分应用 的 ident(未提供隐式参数 α),因此类型暂时无法确定
@ident(显式化所有隐式参数)
1 | |
The process of instantiating these “holes,” or “placeholders,” in a term is often known as elaboration.细化
structures, typeclasses, sigma/record types
structures, typeclasses and sigma/record types are the same thing semantically, but typeclasses have a special role in automation and interface design
下面详细对比和举例 Lean 中三种相关的语法:structure、typeclass(class)、sigma/record types。
1. structure
定义一个结构体,类似于数学中的记录类型(record)。所有字段都要初始化。
1 | |
2. typeclass(class)
用 class 关键字声明一个类型类,Lean 自动把它视作结构体,加上类型类自动推断机制。
1 | |
说明:
class语法跟structure基本一致,但 Lean 给它加了类型类机制。- 用方括号
[MyGroup G]可让 Lean 自动找实例。
3. sigma/record types
Sigma 类型(dependent pair),Lean 语法是 Σ x : A, B x 或 Sigma A B,手写比较多用于某些依赖类型场景。
通常,structure 就是 record type,Sigma 是依赖记录。
1 | |
λ-calculus
1 | |
x: bound variable
def
let : Lean also allows you to introduce “local” definitions using the let keyword. The expression let a := t1; t2 is definitionally equal to the result of replacing every occurrence of a in t2 by t1.
1 | |
Curry-Howard 同构
the type Prop is syntactic sugar for Sort 0(类型中的一种), Type u is also just syntactic sugar for Sort (u+1)
命题即类型
- 而Prop是类型的类型
- 依赖变量的Prop依然是Prop
Theorem,Lemma,Colloray本身是某个Prop的项, 证明即程序 - 一个Prop如果有项则为真
we can use the usual function space constructor p → q from dependent type theory as our notion of implication.
A是B A:B
对p : Prop i.e. Sort 0 , t1 t2 : p , 认为 t1 t2 是定义等价的 , sort 0 的性质, 即更低的层级没有意义, 即只是形式上的东西.语法|语义
From the constructive point of view, proofs are abstract mathematical objects that are denoted by suitable expressions in dependent type theory.
we will slip back and forth between these two ways of talking, at times saying that an expression “==constructs==” or “produces” or “returns” a proof of a proposition, and at other times simply saying that it “is” such a proof. This is similar to the way that computer scientists occasionally blur the distinction between syntax and semantics by saying, at times, that a program “computes” a certain function, and at other times speaking as though the program “is” the function in question.
To prove that assertion, we need to exhibit a term t : p.
head 名称 (输入:类型): 类型 := 值
theorem name : Prop:= Proof
example=Theorem foo
the #print command will show you the proof of a theorem:
And.intro h1 h2 | p And q
∀ x, P(x)对应依赖函数类型(x : X) → P xi.e $\prod _{a:\alpha} ~\beta ~a$ 是指数对象的推广 $\beta ^\alpha$∃ x, P(x)对应依赖对类型{x : X // P x}i.e. $\sum _{a:\alpha} ~\beta ~a$ 是乘积对象的推广 $\alpha \times\beta$
量词范围默认向右延伸到表达式结束
此时,Σ (n : ℕ), n % 2 = 0 的类型仍然是 Type(偶数类型),但它的 可居性 被解释为命题的真假。
1 | |
1 | |

Calculational Proofs
1 | |
证明策略(tactic)
We will describe proofs that consist of sequences of tactics as “tactic-style” proofs, to contrast with the ways of writing proof terms we have seen so far, which we will call “term-style” proofs. Each style has its own advantages and disadvantages. For example, tactic-style proofs can be harder to read, because they require the reader to predict or guess the results of each instruction. But they can also be shorter and easier to write. Moreover, tactics offer a gateway to using Lean’s automation, since automated procedures are themselves tactics.
Natural Number Game
[[lean4game-g_leanprover-community_nng4-2025_7_11.json]]
实际上本来就有这些参数, 只是lean可以结合上下文自动推断
默认作用在goal上, 可以用at 指定对象, ⊢指当前目标
注意名称中都是是下划线
rfl
exact: Now you could finish with rw [h] then rfl, but exact h does it in one line.
- doesn’t just take hypotheses, it will eat any proof which exists in the system.
exact succ_eq_add_one x相当于把(n : ℕ) : MyNat.succ n = n + 1反着用
trivial: If you can turn your goal into True, then the trivial tactic will solve it.
rw
- repeat rw: 注意对 add_comm会带来死循环, 但是可以 add_comm n
- rw [add_zero c]: 实际上本来就有这些参数, 只是lean可以结合上下文自动推断
- rw [\l h]
- nth_rewrite n [h] : 注意是下划线
- rw [zero_add] at h
apply$\Rightarrow$
- apply h1 at h2
- apply h: p ->q will turn the goal q into p
symm: apply h: a = b -> b=a
intro h will turn the gaol p -> q into hypothesis p and goal q
induction n with d hd
d指归纳步骤里出现的前一个数(即n = d + 1时的d),hd就是归纳假设(hypothesis of induction)在n = d时成立的假设。- …generalizing c将变量
c也提升为归纳假设的通用参数
contrapose: 逆否,contrapose! h !表示自动化简
constructor
cases:存在命题同样需要cases引入,如cases h with c hc if h : a ≤ b
if you have a hypothesis h : False then you are done, because a false statement implies any statement.
cases hyz with b hb will turn x ≤ y into hb: x+b =y (or tauto)
left right:changes a goal of P ∨ Q into a goal of PorQ
have: The have tactic can be used to add new hypotheses
use:prove an “exists” statement
simp only [add_assoc, add_left_comm, add_comm]
decide: decide will attempt to solve a goal if it can find an algorithm which it can run to solve it.
1 | |
tauto:The tauto tactic will solve any goal which can be solved purely by logic (that is, by truth tables).
a ≠ b is notation for a = b → False so just intro h to use reductio ad absurdum
forward | backward
构造
1 | |
实际上是(-1), 但是减法还没定义, 构造保证了良定义
1 | |
实际上是(==0), 但是(==)还没定义
- 设计语言避免不必要的转换:eg存在命题,蕴含与条件
元编程
宏
1 | |
Lean4Align
1 | |