bookshelf/Common/List/NonEmpty.lean

81 lines
1.8 KiB
Plaintext
Raw Normal View History

import Mathlib.Algebra.Group.Defs
import Mathlib.Data.Nat.Basic
import Mathlib.Tactic.NormNum
/-! # Common.List.NonEmpty
A `List` with at least one member.
-/
namespace List
structure NonEmpty (α : Type _) : Type _ where
head : α
tail : List α
instance : Coe (NonEmpty α) (List α) where
coe (xs : NonEmpty α) := xs.head :: xs.tail
instance : CoeDep (List α) (cons x xs : List α) (NonEmpty α) where
coe := { head := x, tail := xs }
namespace NonEmpty
/--
The length of a `List.NonEmpty`.
-/
def length (xs : NonEmpty α) : Nat := 1 + xs.tail.length
/--
The length of a `List.NonEmpty` is always one plus the length of its tail.
-/
theorem length_self_eq_one_add_length_tail (xs : NonEmpty α)
: xs.length = 1 + xs.tail.length := rfl
/--
A proof that an index is within the bounds of the `List.NonEmpty`.
-/
abbrev inBounds (xs : NonEmpty α) (i : Nat) : Prop :=
i < xs.length
/--
Retrieves the member of the `List.NonEmpty` at the specified index.
-/
def get (xs : NonEmpty α) : (i : Nat) → (h : xs.inBounds i) → α
| 0, _ => xs.head
| n + 1, h =>
have : n < xs.tail.length := by
unfold inBounds at h
rw [length_self_eq_one_add_length_tail, add_comm] at h
norm_num at h
exact h
xs.tail[n]
/--
Variant of `get` that returns an `Option α` in the case of an invalid index.
-/
def get? : NonEmpty α → Nat → Option α
| xs, 0 => some xs.head
| xs, n + 1 => xs.tail.get? n
/--
Type class instance for allowing direct indexing notation.
-/
instance : GetElem (NonEmpty α) Nat α inBounds where
getElem := get
/--
Convert a `List.NonEmpty` into a plain `List`.
-/
def toList (xs : NonEmpty α) : List α := xs
/--
Retrieve the last member of the `List.NonEmpty`.
-/
def last : NonEmpty αα
| ⟨head, []⟩ => head
| ⟨_, cons x xs⟩ => last (cons x xs)
end NonEmpty
end List