Formal Software Verification

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 declaration uses `sorry`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 declaration uses `sorry`double : := sorry theorem declaration uses `sorry`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 declaration uses `sorry`someEnv : String := sorry theorem declaration uses `sorry`eval_sub : eval someEnv (AExp.sub (AExp.var "y") (AExp.var "x")) = 14 := sorry theorem declaration uses `sorry`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 declaration uses `sorry`sumList : List := sorry theorem declaration uses `sorry`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 declaration uses `sorry`length {α : Type} : List α := sorry theorem declaration uses `sorry`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 declaration uses `sorry`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 declaration uses `sorry`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 declaration uses `sorry`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 declaration uses `sorry`size : AExp := sorry def declaration uses `sorry`depth : AExp := sorry theorem declaration uses `sorry`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 declaration uses `sorry`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.