module SortedList where
open import Data.Sum
open import Data.Product
open import Data.List
import Data.Unit
open Data.Unit hiding (total; _≤_)
module External
(A : Set)
(_≤_ : A → A → Set)
(total : ∀ a b → a ≤ b ⊎ b ≤ a)
where
insert : A → List A → List A
insert a [] = [ a ]
insert a (x ∷ xs) with total a x
... | inj₁ _ = a ∷ x ∷ xs
... | inj₂ _ = x ∷ insert a xs
Sorted : List A → Set
Sorted [] = ⊤
Sorted (_ ∷ []) = ⊤
Sorted (x ∷ y ∷ xs) = (x ≤ y) × Sorted (y ∷ xs)
sorted : (a : A) → (xs : List A) → Sorted xs → Sorted (insert a xs)
sorted a [] _ = tt
sorted a (x ∷ []) _ with total a x
... | inj₁ a≤x = (a≤x , tt)
... | inj₂ x≤a = (x≤a , tt)
sorted a (x ∷ y ∷ xs) (x≤y , sorted-y∷xs) with total a x
... | inj₁ a≤x = ( a≤x , ( x≤y , sorted-y∷xs ) )
... | inj₂ x≤a = lemma x a y xs x≤a x≤y sorted-y∷xs
where
lemma : (a b x : A) → (xs : List A) → a ≤ b → a ≤ x
→ Sorted (x ∷ xs) → Sorted (a ∷ insert b (x ∷ xs))
lemma a b x [] a≤b a≤x _ with total b x
... | inj₁ b≤x = ( a≤b , b≤x , tt )
... | inj₂ x≤b = ( a≤x , x≤b , tt )
lemma a b x (y ∷ xs) a≤b a≤x ( x≤y , sorted-y∷xs ) with total b x
... | inj₁ b≤x = ( a≤b , b≤x , (x≤y , sorted-y∷xs ) )
... | inj₂ x≤b = ( a≤x , lemma x b y xs x≤b x≤y sorted-y∷xs )
isort : List A → List A
isort = foldr insert []
isort-sorted : (xs : List A) → Sorted (isort xs)
isort-sorted [] = tt
isort-sorted (x ∷ xs) = sorted x (isort xs) (isort-sorted xs)
module Internal
(A : Set)
(_≤_ : A → A → Set)
(total : ∀ a b → a ≤ b ⊎ b ≤ a)
(trans : ∀ {a b c} → a ≤ b → b ≤ c → a ≤ c)
where
mutual
data SList : Set where
nil : SList
cons : (a : A) → (xs : SList) → a ≤L xs → SList
_≤L_ : A → SList → Set
a ≤L nil = ⊤
a ≤L (cons x xs _) = (a ≤ x) × (a ≤L xs)
mutual
sinsert : (a : A) → SList → SList
sinsert a nil = cons a nil tt
sinsert a (cons x xs x≤Lxs) with total a x
... | inj₁ a≤x = cons a (cons x xs x≤Lxs) (a≤x , lemma₁ a x xs a≤x x≤Lxs)
where
lemma₁ : (a x : A) → (xs : SList) → a ≤ x → x ≤L xs → a ≤L xs
lemma₁ _ _ nil _ _ = tt
lemma₁ a x (cons y xs y≤Lxs) a≤x (x≤y , x≤Lxs) =
(trans a≤x x≤y , lemma₁ a x xs a≤x x≤Lxs)
... | inj₂ x≤a = cons x (sinsert a xs) (lemma₂ a x xs x≤a x≤Lxs)
lemma₂ : (a x : A) → (xs : SList) → x ≤ a → x ≤L xs → x ≤L sinsert a xs
lemma₂ _ _ nil x≤a _ = (x≤a , tt)
lemma₂ a x (cons y xs y≤Lxs) x≤a (x≤y , x≤Lxs) with total a y
... | inj₁ a≤y = (x≤a , (x≤y , x≤Lxs))
... | inj₂ y≤a = (x≤y , lemma₂ a x xs x≤a x≤Lxs)
isort′ : List A → SList
isort′ = foldr sinsert nil
private
open import Relation.Binary
open import Data.Nat
open DecTotalOrder Data.Nat.decTotalOrder
open External carrier Data.Nat._≤_ total
open Internal carrier Data.Nat._≤_ total trans
ex0 = isort (1 ∷ 0 ∷ 3 ∷ 2 ∷ [])
ex1 = isort′ (1 ∷ 0 ∷ 3 ∷ 2 ∷ [])