{-# OPTIONS --cubical --postfix-projections --safe #-}
open import Relation.Binary
open import Prelude
module Data.List.Sort.MergeSort {e} {E : Type e} {r₁ r₂} (totalOrder : TotalOrder E r₁ r₂) where
open TotalOrder totalOrder hiding (refl)
open import Data.List.Sort.InsertionSort totalOrder using (insert; insert-sort)
open import Data.List
open import Data.List.Properties
open import TreeFold
open import Algebra
open import Relation.Nullary.Decidable.Properties using (from-reflects)
open import Path.Reasoning
mergeˡ : E → (List E → List E) → List E → List E
mergeˡ x xs [] = x ∷ xs []
mergeˡ x xs (y ∷ ys) = if x ≤ᵇ y then x ∷ xs (y ∷ ys) else y ∷ mergeˡ x xs ys
_⋎_ : List E → List E → List E
_⋎_ = foldr mergeˡ id
merge-idʳ : ∀ xs → xs ⋎ [] ≡ xs
merge-idʳ [] = refl
merge-idʳ (x ∷ xs) = cong (x ∷_) (merge-idʳ xs)
merge-assoc : Associative _⋎_
merge-assoc [] ys zs = refl
merge-assoc (x ∷ xs) [] zs = cong (λ xs′ → mergeˡ x (xs′ ⋎_) zs) (merge-idʳ xs)
merge-assoc (x ∷ xs) (y ∷ ys) [] = merge-idʳ ((x ∷ xs) ⋎ (y ∷ ys)) ; cong ((x ∷ xs) ⋎_) (sym (merge-idʳ (y ∷ ys)))
merge-assoc (x ∷ xs) (y ∷ ys) (z ∷ zs)
with merge-assoc xs (y ∷ ys) (z ∷ zs)
| merge-assoc (x ∷ xs) ys (z ∷ zs)
| merge-assoc (x ∷ xs) (y ∷ ys) zs
| x ≤? y in x≤?y
| y ≤? z in y≤?z
... | _ | _ | r | no x≰y | no y≰z rewrite y≤?z rewrite x≤?y =
cong (z ∷_) r ;
cong (bool′ _ _)
(sym (from-reflects false (x ≤? z) (<⇒≱ ≲[ ≱[ y≰z ] ≲; ≱[ x≰y ] ])))
... | _ | r | _ | no x≰y | yes y≤z rewrite y≤?z rewrite x≤?y = cong (y ∷_) r
... | r | _ | _ | yes x≤y | yes y≤z rewrite y≤?z rewrite x≤?y =
cong (bool′ _ _)
(from-reflects true (x ≤? z) (≤-trans x≤y y≤z)) ;
cong (x ∷_) r
merge-assoc (x ∷ xs) (y ∷ ys) (z ∷ zs) | rx≤z | _ | rx≰z | yes x≤y | no y≰z with x ≤? z
... | no x≰z rewrite x≤?y = cong (z ∷_) rx≰z
... | yes x≤z rewrite y≤?z = cong (x ∷_) rx≤z
merge-sort : List E → List E
merge-sort = treeFold _⋎_ [] ∘ map (_∷ [])
merge-insert : ∀ x xs → (x ∷ []) ⋎ xs ≡ insert x xs
merge-insert x [] = refl
merge-insert x (y ∷ xs) with x ≤ᵇ y
... | false = cong (y ∷_) (merge-insert x xs)
... | true = refl
merge≡insert-sort : ∀ xs → merge-sort xs ≡ insert-sort xs
merge≡insert-sort xs =
merge-sort xs ≡⟨⟩
treeFold _⋎_ [] (map (_∷ []) xs) ≡⟨ treeFoldHom _⋎_ [] merge-assoc (map (_∷ []) xs) ⟩
foldr _⋎_ [] (map (_∷ []) xs) ≡⟨ map-fusion _⋎_ [] (_∷ []) xs ⟩
foldr (λ x → (x ∷ []) ⋎_) [] xs ≡⟨ cong (λ f → foldr f [] xs) (funExt (funExt ∘ merge-insert)) ⟩
foldr insert [] xs ≡⟨⟩
insert-sort xs ∎