Zulip Chat Archive

Stream: general

Topic: Substitute local let binding


Nikolai Morin (Jan 01 2024 at 11:26):

In implementing a 2D Array indexing operation, I'm stuck at how to substitute a let binding like this:

def get
  (mat : Mat m n α)
  (i_m : Fin m)
  (i_n : Fin n)
: α :=
  let idx : Nat := i_m.val * n + i_n.val
  let isLt : idx < mat.arr.size :=
       [...]
        have : i_m.val * n + i_n.val  pred_m * n + pred_n := n_succ_pred_n  this
        have : idx  pred_m * n + pred_n := this -- here
        sorry
  mat.arr.get idx, isLt

It's not an equality, so I can't use Eq.subst or the rw tactic.

Yaël Dillies (Jan 01 2024 at 11:28):

rfl should work

Nikolai Morin (Jan 01 2024 at 11:34):

If I write

have aux : idx = i_m.val * n + i_n.val := by simp; rfl

then rfl complains

type mismatch
  HEq.rfl
has type
  HEq ?m.3990 ?m.3990 : Prop
but is expected to have type
  i_m * n + i_n = i_m * n + i_n : Prop

I guess the cross means it's a shadowed variable? I didn't redefine i_m or i_n though. Here's the full function in case that's relevant:

full function

Yaël Dillies (Jan 01 2024 at 11:35):

You should learn how to write functioning that someone can just paste to see what the problem is. Please see #mwe

Nikolai Morin (Jan 01 2024 at 11:38):

@Yaël Dillies Sorry, I've now added the missing Mat definition to my previous post and verified that it's self-contained.

Yaël Dillies (Jan 01 2024 at 11:42):

Oh I see, the problem is that the subsequent match creates new variables i_m and i_n instead of changing the type of the old ones but it doesn't create a new let binding for idx either. That's a bit dumb.

Yaël Dillies (Jan 01 2024 at 11:43):

This works, however,

structure Mat (m : Nat) (n : Nat) (α : Type) where
arr : Array α
size_ok : arr.size = m * n
deriving Repr

def get
(mat : Mat m n α)
(i_m : Fin m)
(i_n : Fin n)
: α :=
let idx : Nat := i_m.val * n + i_n.val
have aux : idx = i_m.val * n + i_n.val := rfl
let isLt : idx < mat.arr.size :=
match m with
| .zero => absurd i_m.isLt (Nat.not_lt_zero i_m.val)
| .succ pred_m =>
have hm₁ : i_m.val  pred_m := Nat.le_of_lt_succ i_m.isLt
have hm₂ : i_m.val * n  pred_m * n := Nat.mul_le_mul_right n hm₁
match n_succ_pred_n : n with
| .zero => absurd i_n.isLt (Nat.not_lt_zero i_n.val)
| .succ pred_n =>
have : i_n.val  pred_n := Nat.le_of_lt_succ i_n.isLt
have : i_m.val * Nat.succ pred_n + i_n.val  pred_m * Nat.succ pred_n + pred_n :=
Nat.add_le_add hm₂ this
have : i_m.val * n + i_n.val  pred_m * n + pred_n := n_succ_pred_n  this
-- have : idx ≤ pred_m * n + pred_n := rfl
sorry
mat.arr.get idx, isLt

Nikolai Morin (Jan 01 2024 at 12:03):

Thanks. Is there a way to preserve the old variables (like n) when matching?


Last updated: May 02 2025 at 03:31 UTC