Initial commit: 15-unit Lean 4 + PL semantics tutorial curriculum
This commit is contained in:
107
tutorial-01-basics/01-types-and-functions.md
Normal file
107
tutorial-01-basics/01-types-and-functions.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Unit 1 — Types and Functions
|
||||
|
||||
**Tutorial 1: Lean 4 Fundamentals** · [← Back to README](../README.md)
|
||||
|
||||
## Goals
|
||||
|
||||
- Define functions with `def` and lambda notation
|
||||
- Understand Lean's basic types: `Nat`, `Int`, `String`, `Bool`, `List`, `Option`
|
||||
- Use pattern matching and `match` expressions
|
||||
- Run code with `#eval`
|
||||
|
||||
## Source
|
||||
|
||||
*Functional Programming in Lean* (FPIL), Chapters 1–2
|
||||
→ https://lean-lang.org/functional_programming_in_lean/
|
||||
|
||||
## Concepts
|
||||
|
||||
| Concept | Lean syntax | Example |
|
||||
|---------|------------|---------|
|
||||
| Function definition | `def f (x : Nat) : Nat :=` | `def double (x : Nat) : Nat := x + x` |
|
||||
| Lambda | `fun x => ...` | `fun x => x + 1` |
|
||||
| Pattern matching | `match e with \| pat => ...` | `match n with \| 0 => "zero" \| _ => "non-zero"` |
|
||||
| Recursion | `def f ... := match ...` | Structural recursion only (no general fixpoint) |
|
||||
| `#eval` | `#eval expr` | `#eval double 21` prints `42` |
|
||||
|
||||
## Exercises
|
||||
|
||||
> **How to work**: Create a file `Unit1.lean`. Write each exercise, then
|
||||
> `#eval` to test it (if it's a function) or just make it compile (if it's a
|
||||
> proof or definition). Fill in the `sorry` placeholders.
|
||||
|
||||
### Exercise 1.1 — Warm-up functions
|
||||
|
||||
```lean
|
||||
-- (a) Write a function that returns the absolute difference between two nats
|
||||
def absDiff (a b : Nat) : Nat :=
|
||||
sorry
|
||||
|
||||
#eval absDiff 7 3 -- expected: 4
|
||||
#eval absDiff 3 7 -- expected: 4
|
||||
#eval absDiff 5 5 -- expected: 0
|
||||
|
||||
-- (b) Write a function that checks whether a list contains an element
|
||||
def contains [BEq α] (x : α) (xs : List α) : Bool :=
|
||||
sorry
|
||||
|
||||
#eval contains 3 [1, 2, 3, 4] -- expected: true
|
||||
#eval contains 5 [1, 2, 3, 4] -- expected: false
|
||||
|
||||
-- (c) Write `map` (without looking at the standard library)
|
||||
def myMap (f : α → β) (xs : List α) : List β :=
|
||||
sorry
|
||||
|
||||
#eval myMap (fun x => x * 2) [1, 2, 3] -- expected: [2, 4, 6]
|
||||
```
|
||||
|
||||
### Exercise 1.2 — Recursion on lists
|
||||
|
||||
```lean
|
||||
-- (a) Sum of a list
|
||||
def sumList (xs : List Nat) : Nat :=
|
||||
sorry
|
||||
|
||||
#eval sumList [1, 2, 3, 4] -- expected: 10
|
||||
|
||||
-- (b) Reverse a list (the slow way is fine)
|
||||
def myReverse (xs : List α) : List α :=
|
||||
sorry
|
||||
|
||||
#eval myReverse [1, 2, 3] -- expected: [3, 2, 1]
|
||||
|
||||
-- (c) Filter: keep elements satisfying p
|
||||
def myFilter (p : α → Bool) (xs : List α) : List α :=
|
||||
sorry
|
||||
|
||||
#eval myFilter (fun x => x % 2 == 0) [1, 2, 3, 4, 5, 6] -- expected: [2, 4, 6]
|
||||
```
|
||||
|
||||
### Exercise 1.3 — Option type
|
||||
|
||||
```lean
|
||||
-- (a) Safe head
|
||||
def safeHead (xs : List α) : Option α :=
|
||||
sorry
|
||||
|
||||
#eval safeHead ([1, 2, 3] : List Nat) -- expected: some 1
|
||||
#eval safeHead ([] : List Nat) -- expected: none
|
||||
|
||||
-- (b) Safe division
|
||||
def safeDiv (a b : Nat) : Option Nat :=
|
||||
sorry
|
||||
|
||||
#eval safeDiv 10 2 -- expected: some 5
|
||||
#eval safeDiv 10 0 -- expected: none
|
||||
|
||||
-- (c) Lookup in an association list
|
||||
def lookup [BEq α] (key : α) (alist : List (α × β)) : Option β :=
|
||||
sorry
|
||||
|
||||
#eval lookup "b" [("a", 1), ("b", 2), ("c", 3)] -- expected: some 2
|
||||
#eval lookup "d" [("a", 1), ("b", 2), ("c", 3)] -- expected: none
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
← [Back to README](../README.md) · Next: [Unit 2 — Inductive Types](02-inductive-types.md)
|
||||
106
tutorial-01-basics/02-inductive-types.md
Normal file
106
tutorial-01-basics/02-inductive-types.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Unit 2 — Inductive Types
|
||||
|
||||
**Tutorial 1: Lean 4 Fundamentals** · [← Back to README](../README.md)
|
||||
|
||||
## Goals
|
||||
|
||||
- Define inductive data types with the `inductive` keyword
|
||||
- Understand constructors and pattern matching
|
||||
- Write structurally recursive functions over inductive types
|
||||
- Define `Nat`, `List`, and `Tree` from scratch
|
||||
|
||||
## Sources
|
||||
|
||||
- *Theorem Proving in Lean 4* (TPIL), Chapter 7 "Inductive Types"
|
||||
→ https://leanprover.github.io/theorem_proving_in_lean4/
|
||||
- *Functional Programming in Lean* (FPIL), Chapter 1
|
||||
|
||||
## Concepts
|
||||
|
||||
| Concept | Lean syntax |
|
||||
|---------|------------|
|
||||
| Inductive definition | `inductive Name where \| ctor1 : ... → Name` |
|
||||
| Pattern matching constructors | `match t with \| ctor1 x => ... \| ctor2 y => ...` |
|
||||
| Structural recursion | Recursion on *structurally smaller* subterms only |
|
||||
| `deriving` clauses | `deriving Repr, BEq, DecidableEq` for auto-generated code |
|
||||
|
||||
## Exercises
|
||||
|
||||
### Exercise 2.1 — Define `Nat` from scratch
|
||||
|
||||
```lean
|
||||
inductive MyNat where
|
||||
| zero : MyNat
|
||||
| succ : MyNat → MyNat
|
||||
deriving Repr
|
||||
|
||||
-- (a) Addition
|
||||
def myAdd (a b : MyNat) : MyNat :=
|
||||
sorry
|
||||
|
||||
-- Test (after defining conversion functions or writing your own checks)
|
||||
|
||||
-- (b) Multiplication
|
||||
def myMul (a b : MyNat) : MyNat :=
|
||||
sorry
|
||||
|
||||
-- (c) Prove that zero is a right identity: myAdd a MyNat.zero = a
|
||||
-- (We'll do proofs properly in Unit 3, but try `by rfl` for now)
|
||||
```
|
||||
|
||||
### Exercise 2.2 — Define `List α` from scratch
|
||||
|
||||
```lean
|
||||
inductive MyList (α : Type) where
|
||||
| nil : MyList α
|
||||
| cons : α → MyList α → MyList α
|
||||
deriving Repr
|
||||
|
||||
-- (a) Length
|
||||
def myLength {α : Type} (xs : MyList α) : Nat :=
|
||||
sorry
|
||||
|
||||
-- (b) Append
|
||||
def myAppend {α : Type} (xs ys : MyList α) : MyList α :=
|
||||
sorry
|
||||
|
||||
-- (c) Prove: myLength (myAppend xs ys) = myLength xs + myLength ys
|
||||
-- (Try this after Unit 4/5)
|
||||
```
|
||||
|
||||
### Exercise 2.3 — Binary trees
|
||||
|
||||
```lean
|
||||
inductive BinTree (α : Type) where
|
||||
| leaf : BinTree α
|
||||
| node : BinTree α → α → BinTree α → BinTree α
|
||||
deriving Repr
|
||||
|
||||
-- (a) Count the number of nodes
|
||||
def size {α : Type} (t : BinTree α) : Nat :=
|
||||
sorry
|
||||
|
||||
-- Example tree: node (node leaf 1 leaf) 2 (node leaf 3 leaf)
|
||||
def exampleTree : BinTree Nat :=
|
||||
BinTree.node (BinTree.node BinTree.leaf 1 BinTree.leaf) 2
|
||||
(BinTree.node BinTree.leaf 3 BinTree.leaf)
|
||||
|
||||
#eval size exampleTree -- expected: 3
|
||||
|
||||
-- (b) Collect all values into a list (inorder traversal)
|
||||
def inorder {α : Type} (t : BinTree α) : List α :=
|
||||
sorry
|
||||
|
||||
#eval inorder exampleTree -- expected: [1, 2, 3]
|
||||
|
||||
-- (c) Check if a tree is a binary search tree
|
||||
-- Assume Int keys. A BST satisfies: left < key < right at every node.
|
||||
-- Write a function that checks this property.
|
||||
-- Hint: you may want a helper with min/max bounds.
|
||||
def isBST (t : BinTree Int) : Bool :=
|
||||
sorry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
← [Previous: Unit 1](01-types-and-functions.md) · Next: [Unit 3 — Propositions and Proofs](03-propositions-and-proofs.md)
|
||||
90
tutorial-01-basics/03-propositions-and-proofs.md
Normal file
90
tutorial-01-basics/03-propositions-and-proofs.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Unit 3 — Propositions and Proofs
|
||||
|
||||
**Tutorial 1: Lean 4 Fundamentals** · [← Back to README](../README.md)
|
||||
|
||||
## Goals
|
||||
|
||||
- Understand propositions as types (Curry-Howard)
|
||||
- Write basic proofs using `example` and `theorem`
|
||||
- Use the tactic language: `intro`, `apply`, `exact`, `have`
|
||||
|
||||
## Source
|
||||
|
||||
*Theorem Proving in Lean 4* (TPIL), Chapters 2–3
|
||||
→ https://leanprover.github.io/theorem_proving_in_lean4/
|
||||
|
||||
## Concepts
|
||||
|
||||
| Concept | Lean |
|
||||
|---------|------|
|
||||
| Proposition | `P : Prop` — a type whose terms are proofs |
|
||||
| Implication `P → Q` | Function from proofs of `P` to proofs of `Q` |
|
||||
| Conjunction `P ∧ Q` | `And.intro` (constructor), `.left` / `.right` (projections) |
|
||||
| Disjunction `P ∨ Q` | `Or.inl` / `Or.inr` |
|
||||
| Negation `¬ P` | `P → False` |
|
||||
| Tactics | `intro`, `apply`, `exact`, `have`, `assumption` |
|
||||
|
||||
## Exercises
|
||||
|
||||
### Exercise 3.1 — Implicational logic
|
||||
|
||||
```lean
|
||||
-- (a) Identity
|
||||
theorem id_prop (A : Prop) : A → A :=
|
||||
by
|
||||
intro h
|
||||
exact h
|
||||
|
||||
-- (b) Composition
|
||||
theorem compose (A B C : Prop) : (A → B) → (B → C) → (A → C) :=
|
||||
by
|
||||
sorry
|
||||
|
||||
-- (c) Currying
|
||||
theorem curry (A B C : Prop) : (A → B → C) → (A ∧ B → C) :=
|
||||
by
|
||||
sorry
|
||||
```
|
||||
|
||||
### Exercise 3.2 — Conjunction and disjunction
|
||||
|
||||
```lean
|
||||
-- (a) Swap conjuncts
|
||||
theorem and_comm (A B : Prop) : A ∧ B → B ∧ A :=
|
||||
by
|
||||
sorry
|
||||
|
||||
-- (b) Disjunction is symmetric
|
||||
theorem or_comm (A B : Prop) : A ∨ B → B ∨ A :=
|
||||
by
|
||||
sorry
|
||||
|
||||
-- (c) Forward reasoning with `have`
|
||||
theorem forward_example (A B C : Prop) (h1 : A → B) (h2 : B → C) (ha : A) : C :=
|
||||
by
|
||||
have hb : B := h1 ha
|
||||
sorry
|
||||
```
|
||||
|
||||
### Exercise 3.3 — Negation
|
||||
|
||||
```lean
|
||||
-- (a) Contradiction
|
||||
theorem contrapositive (A B : Prop) : (A → B) → (¬ B → ¬ A) :=
|
||||
by
|
||||
sorry
|
||||
|
||||
-- (b) Double negation introduction
|
||||
theorem double_neg_intro (A : Prop) : A → ¬ ¬ A :=
|
||||
by
|
||||
sorry
|
||||
|
||||
-- (c) Ex falso quodlibet
|
||||
theorem ex_falso (A : Prop) : False → A :=
|
||||
by
|
||||
sorry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
← [Previous: Unit 2](02-inductive-types.md) · Next: [Unit 4 — Quantifiers and Equality](04-quantifiers-and-equality.md)
|
||||
97
tutorial-01-basics/04-quantifiers-and-equality.md
Normal file
97
tutorial-01-basics/04-quantifiers-and-equality.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Unit 4 — Quantifiers and Equality
|
||||
|
||||
**Tutorial 1: Lean 4 Fundamentals** · [← Back to README](../README.md)
|
||||
|
||||
## Goals
|
||||
|
||||
- Use `∀` (forall) and `∃` (exists) quantifiers
|
||||
- Manipulate equality with `rfl`, `rw`, `calc`
|
||||
- Combine quantifiers with logical connectives
|
||||
|
||||
## Source
|
||||
|
||||
*Theorem Proving in Lean 4* (TPIL), Chapter 4
|
||||
→ https://leanprover.github.io/theorem_proving_in_lean4/
|
||||
|
||||
## Concepts
|
||||
|
||||
| Concept | Lean |
|
||||
|---------|------|
|
||||
| Universal `∀ x, P x` | `intro x` to prove; `h x` or `apply h` to use |
|
||||
| Existential `∃ x, P x` | `⟨x, h⟩` to prove; `rcases h with ⟨x, hx⟩` to use |
|
||||
| Equality `a = b` | `rfl` when definitional; `rw [h]` when propositional |
|
||||
| `calc` block | Chain equalities: `calc a = b := h1; _ = c := h2` |
|
||||
|
||||
## Exercises
|
||||
|
||||
### Exercise 4.1 — Universal quantifier
|
||||
|
||||
```lean
|
||||
-- (a) Prove a simple forall
|
||||
theorem all_imp (P Q : Nat → Prop) (h : ∀ n, P n → Q n) (x : Nat) (hp : P x) : Q x :=
|
||||
by
|
||||
sorry
|
||||
|
||||
-- (b) Distributing ∀ over ∧
|
||||
theorem forall_and_distrib (P Q : Nat → Prop) : (∀ n, P n ∧ Q n) ↔ (∀ n, P n) ∧ (∀ n, Q n) :=
|
||||
by
|
||||
constructor
|
||||
· sorry -- left-to-right
|
||||
· sorry -- right-to-left
|
||||
|
||||
-- (c) Prove that if every natural is even, then 42 is even
|
||||
-- (Use: `Even n := ∃ k, n = 2*k`)
|
||||
def Even (n : Nat) : Prop := ∃ k, n = 2 * k
|
||||
|
||||
theorem all_even_implies_42 : (∀ n, Even n) → Even 42 :=
|
||||
by
|
||||
sorry
|
||||
```
|
||||
|
||||
### Exercise 4.2 — Existential quantifier
|
||||
|
||||
```lean
|
||||
-- (a) Prove existence
|
||||
theorem exists_square (a : Nat) : ∃ n, n = a * a :=
|
||||
by
|
||||
sorry
|
||||
|
||||
-- (b) Distributing ∃ over ∨
|
||||
theorem exists_or_distrib (P Q : Nat → Prop) : (∃ n, P n ∨ Q n) ↔ (∃ n, P n) ∨ (∃ n, Q n) :=
|
||||
by
|
||||
constructor
|
||||
· sorry
|
||||
· sorry
|
||||
|
||||
-- (c) Prove: if something is both even and greater than 10, then something is greater than 5
|
||||
theorem even_and_gt10_implies_gt5 : (∃ n, Even n ∧ n > 10) → (∃ n, n > 5) :=
|
||||
by
|
||||
sorry
|
||||
```
|
||||
|
||||
### Exercise 4.3 — Equality and rewriting
|
||||
|
||||
```lean
|
||||
-- (a) Prove symmetry and transitivity of equality (without using `symm`/`trans`)
|
||||
theorem eq_symm {α : Type} (a b : α) (h : a = b) : b = a :=
|
||||
by
|
||||
sorry
|
||||
|
||||
theorem eq_trans {α : Type} (a b c : α) (h1 : a = b) (h2 : b = c) : a = c :=
|
||||
by
|
||||
sorry
|
||||
|
||||
-- (b) Use `calc` to prove a chain of identities
|
||||
theorem calc_example (a b c d : Nat) (h1 : a = b) (h2 : b = c + 1) (h3 : c + 1 = d) : a = d :=
|
||||
by
|
||||
sorry
|
||||
|
||||
-- (c) Rewrite inside a goal
|
||||
theorem rewrite_example (a b : Nat) (h : a = b + 1) : a * 2 = (b + 1) * 2 :=
|
||||
by
|
||||
sorry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
← [Previous: Unit 3](03-propositions-and-proofs.md) · Next: [Unit 5 — Advanced Tactics](05-advanced-tactics.md)
|
||||
52
tutorial-01-basics/05-advanced-tactics.md
Normal file
52
tutorial-01-basics/05-advanced-tactics.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Unit 5 — Advanced Tactics
|
||||
|
||||
**Tutorial 1: Lean 4 Fundamentals** · [← Back to README](../README.md)
|
||||
|
||||
## Goals
|
||||
|
||||
- Prove properties by induction with `induction`
|
||||
- Use `simp`, `ring`, `omega` for automation
|
||||
- Use `rcases` and `obtain` for case analysis
|
||||
- Work with `Nat` arithmetic proofs
|
||||
|
||||
## Sources
|
||||
|
||||
- TPIL Chapters 5–6 → https://leanprover.github.io/theorem_proving_in_lean4/
|
||||
- *Mathematics in Lean* (MiL), Chapter 1 → https://leanprover-community.github.io/mathematics_in_lean/
|
||||
|
||||
## Exercises
|
||||
|
||||
```lean
|
||||
open Nat
|
||||
|
||||
-- 5.1 — Induction on naturals
|
||||
theorem add_assoc (a b c : Nat) : (a + b) + c = a + (b + c) := by
|
||||
sorry
|
||||
|
||||
theorem add_comm (a b : Nat) : a + b = b + a := by
|
||||
sorry
|
||||
|
||||
theorem mul_comm (a b : Nat) : a * b = b * a := by
|
||||
sorry
|
||||
|
||||
theorem zero_mul (n : Nat) : 0 * n = 0 := by
|
||||
sorry
|
||||
|
||||
-- 5.2 — Induction on lists
|
||||
theorem reverse_reverse (xs : List α) : xs.reverse.reverse = xs := by
|
||||
sorry
|
||||
|
||||
theorem length_append (xs ys : List α) : (xs ++ ys).length = xs.length + ys.length := by
|
||||
sorry
|
||||
|
||||
theorem map_id (xs : List α) : xs.map id = xs := by
|
||||
sorry
|
||||
|
||||
-- 5.3 — Using `simp` and `ring`
|
||||
theorem square_sum (a b : Nat) : (a + b) ^ 2 = a ^ 2 + 2 * a * b + b ^ 2 := by
|
||||
sorry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
← [Previous: Unit 4](04-quantifiers-and-equality.md) · Next: [Unit 6 — Structures and Type Classes](06-structures-type-classes.md)
|
||||
68
tutorial-01-basics/06-structures-type-classes.md
Normal file
68
tutorial-01-basics/06-structures-type-classes.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Unit 6 — Structures and Type Classes
|
||||
|
||||
**Tutorial 1: Lean 4 Fundamentals** · [← Back to README](../README.md)
|
||||
|
||||
## Goals
|
||||
|
||||
- Define `structure` for records with named fields
|
||||
- Understand type classes as structures + instance resolution
|
||||
- Use `deriving` for `Repr`, `BEq`, `Inhabited`
|
||||
- Write monadic code with `do` notation
|
||||
|
||||
## Sources
|
||||
|
||||
- TPIL Chapter 9 (Structures), Chapter 10 (Type Classes)
|
||||
- FPIL Chapters 3–5 (overloading, monads)
|
||||
|
||||
## Exercises
|
||||
|
||||
```lean
|
||||
-- 6.1 — Structures
|
||||
structure Point where
|
||||
x : Float
|
||||
y : Float
|
||||
deriving Repr
|
||||
|
||||
def distance (p q : Point) : Float :=
|
||||
sorry
|
||||
|
||||
#eval distance {x := 0, y := 0} {x := 3, y := 4} -- expected: 5.0
|
||||
|
||||
-- 6.2 — Type classes
|
||||
class Semigroup (α : Type) where
|
||||
mul : α → α → α
|
||||
mul_assoc : ∀ a b c : α, mul (mul a b) c = mul a (mul b c)
|
||||
|
||||
instance : Semigroup Nat where
|
||||
mul := Nat.mul
|
||||
mul_assoc := Nat.mul_assoc
|
||||
|
||||
-- Define Monoid extending Semigroup with an identity
|
||||
class Monoid (α : Type) extends Semigroup α where
|
||||
one : α
|
||||
mul_one : ∀ a : α, mul a one = a
|
||||
one_mul : ∀ a : α, mul one a = a
|
||||
|
||||
instance : Monoid Nat where
|
||||
one := 1
|
||||
mul_one := sorry
|
||||
one_mul := sorry
|
||||
|
||||
-- 6.3 — Option monad and `do` notation
|
||||
def safeDiv (a b : Nat) : Option Nat :=
|
||||
if b == 0 then none else some (a / b)
|
||||
|
||||
-- Rewrite this with `do` notation:
|
||||
def compute (x y z : Nat) : Option Nat :=
|
||||
do
|
||||
let a ← safeDiv x y
|
||||
let b ← safeDiv a z
|
||||
some (b + 1)
|
||||
|
||||
#eval compute 10 2 3 -- expected: some 2
|
||||
#eval compute 10 0 3 -- expected: none
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
← [Previous: Unit 5](05-advanced-tactics.md) · Next: [Unit 7 — Dependent Types](07-dependent-types.md)
|
||||
77
tutorial-01-basics/07-dependent-types.md
Normal file
77
tutorial-01-basics/07-dependent-types.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Unit 7 — Dependent Types
|
||||
|
||||
**Tutorial 1: Lean 4 Fundamentals** · [← Back to README](../README.md)
|
||||
|
||||
## Goals
|
||||
|
||||
- Understand types that depend on values
|
||||
- Work with `Fin n` (numbers < n), `Vector α n` (fixed-length lists)
|
||||
- Write functions whose return type depends on input
|
||||
- See why dependent types matter for PL semantics
|
||||
|
||||
## Sources
|
||||
|
||||
- TPIL Chapter 2 "Dependent Type Theory"
|
||||
- FPIL Chapter 7 "Programming with Dependent Types"
|
||||
- Henson 2025: "Beginner Resources for Formalizing Lambda Calculi"
|
||||
|
||||
## Concepts
|
||||
|
||||
| Concept | Lean |
|
||||
|---------|------|
|
||||
| Pi type `(x : α) → β x` | Function where return type depends on argument |
|
||||
| Sigma type `Σ x : α, β x` | Dependent pair: value + property |
|
||||
| `Fin n` | Natural numbers `< n` |
|
||||
| `Vector α n` | Lists with length tracked in the type |
|
||||
| `h : a = b → ...` | Equality can rewrite types (substitution principle) |
|
||||
|
||||
## Exercises
|
||||
|
||||
```lean
|
||||
-- 7.1 — Fin n
|
||||
-- Define a safe nth function for lists that *cannot* fail at runtime
|
||||
def safeNth {α : Type} (xs : List α) (i : Fin xs.length) : α :=
|
||||
sorry
|
||||
|
||||
-- (You'll need `match` on both `xs` and `i`)
|
||||
-- Test: `safeNth [1,2,3] ⟨0, by decide⟩` should return 1
|
||||
|
||||
-- 7.2 — Vector
|
||||
inductive Vector (α : Type) : Nat → Type where
|
||||
| nil : Vector α 0
|
||||
| cons : α → {n : Nat} → Vector α n → Vector α (n+1)
|
||||
deriving Repr
|
||||
|
||||
-- (a) Append two vectors (length is m + n)
|
||||
def vappend {α : Type} {m n : Nat} (v : Vector α m) (w : Vector α n) : Vector α (m + n) :=
|
||||
sorry
|
||||
|
||||
-- (b) Map over a vector
|
||||
def vmap {α β : Type} {n : Nat} (f : α → β) (v : Vector α n) : Vector β n :=
|
||||
sorry
|
||||
|
||||
-- 7.3 — Dependent types for ASTs
|
||||
-- Define an AST where each expression *carries its type*
|
||||
inductive Expr : Type where
|
||||
| lit : Nat → Expr
|
||||
| add : Expr → Expr → Expr
|
||||
| isZero : Expr → Expr
|
||||
deriving Repr
|
||||
|
||||
-- Now define the *typing predicate* as a dependent relation
|
||||
-- (Preview of Tutorial 2)
|
||||
inductive Ty : Type where | nat : Ty | bool : Ty
|
||||
|
||||
-- Fill this in: `HasType e τ` means "expression e has type τ"
|
||||
inductive HasType : Expr → Ty → Prop where
|
||||
-- (your constructors here)
|
||||
|
||||
-- Then prove: every well-typed `isZero` expression returns a bool
|
||||
theorem isZero_returns_bool (e : Expr) : HasType (Expr.isZero e) Ty.nat → HasType e Ty.nat :=
|
||||
by
|
||||
sorry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
← [Previous: Unit 6](06-structures-type-classes.md) · [← Tutorial 1 Index](./) · Next: [Tutorial 2 — Unit 8](../tutorial-02-semantics/08-syntax-representation.md)
|
||||
Reference in New Issue
Block a user