Source code on Github
{-# OPTIONS --with-K #-}
open import Prelude.Init; open SetAsType
open L.Any using (index)
open L.Mem using (∈-map⁺; ∈-map⁻)
open L.All using (lookup; ¬All⇒Any¬; ¬Any⇒All¬)
open L.Perm using (drop-∷; drop-mid; ∈-resp-↭)
open import Prelude.DecEq.Core
open import Prelude.Membership
open import Prelude.Decidable
open import Prelude.Ord
open import Prelude.Lists.Indexed
open import Prelude.Lists.Membership
open import Prelude.Lists.Subsets
open import Prelude.Lists.Interleaving
open import Prelude.Lists.Count
module Prelude.Lists.Dec {a} {A : Type a} ⦃ _ : DecEq A ⦄ where
private variable
x y z : A
xs ys zs : List A
¬∉⇒∈ : ¬ (x ∉ xs) → x ∈ xs
¬∉⇒∈ {x}{xs = []} ¬x∉ = ⊥-elim $ ¬x∉ λ ()
¬∉⇒∈ {x}{xs = x′ ∷ xs} ¬x∉ with x ≟ x′
... | yes refl = here refl
... | no ¬p = there (¬∉⇒∈ (λ x∉ → ¬x∉ (λ { (here refl) → ⊥-elim $ ¬p refl; (there x∈) → x∉ x∈})))
instance
Dec-⊆ : _⊆_ {A = A} ⁇²
Dec-⊆ {x = []} {y = ys} .dec = yes λ ()
Dec-⊆ {x = x ∷ xs} {y = ys} .dec = case x ∈? ys of λ where
(no x∉ys) → no λ xs⊆ys → x∉ys (xs⊆ys (here refl))
(yes x∈ys) → case ¿ xs ⊆ ys ¿ of λ where
(no xs⊈ys) → no λ xs⊆ys → xs⊈ys (λ {x} z → xs⊆ys (there z))
(yes xs⊆ys) → yes λ{ (here refl) → x∈ys
; (there x∈) → xs⊆ys x∈ }
Dec-⊆′ : _⊆′_ {A = A} ⁇²
Dec-⊆′ {x = xs}{ys} .dec
with ¿ xs ⊆ ys ¿
... | yes p = yes $ mk⊆ p
... | no ¬p = no $ ⊥-elim ∘ ¬p ∘ unmk⊆
Dec-Disjoint : Disjoint {A = A} ⁇²
Dec-Disjoint {x = xs} {y = ys} .dec with all? (_∉? ys) xs
... | yes p = yes (λ {v} (v∈ , v∈′) → lookup p v∈ v∈′ )
... | no ¬p = let (x , x∈ , Px) = find $ ¬All⇒Any¬ (_∉? ys) _ ¬p
in no λ p → p {x} (x∈ , ¬∉⇒∈ Px)
infix 4 _⊆?_ _⊆′?_
_⊆?_ = ¿ _⊆_ {A = A} ¿²
_⊆′?_ = ¿ _⊆′_ {A = A} ¿²
disjoint? = ¿ Disjoint {A = A} ¿²
unique? = ¿ Unique {A = A} ¿¹
nub : List A → List A
nub [] = []
nub (x ∷ xs) with x ∈? xs
... | yes _ = nub xs
... | no _ = x ∷ nub xs
nub-⊆⁺ : xs ⊆ nub xs
nub-⊆⁺ {xs = x ∷ xs} (here refl)
with x ∈? xs
... | yes x∈ = nub-⊆⁺ {xs = xs} x∈
... | no _ = here refl
nub-⊆⁺ {xs = x ∷ xs} (there y∈)
with x ∈? xs
... | yes _ = nub-⊆⁺ {xs = xs} y∈
... | no _ = there $ nub-⊆⁺ {xs = xs} y∈
nub-⊆⁻ : nub xs ⊆ xs
nub-⊆⁻ {xs = x ∷ xs}
with x ∈? xs
... | yes x∈ = there ∘ nub-⊆⁻ {xs = xs}
... | no _ = λ where
(here refl) → here refl
(there y∈) → there $ nub-⊆⁻ {xs = xs} y∈
open import Prelude.General
private variable p : Level; P : Pred A p
All-nub⁺ : All P xs → All P (nub xs)
All-nub⁺ {xs = []} [] = []
All-nub⁺ {xs = x ∷ xs} (p ∷ ps) with x ∈? xs
... | yes _ = All-nub⁺ ps
... | no _ = p ∷ All-nub⁺ ps
All-nub⁻ : All P (nub xs) → All P xs
All-nub⁻ {xs = []} [] = []
All-nub⁻ {xs = x ∷ xs} p with x ∈? xs | p
... | yes x∈ | p = let IH = All-nub⁻ p in lookup IH x∈ ∷ IH
... | no _ | p ∷ ps = p ∷ All-nub⁻ ps
All-nub : All P xs ↔ All P (nub xs)
All-nub = All-nub⁺ , All-nub⁻
Any-nub⁺ : Any P xs → Any P (nub xs)
Any-nub⁺ {xs = x ∷ xs} (here px)
with x ∈? xs
... | yes x∈ = Any-nub⁺ $ L.Any.map (λ where refl → px) x∈
... | no _ = here px
Any-nub⁺ {xs = x ∷ xs} (there p)
with IH ← Any-nub⁺ p
with x ∈? xs
... | yes _ = IH
... | no _ = there IH
Any-nub⁻ : Any P (nub xs) → Any P xs
Any-nub⁻ {xs = x ∷ xs} with x ∈? xs
... | yes _ = there ∘ Any-nub⁻ {xs = xs}
... | no _ = λ where (here px) → here px; (there p) → there (Any-nub⁻ p)
Any-nub : Any P xs ↔ Any P (nub xs)
Any-nub = Any-nub⁺ , Any-nub⁻
Unique-nub : Unique (nub xs)
Unique-nub {[]} = []
Unique-nub {x ∷ xs} with x ∈? xs
... | yes _ = Unique-nub {xs}
... | no x∉ = All-nub⁺ (¬Any⇒All¬ xs x∉) ∷ Unique-nub {xs}
nub-from∘to : Unique xs → nub xs ≡ xs
nub-from∘to {[]} _ = refl
nub-from∘to {x ∷ xs} u@(_ ∷ Uxs) with x ∈? xs
... | no _ = cong (x ∷_) (nub-from∘to Uxs)
... | yes x∈xs = ⊥-elim (unique-∈ u x∈xs)
unique-nub-∈ : Unique xs → (x ∈ nub xs) ≡ (x ∈ xs)
unique-nub-∈ uniq rewrite nub-from∘to uniq = refl
∈-nub⁻ : x ∈ nub xs → x ∈ xs
∈-nub⁻ {x}{x′ ∷ xs} x∈
with x′ ∈? xs
... | yes _ = there (∈-nub⁻ x∈)
... | no ¬p
with x∈
... | (here refl) = here refl
... | (there x∈ˢ) = there (∈-nub⁻ x∈ˢ)
∈-nub⁺ : x ∈ xs → x ∈ nub xs
∈-nub⁺ {x}{.x ∷ xs} (here refl)
with x ∈? xs
... | yes x∈ = ∈-nub⁺ x∈
... | no _ = here refl
∈-nub⁺ {x}{x′ ∷ xs} (there x∈)
with x′ ∈? xs
... | yes x∈ˢ = ∈-nub⁺ x∈
... | no _ = there $ ∈-nub⁺ x∈
∉-nub⁻ : x ∉ nub xs → x ∉ xs
∉-nub⁻ = _∘ ∈-nub⁺
∉-nub⁺ : x ∉ xs → x ∉ nub xs
∉-nub⁺ = _∘ ∈-nub⁻
∈-map∘nub⁻ : ∀ {B : Type ℓ} (f : A → B) x xs →
f x L.Mem.∈ map f (nub xs) → f x L.Mem.∈ map f xs
∈-map∘nub⁻ f _ [] fx∈ = fx∈
∈-map∘nub⁻ f x (y ∷ xs) fx∈ with y ∈? xs
... | yes y∈ = there $ ∈-map∘nub⁻ f x xs fx∈
... | no y∉ with fx∈
... | here eq = here eq
... | there fx∈′ = there $ ∈-map∘nub⁻ f x xs fx∈′
‼-nub⁺ : Index xs → Index (nub xs)
‼-nub⁺ {x ∷ xs} i with x ∈? xs
... | yes x∈ = ‼-nub⁺ {xs} $ L.Any.index x∈
... | no _ = case i of λ where
0F → 0F
(fsuc j) → fsuc $ ‼-nub⁺ {xs} j
‼-nub⁻ : Index (nub xs) → Index xs
‼-nub⁻ {x ∷ xs} i with x ∈? xs
... | yes x∈ = fsuc $ ‼-nub⁻ {xs} i
... | no _ = case i of λ where
0F → 0F
(fsuc j) → fsuc $ ‼-nub⁻ {xs} j
module _ {B : Type ℓ} where
nubBy : (B → A) → List B → List B
nubBy f [] = []
nubBy f (x ∷ xs) with f x ∈? map f xs
... | yes _ = nubBy f xs
... | no _ = x ∷ nubBy f xs
All-nubBy : ∀ {p}{P : Pred B p} (f : B → A) xs → All P xs → All P (nubBy f xs)
All-nubBy f [] [] = []
All-nubBy f (x ∷ xs) (p ∷ ps) with f x ∈? map f xs
... | yes _ = All-nubBy f xs ps
... | no _ = p ∷ All-nubBy f xs ps
module _ (f : B → A) where
∈-nubBy⁻ : ∀ (x : B) xs → x ∈ nubBy f xs → x ∈ xs
∈-nubBy⁻ x (y ∷ xs) x∈ with f y ∈? map f xs
... | yes _ = there (∈-nubBy⁻ x xs x∈)
... | no _ with x∈
... | here refl = here refl
... | there x∈′ = there (∈-nubBy⁻ x xs x∈′)
∈-map∘nubBy⁻ : ∀ (x : B) xs → f x ∈ map f (nubBy f xs) → f x ∈ map f xs
∈-map∘nubBy⁻ _ [] fx∈ = fx∈
∈-map∘nubBy⁻ x (y ∷ xs) fx∈ with f y ∈? map f xs
... | yes y∈ = there $ ∈-map∘nubBy⁻ x xs fx∈
... | no y∉ with fx∈
... | here eq = here eq
... | there fx∈′ = there $ ∈-map∘nubBy⁻ x xs fx∈′
Unique-nubBy : ∀ xs → Unique (nubBy f xs)
Unique-nubBy [] = []
Unique-nubBy (x ∷ xs) with f x ∈? map f xs
... | yes _ = Unique-nubBy xs
... | no fx∉ = All-nubBy f xs (¬Any⇒All¬ xs (fx∉ ∘ ∈-map⁺ f))
∷ Unique-nubBy xs
Unique-map∘nubBy : ∀ xs → Unique $ map f (nubBy f xs)
Unique-map∘nubBy [] = []
Unique-map∘nubBy (x ∷ xs) with f x ∈? map f xs
... | yes _ = Unique-map∘nubBy xs
... | no fx∉ = ¬Any⇒All¬ (map f (nubBy f xs)) (fx∉ ∘ ∈-map∘nubBy⁻ x xs )
∷ Unique-map∘nubBy xs
_\\_ : List A → List A → List A
xs \\ [] = xs
xs \\ (x ∷ ys) with x ∈? xs
... | no _ = xs \\ ys
... | yes x∈xs = (remove xs (index x∈xs)) \\ ys
\\-left : [] ≡ [] \\ xs
\\-left {[]} = refl
\\-left {x ∷ ys} with x ∈? (List _ ∋ [])
... | no _ = \\-left {ys}
... | yes ()
\\-head : [] ≡ [ x ] \\ (x ∷ xs)
\\-head {x = x} {xs = xs} with x ∈? L.[ x ]
... | no ¬p = ⊥-elim (¬p (here refl))
... | yes p with index p
... | 0F = \\-left {xs = xs}
... | fsuc ()
\\-‼ : ∀ {i : Index xs}
→ [] ≡ [ xs ‼ i ] \\ xs
\\-‼ {xs = []} {()}
\\-‼ {xs = x ∷ xs} {0F} with x ∈? L.[ x ]
... | no ¬p = ⊥-elim (¬p (here refl))
... | yes (here relf) = \\-left {xs = xs}
... | yes (there ())
\\-‼ {xs = x ∷ xs} {fsuc i} with x ∈? L.[ xs ‼ i ]
... | no ¬p = \\-‼ {xs = xs} {i}
... | yes (here refl) = \\-left {xs = xs}
... | yes (there ())
postulate \\-⊆ : xs \\ ys ⊆ xs
private
¬[]↭ : ¬ ([] ↭ x ∷ xs)
¬[]↭ (↭-trans {.[]} {[]} {.(_ ∷ _)} []↭ []↭₁) = ¬[]↭ []↭₁
¬[]↭ (↭-trans {.[]} {x ∷ ys} {.(_ ∷ _)} []↭ []↭₁) = ¬[]↭ []↭
↭-remove : ∀ {x∈ : x ∈ ys} → x ∷ remove ys (index x∈) ↭ ys
↭-remove {x} {.(x ∷ _)} {here refl} = ↭-refl
↭-remove {x} {(y ∷ x ∷ _)} {there (here refl)} = ↭-swap x y ↭-refl
↭-remove {x} {(x₁ ∷ x₂ ∷ ys)} {there (there x∈ys)} = ↭-trans h₁ h₂
where
ys′ : List A
ys′ = remove ys (index x∈ys)
h₁ : x ∷ x₁ ∷ x₂ ∷ ys′ ↭ x₁ ∷ x₂ ∷ x ∷ ys′
h₁ = ↭-trans (↭-swap x x₁ ↭-refl) (↭-prep x₁ (↭-swap x x₂ ↭-refl))
h₂ : x₁ ∷ x₂ ∷ x ∷ ys′ ↭ x₁ ∷ x₂ ∷ ys
h₂ = ↭-prep x₁ (↭-prep x₂ ↭-remove)
↭-helper→ : ∀ {x∈ : x ∈ ys}
→ xs ↭ remove ys (index x∈)
→ x ∷ xs ↭ ys
↭-helper→ {x} {xs} {ys} h = ↭-trans (↭-prep x h) ↭-remove
↭-helper← : ∀ {x∈ : x ∈ ys}
→ x ∷ xs ↭ ys
→ xs ↭ remove ys (index x∈)
↭-helper← {x} {x ∷ _} {x∈ = here refl} = drop-∷
↭-helper← {x} {y ∷ x ∷ _} {x∈ = there (here refl)} = drop-mid [] [ y ]
↭-helper← {x} {x₁ ∷ x₂ ∷ ys} {x∈ = there (there x∈ys)} = drop-∷ ∘ flip ↭-trans h
where
ys′ = remove ys (index x∈ys)
h′ : x₂ ∷ ys ↭ x ∷ x₂ ∷ ys′
h′ = ↭-trans (↭-prep x₂ $ ↭-sym ↭-remove) (↭-swap x₂ x ↭-refl)
h : x₁ ∷ x₂ ∷ ys ↭ x ∷ x₁ ∷ x₂ ∷ ys′
h = ↭-trans (↭-prep x₁ h′) (↭-swap x₁ x ↭-refl)
instance
Dec-↭ : _↭_ {A = A} ⁇²
Dec-↭ {x = xs} {y = ys} .dec with xs | ys
... | [] | [] = yes ↭-refl
... | [] | _ ∷ _ = no ¬[]↭
... | x ∷ xs′ | ys′ with x ∈? ys′
... | no x∉ = no λ x∷xs↭ → x∉ (∈-resp-↭ x∷xs↭ (here refl))
... | yes x∈ with ¿ xs′ ↭ remove ys′ (index x∈) ¿
... | no ¬xs↭ = no (¬xs↭ ∘ ↭-helper←)
... | yes xs↭ = yes (↭-helper→ xs↭)
_↭?_ = ¿ _↭_ {A = A} ¿²
instance
Dec-Interleaving : _∥_≡_ {A = A} ⁇³
Dec-Interleaving {x = xs} {y = ys} {z = zs} .dec
with xs | ys | zs
... | [] | [] | [] = yes []
... | [] | [] | _ ∷ _ = no λ ()
... | _ ∷ _ | _ | [] = no λ ()
... | _ | _ ∷ _ | [] = no λ ()
... | xˡ ∷ l | [] | x ∷ l↔r
= case xˡ ≟ x of λ where
(yes refl) → case ¿ l ∥ [] ≡ l↔r ¿ of λ where
(yes p) → yes (keepˡ p)
(no ¬p) → no (λ where (keepˡ p) → ¬p p)
(no x≢) → no λ where (keepˡ _) → x≢ refl
... | [] | xʳ ∷ r | x ∷ l↔r
= case xʳ ≟ x of λ where
(yes refl) → case ¿ [] ∥ r ≡ l↔r ¿ of λ where
(yes p) → yes (keepʳ p)
(no ¬p) → no (λ where (keepʳ p) → ¬p p)
(no x≢) → no λ where (keepʳ _) → x≢ refl
... | xˡ ∷ l | xʳ ∷ r | x ∷ l↔r
with ¿ (xˡ ≡ x) × (l ∥ (xʳ ∷ r) ≡ l↔r) ¿
... | yes (refl , p) = yes (keepˡ p)
... | no x≢׬pˡ
with ¿ (xʳ ≡ x) × ((xˡ ∷ l) ∥ r ≡ l↔r) ¿
... | yes (refl , p) = yes (keepʳ p)
... | no x≢׬pʳ = no λ where
(keepˡ l↔r′) → x≢׬pˡ (refl , l↔r′)
(keepʳ l↔r′) → x≢׬pʳ (refl , l↔r′)
_∥_≟_ = ¿ _∥_≡_ {A = A} ¿³
_⊆[bag]_ _⊈[bag]_ : Rel (List A) _
xs ⊆[bag] ys = All (λ x → count (_≟ x) xs ≤ count (_≟ x) ys) (nub xs)
_⊈[bag]_ = ¬_ ∘₂ _⊆[bag]_
_⊆[bag]?_ = Decidable² _⊆[bag]_ ∋ dec²
postulate
⊆[bag]⇒⊆ : xs ⊆[bag] ys → xs ⊆ ys
⊆[bag]-++ˡ : xs ⊆[bag] (xs ++ ys)
⊆[bag]-++ʳ : ys ⊆[bag] (xs ++ ys)
⊆[bag]-trans : Transitive (Rel (List A) _ ∋ _⊆[bag]_)
⊆[bag]-trans {i = i}{j}{k} p q =
L.All.tabulate (λ {x} x∈ →
Nat.≤-trans (L.All.lookup p {x} x∈)
(lookup q {x} (∈-nub⁺ {xs = j} $ ⊆[bag]⇒⊆ p (∈-nub⁻ {xs = i} x∈))))
bag-mergeWith : Op₂ ℕ → Op₂ (List A)
bag-mergeWith _⊗_ xs ys
= flip concatMap (nub xs)
$ λ x → L.replicate (count (_≟ x) xs ⊗ count (_≟ x) ys) x
_+[bag]_ _∸[bag]_ _*[bag]_ : Op₂ (List A)
_+[bag]_ = bag-mergeWith _+_
_∸[bag]_ = bag-mergeWith _∸_
_*[bag]_ = bag-mergeWith _*_
module _ (_⊗_ : Op₂ ℕ) (⊗-mono : ∀ n m → n ⊗ m ≥ n ⊔ m) {xs ys} where
private xys = bag-mergeWith _⊗_ xs ys
postulate ⊆[bag]-mergeWith : (xs ⊆[bag] xys) × (ys ⊆[bag] xys)
⊆[bag]-mergeWithˡ = ⊆[bag]-mergeWith .proj₁
⊆[bag]-mergeWithʳ = ⊆[bag]-mergeWith .proj₂
module _ ⦃ _ : Ord A ⦄ ⦃ _ : DecOrd A ⦄ ⦃ _ : OrdLaws A ⦄ where postulate
Sorted-nub⁺ : Sorted xs → Sorted (nub xs)
Sorted-bag-mergeWith⁺ : ∀ (_⊗_ : Op₂ ℕ) →
Sorted xs → Sorted (bag-mergeWith _⊗_ xs ys)