lean4-htt/src/Init/Data/List/FinRange.lean
François G. Dorais 7f77bfef4c
feat: add List.mem_finRange (#9515)
This PR adds a missing lemma for the `List` API.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Add `[simp]` lemma `List.mem_finRange` proving any `x : Fin n` is in
`finRange n`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
631f7ca852b1b2de5c7b1e3c7602c268ff47360e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Markus Himmel <markus@lean-fro.org>
Co-authored-by: Kim Morrison <477956+kim-em@users.noreply.github.com>
2025-11-11 04:16:08 +00:00

114 lines
3.5 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2024 François G. Dorais. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: François G. Dorais
-/
module
prelude
import all Init.Data.List.OfFn
public import Init.Data.List.Monadic
public section
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
namespace List
/--
Lists all elements of `Fin n` in order, starting at `0`.
Examples:
* `List.finRange 0 = ([] : List (Fin 0))`
* `List.finRange 2 = ([0, 1] : List (Fin 2))`
-/
@[expose] def finRange (n : Nat) : List (Fin n) := ofFn fun i => i
@[simp, grind =] theorem length_finRange {n : Nat} : (List.finRange n).length = n := by
simp [List.finRange]
@[simp, grind =] theorem getElem_finRange {i : Nat} (h : i < (List.finRange n).length) :
(finRange n)[i] = Fin.cast length_finRange ⟨i, h⟩ := by
simp [List.finRange]
@[simp, grind =] theorem finRange_zero : finRange 0 = [] := by simp [finRange]
theorem finRange_succ {n} : finRange (n+1) = 0 :: (finRange n).map Fin.succ := by
apply List.ext_getElem; simp; intro i; cases i <;> simp
theorem finRange_succ_last {n} :
finRange (n+1) = (finRange n).map Fin.castSucc ++ [Fin.last n] := by
apply List.ext_getElem
· simp
· intros
simp only [List.finRange, List.getElem_ofFn, getElem_append, length_map, length_ofFn,
getElem_map, Fin.castSucc_mk, getElem_singleton]
split
· rfl
next h => exact Fin.eq_last_of_not_lt h
@[grind _=_]
theorem finRange_reverse {n} : (finRange n).reverse = (finRange n).map Fin.rev := by
induction n with
| zero => simp
| succ n ih =>
conv => lhs; rw [finRange_succ_last]
conv => rhs; rw [finRange_succ]
rw [reverse_append, reverse_cons, reverse_nil, nil_append, singleton_append, ← map_reverse,
map_cons, ih, map_map, map_map]
congr 2; funext
simp [Fin.rev_succ]
@[simp, grind ←]
theorem mem_finRange {n} (x : Fin n) : x ∈ finRange n := by
simp [finRange]
end List
namespace Fin
@[grind =] theorem foldlM_eq_foldlM_finRange [Monad m] (f : α → Fin n → m α) (x : α) :
foldlM n f x = (List.finRange n).foldlM f x := by
induction n generalizing x with
| zero => simp
| succ n ih =>
simp [foldlM_succ, List.finRange_succ, List.foldlM_cons]
congr 1
funext y
simp [ih, List.foldlM_map]
@[grind =] theorem foldrM_eq_foldrM_finRange [Monad m] [LawfulMonad m] (f : Fin n → α → m α) (x : α) :
foldrM n f x = (List.finRange n).foldrM f x := by
induction n generalizing x with
| zero => simp
| succ n ih =>
simp [foldrM_succ, List.finRange_succ, ih, List.foldrM_map]
@[grind =] theorem foldl_eq_finRange_foldl (f : α → Fin n → α) (x : α) :
foldl n f x = (List.finRange n).foldl f x := by
induction n generalizing x with
| zero => simp
| succ n ih =>
simp [foldl_succ, List.finRange_succ, ih, List.foldl_map]
@[grind =] theorem foldr_eq_finRange_foldr (f : Fin n → αα) (x : α) :
foldr n f x = (List.finRange n).foldr f x := by
induction n generalizing x with
| zero => simp
| succ n ih =>
simp [foldr_succ, List.finRange_succ, ih, List.foldr_map]
end Fin
namespace List
theorem ofFnM_succ {n} [Monad m] [LawfulMonad m] {f : Fin (n + 1) → m α} :
ofFnM f = (do
let a ← f 0
let as ← ofFnM fun i => f i.succ
pure (a :: as)) := by
simp [ofFnM, Fin.foldlM_eq_foldlM_finRange, List.finRange_succ, List.foldlM_cons_eq_append,
List.foldlM_map]
end List