diff --git a/src/Init/Core.lean b/src/Init/Core.lean index 5a1f9df895..775e9776b5 100644 --- a/src/Init/Core.lean +++ b/src/Init/Core.lean @@ -1382,6 +1382,11 @@ gen_injective_theorems% EStateM.Result gen_injective_theorems% Lean.Name gen_injective_theorems% Lean.Syntax +/-- Replacement for `Array.mk.injEq`; we avoid mentioning the constructor and prefer `List.toArray`. -/ +abbrev List.toArray_inj := @Array.mk.injEq + +attribute [deprecated List.toArray_inj (since := "2024-09-09")] Array.mk.injEq + theorem Nat.succ.inj {m n : Nat} : m.succ = n.succ → m = n := fun x => Nat.noConfusion x id diff --git a/src/Init/Data/Array/BasicAux.lean b/src/Init/Data/Array/BasicAux.lean index c6221d620e..d96e8c3a13 100644 --- a/src/Init/Data/Array/BasicAux.lean +++ b/src/Init/Data/Array/BasicAux.lean @@ -9,7 +9,7 @@ import Init.Data.Nat.Linear import Init.NotationExtra theorem Array.of_push_eq_push {as bs : Array α} (h : as.push a = bs.push b) : as = bs ∧ a = b := by - simp only [push, mk.injEq] at h + simp only [push, List.toArray_inj] at h have ⟨h₁, h₂⟩ := List.of_concat_eq_concat h cases as; cases bs simp_all diff --git a/src/Init/Data/Array/Lemmas.lean b/src/Init/Data/Array/Lemmas.lean index 708b30a6d0..33a717e546 100644 --- a/src/Init/Data/Array/Lemmas.lean +++ b/src/Init/Data/Array/Lemmas.lean @@ -19,24 +19,14 @@ This file contains some theorems about `Array` and `List` needed for `Init.Data. namespace Array -attribute [simp] uset +/-- We avoid mentioning the constructor `Array.mk` directly, preferring `List.toArray`. -/ +@[simp] theorem mk_eq_toArray (as : List α) : Array.mk as = as.toArray := by + apply ext' + simp -@[simp] theorem singleton_def (v : α) : singleton v = #[v] := rfl +@[simp] theorem getElem_toList {a : Array α} {i : Nat} (h : i < a.size) : a.toList[i] = a[i] := rfl -@[simp] theorem toArray_toList : (a : Array α) → a.toList.toArray = a - | ⟨l⟩ => ext' (toList_toArray l) - -@[deprecated toArray_toList (since := "2024-09-09")] -abbrev toArray_data := @toArray_toList - -@[simp] theorem toList_length {l : Array α} : l.toList.length = l.size := rfl - -@[deprecated toList_length (since := "2024-09-09")] -abbrev data_length := @toList_length - -@[simp] theorem mkEmpty_eq (α n) : @mkEmpty α n = #[] := rfl - -@[simp] theorem size_mk (as : List α) : (Array.mk as).size = as.length := by simp [size] +@[simp] theorem getElem_mk {xs : List α} {i : Nat} (h : i < xs.length) : (Array.mk xs)[i] = xs[i] := rfl theorem getElem_eq_toList_getElem (a : Array α) (h : i < a.size) : a[i] = a.toList[i] := by by_cases i < a.size <;> (try simp [*]) <;> rfl @@ -46,27 +36,7 @@ abbrev getElem_eq_data_getElem := @getElem_eq_toList_getElem @[deprecated getElem_eq_toList_getElem (since := "2024-06-12")] theorem getElem_eq_toList_get (a : Array α) (h : i < a.size) : a[i] = a.toList.get ⟨i, h⟩ := by - simp [getElem_eq_toList_getElem] - -theorem foldrM_push [Monad m] (f : α → β → m β) (init : β) (arr : Array α) (a : α) : - (arr.push a).foldrM f init = f a init >>= arr.foldrM f := by - simp [foldrM_eq_reverse_foldlM_toList, -size_push] - -@[simp] theorem foldrM_push' [Monad m] (f : α → β → m β) (init : β) (arr : Array α) (a : α) : - (arr.push a).foldrM f init (start := arr.size + 1) = f a init >>= arr.foldrM f := by - simp [← foldrM_push] - -theorem foldr_push (f : α → β → β) (init : β) (arr : Array α) (a : α) : - (arr.push a).foldr f init = arr.foldr f (f a init) := foldrM_push .. - -@[simp] theorem foldr_push' (f : α → β → β) (init : β) (arr : Array α) (a : α) : - (arr.push a).foldr f init (start := arr.size + 1) = arr.foldr f (f a init) := foldrM_push' .. - -/-- A more efficient version of `arr.toList.reverse`. -/ -@[inline] def toListRev (arr : Array α) : List α := arr.foldl (fun l t => t :: l) [] - -@[simp] theorem toListRev_eq (arr : Array α) : arr.toListRev = arr.toList.reverse := by - rw [toListRev, foldl_eq_foldl_toList, ← List.foldr_reverse, List.foldr_cons_nil] + simp theorem get_push_lt (a : Array α) (x : α) (i : Nat) (h : i < a.size) : have : i < (a.push x).size := by simp [*, Nat.lt_succ_of_le, Nat.le_of_lt] @@ -84,6 +54,78 @@ theorem get_push (a : Array α) (x : α) (i : Nat) (h : i < (a.push x).size) : · simp at h simp [get_push_lt, Nat.le_antisymm (Nat.le_of_lt_succ h) (Nat.ge_of_not_lt h')] +end Array + +namespace List + +open Array + +/-! ### Lemmas about `List.toArray`. -/ + +@[simp] theorem toArray_size (as : List α) : as.toArray.size = as.length := by simp [size] + +@[simp] theorem toArrayAux_size {a : List α} {b : Array α} : + (a.toArrayAux b).size = b.size + a.length := by + simp [size] + +@[simp] theorem toArray_toList : (a : Array α) → a.toList.toArray = a + | ⟨l⟩ => ext' (toList_toArray l) + +@[simp] theorem getElem_toArray {a : List α} {i : Nat} (h : i < a.toArray.size) : + a.toArray[i] = a[i]'(by simpa using h) := by + have h₁ := mk_eq_toArray a + have h₂ := getElem_mk (by simpa using h) + simpa [h₁] using h₂ + +@[simp] theorem toArray_concat {as : List α} {x : α} : + (as ++ [x]).toArray = as.toArray.push x := by + apply ext' + simp + +end List + +namespace Array + +attribute [simp] uset + +@[simp] theorem singleton_def (v : α) : singleton v = #[v] := rfl + +@[deprecated List.toArray_toList (since := "2024-09-09")] +abbrev toArray_data := @List.toArray_toList +@[deprecated List.toArray_toList (since := "2024-09-09")] +abbrev toArray_toList := @List.toArray_toList + +@[simp] theorem toList_length {l : Array α} : l.toList.length = l.size := rfl + +@[deprecated toList_length (since := "2024-09-09")] +abbrev data_length := @toList_length + +@[simp] theorem mkEmpty_eq (α n) : @mkEmpty α n = #[] := rfl + +@[simp] theorem size_mk (as : List α) : (Array.mk as).size = as.length := by simp [size] + +theorem foldrM_push [Monad m] (f : α → β → m β) (init : β) (arr : Array α) (a : α) : + (arr.push a).foldrM f init = f a init >>= arr.foldrM f := by + simp [foldrM_eq_reverse_foldlM_toList, -size_push] + +/-- Variant of `foldrM_push` with the `start := arr.size + 1` rather than `(arr.push a).size`. -/ +@[simp] theorem foldrM_push' [Monad m] (f : α → β → m β) (init : β) (arr : Array α) (a : α) : + (arr.push a).foldrM f init (start := arr.size + 1) = f a init >>= arr.foldrM f := by + simp [← foldrM_push] + +theorem foldr_push (f : α → β → β) (init : β) (arr : Array α) (a : α) : + (arr.push a).foldr f init = arr.foldr f (f a init) := foldrM_push .. + +/-- Variant of `foldr_push` with the `start := arr.size + 1` rather than `(arr.push a).size`. -/ +@[simp] theorem foldr_push' (f : α → β → β) (init : β) (arr : Array α) (a : α) : + (arr.push a).foldr f init (start := arr.size + 1) = arr.foldr f (f a init) := foldrM_push' .. + +/-- A more efficient version of `arr.toList.reverse`. -/ +@[inline] def toListRev (arr : Array α) : List α := arr.foldl (fun l t => t :: l) [] + +@[simp] theorem toListRev_eq (arr : Array α) : arr.toListRev = arr.toList.reverse := by + rw [toListRev, foldl_eq_foldl_toList, ← List.foldr_reverse, List.foldr_cons_nil] + theorem mapM_eq_foldlM [Monad m] [LawfulMonad m] (f : α → m β) (arr : Array α) : arr.mapM f = arr.foldlM (fun bs a => bs.push <$> f a) #[] := by rw [mapM, aux, foldlM_eq_foldlM_toList]; rfl @@ -345,7 +387,7 @@ theorem getElem_mem_toList (a : Array α) (h : i < a.size) : a[i] ∈ a.toList : abbrev getElem_mem_data := @getElem_mem_toList theorem getElem?_eq_toList_get? (a : Array α) (i : Nat) : a[i]? = a.toList.get? i := by - by_cases i < a.size <;> simp_all [getElem?_pos, getElem?_neg, List.get?_eq_get, eq_comm]; rfl + by_cases i < a.size <;> simp_all [getElem?_pos, getElem?_neg, List.get?_eq_get, eq_comm] @[deprecated getElem?_eq_toList_get? (since := "2024-09-09")] abbrev getElem?_eq_data_get? := @getElem?_eq_toList_get? @@ -605,12 +647,12 @@ theorem foldr_induction simp only [mem_def, map_toList, List.mem_map] theorem mapM_eq_mapM_toList [Monad m] [LawfulMonad m] (f : α → m β) (arr : Array α) : - arr.mapM f = return mk (← arr.toList.mapM f) := by + arr.mapM f = return (← arr.toList.mapM f).toArray := by rw [mapM_eq_foldlM, foldlM_eq_foldlM_toList, ← List.foldrM_reverse] conv => rhs; rw [← List.reverse_reverse arr.toList] induction arr.toList.reverse with - | nil => simp; rfl - | cons a l ih => simp [ih]; simp [map_eq_pure_bind, push] + | nil => simp + | cons a l ih => simp [ih]; simp [map_eq_pure_bind] @[deprecated mapM_eq_mapM_toList (since := "2024-09-09")] abbrev mapM_eq_mapM_data := @mapM_eq_mapM_toList diff --git a/src/Init/Data/Array/TakeDrop.lean b/src/Init/Data/Array/TakeDrop.lean index 56b73a66aa..60511d5f44 100644 --- a/src/Init/Data/Array/TakeDrop.lean +++ b/src/Init/Data/Array/TakeDrop.lean @@ -12,6 +12,7 @@ namespace Array theorem exists_of_uset (self : Array α) (i d h) : ∃ l₁ l₂, self.toList = l₁ ++ self[i] :: l₂ ∧ List.length l₁ = i.toNat ∧ (self.uset i d h).toList = l₁ ++ d :: l₂ := by - simpa [Array.getElem_eq_toList_getElem] using List.exists_of_set _ + simpa only [ugetElem_eq_getElem, getElem_eq_toList_getElem, uset, toList_set] using + List.exists_of_set _ end Array diff --git a/src/Init/Data/Repr.lean b/src/Init/Data/Repr.lean index c1f7e522df..7c44ea5d6a 100644 --- a/src/Init/Data/Repr.lean +++ b/src/Init/Data/Repr.lean @@ -163,7 +163,7 @@ protected def _root_.USize.repr (n : @& USize) : String := /-- We statically allocate and memoize reprs for small natural numbers. -/ private def reprArray : Array String := Id.run do - List.range 128 |>.map (·.toUSize.repr) |> Array.mk + List.range 128 |>.map (·.toUSize.repr) |> List.toArray private def reprFast (n : Nat) : String := if h : n < 128 then Nat.reprArray.get ⟨n, h⟩ else diff --git a/src/Init/Prelude.lean b/src/Init/Prelude.lean index 87524cab90..4b43635285 100644 --- a/src/Init/Prelude.lean +++ b/src/Init/Prelude.lean @@ -2709,7 +2709,10 @@ def Array.extract (as : Array α) (start stop : Nat) : Array α := let sz' := Nat.sub (min stop as.size) start loop sz' start (mkEmpty sz') -/-- Auxiliary definition for `List.toArray`. -/ +/-- +Auxiliary definition for `List.toArray`. +`List.toArrayAux as r = r ++ as.toArray` +-/ @[inline_if_reduce] def List.toArrayAux : List α → Array α → Array α | nil, r => r diff --git a/src/Lean/Compiler/LCNF/Simp/ConstantFold.lean b/src/Lean/Compiler/LCNF/Simp/ConstantFold.lean index b950aec8ba..9266a07017 100644 --- a/src/Lean/Compiler/LCNF/Simp/ConstantFold.lean +++ b/src/Lean/Compiler/LCNF/Simp/ConstantFold.lean @@ -180,7 +180,7 @@ let _x.26 := @Array.push _ _x.24 z def foldArrayLiteral : Folder := fun args => do let #[_, .fvar fvarId] := args | return none let some (list, typ, level) ← getPseudoListLiteral fvarId | return none - let arr := Array.mk list + let arr := list.toArray let lit ← mkPseudoArrayLiteral arr typ level return some lit diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/Convert.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/Convert.lean index d08241e95b..f72bda1ede 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/Convert.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/Convert.lean @@ -61,7 +61,7 @@ theorem CNF.Clause.mem_lrat_of_mem (clause : CNF.Clause (PosFin n)) (h1 : l ∈ | nil => cases h1 | cons hd tl ih => unfold DefaultClause.ofArray at h2 - rw [Array.foldr_eq_foldr_toList, Array.toArray_toList] at h2 + rw [Array.foldr_eq_foldr_toList, List.toArray_toList] at h2 dsimp only [List.foldr] at h2 split at h2 · cases h2 @@ -77,7 +77,7 @@ theorem CNF.Clause.mem_lrat_of_mem (clause : CNF.Clause (PosFin n)) (h1 : l ∈ · assumption · next heq _ _ => unfold DefaultClause.ofArray - rw [Array.foldr_eq_foldr_toList, Array.toArray_toList] + rw [Array.foldr_eq_foldr_toList, List.toArray_toList] exact heq · cases h1 · simp only [← Option.some.inj h2] @@ -89,7 +89,7 @@ theorem CNF.Clause.mem_lrat_of_mem (clause : CNF.Clause (PosFin n)) (h1 : l ∈ apply ih assumption unfold DefaultClause.ofArray - rw [Array.foldr_eq_foldr_toList, Array.toArray_toList] + rw [Array.foldr_eq_foldr_toList, List.toArray_toList] exact heq theorem CNF.Clause.convertLRAT_sat_of_sat (clause : CNF.Clause (PosFin n)) diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/Lemmas.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/Lemmas.lean index 0c57e14775..cc71e9ac70 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/Lemmas.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/Lemmas.lean @@ -500,8 +500,7 @@ theorem deleteOne_preserves_strongAssignmentsInvariant {n : Nat} (f : DefaultFor · next id_eq_idx => exfalso have idx_in_bounds2 : idx < f.clauses.size := by - have f_clauses_rw : f.clauses = { toList := f.clauses.toList } := rfl - conv => rhs; rw [f_clauses_rw, Array.size_mk] + conv => rhs; rw [Array.size_mk] exact hbound simp only [getElem!, id_eq_idx, Array.toList_length, idx_in_bounds2, ↓reduceDIte, Fin.eta, Array.get_eq_getElem, Array.getElem_eq_toList_getElem, decidableGetElem?] at heq @@ -534,8 +533,7 @@ theorem deleteOne_preserves_strongAssignmentsInvariant {n : Nat} (f : DefaultFor · next id_eq_idx => exfalso have idx_in_bounds2 : idx < f.clauses.size := by - have f_clauses_rw : f.clauses = { toList := f.clauses.toList } := rfl - conv => rhs; rw [f_clauses_rw, Array.size_mk] + conv => rhs; rw [Array.size_mk] exact hbound simp only [getElem!, id_eq_idx, Array.toList_length, idx_in_bounds2, ↓reduceDIte, Fin.eta, Array.get_eq_getElem, Array.getElem_eq_toList_getElem, decidableGetElem?] at heq @@ -595,8 +593,7 @@ theorem deleteOne_preserves_strongAssignmentsInvariant {n : Nat} (f : DefaultFor · next id_eq_idx => exfalso have idx_in_bounds2 : idx < f.clauses.size := by - have f_clauses_rw : f.clauses = { toList := f.clauses.toList } := rfl - conv => rhs; rw [f_clauses_rw, Array.size_mk] + conv => rhs; rw [Array.size_mk] exact hbound simp only [getElem!, id_eq_idx, Array.toList_length, idx_in_bounds2, ↓reduceDIte, Fin.eta, Array.get_eq_getElem, Array.getElem_eq_toList_getElem, decidableGetElem?] at heq diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean index c5c2bb088f..cd1de9e578 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean @@ -1112,7 +1112,7 @@ theorem nodup_derivedLits {n : Nat} (f : DefaultFormula n) (derivedLits : CNF.Clause (PosFin n)) (derivedLits_satisfies_invariant: DerivedLitsInvariant f f_assignments_size (performRupCheck f rupHints).fst.assignments f'_assignments_size derivedLits) - (derivedLits_arr : Array (Literal (PosFin n))) (derivedLits_arr_def: derivedLits_arr = { toList := derivedLits }) + (derivedLits_arr : Array (Literal (PosFin n))) (derivedLits_arr_def : derivedLits_arr = { toList := derivedLits }) (i j : Fin (Array.size derivedLits_arr)) (i_ne_j : i ≠ j) : derivedLits_arr[i] ≠ derivedLits_arr[j] := by intro li_eq_lj diff --git a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean index 17c703bd7b..f82f9429b1 100644 --- a/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean +++ b/src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean @@ -543,8 +543,8 @@ theorem reduce_fold_fn_preserves_induction_motive {c_arr : Array (Literal (PosFi theorem reduce_postcondition {n : Nat} (c : DefaultClause n) (assignment : Array Assignment) : (reduce c assignment = reducedToEmpty → Incompatible (PosFin n) c assignment) ∧ (∀ l : Literal (PosFin n), reduce c assignment = reducedToUnit l → ∀ (p : (PosFin n) → Bool), p ⊨ assignment → p ⊨ c → p ⊨ l) := by - let c_arr := Array.mk c.clause - have c_clause_rw : c.clause = c_arr.toList := rfl + let c_arr := c.clause.toArray + have c_clause_rw : c.clause = c_arr.toList := by simp [c_arr] rw [reduce, c_clause_rw, ← Array.foldl_eq_foldl_toList] let motive := ReducePostconditionInductionMotive c_arr assignment have h_base : motive 0 reducedToEmpty := by diff --git a/tests/lean/run/2670.lean b/tests/lean/run/2670.lean index 64443b27b5..7120e52b5e 100644 --- a/tests/lean/run/2670.lean +++ b/tests/lean/run/2670.lean @@ -12,12 +12,12 @@ def enumFromTR' (n : Nat) (l : List α) : List (Nat × α) := open List in theorem enumFrom_eq_enumFromTR' : @enumFrom = @enumFromTR' := by - funext α n l; simp [enumFromTR', -Array.size_toArray] + funext α n l; simp only [enumFromTR'] let f := fun (a : α) (n, acc) => (n-1, (n-1, a) :: acc) let rec go : ∀ l n, l.foldr f (n + l.length, []) = (n, enumFrom n l) | [], n => rfl | a::as, n => by rw [← show _ + as.length = n + (a::as).length from Nat.succ_add .., List.foldr, go as] simp [enumFrom, f] - rw [Array.foldr_eq_foldr_data] + rw [Array.foldr_eq_foldr_toList] simp [go] -- Should close the goal