{-# OPTIONS --safe #-}
module Data.List.Membership where
open import Prelude
infixr 5 _∈_ _∈!_
_∈_ : A → List A → Type _
x ∈ xs = Fibre (xs !!_ ) x
_∈!_ : A → List A → Type _
x ∈! xs = isContr (x ∈ xs)
infixr 5 _∉_
_∉_ : A → List A → Type _
x ∉ xs = ¬ (x ∈ xs)
private variable n : ℕ
tabulate-∈ : (f : Fin n → A) (x : Fin n) → f x ∈ tabulate f
tabulate-∈ {n = suc n} f zero = zero , refl
tabulate-∈ {n = suc n} f (suc x) =
let i , p = tabulate-∈ (f ∘ suc) x
in suc i , p
allFins : List (Fin n)
allFins = tabulate id
∈-allFins : (i : Fin n) → i ∈ allFins
∈-allFins = tabulate-∈ id
NoDup : {A : Type a} → List A → Type a
NoDup [] = Poly-⊤
NoDup (x ∷ xs) = (x ∉ xs) × NoDup xs
module _ (_≟_ : Discrete A) where
module _ (x : A) where
find : ∀ xs → Dec (x ∈ xs)
find [] = no λ ()
find (y ∷ xs) with x ≟ y | find xs
... | yes x≡y | _ = yes (zero , sym x≡y)
... | no _ | yes (i , x∈xs) = yes (suc i , x∈xs)
... | no x≢y | no x∉xs = no λ { (zero , x∈xs) → x≢y (sym x∈xs) ; (suc i , x∈xs) → x∉xs (i , x∈xs) }
NoDups? : (xs : List A) → Dec (NoDup xs)
NoDups? [] = yes Poly-tt
NoDups? (x ∷ xs) with find x xs | NoDups? xs
NoDups? (x ∷ xs) | yes x∈xs | _ = no ((_$ x∈xs) ∘ fst)
NoDups? (x ∷ xs) | no x∉xs | yes nds = yes (x∉xs , nds)
NoDups? (x ∷ xs) | no x∉xs | no ¬nds = no (¬nds ∘ snd)
isPropNoDup : (xs : List A) → isProp (NoDup xs)
isPropNoDup [] _ _ = refl
isPropNoDup (x ∷ xs) (l , ls) (r , rs) = cong₂ _,_ (isProp¬ l r) (isPropNoDup xs ls rs)
NoDup⇒Inj : (xs : List A) → NoDup xs → Injective (xs !!_)
NoDup⇒Inj (x ∷ xs) nd {zero} {zero} p = refl
NoDup⇒Inj (x ∷ xs) (_ , nd) {suc i} {suc j} p = cong suc (NoDup⇒Inj xs nd p)
NoDup⇒Inj (x ∷ xs) (n , _) {zero} {suc j} p = absurd (n (j , sym p))
NoDup⇒Inj (x ∷ xs) (n , _) {suc i} {zero} p = absurd (n (i , p))
module _ {x : A} where
infixr 5 _++◇_ _◇++_
_++◇_ : ∀ {xs} ys → x ∈ xs → x ∈ (ys ++ xs)
[] ++◇ p = p
(x ∷ ys) ++◇ p = map-Σ suc id (ys ++◇ p)
_◇++_ : ∀ xs {ys} → x ∈ xs → x ∈ (xs ++ ys)
(x ∷ xs) ◇++ (zero , p) = zero , p
(x ∷ xs) ◇++ (suc i , p) = map-Σ suc id (xs ◇++ (i , p))
cong-∈ : (f : A → B) (xs : List A) {x : A} → x ∈ xs → f x ∈ mapl f xs
cong-∈ f (x ∷ xs) (zero , p) = zero , cong f p
cong-∈ f (x ∷ xs) (suc i , p) = map-Σ suc id (cong-∈ f xs (i , p))
here! : ∀ {x y : A} {xs} → isContr (x ≡ y) → y ∉ xs → y ∈! x ∷ xs
here! Px p∉xs .fst = zero , Px .fst
here! Px p∉xs .snd (zero , p∈xs) = ΣPathP (refl , Px .snd _)
here! Px p∉xs .snd (suc n , p∈xs) = absurd (p∉xs (n , p∈xs))
open import Data.Fin.Properties using (suc-injective)
module MembershipManips where
pull : ∀ {x y : A} {xs} → x ≢ y → y ∈ x ∷ xs → y ∈ xs
pull x≢y (zero , y∈xxs) = absurd (x≢y y∈xxs)
pull x≢y (suc n , y∈xxs) = n , y∈xxs
push : ∀ {x y : A} {xs} → y ∈ xs → y ∈ x ∷ xs
push (n , p) = suc n , p
pull! : ∀ {x y : A} {xs} → x ≢ y → y ∈! x ∷ xs → y ∈! xs
pull! x≢y ((zero , y∈xxs) , c) = absurd (x≢y y∈xxs)
pull! x≢y ((suc n , y∈xxs) , c) .fst = (n , y∈xxs)
pull! x≢y ((suc n , y∈xxs) , c) .snd (m , q) i = pull x≢y (c (suc m , q) i)
push! : ∀ {x y : A} {xs} → x ≢ y → y ∈! xs → y ∈! x ∷ xs
push! ¬Px x∈!xs .fst = push (x∈!xs .fst)
push! ¬Px x∈!xs .snd (zero , px) = absurd (¬Px px)
push! ¬Px x∈!xs .snd (suc n , y∈xs) i = push (x∈!xs .snd (n , y∈xs) i)
open MembershipManips
module _ {a} {A : Type a} (_≟_ : Discrete A) where
isSet⟨A⟩ : isSet A
isSet⟨A⟩ = Discrete→isSet _≟_
infixl 6 _\\_
_\\_ : List A → A → List A
xs \\ x = foldr f [] xs
where
f : A → List A → List A
f y xs with x ≟ y
... | yes p = xs
... | no p = y ∷ xs
uniques : List A → List A
uniques = foldr f []
where
f : A → List A → List A
f x xs = x ∷ (xs \\ x)
x∉xs\\x : ∀ x xs → x ∉ xs \\ x
x∉xs\\x x (y ∷ xs) (n , x∈xs) with x ≟ y
x∉xs\\x x (y ∷ xs) (n , x∈xs) | yes p = x∉xs\\x x xs (n , x∈xs)
x∉xs\\x x (y ∷ xs) (zero , y≡x) | no ¬p = ¬p (sym y≡x)
x∉xs\\x x (y ∷ xs) (suc n , x∈xs) | no ¬p = x∉xs\\x x xs (n , x∈xs)
x∈!x∷xs\\x : ∀ x xs → x ∈! x ∷ xs \\ x
x∈!x∷xs\\x x xs = here! (refl , isSet⟨A⟩ _ _ _) (x∉xs\\x x xs)
x∉xs⇒x∉xs\\y : ∀ (x : A) y xs → x ∉ xs → x ∉ xs \\ y
x∉xs⇒x∉xs\\y x y (z ∷ xs) x∉xs x∈xs\\y with y ≟ z
x∉xs⇒x∉xs\\y x y (z ∷ xs) x∉xs x∈xs\\y | yes p =
x∉xs⇒x∉xs\\y x y xs (x∉xs ∘ map-Σ suc id) x∈xs\\y
x∉xs⇒x∉xs\\y x y (z ∷ xs) x∉xs (zero , x∈xs\\y) | no ¬p =
x∉xs (zero , x∈xs\\y)
x∉xs⇒x∉xs\\y x y (z ∷ xs) x∉xs (suc n , x∈xs\\y) | no ¬p =
x∉xs⇒x∉xs\\y x y xs (x∉xs ∘ map-Σ suc id) (n , x∈xs\\y)
open import Data.Fin.Properties using (zero≢suc ; suc≢zero)
x∈!xs⇒x∈!xs\\y : ∀ (x : A) y xs → y ≢ x → x ∈! xs → x ∈! xs \\ y
x∈!xs⇒x∈!xs\\y x y (z ∷ xs) y≢x x∈!xs with y ≟ z
x∈!xs⇒x∈!xs\\y x y (z ∷ xs) y≢x x∈!xs | yes p =
x∈!xs⇒x∈!xs\\y x y xs y≢x (pull! (y≢x ∘′ (p ;_)) x∈!xs)
x∈!xs⇒x∈!xs\\y x y (z ∷ xs) y≢x ((zero , x∈xs) , uniq) | no ¬p =
here! (x∈xs , isSet⟨A⟩ _ _ _) (x∉xs⇒x∉xs\\y x y xs (zero≢suc ∘′ cong fst ∘′ uniq ∘′ push))
x∈!xs⇒x∈!xs\\y x y (z ∷ xs) y≢x ((suc n , x∈xs) , uniq) | no ¬p =
push! z≢x (x∈!xs⇒x∈!xs\\y x y xs y≢x (pull! z≢x ((suc n , x∈xs) , uniq)))
where z≢x = suc≢zero ∘ cong fst ∘′ uniq ∘′ (zero ,_)
∈⇒∈! : (x : A) (xs : List A) → x ∈ xs → x ∈! uniques xs
∈⇒∈! x (y ∷ xs) (zero , x∈xs) =
subst (_∈! (y ∷ uniques xs \\ y)) x∈xs (x∈!x∷xs\\x y (uniques xs))
∈⇒∈! x (y ∷ xs) (suc n , x∈xs) with y ≟ x
... | yes p = subst (_∈! (y ∷ uniques xs \\ y)) p (x∈!x∷xs\\x y (uniques xs))
... | no ¬p = push! ¬p (x∈!xs⇒x∈!xs\\y x y (uniques xs) ¬p (∈⇒∈! x xs (n , x∈xs)))