lean4-htt/src/Init/Data/String/Lemmas/Modify.lean
Wojciech Różowski 7e3e7cf5d9
feat: add cbv annotations to iterators and strings (#12961)
This PR adds `cbv` annotations to some iterator and string operations.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 11:39:40 +00:00

78 lines
2.6 KiB
Text

/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Markus Himmel
-/
module
prelude
public import Init.Data.String.Modify
import all Init.Data.String.Modify
import Init.Data.String.Lemmas.Basic
/-!
# Lemmas for `Init.Data.String.Modify`
This file contains lemmas for the operations defined in `Init.Data.String.Modify`.
Note that `Init.Data.String.Modify` already proves a few lemmas which are needed immediately.
-/
public section
namespace String
/-- You might want to invoke `Pos.Splits.exists_eq_singleton_append` to be able to apply this. -/
theorem Pos.Splits.pastSet {s : String} {p : s.Pos} {t₁ t₂ : String}
{c d : Char} (h : p.Splits t₁ (singleton c ++ t₂)) :
(p.pastSet d h.ne_endPos_of_singleton).Splits (t₁ ++ singleton d) t₂ := by
generalize h.ne_endPos_of_singleton = hp
obtain ⟨rfl, rfl, rfl⟩ := by simpa using h.eq (p.splits_next_right hp)
apply splits_pastSet
/-- You might want to invoke `Pos.Splits.exists_eq_singleton_append` to be able to apply this. -/
theorem Pos.Splits.pastModify {s : String} {p : s.Pos} {t₁ t₂ : String}
{c : Char} (h : p.Splits t₁ (singleton c ++ t₂)) :
(p.pastModify f h.ne_endPos_of_singleton).Splits
(t₁ ++ singleton (f (p.get h.ne_endPos_of_singleton))) t₂ :=
h.pastSet
theorem toList_mapAux {f : Char → Char} {s : String} {p : s.Pos}
(h : p.Splits t₁ t₂) : (mapAux f s p).toList = t₁.toList ++ t₂.toList.map f := by
fun_induction mapAux generalizing t₁ t₂ with
| case1 s => simp_all
| case2 s p hp ih =>
obtain ⟨c, rfl⟩ := h.exists_eq_singleton_append hp
simp [ih h.pastModify]
@[simp]
theorem toList_map {f : Char → Char} {s : String} : (s.map f).toList = s.toList.map f := by
simp [map, toList_mapAux s.splits_startPos]
/-
Used internally by the `cbv` tactic.
-/
@[cbv_eval]
theorem map_eq_internal {f : Char → Char} {s : String} : s.map f = .ofList (s.toList.map f) := by
apply String.toList_injective
simp only [toList_map, toList_ofList]
@[simp]
theorem length_map {f : Char → Char} {s : String} : (s.map f).length = s.length := by
simp [← length_toList]
@[simp]
theorem map_eq_empty {f : Char → Char} {s : String} : s.map f = "" ↔ s = "" := by
simp [← toList_eq_nil_iff]
@[simp]
theorem map_map {f g : Char → Char} {s : String} : String.map g (String.map f s) = String.map (g ∘ f) s := by
apply String.ext
simp [List.map_map]
@[simp]
theorem map_id {s : String} : String.map id s = s := by
apply String.ext
simp [List.map_id]
end String