Skip to content

Commit b98aea0

Browse files
committed
6,7&8
1 parent 5bf4341 commit b98aea0

File tree

6 files changed

+167
-105
lines changed

6 files changed

+167
-105
lines changed

src/SUMMARY.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
- [实例化与抽象化](./kernel_concepts/instantiation_and_abstraction.md)
1515
- [弱归约与强归约](./kernel_concepts/weak_and_strong_reduction.md)
1616
- [名称](./names.md)
17-
- [Levels](./levels.md)
18-
- [Expressions](./expressions/expressions.md)
19-
- [Notes on Implementing Expressions](./expressions/implementing_expressions.md)
20-
- [Declarations](./declarations/declarations.md)
17+
- [宇宙层级](./levels.md)
18+
- [表达式](./expressions/expressions.md)
19+
- [实现表达式的注意事项](./expressions/implementing_expressions.md)
20+
- [声明](./declarations/declarations.md)
2121
- [The Secret Life of Inductive Types](./declarations/inductive.md)
2222
- [Type Inference](./type_checking/type_inference.md)
2323
- [Definitional Equality](./type_checking/definitional_equality.md)
2424
- [Reduction](./type_checking/reduction.md)
25-
- [Open issues & future work](./future_work.md)
25+
- [未来工作与待解决问题](./future_work.md)
2626
- [延伸阅读](./further_reading.md)

src/declarations/declarations.md

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
# Declarations
2-
3-
Declarations are the big ticket items, and are the last domain elements we need to define.
1+
# 声明
42

3+
声明(Declarations)是核心关键部分,也是我们需要定义的最后一类领域元素。
54

65
```
76
declarationInfo ::= Name, (universe params : List Level), (type : Expr)
@@ -42,32 +41,39 @@ declar ::=
4241
RecRule ::= (constructor name : Name), (number of constructor args : Nat), (val : Expr)
4342
```
4443

44+
## 声明检查
4545

46-
## Checking a declaration
46+
对于所有声明,除针对某些声明类型的额外检查外,都会先执行以下初步检查:
4747

48+
* 声明中 `declarationInfo` 的宇宙参数不得有重复。例如,声明 `def Foo.{u, v, u} ...` 是不允许的。
49+
* 声明的类型不得包含自由变量;所有“完成”的声明中的变量都必须对应某个绑定器。
50+
* 声明的类型必须是一个类型(即 `infer declarationInfo.type` 必须产生 `Sort`)。在 Lean 中,声明 `def Foo : Nat.succ := ..` 不被允许,因为 `Nat.succ` 是一个值,而非类型。
4851

49-
For all declarations, the following preliminary checks are performed before any additional procedures specific to certain kinds of declaration:
52+
### 公理
5053

51-
+ The universe parameters in the declaration's `declarationInfo` must not have duplicates. For example, a declaration `def Foo.{u, v, u} ...` would be prohibited.
54+
对公理的检查仅限于上述所有声明通用的检查,确保其 `declarationInfo` 合法。如果公理的宇宙参数有效且类型无自由变量,则可被加入环境。
5255

53-
+ The declaration's type must not have free variables; all variables in a "finished" declaration must correspond to a binder.
56+
### 商类型
5457

55-
+ The declaration's type must be a type (`infer declarationInfo.type` must produce a `Sort`). In Lean, a declaration `def Foo : Nat.succ := ..` is not permitted; `Nat.succ` is a value, not a type.
58+
`Quot` 声明包括 `Quot``Quot.mk``Quot.ind``Quot.lift`。这些声明有预定的类型,在 Lean 理论中被认为是合理的。因此环境中商类型声明必须完全匹配这些类型。它们在内核实现中是硬编码的,因为它们复杂度不高。
5659

57-
### Axiom
60+
### 定义、定理与不透明声明
5861

59-
The only checks done against axioms are those done for all declarations which ensure the `declarationInfo` passes muster. If an axiom has a valid set of universe parameters and a valid type with no free variables, it is admitted to the environment.
62+
定义、定理和不透明声明(opaque)都同时包含一个类型和值。检查这些声明时,会先推断声明值的类型,然后断言推断出的类型与 `declarationInfo` 中指定的类型定义等价。
6063

61-
### Quot
64+
对于定理:
6265

63-
The `Quot` declarations are `Quot`, `Quot.mk`, `Quot.ind`, and `Quot.lift`. These declarations have prescribed types which are known to be sound within Lean's theory, so the environment's quotient declarations must match those types exactly. These types are hard-coded into kernel implementations since they are not prohibitively complex.
66+
* `declarationInfo` 中的类型是用户声称的类型,即用户试图证明的命题;
67+
* 值是用户提供的该命题的证明。
6468

65-
### Definition, theorem, opaque
69+
推断该值的类型即是验证该证明实际证明了什么,而定义等价断言保证了该证明的命题正是用户声称要证明的命题。
6670

67-
Definition, theorem, and opaque are interesting in that they both a type and a value. Checking these declarations involves inferring a type for the declaration's value, then asserting that the inferred type is definitionally equal to the ascribed type in the `declarationInfo`.
71+
#### 可展性提示
6872

69-
In the case of a theorem, the `declarationInfo`'s type is what the user claims the type is, and therefore what the user is claiming to prove, while the value is what the user has offered as a proof of that type. Inferring the type of the received value amounts to checking what the proof is actually a proof of, and the definitional equality assertion ensures that the thing the value proves is actually what the user intended to prove.
73+
可展性提示(Reducibility hints)包含声明应该如何展开的信息:
7074

71-
#### Reducibility hints
75+
* `abbreviation` 通常总是会被展开;
76+
* `opaque` 不会被展开;
77+
* `regular N` 是否展开则依赖于 `N` 的值。
7278

73-
Reducibility hints contain information about how a declaration should be unfolded. An `abbreviation` will generally always be unfolded, `opaque` will not be unfolded, and `regular N` might be unfolded depending on the value of `N`. The `regular` reducibility hints correspond to a definition's "height", which refers to the number of declarations that definition uses to define itself. A definition `x` with a value that refers to definition `y` will have a height value greater than `y`.
79+
`regular` 的可展性提示对应于定义的“高度”,指定义自身依赖的声明数量。若定义 `x` 的值中引用了定义 `y`,则 `x` 的高度必定大于 `y`

src/expressions/expressions.md

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Expressions
1+
# 表达式
22

3-
## Complete syntax
3+
## 完整语法
44

5-
Expressions will be explained in more detail below, but just to get it out in the open, the complete syntax for expressions, including the string and nat literal extensions, is as follows:
5+
关于表达式的具体解释稍后会更详细展开,这里先完整列出表达式的所有语法形式(包括字符串和自然数字面量扩展):
66

77
```
88
Expr ::=
@@ -30,68 +30,72 @@ let ::= Name, (binderType : Expr), (val : Expr) (body : Expr)
3030
proj ::= Name Nat Expr
3131
literal ::= natLit | stringLit
3232
33-
-- Arbitrary precision nat/unsigned integer
33+
-- 任意精度无符号整数
3434
natLit ::= Nat
35-
-- UTF-8 string
35+
-- UTF-8 字符串
3636
stringLit ::= String
3737
38-
-- fvarId can be implemented by unique names or deBruijn levels;
39-
-- unique names are more versatile, deBruijn levels have better
40-
-- cache behavior
38+
-- fvarId 可以通过唯一命名或deBruijn层级来实现;
39+
-- 唯一命名更通用,deBruijn层级有更好的缓存性能
4140
freeVariable ::= Name, Expr, BinderInfo, fvarId
4241
```
42+
一些说明:
4343

44-
Some notes:
44+
* 用于自然数字面量的 `Nat` 应该是任意精度自然数(大整数)。
4545

46-
+ The `Nat` used by nat literals should be an arbitrary precision natural/bignum.
46+
* 带绑定器的表达式(lambda、pi、let、自由变量)可以将三个参数(绑定器名称 binder\_name、绑定器类型 binder\_type、绑定器风格 binder\_style)合并成一个参数 `Binder`,其中 `Binder ::= Name BinderInfo Expr`。在其他伪代码中,我通常会假设它们具有这种属性,因为这样更易读。
4747

48-
+ The expressions that have binders (lambda, pi, let, free variable) can just as easily bundle the three arguments (binder_name, binder_type, binder_style) as one argument `Binder`, where a binder is `Binder ::= Name BinderInfo Expr`. In the pseudocode that appears elsewhere I will usually treat them as though they have that property, because it's easier to read.
48+
* 自由变量的标识符可以是唯一标识符,也可以是 deBruijn 层级。
4949

50-
+ Free variable identifiers can be either unique identifiers, or they can be deBruijn levels.
50+
* Lean 内部使用的表达式类型还有一个 `mdata` 构造子,用于声明附带元数据的表达式。这些元数据不会影响内核中表达式的行为,因此这里不包含该构造子。
5151

52-
+ The expression type used in Lean proper also has an `mdata` constructor, which declares an expression with attached metadata. This metadata does not effect the expression's behavior in the kernel, so we do not include this constructor.
52+
## 绑定器信息(Binder information)
5353

54-
55-
## Binder information
56-
57-
Expressions constructed with the lambda, pi, let, and free variable constructors contain binder information, in the form of a name, a binder "style", and the binder's type. The binder's name and style are only for use by the pretty printer, and do not alter the core procedures of inference, reduction, or equality checking. In the pretty printer however, the binder style may alter the output depending on the pretty printer options. For example, the user may or may not want to display implicit or instance implicits (typeclass variables) in the output.
54+
由 lambda、pi、let 和自由变量构造的表达式都包含绑定器信息,表现为名称、绑定器“风格”和绑定器类型。绑定器的名称和风格仅供美化打印器使用,不影响推断、归约或等价性检查等核心过程。不过美化打印器会根据绑定器风格和打印选项来调整输出,比如用户可能希望显示或隐藏隐式参数或实例隐式(类型类变量)。
5855

5956
### Sort
6057

61-
`sort` is simply a wrapper around a level, allowing it to be used as an expression.
58+
`sort` 只是对层级的包装,允许其作为表达式使用。
6259

60+
### 绑定变量(Bound variables)
6361

64-
### Bound variables
62+
绑定变量以自然数实现,表示 [deBruijn 索引](https://en.wikipedia.org/wiki/De_Bruijn_index)
6563

66-
Bound variables are implemented as natural numbers representing [deBruijn indices](https://en.wikipedia.org/wiki/De_Bruijn_index).
64+
### 自由变量(Free variables)
6765

68-
### Free variables
66+
自由变量用来在绑定器不可用的情况下,传递有关绑定变量的信息。通常这是因为内核已经进入绑定表达式的主体部分,选择不携带结构化的绑定上下文,而是临时用自由变量替换绑定变量,待需要时再用新的(可能不同的)绑定变量重构绑定器。
6967

70-
Free variables are used to convey information about bound variables in situations where the binder is currently unavailable. Usually this is because the kernel has traversed into the body of a binding expression, and has opted not to carry a structured context of the binding information, instead choosing to temporarily swap out the bound variable for a free variable, with the option of swapping in a new (maybe different) bound variable to reconstruct the binder. This unavailability description may sound vague, but a literal explanation that might help is that expressions are implemented as trees without any kind of parent pointer, so when we descend into child nodes (especially across function boundaries), we end up just losing sight of the elements above where we currently are in a given expression.
68+
这种“不可用”的描述或许模糊,但直观来说,表达式是以树结构实现的,且没有任何指向父节点的指针,因此当我们深入子节点(尤其是函数边界)时,会丢失对当前表达式中“上方”元素的直接访问。
7169

72-
When an open expression is closed by reconstructing binders, the bindings may have changed, invalidating previously valid deBruijn indices. The use of unique names or deBruijn levels allow this re-closing of binders to be done in a way that compensates for any changes and ensures the new deBruijn indices of the re-bound variables are valid with respect the reconstructed telescope (see [this section](./kernel_concepts.md#implementing-free-variable-abstraction)).
70+
当对一个开放表达式通过重构绑定器进行闭合时,绑定关系可能已经改变,导致之前有效的 deBruijn 索引失效。使用唯一名称或 deBruijn 层级可以在重闭绑定时补偿这些变化,确保重绑定变量的新 deBruijn 索引相对于重建的望远镜是有效的(详见[实现自由变量抽象](./kernel_concepts.md#implementing-free-variable-abstraction)部分)。
7371

74-
Going forward, we may use some form of the term "free variable identifier" to refer to the objects in whatever scheme (unique IDs or deBruijn levels) an implementation may be using.
72+
今后,我们可能会用“自由变量标识符”一词来泛指实现中使用的对象,无论是唯一 ID 还是 deBruijn 层级。
7573

7674
### `Const`
7775

78-
The `const` constructor is how an expression refers to another declaration in the environment, it must do so by reference.
76+
`const` 构造子表示表达式中对环境中另一个声明的引用,必须通过名称引用。
7977

80-
In example below, `def plusOne` creates a `Definition` declaration, which is checked, then admitted to the environment. Declarations cannot be placed directly in expressions, so when the type of `plusOne_eq_succ` invokes the previous declaration `plusOne`, it must do so by name. An expression is created: `Expr.const (plusOne, [])`, and when the kernel finds this `const` expression, it can look up the declaration referred to by name, `plusOne`, in the environment:
78+
例如,下面代码:
8179

82-
```
80+
```lean
8381
def plusOne : Nat -> Nat := fun x => x + 1
8482
8583
theorem plusOne_eq_succ (n : Nat) : plusOne n = n.succ := rfl
8684
```
8785

88-
Expressions created with the `const` constructor also carry a list of levels which are substituted into any unfolded or inferred declarations taken from the environment by looking up the definition the `const` expression refers to. For example, inferring the type of `const List [Level.param(x)]` involves looking up the declaration for `List` in the current environment, retrieving its type and universe parameters, then substituting `x` for the universe parameter with which `List` was initially declared.
86+
其中 `def plusOne` 创建了一个 `Definition` 声明,经检查后加入环境。声明不能直接嵌入表达式中,因此当 `plusOne_eq_succ` 的类型使用之前声明的 `plusOne` 时,必须通过名称调用。于是产生表达式:
8987

88+
```
89+
Expr.const (plusOne, [])
90+
```
9091

91-
### Lambda, Pi
92+
内核遇到该 `const` 表达式时,会在环境中查找名称为 `plusOne` 的声明。
9293

93-
`lambda` and `pi` expressions (Lean proper uses the name `forallE` instead of `pi`) refer to function abstraction and the "forall" binder (dependent function types) respectively.
94+
`const` 构造的表达式还携带一个层级列表,这些层级会替换环境中对应定义的宇宙参数。例如,推断 `const List [Level.param(x)]` 的类型时,会查找当前环境中的 `List` 声明,获取其类型和宇宙参数,然后用 `x` 替换 `List` 最初声明时的宇宙参数。
9495

96+
### Lambda、Pi
97+
98+
`lambda``pi` 表达式分别表示函数抽象和“forall”绑定器(依赖函数类型)。Lean 内部将 `pi` 命名为 `forallE`
9599

96100
```
97101
binderName body
@@ -106,7 +110,7 @@ fun (foo : Bar) => 0
106110

107111
### Let
108112

109-
`let` is exactly what it sounds like. While `let` expressions are binders, they do not have a `BinderInfo`, their binder info is treated as `Default`.
113+
`let` 就是字面意思的 let 表达式。虽然 `let` 表达式是绑定器,但它们没有显式的 `BinderInfo`,其绑定信息被视为默认(`Default`)。
110114

111115
```
112116
binderName val
@@ -116,10 +120,15 @@ let (foo : Bar) := 0; foo
116120
binderType .... body
117121
```
118122

119-
120123
### App
121124

122-
`app` expressions represent the application of an argument to a function. App nodes are binary (have only two children, a single function and an single argument), so `f x_0 x_1 .. x_N` is represented by `App(App(App(f, x_0), x_1)..., x_N)`, or visualized as a tree:
125+
`app` 表达式表示函数对参数的应用。`app` 节点是二叉的(只有两个子节点:一个函数和一个参数),因此表达式 `f x_0 x_1 ... x_N` 会被表示为嵌套的形式:
126+
127+
```
128+
App(App(App(f, x_0), x_1) ..., x_N)
129+
```
130+
131+
也可以用树状结构来形象表示:
123132

124133
```
125134
App
@@ -135,25 +144,41 @@ let (foo : Bar) := 0; foo
135144
136145
```
137146

138-
An exceedingly common kernel operation for manipulating expressions is folding and unfolding sequences of applications, getting `(f, [x_0, x_1, .., x_N])` from the tree structure above, or folding `f, [x_0, x_1, .., x_N]` into the tree above.
147+
操作表达式时,内核中一个非常常见的操作是 **折叠(folding)****展开(unfolding)** 一系列函数应用。它可以将上文中的树形结构转换成 `(f, [x_0, x_1, ..., x_N])` 的形式,或者反向将 `(f, [x_0, x_1, ..., x_N])` 折叠成那样的树形结构。
148+
149+
---
150+
151+
### 投影(Projections)
152+
153+
`proj` 构造子表示结构体字段的投影。非递归、只有一个构造子且无指标(indices)的归纳类型可以被视为结构体。
139154

155+
`proj` 接受三个参数:
140156

141-
### Projections
157+
* 类型的名称;
158+
* 一个自然数,表示要投影的字段索引;
159+
* 要应用投影的实际结构表达式。
142160

143-
The `proj` constructor represents structure projections. Inductive types that are not recursive, have only one constructor, and have no indices can be structures.
161+
需要注意的是,内核中的投影索引是 **从 0 开始计数** 的,而 Lean 表层语言中是从 1 开始的,且 0 表示跳过构造子参数后的第一个非参数参数。
162+
163+
例如,内核表达式:
164+
165+
```
166+
proj Prod 0 (@Prod.mk A B a b)
167+
```
144168

145-
The constructor takes a name, which is the name of the type, a natural number indicating the field being projected, and the actual structure the projection is being applied to.
169+
会投影字段 `a`,因为它是跳过参数 `A``B` 后的第 0 个字段。
146170

147-
Be aware that in the kernel, projection indices are 0-based, despite being 1-based in Lean's vernacular, where 0 is the first non-parameter argument to the constructor.
171+
虽然使用类型的递归器(recursor)也能实现 `proj` 的功能,但 `proj` 能更高效地处理内核中的常用操作。
148172

149-
For example, the kernel expression `proj Prod 0 (@Prod.mk A B a b)` would project the `a`, because it is the 0th field after skipping the parameters `A` and `B`.
173+
---
150174

151-
While the behavior offered by `proj` can be accomplished by using the type's recursor, `proj` more efficiently handles frequent kernel operations.
175+
### 字面量(Literals)
152176

153-
### Literals
177+
Lean 内核可选支持任意精度的自然数(Nat)和字符串(String)字面量。
154178

155-
Lean's kernel optionally supports arbitrary precision Nat and String literals. As needed, the kernel can transform a nat literal `n` to `Nat.zero` or `Nat.succ m`, or convert a string literal `s` to `String.mk List.nil` or `String.mk (List.cons (Char.ofNat _) ...)`.
179+
* 内核可以将自然数字面量 `n` 转换为 `Nat.zero``Nat.succ m` 形式;
180+
* 字符串字面量 `s` 则可转换为 `String.mk List.nil``String.mk (List.cons (Char.ofNat _) ...)`
156181

157-
String literals are lazily converted to lists of characters for testing definitional equality, and when they appear as the major premise in reduction of a recursor.
182+
字符串字面量采用惰性转换成字符列表,用于定义等价性测试以及递归器归约时的主要前提。
158183

159-
Nat literals are supported in the same positions as strings (definitional equality and major premises of a recursor application), but the kernel also provide support for addition, multiplication, exponentiation, subtraction, mod, division, as well as boolean equality and "less than or equal" comparisons on nat literals.
184+
自然数字面量可用在与字符串相同的场合(定义等价性和递归器的主要前提),除此之外,内核还支持对自然数字面量的加法、乘法、指数运算、减法、模运算、除法,以及布尔型的等于和“小于等于”比较操作。

0 commit comments

Comments
 (0)