{-# OPTIONS --safe #-}
module Prelude.Lists where
open import Prelude.Init hiding (mapMaybe); open L using (mapMaybe)
open import Prelude.FromNat
open import Prelude.Decidable
open import Prelude.DecEq
open import Prelude.InferenceRules
open import Prelude.Anyable
open import Prelude.Allable
open L.Any using (satisfied)
private variable
A B : Type
xs ys : List A
x x′ y : A
f : A → B
open Nat hiding (_≟_)
module _ m {n o} (open ≤-Reasoning) where
+-∸-assoc≤ : (m + n) ∸ o ≤ m + (n ∸ o)
+-∸-assoc≤
with o ≤? n
... | yes o≤n = ≤-reflexive $ +-∸-assoc _ o≤n
... | no o≰n
with o>n ← <⇒≤ (≰⇒> o≰n)
with m≡m+n∸o ← begin-equality
m ≡˘⟨ +-identityʳ _ ⟩
m + 0 ≡˘⟨ cong (m +_) $ m≤n⇒m∸n≡0 o>n ⟩
m + (n ∸ o) ∎
with o ≥? m + n
... | yes o≥m+n =
begin
(m + n) ∸ o
≡⟨ m≤n⇒m∸n≡0 o≥m+n ⟩
0
≤⟨ z≤n ⟩
m
≡⟨ m≡m+n∸o ⟩
m + (n ∸ o)
∎
... | no o≱m+n =
let o<m+n = <⇒≤ (≰⇒> o≱m+n) in
begin
(m + n) ∸ o
≤⟨ +-cancelʳ-≤ o _ m
$ begin (m + n) ∸ o + o ≡⟨ m∸n+n≡m o<m+n ⟩
m + n ≤⟨ +-monoʳ-≤ m o>n ⟩
m + o ∎
⟩
m
≡⟨ m≡m+n∸o ⟩
m + (n ∸ o)
∎
Null : Pred (List A) _
Null = _≡ []
Null-map⁻ : Null (map f xs) → Null xs
Null-map⁻ {xs = []} _ = refl
private variable P Q : Pred A ℓ
∈-lookup : ∀ {xs : List A} (i : Any P xs) → L.Any.lookup i ∈ xs
∈-lookup = λ where
(here px) → here refl
(there i) → there (∈-lookup i)
anyAll : ∀ {xs : List A} → All Q xs → (i : Any P xs) → Q (L.Any.lookup i)
anyAll q = L.All.lookup q ∘ ∈-lookup
satisfied′ : ∀ {A : Type} {P : A → Type} {xs : List A} →
Any P xs
───────────────────
∃[ x ] x ∈ xs × P x
satisfied′ = λ where
(here px) → -, here refl , px
(there pxs) → let x , x∈ , px = satisfied′ pxs
in x , there x∈ , px
∃⇔Any : ∀ {xs : List A} →
(∃ λ x → P x × x ∈ xs)
══════════════════════
Any P xs
module _ {P : A → Type} {xs : List A} where
∃⇒Any = ∃⇔Any {P = P}{xs = xs} .proj₁
Any⇒∃ = ∃⇔Any {P = P}{xs = xs} .proj₂
∃⇔Any = (λ (_ , px , x∈) → L.Any.map (λ where refl → px) x∈)
, λ where (here px) → -, px , here refl
(there pxs) → map₂ (map₂ there) (Any⇒∃ pxs)
Index : List A → Type
Index = Fin ∘ length
mapWithIndex : ∀ {B : Type} (xs : List A) → (Index xs → B) → List B
mapWithIndex [] _ = []
mapWithIndex (_ ∷ xs) f = f 0 ∷ mapWithIndex xs (f ∘ fsuc)
filterByIndex : (xs : List A) → (Index xs → Bool) → List A
filterByIndex [] _ = []
filterByIndex (x ∷ xs) f =
let xs′ = filterByIndex xs (f ∘ fsuc) in
if f 0 then x ∷ xs′ else xs′
∈-filterByIndex⁻ : ∀ (xs : List A) (f : Index xs → Bool) → filterByIndex xs f ⊆ˢ xs
∈-filterByIndex⁻ (x ∷ xs) f x∈
with f 0
... | false = there $ ∈-filterByIndex⁻ xs (f ∘ fsuc) x∈
... | true
with x∈
... | here refl = here refl
... | there x∈ = there $ ∈-filterByIndex⁻ xs (f ∘ fsuc) x∈
subsetIndices : xs ⊆ˢ ys → List (Index ys)
subsetIndices {xs = []} {ys} p = []
subsetIndices {xs = x ∷ xs} {ys} p =
L.Any.index (p $ here refl) ∷ subsetIndices {xs = xs} (p ∘ there)
removeAt∗ : (xs : List A) → List (Index xs) → List A
removeAt∗ xs is = filterByIndex xs (⌊_⌋ ∘ (_∉? is))
∈-removeAt∗⁻ : ∀ {xs : List A} {is : List (Index xs)} → removeAt∗ xs is ⊆ˢ xs
∈-removeAt∗⁻ = ∈-filterByIndex⁻ _ _
remove⊆ˢ : {xs ys : List A} → xs ⊆ˢ ys → List A
remove⊆ˢ {ys = ys} p = removeAt∗ ys $ subsetIndices p
∈-remove⊆ˢ⁻ : ∀ {xs ys : List A} (p : xs ⊆ˢ ys) → remove⊆ˢ p ⊆ˢ ys
∈-remove⊆ˢ⁻ _ = ∈-removeAt∗⁻
lookup≡proj₁∘satisfied : ∀ {xs : List A} (p : Any P xs) →
L.Any.lookup p ≡ satisfied p .proj₁
lookup≡proj₁∘satisfied (here _) = refl
lookup≡proj₁∘satisfied (there p) = lookup≡proj₁∘satisfied p
∈-removeAt⁻ : ∀ (n : Index xs) {x} → x ∈ L.removeAt xs n → x ∈ xs
∈-removeAt⁻ {xs = _ ∷ _} fzero p = there p
∈-removeAt⁻ {xs = _ ∷ _} (fsuc n) = λ where
(here refl) → here refl
(there p) → there $′ ∈-removeAt⁻ n p
∈-∷ʳ⁻ : ∀ {x y} → x ∈ xs L.∷ʳ y → (x ∈ xs) ⊎ (x ≡ y)
∈-∷ʳ⁻ {xs = xs}{x}{y} x∈ = case L.Mem.∈-++⁻ xs x∈ of λ where
(inj₁ x∈) → inj₁ x∈
(inj₂ (here x≡)) → inj₂ x≡
∅ : Index {A = A} [] → B
∅ ()
[_∶_⋯_∶_] : (x : A) → B → ∀ xs → (Index xs → B) → (Index (x ∷ xs) → B)
[ _ ∶ b ⋯ _ ∶ f ] = λ where
fzero → b
(fsuc i) → f i
_─⋯_ : (xs : List A) → Index xs → List A
xs ─⋯ i = L.drop (suc $ Fi.toℕ i) xs
private
open import Prelude.LiteralSequences
ns = List ℕ ∋ [ 0 ⨾ 1 ⨾ 2 ⨾ 3 ]
_ = ns ─⋯ 0 ≡ [ 1 ⨾ 2 ⨾ 3 ]
∋ refl
_ = ns ─⋯ 1 ≡ [ 2 ⨾ 3 ]
∋ refl
_ = ns ─⋯ 2 ≡ [ 3 ]
∋ refl
_ = ns ─⋯ 3 ≡ []
∋ refl
─⋯-⊆ : (i : Index xs) → (xs ─⋯ i) ⊆ˢ xs
─⋯-⊆ {xs = _ ∷ _} fzero = there
─⋯-⊆ {xs = _ ∷ _} (fsuc i) = there ∘′ ─⋯-⊆ _
─⋯-∷ : (i : Index xs) → ∃ λ ys → xs ≡ ys ++ L.lookup xs i ∷ (xs ─⋯ i)
─⋯-∷ {xs = _ ∷ _} fzero = [] , refl
─⋯-∷ {xs = _ ∷ xs} (fsuc i) = let ys , xs≡ = ─⋯-∷ i in _ ∷ ys , cong (_ ∷_) xs≡
─⋯-len : (i : Index xs) → length (xs ─⋯ i) < length xs
─⋯-len {xs = _ ∷ _} fzero = ≤-refl
─⋯-len {xs = _ ∷ xs} (fsuc i) = s≤s $ <⇒≤ $ ─⋯-len {xs = xs} i
module _ {P : A → Set} (P? : Decidable¹ P) where
filter-length : length xs ≡ length (filter P? xs) + length (filter (¬? ∘ P?) xs)
filter-length {[]} = refl
filter-length {x ∷ xs} with P? x
... | no ¬p
rewrite +-suc (length (filter P? xs)) (length (filter (¬? ∘ P?) xs))
rewrite filter-length {xs = xs} = refl
... | yes p rewrite filter-length {xs = xs} = refl
module _ {Q : A → Set} (Q? : Decidable¹ Q) (P⇔Q : P ≐ Q) where
filter≡ : ∀ xs → filter P? xs ≡ filter Q? xs
filter≡ [] = refl
filter≡ (x ∷ xs)
with IH ← filter≡ xs
with P? x
... | yes px rewrite dec-yes (Q? x) (P⇔Q .proj₁ px) .proj₂ = cong (x ∷_) IH
... | no ¬px rewrite dec-no (Q? x) (¬px ∘ P⇔Q .proj₂) = IH
module _ {P : Pred A ℓ} ⦃ _ : P ⁇¹ ⦄ (f : B → A) where
filter-map : ∀ xs → filter ¿ P ¿¹ (map f xs) ≡ map f (filter (¿ P ¿¹ ∘ f) xs)
filter-map [] = refl
filter-map (x ∷ xs)
with IH ← filter-map xs
with ¿ P (f x) ¿
... | yes _ = cong (_ ∷_) IH
... | no _ = IH
open L.Mem using (mapWith∈)
open L.All using (lookup; tabulate; ¬Any⇒All¬)
open L.Any using (index; _─_)
∈-─⁻ : (x∈′ : x′ ∈ xs) → x ∈ (xs ─ x∈′) → x ∈ xs
∈-─⁻ = λ where
(here _) x∈′ → there x∈′
(there x∈) (here refl) → here refl
(there x∈) (there x∈′) → there $ ∈-─⁻ x∈ x∈′
∈-─⁺ : x ≢ y → (x∈ : x ∈ xs) → y ∈ xs → y ∈ (xs ─ x∈)
∈-─⁺ {xs = x ∷ xs} x≢ = λ where
(here refl) (here refl) → ⊥-elim $ x≢ refl
(there x∈) (here refl) → here refl
(here refl) (there y∈) → y∈
(there x∈) (there y∈) → there $ ∈-─⁺ x≢ x∈ y∈
All-─⁻ : ∀ {A : Type} {P : A → Type} {x : A} xs →
∀ (x∈ : x ∈ xs) →
∙ P x
∙ All P (xs ─ x∈)
─────────────────────
All P xs
All-─⁻ (_ ∷ _) (here refl) x∈ xs∈ = x∈ ∷ xs∈
All-─⁻ (_ ∷ xs) (there x∈xs) x∈ (p ∷ xs∈) = p ∷ All-─⁻ xs x∈xs x∈ xs∈
All∈-dropHead : ∀ {A : Type} {x : A} {xs ys} →
∙ x ∉ ys
∙ All (_∈ (x ∷ xs)) ys
────────────────────
All (_∈ xs) ys
All∈-dropHead x∉ p = L.All.tabulate λ y∈ →
case L.All.lookup p y∈ of λ where
(here refl) → ⊥-elim $ x∉ y∈
(there p) → p
length-mapWith∈ : (f : ∀ {x} → x ∈ xs → B) →
length (mapWith∈ xs f) ≡ length xs
length-mapWith∈ {xs = []} _ = refl
length-mapWith∈ {xs = _ ∷ xs} f = cong suc $ length-mapWith∈ {xs = xs} (f ∘ there)
mapWith∈-∀ : ∀ {xs : List A} {f : ∀ {x : A} → x ∈ xs → B} {P : B → Type}
→ (∀ {x} x∈ → P (f {x} x∈))
→ (∀ {y} → y ∈ mapWith∈ xs f → P y)
mapWith∈-∀ {xs = x ∷ xs} ∀P {y} (here px) rewrite px = ∀P (here refl)
mapWith∈-∀ {xs = x ∷ xs} ∀P {y} (there y∈) = mapWith∈-∀ (∀P ∘ there) y∈
Unique-mapWith∈ : ∀ {A B : Type} {xs : List A} {f : ∀ {x} → x ∈ xs → B}
→ (∀ {x x′} {x∈ : x ∈ xs} {x∈′ : x′ ∈ xs}
→ f x∈ ≡ f x∈′
→ index x∈ ≡ index x∈′)
→ Unique (mapWith∈ xs f)
Unique-mapWith∈ {xs = []} {f = f} f≡ = []
Unique-mapWith∈ {xs = x ∷ xs} {f = f} f≡
= L.All.tabulate (mapWith∈-∀ {P = f (here refl) ≢_} λ _ eq → case f≡ eq of λ () )
∷ Unique-mapWith∈ {xs = xs} (Fi.suc-injective ∘ f≡)
filterWith∈ : (xs : List A) {P : ∀ {x} → x ∈ xs → Set}
(P? : ∀ {x} (x∈ : x ∈ xs) → Dec (P x∈)) → List A
filterWith∈ [] P? = []
filterWith∈ (x ∷ xs) P?
with IH ← filterWith∈ xs (P? ∘ there)
with P? (here refl)
... | yes px = x ∷ IH
... | no ¬px = IH
filterWith∈≡ :
(xs : List A)
{P Q : ∀ {x} → x ∈ xs → Set}
(P? : ∀ {x} (x∈ : x ∈ xs) → Dec (P x∈))
(Q? : ∀ {x} (x∈ : x ∈ xs) → Dec (Q x∈))
(P⇔Q : ∀ {x}{x∈ : x ∈ xs} → P x∈ ↔ Q x∈)
→ filterWith∈ xs P? ≡ filterWith∈ xs Q?
filterWith∈≡ [] P? Q? P⇔Q = refl
filterWith∈≡ (x ∷ xs) P? Q? P⇔Q
with IH ← filterWith∈≡ xs (P? ∘ there) (Q? ∘ there) P⇔Q
with P? (here refl)
... | yes px rewrite dec-yes (Q? (here refl)) (P⇔Q .proj₁ px) .proj₂
= cong (x ∷_) IH
... | no ¬px rewrite dec-no (Q? (here refl)) (¬px ∘ P⇔Q .proj₂)
= IH
filter∘mapWith∈ :
∀ (xs : List A)
→ (f : ∀ {x} → x ∈ xs → B)
→ {P : B → Set}
→ (P? : Decidable¹ P)
→ length (filter P? (mapWith∈ xs f)) ≡ length (filterWith∈ xs (P? ∘ f))
filter∘mapWith∈ [] f {P} P? = refl
filter∘mapWith∈ (x ∷ xs) f {P} P?
with IH ← filter∘mapWith∈ xs (f ∘ there) P?
with P? (f $ here refl)
... | yes px = cong suc IH
... | no ¬px = IH
filterWith∈≗filter : ∀ {P : A → Set} (P? : Decidable¹ P) xs
→ filterWith∈ xs (λ {x} _ → P? x) ≡ filter P? xs
filterWith∈≗filter P? [] = refl
filterWith∈≗filter P? (x ∷ xs)
with IH ← filterWith∈≗filter P? xs
with P? x
... | yes px = cong (x ∷_) IH
... | no ¬px = IH
index∘subst : ∀ {x x′}{xs : List A}{x∈ : x ∈ xs} (eq : x ≡ x′)
→ index (subst (_∈ _) eq x∈) ≡ index x∈
index∘subst refl = refl
module _ (f : A → Maybe B) where
mapMaybe-++ : ∀ xs ys → mapMaybe f (xs ++ ys) ≡ mapMaybe f xs ++ mapMaybe f ys
mapMaybe-++ [] ys = refl
mapMaybe-++ (x ∷ xs) ys with f x
... | just _ = cong (_ ∷_) (mapMaybe-++ xs ys)
... | nothing = mapMaybe-++ xs ys
open L.Mem
∈-mapMaybe-++⁻ : ∀ xs {ys} {x : B}
→ x ∈ mapMaybe f (xs ++ ys)
→ x ∈ mapMaybe f xs
⊎ x ∈ mapMaybe f ys
∈-mapMaybe-++⁻ xs {ys} rewrite mapMaybe-++ xs ys = ∈-++⁻ _
∈-mapMaybe-++⁺ˡ : ∀ {xs ys} {x : B}
→ x ∈ mapMaybe f xs
→ x ∈ mapMaybe f (xs ++ ys)
∈-mapMaybe-++⁺ˡ {xs}{ys} rewrite mapMaybe-++ xs ys = ∈-++⁺ˡ
∈-mapMaybe-++⁺ʳ : ∀ xs {ys} {y : B}
→ y ∈ mapMaybe f ys
→ y ∈ mapMaybe f (xs ++ ys)
∈-mapMaybe-++⁺ʳ xs {ys} rewrite mapMaybe-++ xs ys = ∈-++⁺ʳ _
∈-mapMaybe⁺ : x ∈ xs → f x ≡ just y → y ∈ mapMaybe f xs
∈-mapMaybe⁺ {x = x} {xs = xs} {y = y} x∈ eq
= L.Any.mapMaybe⁺ f xs
$ L.Any.map (λ where refl → subst (Any _) (sym eq) (just refl))
(∈-map⁺ f x∈)
∈-mapMaybe⁻ : y ∈ mapMaybe f xs
→ ∃ λ x → (x ∈ xs) × (f x ≡ just y)
∈-mapMaybe⁻ {y = y} {xs = x ∷ xs} y∈
with f x in fx≡
... | nothing = map₂ (map₁ there) (∈-mapMaybe⁻ y∈)
... | just y′
with y∈
... | here refl = x , here refl , fx≡
... | there y∈′ = map₂ (map₁ there) (∈-mapMaybe⁻ y∈′)
mapMaybe-⊆ : xs ⊆ˢ ys → mapMaybe f xs ⊆ˢ mapMaybe f ys
mapMaybe-⊆ {xs = x ∷ xs} {ys = ys} xs⊆ fx∈ =
let x , x∈ , fx≡ = ∈-mapMaybe⁻ fx∈
in ∈-mapMaybe⁺ (xs⊆ x∈) fx≡
⊆⇒⊆ˢ : xs ⊆ ys → xs ⊆ˢ ys
⊆⇒⊆ˢ (_ ∷ʳ p) = there ∘ ⊆⇒⊆ˢ p
⊆⇒⊆ˢ (refl ∷ p) = λ where
(here refl) → here refl
(there x∈) → there (⊆⇒⊆ˢ p x∈)
⊆ˢ-tail : ∀ {z} → z ∉ xs → z ∷ xs ⊆ˢ z ∷ ys → xs ⊆ˢ ys
⊆ˢ-tail z∉ sub x∈ =
L.Any.tail (lookup (¬Any⇒All¬ _ z∉) x∈ ∘ sym) (sub $ there x∈)
⊆ˢ-length : Unique xs → xs ⊆ˢ ys → length xs ≤ length ys
⊆ˢ-length {xs = []} {ys} uniq xs⊆ = z≤n
⊆ˢ-length {xs = x ∷ xs} {ys} (x∉xs ∷ uniq) xs⊆ =
begin-strict length xs ≤⟨ ⊆ˢ-length uniq xs⊆ys′ ⟩
length ys′ <⟨ ≤-reflexive $ sym $ L.length-removeAt′ ys _ ⟩
length ys ∎
where
open Nat.≤-Reasoning
x∈ys : x ∈ ys
x∈ys = xs⊆ (here refl)
ys′ = ys ─ x∈ys
xs⊆ys′ : xs ⊆ˢ ys′
xs⊆ys′ y∈ = ∈-─⁺ (L.All.lookup x∉xs y∈) x∈ys (xs⊆ $ there y∈)
Fins = List ∘ Fin
module _ {n : ℕ} {x x′ : Fin (suc n)} (x≢ : x′ ≢ x) where
∈-punchOutʳ : ∀ {ys : Fins (suc n)}
→ (x∉ : x′ ∉ ys)
→ x ∈ ys
→ Fi.punchOut {n}{x′}{x} x≢
∈ mapWith∈ ys (λ {y} y∈ → Fi.punchOut {n}{x′}{y} λ where refl → x∉ y∈)
∈-punchOutʳ x∉ = λ where
(here refl) → here refl
(there p) → there $ ∈-punchOutʳ (x∉ ∘ there) p
∈-punchOutˡ : ∀ {ys : Fins (suc n)}
→ (x∉ : x′ ∉ ys)
→ Fi.punchOut {n}{x′}{x} x≢
∈ mapWith∈ ys (λ {y} y∈ → Fi.punchOut {n}{x′}{y} λ where refl → x∉ y∈)
→ x ∈ ys
∈-punchOutˡ {ys = _ ∷ _} x∉ = λ where
(here px) → here $ Fi.punchOut-injective x≢ (λ where refl → x∉ $ here refl) px
(there p) → there $ ∈-punchOutˡ (x∉ ∘ there) p
∈-punchOut : ∀ {ys : Fins (suc n)}
→ (x∉ : x′ ∉ ys)
→ (Fi.punchOut {n}{x′}{x} x≢
∈ mapWith∈ ys (λ {y} y∈ → Fi.punchOut {n}{x′}{y} λ where refl → x∉ y∈))
↔ (x ∈ ys)
∈-punchOut x∉ = ∈-punchOutˡ x∉ , ∈-punchOutʳ x∉
punchOut≡⇒index≡ : ∀ {n}{xs : Fins (suc n)}{x x′ x₀}{x∈ : x ∈ xs}{x∈′ : x′ ∈ xs}
→ Unique xs
→ (x≢ : L.All.All (x₀ ≢_) xs)
→ Fi.punchOut (lookup x≢ x∈) ≡ Fi.punchOut (lookup x≢ x∈′)
→ index x∈ ≡ index x∈′
punchOut≡⇒index≡ {n}{xs}{x}{x′}{x₀}{x∈}{x∈′} uxs x≢ eq = let open ≡-Reasoning in
begin
index x∈
≡⟨ cong index $ unique⇒irrelevant uxs x∈ _ ⟩
index (subst (_∈ _) x≡ x∈′)
≡⟨ index∘subst x≡ ⟩
index x∈′
∎
where
open import Data.List.Membership.Propositional.Properties.WithK
using (unique⇒irrelevant)
x≡ : x′ ≡ x
x≡ = sym $ Fi.punchOut-injective (lookup x≢ x∈) (lookup x≢ x∈′) eq
Prefix≡ : List A → List A → Type _
Prefix≡ = Prefix _≡_
≡⇒Prefix : xs ≡ ys → Prefix≡ xs ys
≡⇒Prefix {xs = []} {ys = []} refl = []
≡⇒Prefix {xs = _ ∷ _} {ys = _ ∷ _} refl = refl ∷ ≡⇒Prefix refl
instance
Dec-Prefix≡ : ⦃ DecEq A ⦄ → Prefix≡ {A = A} ⁇²
Dec-Prefix≡ = ⁇ L.Pre.prefix? _≟_ _ _
Prefix⇒⊆ : Prefix≡ xs ys → xs ⊆ˢ ys
Prefix⇒⊆ (refl ∷ pre) = λ where
(here refl) → here refl
(there p) → there (Prefix⇒⊆ pre p)
Prefix⇒All : ∀ {P : Pred A ℓ} → Prefix≡ xs ys → L.All.All P ys → L.All.All P xs
Prefix⇒All = L.SubS.All-resp-⊇ ∘ Prefix⇒⊆
Prefix-take : ∀ {n} → Prefix≡ (L.take n xs) xs
Prefix-take {xs = xs} {n = n} with n
... | zero = []
... | suc _ with xs
... | [] = []
... | _ ∷ _ = refl ∷ Prefix-take
Suffix≡ : List A → List A → Type _
Suffix≡ = Suffix _≡_
≡⇒Suffix : xs ≡ ys → Suffix≡ xs ys
≡⇒Suffix = here ∘ L.PW.≡⇒Pointwise-≡
instance
Dec-Suffix≡ : ⦃ DecEq A ⦄ → Suffix≡ {A = A} ⁇²
Dec-Suffix≡ = ⁇ L.Suf.suffix? _≟_ _ _
Suffix⇒⊆ : Suffix≡ xs ys → xs ⊆ˢ ys
Suffix⇒⊆ (here eq) rewrite L.PW.Pointwise-≡⇒≡ eq = id
Suffix⇒⊆ (there p) = there ∘ Suffix⇒⊆ p
Suffix⇒All : ∀ {P : Pred A ℓ} → Suffix≡ xs ys → L.All.All P ys → L.All.All P xs
Suffix⇒All = L.SubS.All-resp-⊇ ∘ Suffix⇒⊆
Suffix-drop : ∀ n → Suffix≡ (L.drop n xs) xs
Suffix-drop zero = ≡⇒Suffix refl
Suffix-drop {xs = xs} (suc n) with xs
... | [] = here []
... | _ ∷ _ = there $′ Suffix-drop n
nonEmpty∈ : length xs > 0 → ∃ (_∈ xs)
nonEmpty∈ {xs = _ ∷ _} _ = -, here refl
module _ ⦃ _ : DecEq A ⦄ where
infixr 7 _∩_
_∩_ : Op₂ (List A)
xs ∩ ys = filter (_∈? ys) xs
∈-∩⁻ : ∀ x xs ys → x ∈ (xs ∩ ys) → (x ∈ xs) × (x ∈ ys)
∈-∩⁻ _ _ _ = L.Mem.∈-filter⁻ (_∈? _)
Unique-∩ : Unique xs → Unique (xs ∩ ys)
Unique-∩ = L.Unique.filter⁺ (_∈? _)
∩-identityˡ : Null ([] ∩ xs)
∩-identityˡ = refl
∩-identityʳ : Null (xs ∩ [])
∩-identityʳ {xs} = L.filter-none _ {xs} $ L.All.tabulate λ where _ ()
length-∩ˡ : ∀ {n}{xs ys : Fins n}
→ length (xs ∩ ys) ≤ length xs
length-∩ˡ {xs = []} {ys} = z≤n
length-∩ˡ {xs = x ∷ xs} {ys}
with x ∈? ys
... | no _ = let open ≤-Reasoning in
begin length (xs ∩ ys) ≤⟨ length-∩ˡ {xs = xs} ⟩
length xs ≤⟨ n≤1+n _ ⟩
1 + length xs ∎
... | yes _ = let open ≤-Reasoning in
begin 1 + length (xs ∩ ys) ≤⟨ +-mono-≤ ≤-refl $ length-∩ˡ {xs = xs} ⟩
1 + length xs ∎
length-unique-fin : ∀ {n}{xs : Fins n}
→ Unique xs
→ length xs ≤ n
length-unique-fin {xs = []} _ = z≤n
length-unique-fin {suc n} {x ∷ xs} (x≢ ∷ uxs)
= s≤s $ let open ≤-Reasoning in
begin
length xs
≡˘⟨ length-mapWith∈ (Fi.punchOut ∘ lookup x≢) ⟩
length xs′
≤⟨ length-unique-fin {xs = xs′} uxs′ ⟩
n
∎
where
xs′ : Fins n
xs′ = mapWith∈ xs (Fi.punchOut ∘ lookup x≢)
uxs′ : Unique xs′
uxs′ = Unique-mapWith∈ $ punchOut≡⇒index≡ uxs x≢
length-∩ : ∀ {n}{xs ys : Fins n}
→ Unique xs
→ Unique ys
→ length (xs ∩ ys) ≥ length xs + length ys ∸ n
length-∩ {n} {[]} {ys} _ uys = let open ≤-Reasoning in
begin
length ys ∸ n
≡⟨ m≤n⇒m∸n≡0 (length-unique-fin uys) ⟩
0
∎
length-∩ {suc n} {x ∷ xs} {ys} (x≢ ∷ uxs) uys
with IH ← length-∩ {suc n}{xs} uxs uys
with x ∈? ys
... | yes x∈ = let open ≤-Reasoning in
begin
length xs + length ys ∸ n
≡⟨⟩
(1 + (length xs + length ys)) ∸ suc n
≤⟨ +-∸-assoc≤ 1 {o = suc n} ⟩
1 + (length xs + length ys ∸ suc n)
≤⟨ +-monoʳ-≤ 1 IH ⟩
1 + length (xs ∩ ys)
∎
... | no x∉ = let open ≤-Reasoning in
begin
length xs + length ys ∸ n
≡˘⟨ cong (λ ◆ → ◆ + _ ∸ n) len≡-xs ⟩
length xs′ + length ys ∸ n
≡˘⟨ cong (λ ◆ → length xs′ + ◆ ∸ n) len≡-ys ⟩
length xs′ + length ys′ ∸ n
≤⟨ IH′ ⟩
length (xs′ ∩ ys′)
≡⟨ len≡ ⟩
length (xs ∩ ys)
∎
where
x↓ : {x : Fin (suc n)} → x ∈ xs → Fin n
x↓ = Fi.punchOut ∘ lookup x≢
xs′ : Fins n
xs′ = mapWith∈ xs x↓
uxs′ : Unique xs′
uxs′ = Unique-mapWith∈ $ punchOut≡⇒index≡ uxs x≢
len-xs′ : length xs′ ≤ n
len-xs′ = length-unique-fin uxs′
len≡-xs : length xs′ ≡ length xs
len≡-xs = length-mapWith∈ x↓
y↓ : {y : Fin (suc n)} → y ∈ ys → Fin n
y↓ {y} y∈ = Fi.punchOut {i = x} {j = y} λ where refl → x∉ y∈
ys′ : Fins n
ys′ = mapWith∈ ys y↓
uys′ : Unique ys′
uys′ = Unique-mapWith∈ $ punchOut≡⇒index≡ uys (¬Any⇒All¬ ys x∉)
len-ys′ : length ys′ ≤ n
len-ys′ = length-unique-fin uys′
len≡-ys : length ys′ ≡ length ys
len≡-ys = length-mapWith∈ y↓
IH′ : length (xs′ ∩ ys′) ≥ length xs′ + length ys′ ∸ n
IH′ = length-∩ {n = n} uxs′ uys′
len≡ : length (xs′ ∩ ys′) ≡ length (xs ∩ ys)
len≡ = let open ≡-Reasoning in
begin
length (xs′ ∩ ys′)
≡⟨⟩
length (filter (_∈? ys′) xs′)
≡⟨⟩
length (filter (_∈? mapWith∈ ys y↓) $ mapWith∈ xs x↓)
≡⟨ filter∘mapWith∈ xs x↓ (_∈? mapWith∈ ys y↓) ⟩
length (filterWith∈ xs ((_∈? mapWith∈ ys y↓) ∘ x↓))
≡⟨⟩
length (filterWith∈ xs λ {x} x∈ → x↓ x∈ ∈? mapWith∈ ys y↓)
≡⟨ cong length
$ filterWith∈≡
xs
(λ {x} x∈ → x↓ x∈ ∈? mapWith∈ ys y↓)
(λ {x} _ → x ∈? ys)
(λ {x} {x∈} → ∈-punchOut (lookup x≢ x∈) x∉)
⟩
length (filterWith∈ xs λ {x} _ → x ∈? ys)
≡⟨ (cong length $ filterWith∈≗filter (_∈? ys) xs) ⟩
length (filter (_∈? ys) xs)
≡⟨⟩
length (xs ∩ ys)
∎
enumerate∈ : ∀ {A : Type} → (xs : List A) → List $ ∃ (_∈ xs)
enumerate∈ xs = mapWith∈ xs λ {x} x∈ → x , x∈
All-mapWith∈⁺ : ∀ {P : B → Type} {f : ∀ {x : A} → x ∈ xs → B} →
All (λ (x , x∈) → P (f {x} x∈)) (enumerate∈ xs) →
All P (mapWith∈ xs f)
All-mapWith∈⁺ {xs = []} [] = []
All-mapWith∈⁺ {xs = _ ∷ xs} {P = P} {f = f} (p ∷ ps)
= p
∷ All-mapWith∈⁺ {xs = xs} (L.All.map⁻ ps′)
where
ps′ : L.All.All (λ (x , x∈) → P (f {x} x∈))
(map (λ (x , x∈) → x , there x∈) $ enumerate∈ xs)
ps′ = subst
(λ ◆ → L.All.All (λ (x , x∈) → P (f {x} x∈)) ◆)
(sym $ L.Mem.map-mapWith∈ xs (λ {x} x∈ → x , x∈) (λ (x , x∈) → x , there x∈))
ps
∈-mapWith∈⁻ : ∀ {xs : List A} {f : ∀ {x} → x ∈ xs → B} {y : B}
→ y ∈ mapWith∈ xs f
→ ∃ λ x → Σ (x ∈ xs) λ x∈ → y ≡ f {x} x∈
∈-mapWith∈⁻ {xs = x ∷ _} (here refl) = x , here refl , refl
∈-mapWith∈⁻ {xs = x ∷ xs} (there p) = let x , x∈ , y≡ = ∈-mapWith∈⁻ p in x , there x∈ , y≡
Unique-mapWith∈⁺ : ∀ {f : ∀ {x : A} → x ∈ xs → B} →
(∀ {x y} (x∈ : x ∈ xs) (y∈ : y ∈ xs) → f x∈ ≡ f y∈ → x ≡ y) →
Unique xs →
Unique (mapWith∈ xs f)
Unique-mapWith∈⁺ {xs = []} f≡ uniq = []
Unique-mapWith∈⁺ {xs = x ∷ xs} {f = f} f≡ (x∉ ∷ uniq)
= All-mapWith∈⁺ QED
∷ Unique-mapWith∈⁺ {xs = xs} (λ x∈ y∈ → f≡ (there x∈) (there y∈)) uniq
where
QED : L.All.All (λ (y , y∈) → f {x} (here refl) ≢ (f {y} $ there y∈)) (enumerate∈ xs)
QED = tabulate λ x∈ f∘there≡ → let _ , p , eq = ∈-mapWith∈⁻ x∈ in
L.All.lookup x∉ (subst (λ ◆ → ◆ .proj₁ ∈ xs) (sym eq) p) $
f≡ (here refl) (there _) f∘there≡
UniqueBy : (A → B) → List A → Type
UniqueBy f = Unique ∘ map f
∉-─ : ∀ {A B : Type} {x : A} {xs} (f : A → B) →
∀ (x∈ : x ∈ xs)
→ UniqueBy f xs
→ x ∉ xs L.Mem.─ x∈
∉-─ {xs = _ ∷ xs} _ = λ where
(here refl) (x∉ ∷ _) x∈ → L.All.lookup x∉ (L.Mem.∈-map⁺ _ x∈) refl
(there x∈) (x∉ ∷ _) (here refl) → L.All.lookup x∉ (L.Mem.∈-map⁺ _ x∈) refl
(there x∈) (_ ∷ uniq) (there p) → ∉-─ {xs = xs} _ x∈ uniq p
module _ ⦃ _ : DecEq A ⦄ where
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∈
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
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-filter : {P : A → Set} (P? : Decidable¹ P) → nub (filter P? xs) ≡ filter P? (nub xs)
nub-filter {xs = []} P? = refl
nub-filter {xs = x ∷ xs} P?
with P? x | x ∈? xs
... | no _ | yes _ = nub-filter {xs = xs} P?
... | no ¬p | no _
rewrite L.filter-reject P? {x}{nub xs} ¬p
= nub-filter {xs = xs} P?
... | yes p | no x∉
rewrite L.filter-accept P? {x}{nub xs} p
with x ∈? filter P? xs
... | yes x∈ = ⊥-elim (x∉ (proj₁ $ L.Mem.∈-filter⁻ P? x∈ ))
... | no _ = cong (x ∷_) $ nub-filter {xs = xs} P?
nub-filter {xs = x ∷ xs} P? | yes p | yes x∈ with x ∈? filter P? xs
... | yes _ = nub-filter {xs = xs} P?
... | no x∉ = ⊥-elim $ x∉ (L.Mem.∈-filter⁺ P? x∈ p)
nub-length : length (nub xs) ≤ length (nub (x ∷ xs))
nub-length {xs}{x} with x ∈? xs
... | yes _ = ≤-refl
... | no _ = n≤1+n _
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
module _ (f : B → A) where
nubBy-⊆⁻ : nubBy f xs ⊆ˢ xs
nubBy-⊆⁻ {xs = y ∷ xs} x∈ with f y ∈? map f xs
... | yes _ = there (nubBy-⊆⁻ {xs = xs} x∈)
... | no _ with x∈
... | here refl = here refl
... | there x∈′ = there (nubBy-⊆⁻ {xs = xs} x∈′)
nubBy-⊆⁺ : map f xs ⊆ˢ map f (nubBy f xs)
nubBy-⊆⁺ {xs = y ∷ xs} (here refl)
with f y ∈? map f xs
... | yes fy∈ = nubBy-⊆⁺ {xs = xs} fy∈
... | no _ = here refl
nubBy-⊆⁺ {xs = y ∷ xs} (there x∈)
with f y ∈? map f xs
... | yes fy∈ = nubBy-⊆⁺ x∈
... | no _ = there (nubBy-⊆⁺ x∈)
UniqueBy-nubBy : ∀ xs → UniqueBy f (nubBy f xs)
UniqueBy-nubBy [] = []
UniqueBy-nubBy (x ∷ xs) with f x ∈? map f xs
... | yes _ = UniqueBy-nubBy xs
... | no fx∉ = ¬Any⇒All¬ (map f (nubBy f xs)) (fx∉ ∘ L.SubS.map⁺ _ nubBy-⊆⁻)
∷ UniqueBy-nubBy xs
++-injectiveʳ : ∀ {xs ys zs : List A} →
xs ++ ys ≡ xs ++ zs
────────────────────
ys ≡ zs
++-injectiveʳ {xs = []} = id
++-injectiveʳ {xs = _ ∷ _} = ++-injectiveʳ ∘ L.∷-injectiveʳ