Skip to content

Conversation

@alok
Copy link

@alok alok commented Dec 16, 2025

Summary

  • Add Store and Heap instances for TreeMap K V cmp and ExtTreeMap K V cmp
  • Add Store, Heap, RepFunStore, and IsoFunStore instances for function types
  • Prove getElem?_mergeWith' lemma for both map types with full WF tracking through internal foldl operations

Implementation

The key challenge was proving getElem?_mergeWith' which requires tracking well-formedness through Std.DTreeMap.Internal.Impl operations. This was solved by:

  1. Building custom helper lemmas (get?_foldl_alter_impl_sigma, foldl_alter_getElem?) that track WF through foldl with alter operations
  2. Using ordered_iff_pairwise_keys to derive pairwise distinctness from the tree's Ordered property
  3. For ExtTreeMap, using quotient induction to reduce to DTreeMap representatives and reuse the TreeMap proof

Test plan

  • lake build passes with no sorries
  • All existing tests pass

Closes #105

@alok alok force-pushed the feat/heap-instances-105 branch from ddf9987 to 0a27a2f Compare December 16, 2025 08:10
@alok alok marked this pull request as draft December 16, 2025 08:11
@alok alok force-pushed the feat/heap-instances-105 branch 4 times, most recently from 6bb7a12 to e9f9512 Compare December 16, 2025 08:38
@alok alok marked this pull request as ready for review December 18, 2025 00:07
@markusdemedeiros
Copy link
Collaborator

Nice, thanks for doing this!

@alok
Copy link
Author

alok commented Dec 19, 2025

thanks @claude

Copy link
Collaborator

@markusdemedeiros markusdemedeiros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good start! This might be okay to use in unstable, but the proofs are very redundant and need to be refactored before merging into main. Please review some of the other files in the development to get a better idea of our style.

I have left some high-level comments and will review again after the code is cleaned up.

| some v => simp [alterFn]
· rw [Impl.Const.get?_alter! hinit]
simp only [heq, ↓reduceIte]
have hfind : List.find? (fun kv => compare kv.1 k == .eq) (hd :: tl) =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant have

cases Impl.Const.get? init k <;> rfl
| cons hd tl ih =>
simp only [List.foldl_cons]
let alterFn : Option V → Option V := fun
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be simplified using more Option primitives

(l.foldl (fun acc kv => acc.alter kv.1 fun
| none => some kv.2
| some v1 => some (f kv.1 v1 kv.2)) init)[k]? =
match init[k]?, l.find? (fun kv => cmp kv.1 k == .eq) with
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just Option.merge f

cases init[hd.1]? <;> rfl
· -- hd.1 doesn't match k
simp only [getElem?_alter, heq, ↓reduceIte]
have hfind : List.find? (fun kv => cmp kv.1 k == .eq) (hd :: tl) =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant have

rw [hfind]

/-- TreeMap.mergeWith equals list foldl with alter at the getElem? level. -/
theorem getElem?_mergeWith_eq_foldl [LawfulEqCmp cmp] {t₁ t₂ : TreeMap K V cmp}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This proof is long. Can you break it up and simplify please?

have hfind : List.find? (fun kv => compare kv.1 k == .eq) (hd :: tl) =
tl.find? (fun kv => compare kv.1 k == .eq) := by
simp only [List.find?_cons]
have hne : (compare hd.1 k == .eq) = false := by simp [beq_eq_false_iff_ne, heq]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have+simp can be inlined

by_cases heq : cmp hd.1 k = .eq
· -- hd.1 matches k
simp only [getElem?_alter, getElem?_congr (OrientedCmp.eq_symm heq)]
have hfind : List.find? (fun kv => cmp kv.1 k == .eq) (hd :: tl) = some hd := by
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have+rw can be inlined

have hfind_eq := h_find t₂.inner.inner.toListModel
rw [← h_toList] at hfind_eq

cases hres : t₂.inner.inner.toListModel.find? (fun kv => cmp kv.1 k == .eq) with
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nearly identical match arms, can you factor out the have+simp somehow?

@[simp] theorem getElem?_mergeWith' [LawfulEqCmp cmp] {t₁ t₂ : TreeMap K V cmp}
{f : K → V → V → V} {k : K} :
(t₁.mergeWith f t₂)[k]? =
match t₁[k]?, t₂[k]? with
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is Option.merge

-- Use the helper lemma that connects mergeWith to foldl
have mergeWith_eq := getElem?_mergeWith_eq_foldl (t₁ := t₁) (t₂ := t₂) (f := f) (k := k)

-- Case split based on t₁[k]? and t₂[k]?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identical match arms

@alok alok force-pushed the feat/heap-instances-105 branch 2 times, most recently from f32b896 to c4b3448 Compare December 27, 2025 00:35
Implements Heap typeclass instances for Batteries' TreeMap and ExtTreeMap,
enabling their use in Iris separation logic proofs.

Key additions:
- Store instances for TreeMap/ExtTreeMap (insert, alter, erase operations)
- Heap instances with disjoint union via mergeWith
- Helper lemmas connecting TreeMap operations to list-based specifications
- Uses grind tactic for cleaner proofs where applicable
@alok alok force-pushed the feat/heap-instances-105 branch from c4b3448 to 8f928e4 Compare December 27, 2025 00:59
@markusdemedeiros
Copy link
Collaborator

Just FYI I think there is a git error here, you seemed to push a bunch of unrelated commits like 2949701.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Heap Instance for Lean map types

2 participants