3.8. Exercises
Define each function and prove or state each theorem, replacing sorry. Download the exercise file Lecture03.lean and open it in VS Code. The file already contains the definitions of AExp, eval, appendPretty, and reverse from the lecture.
Exercise 1. Define the predecessor function, with pred 0 = 0.
def pred : ℕ → ℕ := sorry
-- Expected: #eval pred 5 gives 4, #eval pred 0 gives 0.
Exercise 2. Define doubling by recursion, without *, and prove the ground equation by computation.
def double : ℕ → ℕ := sorry
theorem double_five : double 5 = 10 := sorry
Exercise 3. Define the environment that maps "x" to 3, "y" to 17, and every other name to 201, and prove the two evaluations by computation.
def someEnv : String → ℤ := sorry
theorem eval_sub :
eval someEnv
(AExp.sub (AExp.var "y") (AExp.var "x")) = 14 :=
sorry
theorem eval_div_zero :
eval someEnv
(AExp.div (AExp.var "y") (AExp.num 0)) = 0 :=
sorry
Exercise 4. Define the sum of a list of natural numbers, and prove the ground equation by computation.
def sumList : List ℕ → ℕ := sorry
theorem sumList_example : sumList [1, 2, 3] = 6 := sorry
Exercise 5. Define the length of a list, with an implicit type argument, and prove the ground equation by computation.
def length {α : Type} : List α → ℕ := sorry
theorem length_three : length [1, 2, 3] = 3 := sorry
Exercise 6. Define map, which applies a function to every element, then state, with sorry, its two functorial laws. Mapping the identity function changes nothing, and mapping a composition equals composing the maps.
def map {α β : Type} (f : α → β) : List α → List β :=
sorry
-- State the two laws here as theorems proved by sorry:
-- map_ident : mapping (fun x => x) over xs gives xs.
-- map_comp : map g (map f xs) equals mapping their
-- composition over xs.
Exercise 7. Define flatten, which concatenates a list of lists with appendPretty, then state, with sorry, that the length of the result is the sum of the lengths of the inner lists, using length, map and sumList of the exercises above.
def flatten {α : Type} : List (List α) → List α := sorry
-- State flatten_length here as a theorem proved by sorry:
-- length (flatten xss) equals sumList (map length xss).
Exercise 8. Define constFold, which folds an addition or a multiplication of two numerals into the single numeral of its value and leaves every other expression unchanged, then state, with sorry, its correctness. Folding preserves the value under every environment.
def constFold : AExp → AExp := sorry
-- State constFold_correct here as a theorem proved by
-- sorry: for every env and e, eval env (constFold e)
-- equals eval env e.
Exercise 9. Define the size of an expression, counting every constructor, and its depth, counting the longest constructor chain, then state, with sorry, that the depth never exceeds the size.
def size : AExp → ℕ := sorry
def depth : AExp → ℕ := sorry
theorem depth_le_size (e : AExp) :
depth e ≤ size e := sorry
Exercise 10. Define zeroVars, which replaces every variable by the numeral 0 and leaves the structure otherwise unchanged, then state, with sorry, that its value under any environment equals the value of the original expression under the environment that maps every name to 0.
def zeroVars : AExp → AExp := sorry
-- State zeroVars_eval here as a theorem proved by sorry:
-- for every env and e, eval env (zeroVars e) equals
-- eval (fun _ => 0) e.