Zulip Chat Archive
Stream: new members
Topic: Proving two filterMaps are equal
Dhruv Chaurasiya (Feb 02 2026 at 13:59):
import Std
import Lean
open Std
open Lean
abbrev SortName := String
structure TypedValue where
sort : SortName
val : String
deriving Repr, BEq, Hashable, Inhabited, DecidableEq
def tv (s : SortName) (v : String) : TypedValue := { sort := s, val := v }
inductive Param where
| bot
| top
| val (tv : TypedValue)
deriving Repr, BEq, Hashable,Inhabited, DecidableEq
def get_top_indices (ps : List Param) : List Nat :=
(List.range ps.length |>.zip ps).filterMap fun
| (i, Param.top) => some i
| _ => none
theorem tops_equal
(i : Nat)
(params1 params2 : List Param)
(h_len : params1.length = params2.length)
(h_at_i_bot : params1[i]? = some Param.bot)
(h_at_i_val : ∃ tv : TypedValue, params2[i]? = some (Param.val tv))
(h_others_match : ∀ (j : Nat), ¬j = i → params1[j]? = params2[j]?) :
get_top_indices params1 = get_top_indices params2 := by
simp [get_top_indices]
How can i go on proving two List.filterMap are equal, from the given hypothesis, that the length of both the List are same, and other hypothesis regarding their values at each index, I can see this must be true, but I cannot find any way too simplify this.
Is there any dedicated channel for such issues?
Johannes Tantow (Feb 02 2026 at 14:15):
Ruben Van de Velde (Feb 02 2026 at 17:25):
Here is fine, but yes, please follow the #mwe link and give us a code snippet we can easily work with
Dhruv Chaurasiya (Feb 03 2026 at 11:39):
Ruben Van de Velde said:
Here is fine, but yes, please follow the #mwe link and give us a code snippet we can easily work with
I have provided the information needed, please let me know if anything else is required
Ruben Van de Velde (Feb 03 2026 at 11:42):
Can you read it again? I don't see a single code snippet that I can run to see the exact issue you're asking for help with
Dhruv Chaurasiya (Feb 03 2026 at 12:00):
Ruben Van de Velde said:
Here is fine, but yes, please follow the #mwe link and give us a code snippet we can easily work with
Ruben Van de Velde said:
Can you read it again? I don't see a single code snippet that I can run to see the exact issue you're asking for help with
you can copy paste the first code snippet in your lean file to check that
Robin Arnez (Feb 03 2026 at 12:03):
Here's a proof:
abbrev SortName := String
structure TypedValue where
sort : SortName
val : String
deriving Repr, BEq, Hashable, Inhabited, DecidableEq
def tv (s : SortName) (v : String) : TypedValue := { sort := s, val := v }
inductive Param where
| bot
| top
| val (tv : TypedValue)
deriving Repr, BEq, Hashable, Inhabited, DecidableEq
def get_top_indices (ps : List Param) : List Nat :=
(List.range ps.length |>.zip ps).filterMap fun
| (i, Param.top) => some i
| _ => none
theorem filterMap_id_map (l : List α) (f : α → Option β) :
List.filterMap id (List.map f l) = List.filterMap f l := by simp
theorem tops_equal {tv : TypedValue}
(i : Nat)
(params1 params2 : List Param)
(h_len : params1.length = params2.length)
(h_at_i_bot : params1[i]? = some Param.bot)
(h_at_i_val : params2[i]? = some (Param.val tv))
(h_others_match : ∀ (j : Nat), ¬j = i → params1[j]? = params2[j]?) :
get_top_indices params1 = get_top_indices params2 := by
simp only [get_top_indices]
conv => lhs; rw [← filterMap_id_map]
conv => rhs; rw [← filterMap_id_map]
congr 1
ext1 k
specialize h_others_match k
grind
The argument is basically that you can rewrite a filterMap to flattening a map and the maps are equal at every position.
Dhruv Chaurasiya (Feb 03 2026 at 12:08):
Robin Arnez said:
Here's a proof:
abbrev SortName := String structure TypedValue where sort : SortName val : String deriving Repr, BEq, Hashable, Inhabited, DecidableEq def tv (s : SortName) (v : String) : TypedValue := { sort := s, val := v } inductive Param where | bot | top | val (tv : TypedValue) deriving Repr, BEq, Hashable, Inhabited, DecidableEq def get_top_indices (ps : List Param) : List Nat := (List.range ps.length |>.zip ps).filterMap fun | (i, Param.top) => some i | _ => none theorem filterMap_id_map (l : List α) (f : α → Option β) : List.filterMap id (List.map f l) = List.filterMap f l := by simp theorem tops_equal {tv : TypedValue} (i : Nat) (params1 params2 : List Param) (h_len : params1.length = params2.length) (h_at_i_bot : params1[i]? = some Param.bot) (h_at_i_val : params2[i]? = some (Param.val tv)) (h_others_match : ∀ (j : Nat), ¬j = i → params1[j]? = params2[j]?) : get_top_indices params1 = get_top_indices params2 := by simp only [get_top_indices] conv => lhs; rw [← filterMap_id_map] conv => rhs; rw [← filterMap_id_map] congr 1 ext1 k specialize h_others_match k grindThe argument is basically that you can rewrite a
filterMapto flattening a map and themaps are equal at every position.
thanks a lot for the proof.
Johannes Tantow (Feb 03 2026 at 12:08):
You can also express your zip construction with List.zipIdx
Dhruv Chaurasiya (Feb 03 2026 at 12:09):
Johannes Tantow said:
You can also express your zip construction with
List.zipIdx
I did not know that. Thanks, I would try it out.
Last updated: Feb 28 2026 at 14:05 UTC