migrate all tutorials from Markdown to Org mode

Converted with pandoc 3.7 (markdown → org), all 17 files:
- README, references, 15 tutorial units
- Internal file links updated from .md to .org
- Source code blocks (#+begin_src lean) preserved
- Tables, math notation, links intact

For the Emacs workflow.
This commit is contained in:
2026-05-28 20:15:38 +02:00
parent 0cf85517c2
commit 6e2914b06e
22 changed files with 805 additions and 611 deletions

View File

@@ -1,28 +1,36 @@
# Unit 8 Representing Syntax
**Tutorial 2: PL Semantics in Lean** · [← Back to README](../README.md)
## Goals
* Unit 8 --- Representing Syntax
:PROPERTIES:
:CUSTOM_ID: unit-8-representing-syntax
:END:
*Tutorial 2: PL Semantics in Lean* · [[../README.org][← Back to README]]
** Goals
:PROPERTIES:
:CUSTOM_ID: goals
:END:
- Encode lambda calculus terms as an inductive type
- Understand three binding representations:
1. **Named** (strings simple, but α-equiv isn't definitional)
2. **de Bruijn indices** (numbers α-equiv is free, shifting is painful)
3. **Locally nameless** (free vars named, bound vars indexed compromise)
1. *Named* (strings --- simple, but α-equiv isn't definitional)
2. *de Bruijn indices* (numbers --- α-equiv is free, shifting is painful)
3. *Locally nameless* (free vars named, bound vars indexed --- compromise)
We'll use de Bruijn indices (the "heavy lifter") for the rest of this tutorial,
with locally nameless for comparison.
## Sources
- syndikos/lean4-stlc `Syntax.lean`: https://github.com/syndikos/lean4-stlc
** Sources
:PROPERTIES:
:CUSTOM_ID: sources
:END:
- syndikos/lean4-stlc =Syntax.lean=: https://github.com/syndikos/lean4-stlc
- Chris Henson 2025: https://chrishenson.net/posts/2025-05-10-formalized_lambda_calculus.html
- chenson2018/LeanScratch: https://github.com/chenson2018/LeanScratch
- Software Foundations Vol.2: https://softwarefoundations.cis.upenn.edu/
## Exercises
```lean
** Exercises
:PROPERTIES:
:CUSTOM_ID: exercises
:END:
#+begin_src lean
-- 8.1 — Named representation
inductive NamedTerm where
| var (x : String)
@@ -68,15 +76,17 @@ inductive LNTerm where
| lam (body : LNTerm) -- binder
| app (f arg : LNTerm)
deriving Repr
```
#+end_src
### Key insight for PL semantics
When we encode **typing contexts** `Γ = x₁:τ₁, x₂:τ₂, ...`, de Bruijn indices
*** Key insight for PL semantics
:PROPERTIES:
:CUSTOM_ID: key-insight-for-pl-semantics
:END:
When we encode *typing contexts* =Γ = x₁:τ₁, x₂:τ₂, ...=, de Bruijn indices
give us "index into the context" for free. The last binding is index 0, the
second-last is index 1, etc. This makes the typing rules elegant in Lean
second-last is index 1, etc. This makes the typing rules elegant in Lean ---
no name-clash avoidance needed.
---
--------------
← [Tutorial 1 — Unit 7](../tutorial-01-basics/07-dependent-types.md) · Next: [Unit 9 — Substitution](09-substitution.md)
← [[../tutorial-01-basics/07-dependent-types.org][Tutorial 1 --- Unit 7]] · Next: [[file:09-substitution.org][Unit 9 --- Substitution]]

View File

@@ -1,22 +1,30 @@
# Unit 9 Substitution and α-Equivalence
* Unit 9 --- Substitution and α-Equivalence
:PROPERTIES:
:CUSTOM_ID: unit-9-substitution-and-α-equivalence
:END:
*Tutorial 2: PL Semantics in Lean* · [[../README.org][← Back to README]]
**Tutorial 2: PL Semantics in Lean** · [← Back to README](../README.md)
## Goals
- Implement `subst` (substitution) for de Bruijn terms
- Implement `lift` (index shifting) the key operation that avoids capture
** Goals
:PROPERTIES:
:CUSTOM_ID: goals
:END:
- Implement =subst= (substitution) for de Bruijn terms
- Implement =lift= (index shifting) --- the key operation that avoids capture
- Prove fundamental substitution lemmas
## Sources
- syndikos/lean4-stlc `Syntax.lean` and `Reduction.lean`
** Sources
:PROPERTIES:
:CUSTOM_ID: sources
:END:
- syndikos/lean4-stlc =Syntax.lean= and =Reduction.lean=
- chenson2018/LeanScratch: https://github.com/chenson2018/LeanScratch
- PLFA Part 2: https://plfa.github.io/
## Exercises
```lean
** Exercises
:PROPERTIES:
:CUSTOM_ID: exercises
:END:
#+begin_src lean
open DBTerm -- from Unit 8
-- 9.1 — Lift: shift all *free* variables above a cutoff by k
@@ -67,15 +75,17 @@ lemma subst_lift_commute (t s : DBTerm) (n : Nat) :
-- This lemma is *critical* for proving preservation/type safety later.
-- It says that shifting before and after substitution agree.
```
### Why this matters
#+end_src
*** Why this matters
:PROPERTIES:
:CUSTOM_ID: why-this-matters
:END:
Substitution is the core operation of operational semantics. Doing it right
(no variable capture) is the hardest part of formalizing lambda calculi.
de Bruijn indices make capture impossible the arithmetic is mechanical.
de Bruijn indices make capture impossible --- the arithmetic is mechanical.
The lemmas here are boilerplate you prove once, then reuse everywhere.
---
--------------
← [Previous: Unit 8](08-syntax-representation.md) · Next: [Unit 10 — Small-Step Semantics](10-small-step-semantics.md)
← [[file:08-syntax-representation.org][Previous: Unit 8]] · Next: [[file:10-small-step-semantics.org][Unit 10 --- Small-Step Semantics]]

View File

@@ -1,22 +1,30 @@
# Unit 10 Small-Step Operational Semantics
* Unit 10 --- Small-Step Operational Semantics
:PROPERTIES:
:CUSTOM_ID: unit-10-small-step-operational-semantics
:END:
*Tutorial 2: PL Semantics in Lean* · [[../README.org][← Back to README]]
**Tutorial 2: PL Semantics in Lean** · [← Back to README](../README.md)
** Goals
:PROPERTIES:
:CUSTOM_ID: goals
:END:
- Define single-step reduction =→= for call-by-value λ-calculus
- Define reflexive-transitive closure =→*=
- Prove determinism: =t → t₁ ∧ t → t₂ ⇒ t₁ = t₂=
## Goals
- Define single-step reduction `→` for call-by-value λ-calculus
- Define reflexive-transitive closure `→*`
- Prove determinism: `t → t₁ ∧ t → t₂ ⇒ t₁ = t₂`
## Sources
- syndikos/lean4-stlc `Reduction.lean`, `Semantics.lean`
** Sources
:PROPERTIES:
:CUSTOM_ID: sources
:END:
- syndikos/lean4-stlc =Reduction.lean=, =Semantics.lean=
- Software Foundations Vol.2 "Smallstep"
- PLFA Part 2
## Exercises
```lean
** Exercises
:PROPERTIES:
:CUSTOM_ID: exercises
:END:
#+begin_src lean
open DBTerm
-- 10.1 — Single-step cbv reduction
@@ -62,4 +70,4 @@ def stuckExample : DBTerm :=
app (var 0) (var 1) -- a free variable applied to another free variable
-- Show it's stuck (you'll prove something similar in Unit 12 with types)
```
#+end_src

View File

@@ -1,22 +1,30 @@
# Unit 11 STLC Type System
* Unit 11 --- STLC Type System
:PROPERTIES:
:CUSTOM_ID: unit-11-stlc-type-system
:END:
*Tutorial 2: PL Semantics in Lean* · [[../README.org][← Back to README]]
**Tutorial 2: PL Semantics in Lean** · [← Back to README](../README.md)
** Goals
:PROPERTIES:
:CUSTOM_ID: goals
:END:
- Define simple types (=Nat → Bool=, etc.)
- Define typing contexts =Γ= as lists of types
- Encode the STLC typing judgment =Γ ⊢ t : τ=
## Goals
- Define simple types (`Nat → Bool`, etc.)
- Define typing contexts `Γ` as lists of types
- Encode the STLC typing judgment `Γ ⊢ t : τ`
## Sources
- syndikos/lean4-stlc `Typing.lean`
** Sources
:PROPERTIES:
:CUSTOM_ID: sources
:END:
- syndikos/lean4-stlc =Typing.lean=
- Software Foundations Vol.2 "Types"
- sdemos/type-inference for type inference perspective
## Exercises
```lean
** Exercises
:PROPERTIES:
:CUSTOM_ID: exercises
:END:
#+begin_src lean
open DBTerm
-- 11.1 — Types
@@ -75,4 +83,4 @@ theorem weakening (Γ Δ : Ctx) (t : DBTerm) (τ : Ty)
(h : HasType Γ t τ) (hsub : ∀ i, lookup Γ i = lookup (Δ ++ Γ) i) : HasType (Δ ++ Γ) t τ :=
by
sorry
```
#+end_src

View File

@@ -1,22 +1,30 @@
# Unit 12 Type Safety (Progress + Preservation)
* Unit 12 --- Type Safety (Progress + Preservation)
:PROPERTIES:
:CUSTOM_ID: unit-12-type-safety-progress-preservation
:END:
*Tutorial 2: PL Semantics in Lean* · [[../README.org][← Back to README]]
**Tutorial 2: PL Semantics in Lean** · [← Back to README](../README.md)
** Goals
:PROPERTIES:
:CUSTOM_ID: goals
:END:
- Prove *Progress*: well-typed terms are either values or can step
- Prove *Preservation* (Subject Reduction): types survive reduction
- Combine them: *Type Soundness* = well-typed programs don't get stuck
## Goals
- Prove **Progress**: well-typed terms are either values or can step
- Prove **Preservation** (Subject Reduction): types survive reduction
- Combine them: **Type Soundness** = well-typed programs don't get stuck
## Sources
- syndikos/lean4-stlc `Metatheory.lean`
** Sources
:PROPERTIES:
:CUSTOM_ID: sources
:END:
- syndikos/lean4-stlc =Metatheory.lean=
- Software Foundations Vol.2
- PLFA Part 2: DeBruijn chapter
## Key Lemmas
```
** Key Lemmas
:PROPERTIES:
:CUSTOM_ID: key-lemmas
:END:
#+begin_example
Canonical Forms:
If [] ⊢ v : τ₁ ⇒ τ₂ and v is a value, then v = λ.t
@@ -28,11 +36,13 @@ Preservation:
Progress:
If [] ⊢ t : τ, then either Value t or ∃ t', t → t'
```
#+end_example
## Exercises
```lean
** Exercises
:PROPERTIES:
:CUSTOM_ID: exercises
:END:
#+begin_src lean
open DBTerm
open Step
open HasType
@@ -101,4 +111,4 @@ theorem soundness {t : DBTerm} {τ : Ty} (h : HasType [] t τ) :
· exact hnotval hv
· apply hnostep
exact hstep
```
#+end_src

View File

@@ -1,43 +1,56 @@
# Unit 13 Hindley-Milner Declarative Typing Rules
* Unit 13 --- Hindley-Milner Declarative Typing Rules
:PROPERTIES:
:CUSTOM_ID: unit-13-hindley-milner-declarative-typing-rules
:END:
*Tutorial 2: PL Semantics in Lean* · [[../README.org][← Back to README]]
**Tutorial 2: PL Semantics in Lean** · [← Back to README](../README.md)
## Goals
- Extend STLC with **let-polymorphism**
- Encode HM types with **type schemes** `∀α. τ`
** Goals
:PROPERTIES:
:CUSTOM_ID: goals
:END:
- Extend STLC with *let-polymorphism*
- Encode HM types with *type schemes* =∀α. τ=
- Formalize the 6 declarative typing rules (Var, App, Abs, Let, Inst, Gen)
- Understand the distinction between monomorphic (`τ`) and polymorphic (`σ = ∀α.τ`) types
- Understand the distinction between monomorphic (=τ=) and polymorphic (=σ = ∀α.τ=) types
## Sources
** Sources
:PROPERTIES:
:CUSTOM_ID: sources
:END:
- [[https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system][Wikipedia: Hindley-Milner type system]]
- [[https://www.jeffvaughan.net/docs/hmproof.pdf][Vaughan 2008]] (declarative rules, §2)
- [[https://github.com/sdemos/type-inference][sdemos/type-inference]] (Lean formalization)
- [Wikipedia: Hindley-Milner type system](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system)
- [Vaughan 2008](https://www.jeffvaughan.net/docs/hmproof.pdf) (declarative rules, §2)
- [sdemos/type-inference](https://github.com/sdemos/type-inference) (Lean formalization)
** Background
:PROPERTIES:
:CUSTOM_ID: background
:END:
HM adds *let-polymorphism* to STLC:
## Background
HM adds **let-polymorphism** to STLC:
```
#+begin_example
let x = e₁ in e₂
```
In STLC, `x` would have a single monomorphic type. In HM, `x` gets a type
*scheme* — e.g., `∀α. αα` for the identity function — and each use of `x`
#+end_example
In STLC, =x= would have a single monomorphic type. In HM, =x= gets a type
/scheme/ --- e.g., =∀α. αα= for the identity function --- and each use of =x=
instantiates the scheme with fresh type variables.
The declarative rules:
```
#+begin_example
Var: Γ, x:σ ⊢ x : σ
App: Γ ⊢ e₁ : τ₁ → τ₂ Γ ⊢ e₂ : τ₁ ⇛ Γ ⊢ e₁ e₂ : τ₂
Abs: Γ, x:τ₁ ⊢ e : τ₂ ⇛ Γ ⊢ λx.e : τ₁ → τ₂
Let: Γ ⊢ e₁ : σ Γ, x:σ ⊢ e₂ : τ ⇛ Γ ⊢ let x = e₁ in e₂ : τ
Inst: Γ ⊢ e : ∀α.τ ⇛ Γ ⊢ e : τ[α := τ']
Gen: Γ ⊢ e : τ ∧ α ∉ ftv(Γ) ⇛ Γ ⊢ e : ∀α.τ
```
#+end_example
## Exercises
```lean
** Exercises
:PROPERTIES:
:CUSTOM_ID: exercises
:END:
#+begin_src lean
-- 13.1 — Types and type schemes
inductive MonoType where
| tvar (id : Nat) -- type variable α
@@ -112,8 +125,8 @@ theorem self_app_id_typed (τ : MonoType) :
HMTyping [] self_app_id {vars := [], body := τ ⇒ τ} :=
by
sorry
```
#+end_src
---
--------------
← [Previous: Unit 12](12-type-safety.md) · Next: [Unit 14 — Algorithm W](14-algorithm-w.md)
← [[file:12-type-safety.org][Previous: Unit 12]] · Next: [[file:14-algorithm-w.org][Unit 14 --- Algorithm W]]

View File

@@ -1,39 +1,49 @@
# Unit 14 Algorithm W (Hindley-Milner Type Inference)
**Tutorial 2: PL Semantics in Lean** · [← Back to README](../README.md)
## Goals
* Unit 14 --- Algorithm W (Hindley-Milner Type Inference)
:PROPERTIES:
:CUSTOM_ID: unit-14-algorithm-w-hindley-milner-type-inference
:END:
*Tutorial 2: PL Semantics in Lean* · [[../README.org][← Back to README]]
** Goals
:PROPERTIES:
:CUSTOM_ID: goals
:END:
- Understand type inference as solving unification constraints
- Implement **Algorithm W**: the classic HM inference algorithm
- Write `unify` (Robinson's unification)
- Write `infer` (the main inference loop)
- Implement *Algorithm W*: the classic HM inference algorithm
- Write =unify= (Robinson's unification)
- Write =infer= (the main inference loop)
## Sources
- [Vaughan 2008, §3](https://www.jeffvaughan.net/docs/hmproof.pdf)
- [sdemos/type-inference](https://github.com/sdemos/type-inference)
- [Wikipedia: Algorithm W](https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system#Algorithm_W)
## Background
** Sources
:PROPERTIES:
:CUSTOM_ID: sources
:END:
- [[https://www.jeffvaughan.net/docs/hmproof.pdf][Vaughan 2008, §3]]
- [[https://github.com/sdemos/type-inference][sdemos/type-inference]]
- [[https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system#Algorithm_W][Wikipedia: Algorithm W]]
** Background
:PROPERTIES:
:CUSTOM_ID: background
:END:
Algorithm W takes an expression and returns a substitution + type:
```
#+begin_example
infer(Γ, e) = (S, τ)
```
#+end_example
- `Γ` maps variables to type schemes
- `e` is the expression to type
- `S` is a type substitution (unifies constraints found during inference)
- `τ` is the inferred monotype
- =Γ= maps variables to type schemes
- =e= is the expression to type
- =S= is a type substitution (unifies constraints found during inference)
- =τ= is the inferred monotype
The algorithm uses a supply of *fresh type variables* to build constraints,
The algorithm uses a supply of /fresh type variables/ to build constraints,
then unifies them.
## Exercises
```lean
** Exercises
:PROPERTIES:
:CUSTOM_ID: exercises
:END:
#+begin_src lean
open MonoType
open HMExpr
open TypeScheme
@@ -149,8 +159,8 @@ def infer_id : Option (Subst × MonoType × Nat) :=
-- 14.7 — Exercise: infer the type of let x = λy. y in x x
def infer_self_app : Option (Subst × MonoType × Nat) :=
inferW [] self_app_id 0
```
#+end_src
---
--------------
← [Previous: Unit 13](13-hm-declarative.md) · Next: [Unit 15 — Soundness and Completeness](15-soundness-completeness.md)
← [[file:13-hm-declarative.org][Previous: Unit 13]] · Next: [[file:15-soundness-completeness.org][Unit 15 --- Soundness and Completeness]]

View File

@@ -1,28 +1,38 @@
# Unit 15 Soundness and Completeness of Algorithm W
* Unit 15 --- Soundness and Completeness of Algorithm W
:PROPERTIES:
:CUSTOM_ID: unit-15-soundness-and-completeness-of-algorithm-w
:END:
*Tutorial 2: PL Semantics in Lean* · [[../README.org][← Back to README]]
**Tutorial 2: PL Semantics in Lean** · [← Back to README](../README.md)
## Goals
- Prove that Algorithm W is **sound**: every inferred type is derivable in the declarative system
- Prove that Algorithm W is **complete**: every derivable type can be inferred (up to generalization)
** Goals
:PROPERTIES:
:CUSTOM_ID: goals
:END:
- Prove that Algorithm W is *sound*: every inferred type is derivable in the declarative system
- Prove that Algorithm W is *complete*: every derivable type can be inferred (up to generalization)
- Understand the relationship between inference and declarative rules
## Sources
** Sources
:PROPERTIES:
:CUSTOM_ID: sources
:END:
- [[https://www.jeffvaughan.net/docs/hmproof.pdf][Vaughan 2008, §4]]
- [[https://github.com/sdemos/type-inference][sdemos/type-inference]] =Soundness.lean=, =Completeness.lean=
- [Vaughan 2008, §4](https://www.jeffvaughan.net/docs/hmproof.pdf)
- [sdemos/type-inference](https://github.com/sdemos/type-inference) `Soundness.lean`, `Completeness.lean`
** The Theorems
:PROPERTIES:
:CUSTOM_ID: the-theorems
:END:
*Soundness*: If =infer(Γ, e) = (S, τ)=, then =Γ ⊢ e : τ= declaratively.
## The Theorems
*Completeness*: If =Γ ⊢ e : τ= declaratively, then there exists =S, τ'= such that
=infer(Γ, e) = (S, τ')= and =τ= is a substitution instance of =τ'= (i.e., W finds the /most general/ type).
**Soundness**: If `infer(Γ, e) = (S, τ)`, then `Γ ⊢ e : τ` declaratively.
**Completeness**: If `Γ ⊢ e : τ` declaratively, then there exists `S, τ'` such that
`infer(Γ, e) = (S, τ')` and `τ` is a substitution instance of `τ'` (i.e., W finds the *most general* type).
## Exercises
```lean
** Exercises
:PROPERTIES:
:CUSTOM_ID: exercises
:END:
#+begin_src lean
open HMTyping
open MonoType
@@ -78,8 +88,8 @@ theorem principal_types (Γ : HMEnv) (e : HMExpr) (σ : TypeScheme)
(∃ S', applySubst S' τ_principal = σ.body) :=
by
exact completeness_W Γ e σ h
```
#+end_src
---
--------------
← [Previous: Unit 14](14-algorithm-w.md) · [← Tutorial 2 Index](.) · [← Back to README](../README.md)
← [[file:14-algorithm-w.org][Previous: Unit 14]] · [[file:.][← Tutorial 2 Index]] · [[../README.org][← Back to README]]