Source code on Github
open import Prelude.Init; open SetAsType; open ≡-Reasoning
open import Prelude.DecEq
open import Prelude.Decidable
open import Prelude.Maybes
open import Prelude.Membership
open import Prelude.ToList
open import Prelude.Apartness
open import Prelude.Lists.Dec
open import Prelude.InferenceRules

module Common.Maps {K V : Type} ⦃ _ : DecEq K ⦄ ⦃ _ : DecEq V ⦄ where

-- list properties
postulate
  nubBy-from∘to : ∀ {A B : Type} ⦃ _ : DecEq B ⦄ {f : A → B} {xs : List A} →
    Unique (map f xs) → nubBy f xs ≡ xs
  Unique-proj₁ : ∀ {A B : Type} {xys : List (A × B)} →
    Unique (map proj₁ xys) → Unique xys
  Disjoint-proj₁ : ∀ {A B : Type} {xys xys′ : List (A × B)} →
    map proj₁ xys ♯ map proj₁ xys′ → xys ♯ xys′

nub∘nubBy-from∘to : ∀ {A B : Type} ⦃ _ : DecEq A ⦄ ⦃ _ : DecEq B ⦄
  {f : A → B} {xs : List A} →
  Unique (map f xs) →
    nub (nubBy f xs) ≡ xs
nub∘nubBy-from∘to {f = f}{xs} uniq =
  begin
    nub (nubBy f xs)
  ≡⟨ nub-from∘to $ Unique-nubBy f xs ⟩
    nubBy f xs
  ≡⟨ nubBy-from∘to uniq ⟩
    xs
  ∎
--

open import Prelude.Maps public
  hiding (∈ᵈ⇒⁉)

-- [MONKEY PATCH] replace postulated `Prelude.Maps.∈ᵈ⇒⁉` + `_‼_`
∈ᵈ⇒⁉ : ∀ (s : Map⟨ K ↦ V ⟩) {k} → k ∈ᵈ s → Is-just (s ⁉ k)
∈ᵈ⇒⁉ s {k} k∈ rewrite dec-yes (k ∈ᵈ? s) k∈ .proj₂ = auto

_‼_ : {k : K} (m : Map⟨ K ↦ V ⟩) → k ∈ᵈ m → V
m ‼ k∈ = destruct-Is-just (∈ᵈ⇒⁉ m k∈) .proj₁

private variable
  m m′ : Map⟨ K ↦ V ⟩
  s s₁ s₂ s₃ s₁₂ s₂₃ : Map⟨ K ↦ V ⟩
  k : K
  v : V

private pattern 𝟘 = here refl

⁉-singleton : singleton (k , v) ⁉ k ≡ just v
⁉-singleton {k} rewrite ≟-refl k = refl

postulate ‼-singleton : singleton (k , v) ‼ 𝟘 ≡ v

-- map properties
postulate
  ⊎≡-comm : Symmetric (⟨_⊎_⟩≡ s)
  ⊎≈-assocʳ :
    ∙ ⟨ s₁ ⊎ s₂₃ ⟩≡ s
    ∙ ⟨ s₂ ⊎ s₃  ⟩≡ s₂₃
      ─────────────────────
      ⟨ (s₁ ∪ s₂) ⊎ s₃ ⟩≡ s
    × (s₁ ♯ s₂)
  ⊎≈-assocˡ : ∀ {s₁₂} →
    ∙ ⟨ s₁₂ ⊎ s₃ ⟩≡ s
    ∙ ⟨ s₁ ⊎ s₂  ⟩≡ s₁₂
      ───────────────────
      ⟨ s₁ ⊎ (s₂ ∪ s₃) ⟩≡ s
    × (s₂ ♯ s₃)
--

_─ᵏˢ_ : Map⟨ K ↦ V ⟩ → List K → Map⟨ K ↦ V ⟩
m ─ᵏˢ ks = filterK (_∉? ks) m

keys : Map⟨ K ↦ V ⟩ → List K
keys = map proj₁ ∘ toList

values⊑ : (m : Map⟨ K ↦ V ⟩) → ∃ $ All (_∈ᵈ m) → List V
values⊑ m (ks , ks⊆) = mapWith∈ ks ((m ‼_) ∘ L.All.lookup ks⊆)

values values′ : Map⟨ K ↦ V ⟩ → List V
values = map proj₂ ∘ toList
values′ m = values⊑ m (keys m , L.All.tabulate id)

toList-∪ : keys m ♯ keys m′ →  toList (m ∪ m′) ≡ toList m ++ toList m′
toList-∪ {m@(_ ⊣ ·uniq-m)}{m′@(_ ⊣ ·uniq-m′)} m♯m′ =
  begin
    toList (m ∪ m′)
  ≡⟨⟩
    nub (nubBy proj₁ (toList m ++ toList m′))
  ≡⟨ cong nub $ nubBy-from∘to uniq-proj₁-++ ⟩
    nub (toList m ++ toList m′)
  ≡⟨ nub-from∘to uniq-++ ⟩
    toList m ++ toList m′
  ∎
  where
    uniq-m  = recompute dec ·uniq-m
    uniq-m′ = recompute dec ·uniq-m′

    uniq-++ : Unique (toList m ++ toList m′)
    uniq-++ = L.Uniq.++⁺ (Unique-proj₁ uniq-m) (Unique-proj₁ uniq-m′)
                         (Disjoint-proj₁ m♯m′)

    uniq-proj₁-++ : Unique $ map proj₁ (toList m ++ toList m′)
    uniq-proj₁-++ rewrite L.map-++-commute proj₁ (toList m) (toList m′)
      = L.Uniq.++⁺ uniq-m uniq-m′ m♯m′