Operation on tuples #
We interpret maps ∀ i : Fin n, α i
as n
-tuples of elements of possibly varying type α i
,
(α 0, …, α (n-1))
. A particular case is Fin n → α
of elements with all the same type.
In this case when α i
is a constant map, then tuples are isomorphic (but not definitionally equal)
to Vector
s.
Main declarations #
There are three (main) ways to consider Fin n
as a subtype of Fin (n + 1)
, hence three (main)
ways to move between tuples of length n
and of length n + 1
by adding/removing an entry.
Adding at the start #
Fin.succ
: Sendi : Fin n
toi + 1 : Fin (n + 1)
. This is defined in Core.Fin.cases
: Induction/recursion principle forFin
: To prove a property/define a function for allFin (n + 1)
, it is enough to prove/define it for0
and fori.succ
for alli : Fin n
. This is defined in Core.Fin.cons
: Turn a tuplef : Fin n → α
and an entrya : α
into a tupleFin.cons a f : Fin (n + 1) → α
by addinga
at the start. In general, tuples can be dependent functions, in which casef : ∀ i : Fin n, α i.succ
anda : α 0
. This is a special case ofFin.cases
.Fin.tail
: Turn a tuplef : Fin (n + 1) → α
into a tupleFin.tail f : Fin n → α
by forgetting the start. In general, tuples can be dependent functions, in which caseFin.tail f : ∀ i : Fin n, α i.succ
.
Adding at the end #
Fin.castSucc
: Sendi : Fin n
toi : Fin (n + 1)
. This is defined in Core.Fin.lastCases
: Induction/recursion principle forFin
: To prove a property/define a function for allFin (n + 1)
, it is enough to prove/define it forlast n
and fori.castSucc
for alli : Fin n
. This is defined in Core.Fin.snoc
: Turn a tuplef : Fin n → α
and an entrya : α
into a tupleFin.snoc f a : Fin (n + 1) → α
by addinga
at the end. In general, tuples can be dependent functions, in which casef : ∀ i : Fin n, α i.castSucc
anda : α (last n)
. This is a special case ofFin.lastCases
.Fin.init
: Turn a tuplef : Fin (n + 1) → α
into a tupleFin.init f : Fin n → α
by forgetting the start. In general, tuples can be dependent functions, in which caseFin.init f : ∀ i : Fin n, α i.castSucc
.
Adding in the middle #
For a pivot p : Fin (n + 1)
,
Fin.succAbove
: Sendi : Fin n
toFin.succAboveCases
: Induction/recursion principle forFin
: To prove a property/define a function for allFin (n + 1)
, it is enough to prove/define it forp
and forp.succAbove i
for alli : Fin n
.Fin.insertNth
: Turn a tuplef : Fin n → α
and an entrya : α
into a tupleFin.insertNth f a : Fin (n + 1) → α
by addinga
in positionp
. In general, tuples can be dependent functions, in which casef : ∀ i : Fin n, α (p.succAbove i)
anda : α p
. This is a special case ofFin.succAboveCases
.- There is currently no equivalent of
Fin.tail
/Fin.init
for adding in the middle.
p = 0
means we add at the start. p = last n
means we add at the end.
Miscellaneous #
Fin.find p
: returns the first indexn
wherep n
is satisfied, andnone
if it is never satisfied.Fin.append a b
: append two tuples.Fin.repeat n a
: repeat a tuplen
times.
Updating a tuple and adding an element at the beginning commute.
As a binary function, Fin.cons
is injective.
Recurse on an n+1
-tuple by splitting it into a single element and an n
-tuple.
Equations
- Fin.consCases h x = cast ⋯ (h (x 0) (Fin.tail x))
Instances For
Recurse on a tuple by splitting into Fin.elim0
and Fin.cons
.
Equations
- Fin.consInduction h0 h x_2 = ⋯.mpr (id h0)
- Fin.consInduction h0 h x_2 = Fin.consCases (fun (x₀ : α) (x : Fin n → α) => h x₀ x (Fin.consInduction h0 (fun {n : ℕ} => h) x)) x_2
Instances For
Updating a nonzero element and taking the tail commute.
Append a tuple of length m
to a tuple of length n
to get a tuple of length m + n
.
This is a non-dependent version of Fin.add_cases
.
Equations
- Fin.append a b = Fin.addCases a b
Instances For
Repeat a
m
times. For example Fin.repeat 2 ![0, 3, 7] = ![0, 3, 7, 0, 3, 7]
.
Equations
- Fin.repeat m a x = let i := x; a i.modNat
Instances For
In the previous section, we have discussed inserting or removing elements on the left of a
tuple. In this section, we do the same on the right. A difference is that Fin (n+1)
is constructed
inductively from Fin n
starting from the left, not from the right. This implies that Lean needs
more help to realize that elements belong to the right types, i.e., we need to insert casts at
several places.
Adding an element at the end of an n
-tuple, to get an n+1
-tuple. The name snoc
comes from
cons
(i.e., adding an element to the left of a tuple) read in reverse order.
Instances For
Updating a tuple and adding an element at the end commute.
Updating an element and taking the beginning commute.
Appending a one-tuple to the right is the same as Fin.snoc
.
Fin.snoc
is the same as appending a one-tuple
Recurse on an n+1
-tuple by splitting it its initial n
-tuple and its last element.
Equations
- Fin.snocCases h x = cast ⋯ (h (Fin.init x) (x (Fin.last n)))
Instances For
Recurse on a tuple by splitting into Fin.elim0
and Fin.snoc
.
Equations
- Fin.snocInduction h0 h x_2 = ⋯.mpr (id h0)
- Fin.snocInduction h0 h x_2 = Fin.snocCases (fun (x₀ : Fin n → α) (x : α) => h x₀ x (Fin.snocInduction h0 (fun {n : ℕ} => h) x₀)) x_2
Instances For
Define a function on Fin (n + 1)
from a value on i : Fin (n + 1)
and values on each
Fin.succAbove i j
, j : Fin n
. This version is elaborated as eliminator and works for
propositions, see also Fin.insertNth
for a version without an @[elab_as_elim]
attribute.
Equations
Instances For
Insert an element into a tuple at a given position. For i = 0
see Fin.cons
,
for i = Fin.last n
see Fin.snoc
. See also Fin.succAboveCases
for a version elaborated
as an eliminator.
Equations
- i.insertNth x p j = i.succAboveCases x p j
Instances For
find p
returns the first index n
where p n
is satisfied, and none
if it is never
satisfied.
Equations
Instances For
If find p = some i
, then p i
holds