The standard library's AVL tree implementation uses dependent pairs to store key-value pairs. I have two such pairs whose keys (k
and k′
) I have shown to be equal (k≡k′
). They also contain the same value (v
). I'd like to prove that the pairs are equal. Here's the goal:
open import Agda.Primitive
open import Data.Nat
open import Data.Nat.Properties
open import Data.Product
open import Relation.Binary.PropositionalEquality
open import Data.AVL.Indexed <-strictTotalOrder
module Repro (ℓ : Level) (V : Value ℓ) where
Val = Value.family V
V≈ = Value.respects V
proof : (k k′ : ℕ) → (v : Val k) → (k≡k′ : k ≡ k′) → (k , v) ≡ (k′ , V≈ k≡k′ v)
proof k k′ v k≡k′ = {!!}
I tried rewriting with k≡k′
, which turns k
on the LHS into k′
and k≡k′
on the RHS into refl
. That's where I get stuck. I feel like I'm missing something obvious, as this seems a pretty basic thing to do.
(As an exercise, I'm trying to prove the standard library's AVL tree insertion correct. Hence my recent obsession with its AVL tree code.)
Update
Hmm. Maybe this isn't as trivial as I thought, at least without knowing more about V
. After all, what I currently know is that:
There's a way to turn a value of type
Val k
into a value of typeVal k′
- by way ofV≈
.That
V≈ refl
takes aVal foo
and returns aVal foo
.
What I don't know at this point is that V≈ refl
is the identity function, which seems to be what I'd need to do my proof.
Update II
If, for example, I knew that V≈
was actually subst Val
, then my proof would be:
proof′ : (k k′ : ℕ) → (v : Val k) → (k≡k′ : k ≡ k′) → (k , v) ≡ (k′ , subst Val k≡k′ v)
proof′ k k′ v k≡k′ rewrite k≡k′ = cong (k′ ,_) refl
So, I guess my question ultimately is:
Can I complete my original proof with what I have?
If not, then what property do I need
V≈
to have to complete my original proof (i.e., to "restrict it to functions that are likesubst
")?
Update III
I am providing more context in response to MrO's comment. Instead of stripping down my actual proof, I'll provide something even simpler. Let's prove a special case of AVL tree insertion, which leads to the same problem that I'm facing in the general case.
Let's prove that inserting a value v
for key k
into an empty tree and then looking up the value for key k
yields the value v
that we inserted.
Let's get set up:
open import Agda.Primitive using (Level)
open import Data.Maybe using (just)
open import Data.Nat using (ℕ)
open import Data.Nat.Properties using (<-strictTotalOrder ; <-cmp)
open import Data.Product using (proj₂)
open import Function using () renaming (const to constᶠ)
open import Relation.Binary using (tri< ; tri≈ ; tri>)
open import Relation.Binary.PropositionalEquality using (_≡_ ; refl )
open import Relation.Nullary.Negation using (contradiction)
open import Data.AVL.Indexed <-strictTotalOrder
module Simple {ℓ : Level} (V : Value ℓ) where
private
Val = Value.family V
V≈ = Value.respects V
Now, a function to create an empty tree:
make-empty : ∀ {l u} → l <⁺ u → Tree V l u 0
make-empty = leaf
And the proof:
proof : ∀ {l u} (k : ℕ) (v : Val k) (l<u : l <⁺ u) (l<k<u : l < k < u) →
lookup k (proj₂ (insertWith k (constᶠ v) (make-empty l<u) l<k<u)) l<k<u ≡ just v
proof k v l<u l<k<u with <-cmp k k
... | tri< _ p _ = contradiction refl p
... | tri> _ p _ = contradiction refl p
... | tri≈ _ p _ rewrite p = {!!}
The goal that I'm trying to fill in is just (V≈ refl v) ≡ just v
.
proof′ _ _ _ refl = refl
and also instead of usingsubst Val k≡k′ v
couldn't you simply usev
? I'm confused as to what really needs to be proved in your question. – MrOV≈ : x ≡ y → Val x → Val y
is asubst
-like function for turning a value of typeVal x
into a value of typeVal y
. It is a parameter to the AVL tree module, so I don't know its definition, only its type. I'd like to generalize the proof in my second update fromsubst
toV≈
. As I understand it, the proof in my second update uses the fact thatsubst P refl
is the identity function, so thatsubst Val k≡k′ v ≡ v
. I can't seem to use this fact forV≈
, as I don't know thatV≈ refl
is the identity function. – 123omnomnomv′ : Val k′
at keyk′ : ℕ
, do a lookup in the tree with a keyk : ℕ
wherek ≡ k′
. The lookup finds the valuev′ : Val k′
in the tree. The AVL code now usesV≈
to turnv′
from aVal k′
into aVal k
to return. We did the lookup withk
and notk′
, so we get back aVal k
- even thoughk ≡ k′
. In my proof about AVL tree insertion I am stuck atV≈ refl v′ ≡ v′
. It seems to me that I cannot proceed without knowing more aboutV≈
. And so I wonder whether I am missing anything. – 123omnomnomVal k
, so that equality of types would imply equality of values. If I understand things correctly, then we wouldn't need to know anything aboutV≈ refl
other than the fact that it takes aVal k
and produces aVal k
. – 123omnomnom