Zulip Chat Archive

Stream: new members

Topic: Strugling with coercion of dependent types and Vectors


Lars (Oct 28 2024 at 14:29):

Hi all,

I've been struggling quite a bit with the following. I have Mathlib.Vectors for which I want to define some rewrite rules. But if the Vectors have equivalent but different types, I am unable to do this. For example here I have a vector with types:

  • Vector ℤ (k + 1 - (i + 1))
  • Vector ℤ (k + 1 - 1 - i)

But proving the following, I first had to use a 'cast' with and furthermore I could not finish my proof.

This is the example. Any clue what I could do better here?

import Mathlib.Tactic
open Mathlib

lemma h : (k + 1 - 1 - i = k + 1 - (i + 1)) := by
  simp

lemma vector_drop_tail {a: Vector Int (k+1)}:
  Vector.drop (i+1) a  = h  (Vector.drop (i) a.tail) := by
  rw [Vector.drop, Vector.drop]
  match a with
  | a::as, a_l =>
    rw [Vector.tail]
    simp

    -- rfl -- This fails
    sorry

Daniel Weber (Oct 28 2024 at 14:44):

You can try to use docs#Mathlib.Vector.congr

Daniel Weber (Oct 28 2024 at 14:52):

import Mathlib.Tactic
open Mathlib

lemma h : (k + 1 - 1 - i = k + 1 - (i + 1)) := by
  simp

@[simp]
theorem Mathlib.Vector.toList_congr (v : Mathlib.Vector α n) (h : n = m) :
    (v.congr h).toList = v.toList := rfl

@[simp]
theorem Mathlib.Vector.tail_toList {α : Type*} {n : } (v : Vector α n) : v.tail.toList = v.toList.tail := by
  cases' v with a _
  cases a <;> rfl

lemma vector_drop_tail {a: Vector Int (k+1)}:
  Vector.drop (i+1) a  = (Vector.drop (i) a.tail).congr h := by
  apply Vector.toList_injective
  simp

Lars (Oct 28 2024 at 15:07):

Thanks this is great, congr helps a lot!

Lars (Oct 28 2024 at 15:37):

Another question, which was I guess actually the thing I ran into.
Can I prove equality of arbitrary functions, when they are equal modulo the congr of their arguments.

So for instance, I have the following:

def vector_sum : Vector Int k   Int
| [], _⟩ => 0
| x :: xs, xl => x + vector_sum xs, congrArg Nat.pred xl

lemma apply_congr (a: Vector Int (k+1)):
  vector_sum (Vector.drop (i+1) a) = vector_sum (Vector.drop (i) a.tail) := by
  rw [vector_drop_tail]
  sorry -- ???

Daniel Weber (Oct 28 2024 at 15:41):

You can first prove

@[simp]
lemma vector_sum_congr (v : Mathlib.Vector Int n) (h : n = m) :
    vector_sum (v.congr h) = vector_sum v := by
  subst h
  rfl

and then it's just simp. (You can also use congr 1 and then prove the HEq , but that's usually unpleasant to work with)

Lars (Oct 28 2024 at 16:02):

Ah that is so great, thanks a bunch. I was struggling over this for over a week..

Anyway, would it then note make sense to add things like the following to Mathlib? I could make a pull request if needed (or you, since it's really your ideas)

@[simp]
lemma Vector.cong_arg (f:  k, Mathlib.Vector α k  β) (v : Mathlib.Vector α n) (h : n = m) :
    f m (v.congr h) = f n v := by
  subst h
  rfl

Daniel Weber (Oct 28 2024 at 16:09):

I think this makes sense as a lemma, but I think it might be quite inefficient as @[simp] (the discrimination tree is @Eq _ _ _). Feel free to make a PR


Last updated: May 02 2025 at 03:31 UTC