Skip to content

Commit 16190b7

Browse files
feat: port Data.Vector from lean-core (#834)
Have also added some needed lemmas for Lists; from e574b1a4e891376b0ef974b926da39e05da12a06
1 parent e340c6a commit 16190b7

File tree

4 files changed

+474
-0
lines changed

4 files changed

+474
-0
lines changed

Mathlib.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ import Mathlib.Data.Sum.Order
199199
import Mathlib.Data.UInt
200200
import Mathlib.Data.ULift
201201
import Mathlib.Data.UnionFind
202+
import Mathlib.Data.Vector
202203
import Mathlib.GroupTheory.EckmannHilton
203204
import Mathlib.GroupTheory.GroupAction.Defs
204205
import Mathlib.GroupTheory.GroupAction.Option
@@ -218,6 +219,8 @@ import Mathlib.Init.Data.Bool.Lemmas
218219
import Mathlib.Init.Data.Fin.Basic
219220
import Mathlib.Init.Data.Int.Basic
220221
import Mathlib.Init.Data.Int.Order
222+
import Mathlib.Init.Data.List.Basic
223+
import Mathlib.Init.Data.List.Lemmas
221224
import Mathlib.Init.Data.Nat.Basic
222225
import Mathlib.Init.Data.Nat.Lemmas
223226
import Mathlib.Init.Data.Ordering.Basic

Mathlib/Data/Vector.lean

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
/-
2+
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Leonardo de Moura
5+
-/
6+
import Mathlib.Mathport.Rename
7+
import Std.Data.List.Basic
8+
import Std.Data.List.Lemmas
9+
import Mathlib.Init.Data.List.Basic
10+
import Mathlib.Init.Data.List.Lemmas
11+
12+
/-!
13+
The type `Vector` represents lists with fixed length.
14+
-/
15+
16+
universe u v w
17+
/-- `Vector α n` is the type of lists of length `n` with elements of type `α`. -/
18+
def Vector (α : Type u) (n : ℕ) :=
19+
{ l : List α // l.length = n }
20+
#align vector Vector
21+
22+
namespace Vector
23+
24+
variable {α : Type u} {β : Type v} {φ : Type w}
25+
26+
variable {n : ℕ}
27+
28+
instance [DecidableEq α] : DecidableEq (Vector α n) := by
29+
unfold Vector
30+
infer_instance
31+
32+
/-- The empty vector with elements of type `α` -/
33+
@[match_pattern]
34+
def nil : Vector α 0 :=
35+
⟨[], rfl⟩
36+
#align vector.nil Vector.nil
37+
38+
/-- If `a : α` and `l : Vector α n`, then `cons a l`, is the vector of length `n + 1`
39+
whose first element is a and with l as the rest of the list. -/
40+
@[match_pattern]
41+
def cons : α → Vector α n → Vector α (Nat.succ n)
42+
| a, ⟨v, h⟩ => ⟨a :: v, congrArg Nat.succ h⟩
43+
#align vector.cons Vector.cons
44+
45+
46+
/-- The length of a vector. -/
47+
@[reducible, nolint unusedArguments]
48+
def length (_ : Vector α n) : ℕ :=
49+
n
50+
#align vector.length Vector.length
51+
52+
open Nat
53+
54+
/-- The first element of a vector with length at least `1`. -/
55+
def head : Vector α (Nat.succ n) → α
56+
| ⟨[], h⟩ => by contradiction
57+
| ⟨a :: _, _⟩ => a
58+
#align vector.head Vector.head
59+
60+
/-- The head of a vector obtained by prepending is the element prepended. -/
61+
theorem head_cons (a : α) : ∀ v : Vector α n, head (cons a v) = a
62+
| ⟨_, _⟩ => rfl
63+
#align vector.head_cons Vector.head_cons
64+
65+
/-- The tail of a vector, with an empty vector having empty tail. -/
66+
def tail : Vector α n → Vector α (n - 1)
67+
| ⟨[], h⟩ => ⟨[], congrArg pred h⟩
68+
| ⟨_ :: v, h⟩ => ⟨v, congrArg pred h⟩
69+
#align vector.tail Vector.tail
70+
71+
/-- The tail of a vector obtained by prepending is the vector prepended. to -/
72+
theorem tail_cons (a : α) : ∀ v : Vector α n, tail (cons a v) = v
73+
| ⟨_, _⟩ => rfl
74+
#align vector.tail_cons Vector.tail_cons
75+
76+
/-- Prepending the head of a vector to its tail gives the vector. -/
77+
@[simp]
78+
theorem cons_head_tail : ∀ v : Vector α (succ n), cons (head v) (tail v) = v
79+
| ⟨[], h⟩ => by contradiction
80+
| ⟨a :: v, h⟩ => rfl
81+
#align vector.cons_head_tail Vector.cons_head_tail
82+
83+
/-- The list obtained from a vector. -/
84+
def toList (v : Vector α n) : List α :=
85+
v.1
86+
#align vector.to_list Vector.toList
87+
88+
/-- nth element of a vector, indexed by a `Fin` type. -/
89+
def nth : ∀ _ : Vector α n, Fin n → α
90+
| ⟨l, h⟩, i => l.nthLe i.1 (by rw [h] ; exact i.2)
91+
#align vector.nth Vector.nth
92+
93+
/-- Appending a vector to another. -/
94+
def append {n m : Nat} : Vector α n → Vector α m → Vector α (n + m)
95+
| ⟨l₁, h₁⟩, ⟨l₂, h₂⟩ => ⟨l₁ ++ l₂, by simp [*]⟩
96+
#align vector.append Vector.append
97+
98+
/- warning: vector.elim -> Vector.elim is a dubious translation:
99+
lean 3 declaration is
100+
forall {α : Type.{u_1}} {C : forall {n : ℕ},
101+
(Vector.{u_1} α n) -> Sort.{u}}, (forall (l : List.{u_1} α),
102+
C (List.length.{u_1} α l) (Subtype.mk.{succ u_1} (List.{u_1} α)
103+
(fun (l_1 : List.{u_1} α) => Eq.{1} ℕ (List.length.{u_1} α l_1)
104+
(List.length.{u_1} α l)) l (Vector.Elim._proof_1.{u_1} α l))) ->
105+
(forall {n : ℕ} (v : Vector.{u_1} α n), C n v)
106+
but is expected to have type
107+
forall {α : Type.{_aux_param_0}} {C : forall {n : ℕ}, (Vector.{_aux_param_0} α n) -> Sort.{u}},
108+
(forall (l : List.{_aux_param_0} α),
109+
C (List.length.{_aux_param_0} α l) (Subtype.mk.{succ _aux_param_0} (List.{_aux_param_0} α)
110+
(fun (l_1 : List.{_aux_param_0} α) => Eq.{1} ℕ (List.length.{_aux_param_0} α l_1)
111+
(List.length.{_aux_param_0} α l)) l (rfl.{1} ℕ (List.length.{_aux_param_0} α l)))) ->
112+
(forall {n : ℕ} (v : Vector.{_aux_param_0} α n), C n v)
113+
Case conversion may be inaccurate. Consider using '#align vector.elim Vector.elimₓ'. -/
114+
/-- Elimination rule for `Vector`. -/
115+
@[elab_as_elim]
116+
def elim {α} {C : ∀ {n}, Vector α n → Sort u}
117+
(H : ∀ l : List α, C ⟨l, rfl⟩) {n : ℕ} : ∀ v : Vector α n, C v
118+
| ⟨l, h⟩ =>
119+
match n, h with
120+
| _, rfl => H l
121+
#align vector.elim Vector.elim
122+
123+
/-- Map a vector under a function. -/
124+
def map (f : α → β) : Vector α n → Vector β n
125+
| ⟨l, h⟩ => ⟨List.map f l, by simp [*]⟩
126+
#align vector.map Vector.map
127+
128+
/-- A `nil` vector maps to a `nil` vector. -/
129+
@[simp]
130+
theorem map_nil (f : α → β) : map f nil = nil :=
131+
rfl
132+
#align vector.map_nil Vector.map_nil
133+
134+
/-- `map` is natural with respect to `cons`. -/
135+
theorem map_cons (f : α → β) (a : α) : ∀ v : Vector α n, map f (cons a v) = cons (f a) (map f v)
136+
| ⟨_, _⟩ => rfl
137+
#align vector.map_cons Vector.map_cons
138+
139+
/-- Mapping two vectors under a curried function of two variables. -/
140+
def map₂ (f : α → β → φ) : Vector α n → Vector β n → Vector φ n
141+
| ⟨x, _⟩, ⟨y, _⟩ => ⟨List.map₂ f x y, by simp [*]⟩
142+
#align vector.map₂ Vector.map₂
143+
144+
/-- Vector obtained by repeating an element. -/
145+
def «repeat» (a : α) (n : ℕ) : Vector α n :=
146+
⟨List.repeat a n, List.length_repeat a n⟩
147+
#align vector.repeat Vector.repeat
148+
149+
/-- Drop `i` elements from a vector of length `n`; we can have `i > n`. -/
150+
def drop (i : ℕ) : Vector α n → Vector α (n - i)
151+
| ⟨l, p⟩ => ⟨List.drop i l, by simp [*]⟩
152+
#align vector.drop Vector.drop
153+
154+
/-- Take `i` elements from a vector of length `n`; we can have `i > n`. -/
155+
def take (i : ℕ) : Vector α n → Vector α (min i n)
156+
| ⟨l, p⟩ => ⟨List.take i l, by simp [*]⟩
157+
#align vector.take Vector.take
158+
159+
/-- Remove the element at position `i` from a vector of length `n`. -/
160+
def removeNth (i : Fin n) : Vector α n → Vector α (n - 1)
161+
| ⟨l, p⟩ => ⟨List.removeNth l i.1, by rw [l.length_removeNth] <;> rw [p] ; exact i.2
162+
#align vector.remove_nth Vector.removeNth
163+
164+
/-- Vector of length `n` from a function on `Fin n`. -/
165+
def ofFn : ∀ {n}, (Fin n → α) → Vector α n
166+
| 0, _ => nil
167+
| _ + 1, f => cons (f 0) (ofFn fun i ↦ f i.succ)
168+
#align vector.of_fn Vector.ofFn
169+
170+
section Accum
171+
172+
open Prod
173+
174+
variable {σ : Type}
175+
176+
/-- Runs a function over a vector returning the intermediate results and a
177+
a final result.
178+
-/
179+
def mapAccumr (f : α → σ → σ × β) : Vector α n → σ → σ × Vector β n
180+
| ⟨x, px⟩, c =>
181+
let res := List.mapAccumr f x c
182+
⟨res.1, res.2, by simp [*]⟩
183+
#align vector.map_accumr Vector.mapAccumr
184+
185+
/-- Runs a function over a pair of vectors returning the intermediate results and a
186+
a final result.
187+
-/
188+
def mapAccumr₂ {α β σ φ : Type} (f : α → β → σ → σ × φ) :
189+
Vector α n → Vector β n → σ → σ × Vector φ n
190+
| ⟨x, px⟩, ⟨y, py⟩, c =>
191+
let res := List.mapAccumr₂ f x y c
192+
⟨res.1, res.2, by simp [*]⟩
193+
#align vector.map_accumr₂ Vector.mapAccumr₂
194+
195+
end Accum
196+
197+
/-- Vector is determined by the underlying list. -/
198+
protected theorem eq {n : ℕ} : ∀ a1 a2 : Vector α n, toList a1 = toList a2 → a1 = a2
199+
| ⟨_, _⟩, ⟨_, _⟩, rfl => rfl
200+
#align vector.eq Vector.eq
201+
202+
/-- A vector of length `0` is a `nil` vector. -/
203+
protected theorem eq_nil (v : Vector α 0) : v = nil :=
204+
v.eq nil (List.eq_nil_of_length_eq_zero v.2)
205+
#align vector.eq_nil Vector.eq_nil
206+
207+
/-- Vector of length from a list `v`
208+
with witness that `v` has length `n` maps to `v` under `toList`. -/
209+
@[simp]
210+
theorem toList_mk (v : List α) (P : List.length v = n) : toList (Subtype.mk v P) = v :=
211+
rfl
212+
#align vector.to_list_mk Vector.toList_mk
213+
214+
/-- A nil vector maps to a nil list. -/
215+
@[simp]
216+
theorem to_list_nil : toList nil = @List.nil α :=
217+
rfl
218+
#align vector.to_list_nil Vector.to_list_nil
219+
220+
/-- The length of the list to which a vector of length `n` maps is `n`. -/
221+
@[simp]
222+
theorem to_list_length (v : Vector α n) : (toList v).length = n :=
223+
v.2
224+
#align vector.to_list_length Vector.to_list_length
225+
226+
/-- `toList` of `cons` of a vector and an element is
227+
the `cons` of the list obtained by `toList` and the element -/
228+
@[simp]
229+
theorem to_list_cons (a : α) (v : Vector α n) : toList (cons a v) = a :: toList v := by
230+
cases v ; rfl
231+
#align vector.to_list_cons Vector.to_list_cons
232+
233+
/-- Appending of vectors corresponds under `toList` to appending of lists. -/
234+
@[simp]
235+
theorem to_list_append {n m : ℕ} (v : Vector α n) (w : Vector α m) :
236+
toList (append v w) = toList v ++ toList w := by
237+
cases v
238+
cases w
239+
rfl
240+
#align vector.to_list_append Vector.to_list_append
241+
242+
/-- `drop` of vectors corresponds under `toList` to `drop` of lists. -/
243+
@[simp]
244+
theorem to_list_drop {n m : ℕ} (v : Vector α m) : toList (drop n v) = List.drop n (toList v) := by
245+
cases v
246+
rfl
247+
#align vector.to_list_drop Vector.to_list_drop
248+
249+
/-- `take` of vectors corresponds under `toList` to `take` of lists. -/
250+
@[simp]
251+
theorem to_list_take {n m : ℕ} (v : Vector α m) : toList (take n v) = List.take n (toList v) := by
252+
cases v
253+
rfl
254+
#align vector.to_list_take Vector.to_list_take
255+
256+
end Vector

Mathlib/Init/Data/List/Basic.lean

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/-
2+
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Leonardo de Moura
5+
-/
6+
import Mathlib.Mathport.Rename
7+
import Mathlib.Init.Data.Nat.Basic
8+
import Std.Data.Nat.Lemmas
9+
import Std.Data.List.Basic
10+
/-!
11+
Definitions for `List` not (yet) in `Std`
12+
-/
13+
14+
15+
open Decidable List
16+
17+
universe u v w
18+
19+
namespace List
20+
21+
22+
23+
open Option Nat
24+
25+
/-- Optionally return nth element of a list. -/
26+
@[simp]
27+
def nth : List α → ℕ → Option α
28+
| [], _ => none
29+
| a :: _, 0 => some a
30+
| _ :: l, n + 1 => nth l n
31+
#align list.nth List.nth
32+
33+
/-- nth element of a list `l` given `n < l.length`. -/
34+
def nthLe : ∀ (l : List α) (n), n < l.length → α
35+
| [], n, h => absurd h n.not_lt_zero
36+
| a :: _, 0, _ => a
37+
| _ :: l, n + 1, h => nthLe l n (le_of_succ_le_succ h)
38+
#align list.nth_le List.nthLe
39+
40+
/-- Mapping a pair of lists under a curried function of two variables. -/
41+
@[simp]
42+
def map₂ (f : α → β → γ) : List α → List β → List γ
43+
| [], _ => []
44+
| _, [] => []
45+
| x :: xs, y :: ys => f x y :: map₂ f xs ys
46+
47+
/-- Auxiliary function for `mapWithIndex`. -/
48+
def mapWithIndexCore (f : ℕ → α → β) : ℕ → List α → List β
49+
| _, [] => []
50+
| k, a :: as => f k a :: mapWithIndexCore f (k + 1) as
51+
#align list.map_with_index_core List.mapWithIndexCore
52+
53+
/-- Given a function `f : ℕ → α → β` and `as : list α`, `as = [a₀, a₁, ...]`, returns the list
54+
`[f 0 a₀, f 1 a₁, ...]`. -/
55+
def mapWithIndex (f : ℕ → α → β) (as : List α) : List β :=
56+
mapWithIndexCore f 0 as
57+
#align list.map_with_index List.mapWithIndex
58+
59+
/-- Find index of element with given property. -/
60+
def findIndex (p : α → Prop) [DecidablePred p] : List α → ℕ
61+
| [] => 0
62+
| a :: l => if p a then 0 else succ (findIndex p l)
63+
#align list.find_index List.findIndex
64+
65+
/-- Update the nth element of a list. -/
66+
def updateNth : List α → ℕ → α → List α
67+
| _ :: xs, 0, a => a :: xs
68+
| x :: xs, i + 1, a => x :: updateNth xs i a
69+
| [], _, _ => []
70+
#align list.update_nth List.updateNth
71+
72+
/-- Big or of a list of Booleans. -/
73+
def bor (l : List Bool) : Bool :=
74+
any l id
75+
#align list.bor List.bor
76+
77+
/-- Big and of a list of Booleans. -/
78+
def band (l : List Bool) : Bool :=
79+
all l id
80+
#align list.band List.band
81+
82+
/-- List consisting of an element `a` repeated a specified number of times. -/
83+
@[simp]
84+
def «repeat» (a : α) : Nat → List α
85+
| 0 => []
86+
| succ n => a :: «repeat» a n
87+
#align list.repeat List.repeat
88+
89+
/-- The last element of a non-empty list. -/
90+
def last : ∀ l : List α, l ≠ [] → α
91+
| [], h => absurd rfl h
92+
| [a], _ => a
93+
| _ :: b :: l, _ => last (b :: l) fun h => List.noConfusion h
94+
#align list.last List.last
95+
96+
/-- The last element of a list, with the default if list empty -/
97+
def ilast [Inhabited α] : List α → α
98+
| [] => default
99+
| [a] => a
100+
| [_, b] => b
101+
| _ :: _ :: l => ilast l
102+
#align list.ilast List.ilast
103+
104+
/-- Initial segment of a list, i.e., with the last element dropped. -/
105+
def init : List α → List α
106+
| [] => []
107+
| [_] => []
108+
| a :: l => a :: init l
109+
#align list.init List.init
110+
111+
/-- List with a single given element. -/
112+
@[inline]
113+
protected def ret {α : Type u} (a : α) : List α :=
114+
[a]
115+
#align list.ret List.ret
116+
117+
/-- `≤` implies not `>` for lists. -/
118+
theorem le_eq_not_gt [LT α] : ∀ l₁ l₂ : List α, (l₁ ≤ l₂) = ¬l₂ < l₁ := fun _ _ => rfl
119+
#align list.le_eq_not_gt List.le_eq_not_gt
120+
121+
122+
end List

0 commit comments

Comments
 (0)