Formal Software Verification

6.8. Exercises🔗

Define each function and prove each law in Lean, replacing sorry. Download the exercise file Lecture06.lean and open it in VS Code. Each type is given; your task is the functions and the proofs. The laws here are settled by rfl or decide on closed values, since the proofs by induction belong to Lecture 7. Exercises 9 and 10 are optional.

Exercise 1. Define turnRight on the four compass directions, and prove by decide that turning right four times returns north.

namespace FuncEx inductive Direction where | north | east | south | west deriving DecidableEq def declaration uses `sorry`turnRight : Direction Direction := sorry theorem declaration uses `sorry`turn_four : turnRight (turnRight (turnRight (turnRight Direction.north))) = Direction.north := sorry end FuncEx

Exercise 2. Define lastOpt, the last element of a list as an option, and prove its value on the empty list and on a concrete list.

namespace FuncEx def declaration uses `sorry`lastOpt {α : Type} : List α Option α := sorry theorem declaration uses `sorry`last_opt_nil {α : Type} : lastOpt ([] : List α) = none := sorry theorem declaration uses `sorry`last_opt_example : lastOpt [3, 1, 4] = some 4 := sorry end FuncEx

Exercise 3. Define the area of a rectangle and prove a concrete area.

namespace FuncEx structure Rectangle where width : height : def declaration uses `sorry`area (r : Rectangle) : := sorry theorem declaration uses `sorry`area_example : area { width := 3, height := 4 } = 12 := sorry end FuncEx

Exercise 4. Extend the rectangle to a box with a depth, and define its volume from the inherited fields.

namespace FuncExBox structure Rectangle where width : height : structure Box extends Rectangle where depth : def declaration uses `sorry`volume (b : Box) : := sorry theorem declaration uses `sorry`volume_example : volume { width := 2, height := 3, depth := 4 } = 24 := sorry end FuncExBox

Exercise 5. Complete the Doubler instances, doubling a number by addition and a list by self-append, and the selector, then prove the doubled value for ℕ.

namespace FuncEx class Doubler (α : Type) where dup : α α declaration uses `sorry`instance : Doubler := sorry declaration uses `sorry`instance {α : Type} : Doubler (List α) := sorry def declaration uses `sorry`applyDup {α : Type} [Doubler α] (a : α) : α := sorry theorem declaration uses `sorry`dup_nat : applyDup (3 : ) = 6 := sorry end FuncEx

Exercise 6. Count the leaves and the branches of a binary tree, and check the relation between them on a concrete tree.

namespace FuncEx inductive Tree (α : Type) where | leaf | branch (l : Tree α) (x : α) (r : Tree α) def declaration uses `sorry`leaves {α : Type} : Tree α := sorry def declaration uses `sorry`nodes {α : Type} : Tree α := sorry def tx : Tree := .branch (.branch .leaf 1 .leaf) 2 .leaf theorem declaration uses `sorry`leaves_nodes : leaves tx = nodes tx + 1 := sorry end FuncEx

Exercise 7. Define replicate, the list of n copies of a value, and prove its value at 0.

namespace FuncEx def declaration uses `sorry`replicate {α : Type} : α List α := sorry theorem declaration uses `sorry`replicate_zero {α : Type} (x : α) : replicate 0 x = [] := sorry end FuncEx

Exercise 8. Define isEmpty by a match, and prove its two computational laws.

namespace FuncEx def declaration uses `sorry`isEmpty {α : Type} : List α Bool := sorry theorem declaration uses `sorry`is_empty_nil {α : Type} : isEmpty ([] : List α) = true := sorry theorem declaration uses `sorry`is_empty_cons {α : Type} (x : α) (xs : List α) : isEmpty (x :: xs) = false := sorry end FuncEx

Exercise 9. Optional. A rose tree branches into a list of subtrees. Define rsize, the number of its nodes, noting the nested recursion through List.

namespace FuncEx inductive Rose (α : Type) where | node (x : α) (children : List (Rose α)) def declaration uses `sorry`rsize {α : Type} : Rose α := sorry end FuncEx

Exercise 10. Optional. A length-indexed vector rules out the empty case in its type. Define the total head of a nonempty vector and evaluate it.

namespace FuncEx inductive Vec (α : Type) : Type where | nil : Vec α 0 | cons {n : } : α Vec α n Vec α (n + 1) def declaration uses `sorry`vhead {α : Type} {n : } : Vec α (n + 1) α := sorry def vx : Vec 2 := .cons 3 (.cons 4 .nil) end FuncEx