PLFA agda exercises
---
title     : "Collections: Representing collections as lists"
permalink : /Collections
---

This chapter presents operations on collections and a number of
useful operations on them.


## Imports

\begin{code}
import Relation.Binary.PropositionalEquality as Eq
open Eq using (_≡_; _≢_; refl; sym; trans; cong)
open Eq.≡-Reasoning
open import Data.Nat using (ℕ; zero; suc; _+_; _*_; _∸_; _≤_; s≤s; z≤n)
-- open import Data.Nat.Properties using
--   (+-assoc; +-identityˡ; +-identityʳ; *-assoc; *-identityˡ; *-identityʳ)
open import Relation.Nullary using (¬_)
open import Data.Product using (_×_; proj₁; proj₂) renaming (_,_ to ⟨_,_⟩)
open import Data.Sum using (_⊎_; inj₁; inj₂)
open import Data.Empty using (⊥; ⊥-elim)
open import Function using (_∘_)
open import Level using (Level)
open import Data.List using (List; []; _∷_; [_]; _++_; map; foldr; filter)
open import Data.List.All using (All; []; _∷_)
open import Data.List.Any using (Any; here; there)
open import Data.Maybe using (Maybe; just; nothing)
-- open import Data.List.Any.Membership.Propositional using (_∈_)
open import Relation.Nullary using (¬_; Dec; yes; no)
open import Relation.Nullary.Negation using (contraposition; ¬?)
open import Relation.Nullary.Product using (_×-dec_)
-- open import Relation.Binary using (IsEquivalence)
\end{code}


## Collections

\begin{code}
module fresh.Collections (A : Set) (_≟_ : ∀ (x y : A) → Dec (x ≡ y)) where

    Coll : Set → Set
    Coll A  =  List A

    infix 4 _∈_
    infix 4 _⊆_
    infixl 5 _\\_

    data _∈_ : A → List A → Set where

      here : ∀ {x xs} →
        ----------
        x ∈ x ∷ xs

      there : ∀ {w x xs} →
        w ∈ xs →
        ----------
        w ∈ x ∷ xs

    _∉_ : A → List A → Set
    x ∉ xs = ¬ (x ∈ xs)

    _⊆_ : List A → List A → Set
    xs ⊆ ys  =  ∀ {w} → w ∈ xs → w ∈ ys

    _\\_ : List A → A → List A
    xs \\ x  =  filter (¬? ∘ (_≟ x)) xs

    refl-⊆ : ∀ {xs} → xs ⊆ xs
    refl-⊆ ∈xs  =  ∈xs

    trans-⊆ : ∀ {xs ys zs} → xs ⊆ ys → ys ⊆ zs → xs ⊆ zs
    trans-⊆ xs⊆ ys⊆  =  ys⊆ ∘ xs⊆

    ∈-[_] : ∀ {w x} → w ∈ [ x ] → w ≡ x
    ∈-[_] here         =  refl
    ∈-[_] (there ())

    there⁻¹ : ∀ {w x xs} → w ∈ x ∷ xs → w ≢ x → w ∈ xs
    there⁻¹ here       w≢  =  ⊥-elim (w≢ refl)
    there⁻¹ (there w∈) w≢  =  w∈

    there⟨_⟩ : ∀ {w x y xs} → w ∈ xs × w ≢ x → w ∈ y ∷ xs × w ≢ x
    there⟨ ⟨ w∈ , w≢ ⟩ ⟩  =  ⟨ there w∈ , w≢ ⟩

    \\-to-∈-≢ : ∀ {w x xs} → w ∈ xs \\ x → w ∈ xs × w ≢ x
    \\-to-∈-≢ {_} {x} {[]}    ()
    \\-to-∈-≢ {_} {x} {y ∷ _} w∈            with y ≟ x
    \\-to-∈-≢ {_} {x} {y ∷ _} w∈               | yes refl  =  there⟨ \\-to-∈-≢ w∈ ⟩
    \\-to-∈-≢ {_} {x} {y ∷ _} here             | no  w≢    =  ⟨ here , w≢ ⟩
    \\-to-∈-≢ {_} {x} {y ∷ _} (there w∈)       | no  _     =  there⟨ \\-to-∈-≢ w∈ ⟩

    ∈-≢-to-\\ : ∀ {w x xs} → w ∈ xs → w ≢ x → w ∈ xs \\ x
    ∈-≢-to-\\ {_} {x} {y ∷ _} here       w≢ with y ≟ x
    ...                                        | yes refl  =  ⊥-elim (w≢ refl)
    ...                                        | no  _     =  here
    ∈-≢-to-\\ {_} {x} {y ∷ _} (there w∈) w≢ with y ≟ x
    ...                                        | yes refl  =  ∈-≢-to-\\ w∈ w≢
    ...                                        | no  _     =  there (∈-≢-to-\\ w∈ w≢)


    \\-to-∷ : ∀ {x xs ys} → xs \\ x ⊆ ys → xs ⊆ x ∷ ys
    \\-to-∷ {x} ⊆ys {w} ∈xs
         with w ≟ x
    ...     | yes refl  =  here
    ...     | no  ≢x    =  there (⊆ys (∈-≢-to-\\ ∈xs ≢x))

    ∷-to-\\ : ∀ {x xs ys} → xs ⊆ x ∷ ys → xs \\ x ⊆ ys
    ∷-to-\\ {x} xs⊆ {w} w∈
         with \\-to-∈-≢ w∈
    ...     | ⟨ ∈xs , ≢x ⟩ with w ≟ x
    ...                       | yes refl                  =  ⊥-elim (≢x refl)
    ...                       | no  w≢   with (xs⊆ ∈xs)
    ...                                     | here        =  ⊥-elim (≢x refl)
    ...                                     | there ∈ys   =  ∈ys

    ⊆-++₁ : ∀ {xs ys} → xs ⊆ xs ++ ys
    ⊆-++₁ here         =  here
    ⊆-++₁ (there ∈xs)  =  there (⊆-++₁ ∈xs)

    ⊆-++₂ : ∀ {xs ys} → ys ⊆ xs ++ ys
    ⊆-++₂ {[]}     ∈ys  =  ∈ys
    ⊆-++₂ {x ∷ xs} ∈ys  =  there (⊆-++₂ {xs} ∈ys)

    ++-to-⊎ : ∀ {xs ys w} → w ∈ xs ++ ys → w ∈ xs ⊎ w ∈ ys
    ++-to-⊎ {[]}     ∈ys                            =  inj₂ ∈ys
    ++-to-⊎ {x ∷ xs} here                           =  inj₁ here
    ++-to-⊎ {x ∷ xs} (there w∈) with ++-to-⊎ {xs} w∈
    ...                            | inj₁ ∈xs       =  inj₁ (there ∈xs)
    ...                            | inj₂ ∈ys       =  inj₂ ∈ys


\end{code}

Neither of the following are currently needed, but I put them here
in case they turn out to be useful later.

\begin{code}
    _?∈_ : ∀ (x : A) (xs : List A) → Dec (x ∈ xs)
    x ?∈ []  =  no (λ())
    x ?∈ (y ∷ ys) with x ≟ y
    ...              | yes refl               =  yes here
    ...              | no  x≢  with x ?∈ ys
    ...                           | yes x∈    =  yes (there x∈)
    ...                           | no  x∉    =  no  (λ{ here       → x≢ refl
                                                       ; (there x∈) → x∉ x∈
                                                       })

    distinct : List A → List A
    distinct []  =  []
    distinct (x ∷ xs) with x ?∈ distinct xs
    ... | yes x∈  =  distinct xs
    ... | no  x∉  =  x ∷ distinct xs
\end{code}


## Standard Library

Definitions similar to those in this chapter can be found in the standard library.
\begin{code}
-- EDIT
\end{code}
The standard library version of `IsMonoid` differs from the
one given here, in that it is also parameterised on an equivalence relation.


## Unicode

This chapter uses the following unicode.

    EDIT
    ∷  U+2237  PROPORTION  (\::)
    ⊗  U+2297  CIRCLED TIMES  (\otimes)
    ∈  U+2208  ELEMENT OF  (\in)
    ∉  U+2209  NOT AN ELEMENT OF  (\inn)