module _ where open import list open import nat open import nat-thms open import bool open import bool-thms open import eq open import product open import product-thms open import sum {- 1. Define `merge` following the pattern in class we did for quicksort. Here's the definition of the function, as if termination weren't a concern. merge : 𝕃 ℕ -> 𝕃 ℕ -> 𝕃 ℕ merge [] l = l merge (x :: l) [] = (x :: l) merge (x₁ :: ls₁) (x₂ :: ls₂) with x₁ ≤ x₂ ... | tt = x₁ :: (merge ls₁ (x₂ :: ls₂)) ... | ff = x₂ :: (merge (x₁ :: ls₁) ls₂) Note that the termination checker does not accept these recursive calls, but if the `with` clause isn't there (instead using if_then_else_), then it seems to accept them --- but don't use that! Instead use evidence that merge terminates, via the `merget` data definition. (You'll need it to do proofs about `merge` and the termination check will probably get upset about them even if it doesn't about `merge` itself.) -} data merget : 𝕃 ℕ -> 𝕃 ℕ -> Set where -- for any list, merge terminates -- when passed the empty list and that list merge[]l : ∀ l -> merget [] l -- for any singleton list, merge terminates -- when passed that list and the empty list mergel[] : ∀ x l -> merget (x :: l) [] -- if merge terminates when given l and y::m, -- and it also terminates when given x::l and m, -- then it will terminate when given x::l and y::m. merge::: : ∀ x l y m -> merget l (y :: m) -> merget (x :: l) m -> merget (x :: l) (y :: m) {- 2. Prove that merge always terminates, ie, for any two lists, you can build a `merget` for them. Use that proof to define merge with this signature: merge : 𝕃 ℕ -> 𝕃 ℕ -> 𝕃 ℕ -} evens : 𝕃 ℕ -> 𝕃 ℕ odds : 𝕃 ℕ -> 𝕃 ℕ evens [] = [] evens (x :: l) = odds l odds [] = [] odds (x :: l) = x :: evens l {- 3. This is the basic mergesort algorithm. Agda is happy with `evens` and `odds` but cannot determine that `ms` terminates. Prove that `ms` terminates in a manner similar to the way we did in class with quicksort. Keep the same top-level signature and behavior so that the test cases below pass. You will need to think about what gets smaller and how exactly it gets smaller and will need to prove some lemmas about `evens` and `odds` to get everything sorted out. ms : 𝕃 ℕ -> 𝕃 ℕ ms [] = [] ms (x :: []) = x :: [] ms (x :: l) = merge (ms (evens (x :: l))) (ms (odds (x :: l))) -} {- test cases for ms; all should pass; feel free to comment them out while working on the definitions of `merge` and `ms` -} _ : ms [] ≡ [] _ = refl _ : ms (1 :: []) ≡ 1 :: [] _ = refl _ : ms (1 :: 2 :: []) ≡ 1 :: 2 :: [] _ = refl _ : ms (2 :: 1 :: []) ≡ 1 :: 2 :: [] _ = refl _ : ms (1 :: 2 :: 3 :: []) ≡ 1 :: 2 :: 3 :: [] _ = refl _ : ms (1 :: 3 :: 2 :: []) ≡ 1 :: 2 :: 3 :: [] _ = refl _ : ms (2 :: 1 :: 3 :: []) ≡ 1 :: 2 :: 3 :: [] _ = refl _ : ms (2 :: 3 :: 1 :: []) ≡ 1 :: 2 :: 3 :: [] _ = refl _ : ms (3 :: 1 :: 2 :: []) ≡ 1 :: 2 :: 3 :: [] _ = refl _ : ms (3 :: 2 :: 1 :: []) ≡ 1 :: 2 :: 3 :: [] _ = refl _ : ms (2 :: 1 :: 1 :: []) ≡ 1 :: 1 :: 2 :: [] _ = refl _ : ms (1 :: 2 :: 1 :: []) ≡ 1 :: 1 :: 2 :: [] _ = refl _ : ms (1 :: 1 :: 2 :: []) ≡ 1 :: 1 :: 2 :: [] _ = refl _ : ms (1 :: 1 :: 1 :: []) ≡ 1 :: 1 :: 1 :: [] _ = refl _ : ms (1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: []) ≡ 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: [] _ = refl _ : ms (8 :: 7 :: 6 :: 5 :: 4 :: 3 :: 2 :: 1 :: []) ≡ 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: [] _ = refl _ : ms (1 :: 3 :: 5 :: 7 :: 8 :: 6 :: 4 :: 2 :: []) ≡ 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: [] _ = refl {- 4. Prove that merge sort sorts. The definition of ≤∀ is the same as Increasing from Shu-Hung's lectures and `Sorted` captures what sorted is. You'll need to prove some lemmas to get this done; the most important one being one that captures what merge does. The final, top-level theorem should have this type: ∀ l -> Sorted (ms l) -} data _≤∀_ : ℕ -> 𝕃 ℕ -> Set where ismt : ∀ x -> x ≤∀ [] iscons : ∀ x y l -> x ≤ y ≡ tt -> y ≤∀ l -> x ≤∀ (y :: l) Sorted : 𝕃 ℕ -> Set Sorted l = 0 ≤∀ l {- 5. prove that if x is in some list l, then it is in ms l. The final, top-level theorem should have this type: ∀ x l -> x ∈ l -> x ∈ ms l This part is mandatory for pairs and optional for singletons. -} data _∈_ {l} {A : Set l} : A -> 𝕃 A -> Set where here : ∀ x l -> x ∈ (x :: l) there : ∀ x y l -> x ∈ l -> x ∈ (y :: l)