Zulip Chat Archive

Stream: new members

Topic: Help with proofs


Simon Daniel (Feb 21 2024 at 09:51):

I have a structure Type that represents an existing key of an AssocList. Lean is smart enough to automatically "convert" the type to other lists where the key is present aswell. It can figure out, that if replace any key-value pair, the resulting list will still contain the key. However when choosing the replaced key to be arbitrary lean fails to do so which confuses me

structure contained_elem (l: Lean.AssocList Nat Unit) where
  n: Nat
  p: (l.find? n).isSome := by decide

def test_list: Lean.AssocList Nat Unit := [(3, ())].toAssocList'
def ce: contained_elem test_list := contained_elem.mk 3

variable (x:Nat)

def ce2: contained_elem (test_list.replace 3 ()) := ce -- conversion works magically
def ce3: contained_elem (test_list.replace x ()) := ce -- conversion does not work

def test_fun {ls: Lean.AssocList Nat Unit}: contained_elem ls -> Unit
| ce =>
  let other_l: contained_elem (ls.replace 4 ()) := ce -- also does not work
  ()

Bolton Bailey (Feb 21 2024 at 11:52):

This seems like a sensible error to me. In the definition of ce2 you replace the element with the same element so the Assoclist is the same, so it is fine that ce is used as a contained_elem of that list, that type checks. But if x is different from 3, the list may not be the same so it is not permissible to use ce as an contained_elem of that list, because the type of ce is only known to be contained_elem test_list, not contained_elem (test_list.replace x ())

Bolton Bailey (Feb 21 2024 at 11:55):

I guess your point is test_list.replace x () will always be equal to test_list no matter what x is. But that is a fact that needs proof.

Simon Daniel (Feb 21 2024 at 11:59):

Bolton Bailey said:

I guess your point is test_list.replace x () will always be equal to test_list no matter what x is. But that is a fact that needs proof.

thats it, i tried to prove it with simp? and exact?, but those cannot close the goal (which i thought they should be able to)

also my example works for any chosen Nat, not only 3

def ce2: contained_elem (test_list.replace 666 ()) := ce -- doesnt touch key 3 and works

Bolton Bailey (Feb 21 2024 at 12:01):

also my example works for any chosen Nat not only 3

Yes, I see that now. But my confusion was the same as Lean's in this instance. I was not aware of the exact definition of replace so I didn't know if the types would be equal. It seems like a case of the difference between propositional and definitional equality.

Seems like filling in the sorry below is what you want to do

def ce3: contained_elem (test_list.replace x ()) :=
  cast
  (by
    congr
    by_cases h : x = 3
    · rw [h]
      rfl
    ·
      sorry
  ) ce -- conversion does not work

Last updated: May 02 2025 at 03:31 UTC