Skip to content

Commit 100c5c1

Browse files
feat: Finite Maps (#160)
Co-authored-by: Zongyuan Liu <zy.liu@cs.au.dk>
1 parent 8234092 commit 100c5c1

File tree

5 files changed

+727
-86
lines changed

5 files changed

+727
-86
lines changed

lake-manifest.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
{"version": "1.1.0",
22
"packagesDir": ".lake/packages",
33
"packages":
4-
[{"url": "https://github.com/leanprover-community/quote4",
4+
[{"url": "https://github.com/leanprover-community/batteries",
5+
"type": "git",
6+
"subDir": null,
7+
"scope": "leanprover-community",
8+
"rev": "b25b36a7caf8e237e7d1e6121543078a06777c8a",
9+
"name": "batteries",
10+
"manifestFile": "lake-manifest.json",
11+
"inputRev": "v4.27.0",
12+
"inherited": false,
13+
"configFile": "lakefile.toml"},
14+
{"url": "https://github.com/leanprover-community/quote4",
515
"type": "git",
616
"subDir": null,
717
"scope": "leanprover-community",

lakefile.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ name = "Qq"
77
scope = "leanprover-community"
88
version = "git#stable"
99

10+
[[require]]
11+
name = "batteries"
12+
scope = "leanprover-community"
13+
rev = "v4.27.0"
14+
1015
[[lean_lib]]
1116
name = "Iris"
1217

src/Iris/Std/FromMathlib.lean

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/-
2+
Copyright (c) 2026 Zongyuan Liu, Markus de Medeiros. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
-/
5+
6+
namespace FromMathlib
7+
8+
/-- NB. Copied from Mathlib -/
9+
theorem List.Nodup.of_map (f : α → β) {l : List α} : List.Nodup (List.map f l) → List.Nodup l := by
10+
refine (List.Pairwise.of_map f) fun _ _ => mt <| fun a => (congrArg f ∘ fun _ => a) α
11+
12+
/-- NB. Copied from Mathlib -/
13+
theorem Pairwise.forall {l : List α} {R : α → α → Prop} (hR : ∀ {a b}, R a b ↔ a ≠ b)
14+
(hl : l.Pairwise (· ≠ ·)) : ∀ ⦃a⦄, a ∈ l → ∀ ⦃b⦄, b ∈ l → a ≠ b → R a b := by
15+
induction l with
16+
| nil => simp
17+
| cons a l ih =>
18+
simp only [List.mem_cons]
19+
rintro x (rfl | hx) y (rfl | hy)
20+
· simp
21+
· exact fun a => hR.mpr a
22+
· exact fun a => hR.mpr a
23+
· refine ih (List.Pairwise.of_cons hl) hx hy
24+
25+
/-- NB. Copied from Mathlib -/
26+
theorem inj_on_of_nodup_map {f : α → β} {l : List α} (d : List.Nodup (List.map f l)) :
27+
∀ ⦃x⦄, x ∈ l → ∀ ⦃y⦄, y ∈ l → f x = f y → x = y := by
28+
induction l with
29+
| nil => simp
30+
| cons hd tl ih =>
31+
simp only [List.map, List.nodup_cons, List.mem_map, not_exists, not_and, ← Ne.eq_def] at d
32+
simp only [List.mem_cons]
33+
rintro _ (rfl | h₁) _ (rfl | h₂) h₃
34+
· rfl
35+
· apply (d.1 _ h₂ h₃.symm).elim
36+
· apply (d.1 _ h₁ h₃).elim
37+
· apply ih d.2 h₁ h₂ h₃
38+
39+
/-- NB. Copied from Mathlib -/
40+
theorem Nodup.map_on {f : α → β} (H : ∀ x ∈ l, ∀ y ∈ l, f x = f y → x = y) (d : List.Nodup l) :
41+
(List.map f l).Nodup :=
42+
List.Pairwise.map _ (fun a b ⟨ma, mb, n⟩ e => n (H a ma b mb e)) (List.Pairwise.and_mem.1 d)
43+
44+
/-- NB. Copied from Mathlib -/
45+
theorem Nodup.filterMap {f : α → Option β} (h : ∀ a a' b, b ∈ f a → b ∈ f a' → a = a') :
46+
List.Nodup l → List.Nodup (List.filterMap f l) :=
47+
(List.Pairwise.filterMap f) @fun a a' n b bm b' bm' e => n <| h a a' b' (by rw [← e]; exact bm) bm'
48+
49+
/-- NB. Copied from Mathlib -/
50+
theorem Nodup.filter (p : α → Bool) {l} : List.Nodup l → List.Nodup (List.filter p l) := by
51+
simpa using List.Pairwise.filter p
52+
53+
end FromMathlib

src/Iris/Std/HeapInstances.lean

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,13 @@ private theorem get?_foldl_alter_impl_sigma {l : List ((_ : K) × V)}
290290
((l.find? (fun x => (compare x.1 k).isEq)).map (fun kv => (kv.1, kv.2))) := by
291291
induction l generalizing init with
292292
| nil =>
293-
simp [foldl_nil]
293+
simp [List.foldl_nil]
294294
| cons hd tl IH =>
295-
rw [foldl_cons, IH (WF.constAlter! hinit) (hl.tail), Const.get?_alter! hinit]
295+
rw [List.foldl_cons, IH (WF.constAlter! hinit) (hl.tail), Const.get?_alter! hinit]
296296
by_cases h : compare hd.1 k = .eq <;> simp [h]
297297
rw [← Const.get?_congr hinit h]
298298
have hhead_none : tl.find? (fun x => (compare x.1 k).isEq) = none := by
299-
refine find?_eq_none.mpr fun _ hkv He => rel_of_pairwise_cons hl hkv ?_
299+
refine List.find?_eq_none.mpr fun _ hkv He => List.rel_of_pairwise_cons hl hkv ?_
300300
refine isEq_iff_eq_eq.mpr <| compare_eq_iff_eq.mpr ?_
301301
rw [eq_of_compare h, compare_eq_iff_eq.mp <| isEq_iff_eq_eq.mp He]
302302
rw [hhead_none, map_none, pairMerge_none_right]
@@ -309,11 +309,11 @@ private theorem getElem?_foldl_alter {l : List (K × V)} {init : TreeMap K V com
309309
| nil =>
310310
simp
311311
| cons hd tl ih =>
312-
rw [foldl_cons, ih (hl.tail)]
312+
rw [List.foldl_cons, ih (hl.tail)]
313313
by_cases heq : compare hd.1 k = .eq
314314
· have htl : tl.find? (fun kv => (compare kv.1 k).isEq) = none := by
315-
refine find?_eq_none.mpr fun kv hkv h => ?_
316-
refine rel_of_pairwise_cons hl hkv (eq_trans heq ?_)
315+
refine List.find?_eq_none.mpr fun kv hkv h => ?_
316+
refine List.rel_of_pairwise_cons hl hkv (eq_trans heq ?_)
317317
rw [compare_eq_iff_eq.mp <| isEq_iff_eq_eq.mp h]
318318
exact compare_self
319319
simp [getElem?_congr (eq_symm heq), htl, heq]
@@ -346,7 +346,7 @@ private theorem getElem?_mergeWith_eq_foldl {t₁ t₂ : TreeMap K V compare}
346346
fun l => by induction l with grind [isEq]
347347
rw [hfind_map]
348348
refine get?_foldl_alter_impl_sigma t₁.inner.wf ?_
349-
refine (pairwise_map.mp <|
349+
refine (List.pairwise_map.mp <|
350350
SameKeys.ordered_iff_pairwise_keys.mp t₂.inner.wf.ordered).imp ?_
351351
rintro hlt heq H
352352
simp [H]
@@ -373,11 +373,11 @@ theorem getElem?_mergeWith' {t₁ t₂ : TreeMap K V compare} {f : K → V → V
373373
getElem?_eq_some_iff_exists_compare_eq_eq_and_mem_toList.mp h
374374
have hpred : (compare k' k).isEq = true := by simp [eq_symm hcmp]
375375
obtain ⟨kv, hfind⟩ := isSome_iff_exists.mp <|
376-
find?_isSome (p := fun kv => (compare kv.1 k).isEq) |>.mpr ⟨(k', v), hmem, hpred⟩
376+
List.find?_isSome (p := fun kv => (compare kv.1 k).isEq) |>.mpr ⟨(k', v), hmem, hpred⟩
377377
have hkv_cmp : compare kv.1 k = .eq := by
378378
simpa [beq_iff_eq] using List.find?_some hfind
379379
have hval : kv.2 = v := by grind
380-
have hfind : find? (fun kv => (compare kv.fst k).isEq) t₂.toList =
380+
have hfind : List.find? (fun kv => (compare kv.fst k).isEq) t₂.toList =
381381
some (kv.fst, v) := by
382382
simp [← hval, ← hfind]
383383
simp [← hval, hfind]
@@ -392,6 +392,32 @@ instance : LawfulPartialMap (TreeMap K · compare) K where
392392
get?_bindAlter := by simp [Iris.Std.get?, Iris.Std.bindAlter]
393393
get?_merge := getElem?_mergeWith'
394394

395+
instance : FiniteMap (TreeMap K · compare) K where
396+
toList t := t.toList
397+
398+
instance : LawfulFiniteMap (TreeMap K · compare) K where
399+
toList_empty := rfl
400+
toList_noDupKeys := by
401+
intro V m
402+
have h' : List.Pairwise (fun a b => ¬compare a b = eq) (m.toList.map (·.1)) := by
403+
refine List.pairwise_map.mpr ?_
404+
refine (distinct_keys_toList (t := m)).imp ?_
405+
intro _ _ hab
406+
exact hab
407+
refine h'.imp ?_
408+
intro a b hab
409+
rw [compare_eq_iff_eq] at hab
410+
exact hab
411+
toList_get := by
412+
intro V m k v
413+
constructor
414+
· intro h
415+
exact getElem?_eq_some_iff_exists_compare_eq_eq_and_mem_toList.mpr ⟨k, compare_self, h⟩
416+
· intro h
417+
obtain ⟨_, hcmp, hmem⟩ := getElem?_eq_some_iff_exists_compare_eq_eq_and_mem_toList.mp h
418+
rw [compare_eq_iff_eq.mp hcmp]
419+
exact hmem
420+
395421
end HeapInstance
396422

397423
end Std.TreeMap

0 commit comments

Comments
 (0)