diff --git a/CODEOWNERS b/CODEOWNERS index 9e97a85a616b..408e831f7da3 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -21,6 +21,11 @@ /src/Lean/Server/ @mhuisi /src/Lean/Widget/ @Vtec234 /src/runtime/io.cpp @joehendrix +/src/Init/Data/ @semorrison +/src/Init/Data/Array/Lemmas.lean @digama0 +/src/Init/Data/List/Lemmas.lean @digama0 +/src/Init/Data/List/BasicAux.lean @digama0 +/src/Init/Data/Array/Subarray.lean @david-christiansen /src/Lean/Elab/Tactic/RCases.lean @digama0 /src/Init/RCases.lean @digama0 /src/Lean/Elab/Tactic/Ext.lean @digama0 @@ -39,5 +44,4 @@ /src/Lean/Elab/Tactic/Guard.lean @digama0 /src/Init/Guard.lean @digama0 /src/Lean/Server/CodeActions/ @digama0 -/src/Init/Data/Array/Subarray.lean @david-christiansen diff --git a/src/Init/Data/Array/Lemmas.lean b/src/Init/Data/Array/Lemmas.lean index aad2112a62e5..2fd2eef5cd2f 100644 --- a/src/Init/Data/Array/Lemmas.lean +++ b/src/Init/Data/Array/Lemmas.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro -/ prelude import Init.Data.Nat.MinMax +import Init.Data.Nat.Lemmas import Init.Data.List.Lemmas import Init.Data.Fin.Basic import Init.Data.Array.Mem @@ -187,7 +188,8 @@ theorem anyM_stop_le_start [Monad m] (p : α → m Bool) (as : Array α) (start theorem mem_def (a : α) (as : Array α) : a ∈ as ↔ a ∈ as.data := ⟨fun | .mk h => h, Array.Mem.mk⟩ -/-- # get -/ +/-! # get -/ + @[simp] theorem get_eq_getElem (a : Array α) (i : Fin _) : a.get i = a[i.1] := rfl theorem getElem?_lt @@ -217,7 +219,7 @@ theorem get!_eq_getD [Inhabited α] (a : Array α) : a.get! n = a.getD n default @[simp] theorem get!_eq_getElem? [Inhabited α] (a : Array α) (i : Nat) : a.get! i = (a.get? i).getD default := by by_cases p : i < a.size <;> simp [getD_get?, get!_eq_getD, p] -/-- # set -/ +/-! # set -/ @[simp] theorem getElem_set_eq (a : Array α) (i : Fin a.size) (v : α) {j : Nat} (eq : i.val = j) (p : j < (a.set i v).size) : @@ -240,7 +242,7 @@ theorem getElem_set (a : Array α) (i : Fin a.size) (v : α) (j : Nat) (ne : i.val ≠ j) : (a.set i v)[j]? = a[j]? := by by_cases h : j < a.size <;> simp [getElem?_lt, getElem?_ge, Nat.ge_of_not_lt, ne, h] -/- # setD -/ +/-! # setD -/ @[simp] theorem set!_is_setD : @set! = @setD := rfl @@ -266,4 +268,44 @@ theorem getElem?_setD_eq (a : Array α) {i : Nat} (p : i < a.size) (v : α) : (a by_cases h : i < a.size <;> simp [setD, Nat.not_lt_of_le, h, getD_get?] +/-! # ofFn -/ + +@[simp] theorem size_ofFn_go {n} (f : Fin n → α) (i acc) : + (ofFn.go f i acc).size = acc.size + (n - i) := by + if hin : i < n then + unfold ofFn.go + have : 1 + (n - (i + 1)) = n - i := + Nat.sub_sub .. ▸ Nat.add_sub_cancel' (Nat.le_sub_of_add_le (Nat.add_comm .. ▸ hin)) + rw [dif_pos hin, size_ofFn_go f (i+1), size_push, Nat.add_assoc, this] + else + have : n - i = 0 := Nat.sub_eq_zero_of_le (Nat.le_of_not_lt hin) + unfold ofFn.go + simp [hin, this] +termination_by n - i + +@[simp] theorem size_ofFn (f : Fin n → α) : (ofFn f).size = n := by simp [ofFn] + +theorem getElem_ofFn_go (f : Fin n → α) (i) {acc k} + (hki : k < n) (hin : i ≤ n) (hi : i = acc.size) + (hacc : ∀ j, ∀ hj : j < acc.size, acc[j] = f ⟨j, Nat.lt_of_lt_of_le hj (hi ▸ hin)⟩) : + haveI : acc.size + (n - acc.size) = n := Nat.add_sub_cancel' (hi ▸ hin) + (ofFn.go f i acc)[k]'(by simp [*]) = f ⟨k, hki⟩ := by + unfold ofFn.go + if hin : i < n then + have : 1 + (n - (i + 1)) = n - i := + Nat.sub_sub .. ▸ Nat.add_sub_cancel' (Nat.le_sub_of_add_le (Nat.add_comm .. ▸ hin)) + simp only [dif_pos hin] + rw [getElem_ofFn_go f (i+1) _ hin (by simp [*]) (fun j hj => ?hacc)] + cases (Nat.lt_or_eq_of_le <| Nat.le_of_lt_succ (by simpa using hj)) with + | inl hj => simp [get_push, hj, hacc j hj] + | inr hj => simp [get_push, *] + else + simp [hin, hacc k (Nat.lt_of_lt_of_le hki (Nat.le_of_not_lt (hi ▸ hin)))] +termination_by n - i + +@[simp] theorem getElem_ofFn (f : Fin n → α) (i : Nat) (h) : + (ofFn f)[i] = f ⟨i, size_ofFn f ▸ h⟩ := + getElem_ofFn_go _ _ _ (by simp) (by simp) nofun + + end Array diff --git a/src/Init/Data/List/BasicAux.lean b/src/Init/Data/List/BasicAux.lean index 87da6de4a840..0dbdf63d7dda 100644 --- a/src/Init/Data/List/BasicAux.lean +++ b/src/Init/Data/List/BasicAux.lean @@ -5,6 +5,7 @@ Author: Leonardo de Moura -/ prelude import Init.Data.Nat.Linear +import Init.Ext universe u @@ -43,6 +44,14 @@ See also `get?` and `get!`. def getD (as : List α) (i : Nat) (fallback : α) : α := (as.get? i).getD fallback +@[ext] theorem ext : ∀ {l₁ l₂ : List α}, (∀ n, l₁.get? n = l₂.get? n) → l₁ = l₂ + | [], [], _ => rfl + | a :: l₁, [], h => nomatch h 0 + | [], a' :: l₂, h => nomatch h 0 + | a :: l₁, a' :: l₂, h => by + have h0 : some a = some a' := h 0 + injection h0 with aa; simp only [aa, ext fun n => h (n+1)] + /-- Returns the first element in the list. diff --git a/src/Init/Data/List/Lemmas.lean b/src/Init/Data/List/Lemmas.lean index 48bfbd65bd0e..a8428f87716c 100644 --- a/src/Init/Data/List/Lemmas.lean +++ b/src/Init/Data/List/Lemmas.lean @@ -274,6 +274,19 @@ theorem get?_reverse {l : List α} (i) (h : i < length l) : @[simp] theorem getD_cons_succ : getD (x :: xs) (n + 1) d = getD xs n d := rfl +theorem ext_get {l₁ l₂ : List α} (hl : length l₁ = length l₂) + (h : ∀ n h₁ h₂, get l₁ ⟨n, h₁⟩ = get l₂ ⟨n, h₂⟩) : l₁ = l₂ := + ext fun n => + if h₁ : n < length l₁ then by + rw [get?_eq_get, get?_eq_get, h n h₁ (by rwa [← hl])] + else by + have h₁ := Nat.le_of_not_lt h₁ + rw [get?_len_le h₁, get?_len_le]; rwa [← hl] + +@[simp] theorem get_map (f : α → β) {l n} : + get (map f l) n = f (get l ⟨n, length_map l f ▸ n.2⟩) := + Option.some.inj <| by rw [← get?_eq_get, get?_map, get?_eq_get]; rfl + /-! ### take and drop -/ @[simp] theorem take_append_drop : ∀ (n : Nat) (l : List α), take n l ++ drop n l = l @@ -391,6 +404,14 @@ theorem foldr_eq_foldrM (f : α → β → β) (b) (l : List α) : theorem foldr_self (l : List α) : l.foldr cons [] = l := by simp +theorem foldl_map (f : β₁ → β₂) (g : α → β₂ → α) (l : List β₁) (init : α) : + (l.map f).foldl g init = l.foldl (fun x y => g x (f y)) init := by + induction l generalizing init <;> simp [*] + +theorem foldr_map (f : α₁ → α₂) (g : α₂ → β → β) (l : List α₁) (init : β) : + (l.map f).foldr g init = l.foldr (fun x y => g (f x) y) init := by + induction l generalizing init <;> simp [*] + /-! ### mapM -/ /-- Alternate (non-tail-recursive) form of mapM for proofs. -/