refactor(library/data): rename fixed_list -> tuple

This commit is contained in:
Leonardo de Moura 2015-08-13 16:45:34 -07:00
parent 9bb778dc7c
commit 49eb7166f0
3 changed files with 66 additions and 66 deletions

View file

@ -16,9 +16,9 @@ the expression =v = w= since it would not be able to establish that
_definitionally equal_. _definitionally equal_.
#+BEGIN_SRC lean #+BEGIN_SRC lean
import data.fixed_list data.nat import data.tuple data.nat
open nat open nat
check λ (v : fixed_list nat (2+3)) (w : fixed_list nat 5), v = w check λ (v : tuple nat (2+3)) (w : tuple nat 5), v = w
#+END_SRC #+END_SRC
Similarly, the following definition only type checks because =id= is transparent, and the type checker can establish that Similarly, the following definition only type checks because =id= is transparent, and the type checker can establish that

View file

@ -6,7 +6,7 @@ Author: Floris van Doorn, Leonardo de Moura
This file demonstrates how to encode vectors using indexed inductive families. This file demonstrates how to encode vectors using indexed inductive families.
In standard library we do not use this approach. In standard library we do not use this approach.
-/ -/
import data.nat data.list data.fin data.fixed_list import data.nat data.list data.fin
open nat prod fin open nat prod fin
inductive vector (A : Type) : nat → Type := inductive vector (A : Type) : nat → Type :=

View file

@ -3,51 +3,51 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE. Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura Author: Leonardo de Moura
The length of a list is encoded into its type. Tuples are lists of a fixed size.
It is implemented as a subtype. It is implemented as a subtype.
-/ -/
import logic data.list data.fin import logic data.list data.fin
open nat list subtype function open nat list subtype function
definition fixed_list [reducible] (A : Type) (n : nat) := {l : list A | length l = n} definition tuple [reducible] (A : Type) (n : nat) := {l : list A | length l = n}
namespace fixed_list namespace tuple
variables {A B C : Type} variables {A B C : Type}
theorem induction_on [recursor 4] {P : ∀ {n}, fixed_list A n → Prop} theorem induction_on [recursor 4] {P : ∀ {n}, tuple A n → Prop}
: ∀ {n} (v : fixed_list A n), (∀ (l : list A) {n : nat} (h : length l = n), P (tag l h)) → P v : ∀ {n} (v : tuple A n), (∀ (l : list A) {n : nat} (h : length l = n), P (tag l h)) → P v
| n (tag l h) H := @H l n h | n (tag l h) H := @H l n h
definition nil : fixed_list A 0 := definition nil : tuple A 0 :=
tag [] rfl tag [] rfl
lemma length_succ {n : nat} {l : list A} (a : A) : length l = n → length (a::l) = succ n := lemma length_succ {n : nat} {l : list A} (a : A) : length l = n → length (a::l) = succ n :=
λ h, congr_arg succ h λ h, congr_arg succ h
definition cons {n : nat} : A → fixed_list A n → fixed_list A (succ n) definition cons {n : nat} : A → tuple A n → tuple A (succ n)
| a (tag v h) := tag (a::v) (length_succ a h) | a (tag v h) := tag (a::v) (length_succ a h)
notation a :: b := cons a b notation a :: b := cons a b
protected definition is_inhabited [instance] [h : inhabited A] : ∀ (n : nat), inhabited (fixed_list A n) protected definition is_inhabited [instance] [h : inhabited A] : ∀ (n : nat), inhabited (tuple A n)
| 0 := inhabited.mk nil | 0 := inhabited.mk nil
| (succ n) := inhabited.mk (inhabited.value h :: inhabited.value (is_inhabited n)) | (succ n) := inhabited.mk (inhabited.value h :: inhabited.value (is_inhabited n))
protected definition has_decidable_eq [instance] [h : decidable_eq A] : ∀ (n : nat), decidable_eq (fixed_list A n) := protected definition has_decidable_eq [instance] [h : decidable_eq A] : ∀ (n : nat), decidable_eq (tuple A n) :=
_ _
definition head {n : nat} : fixed_list A (succ n) → A definition head {n : nat} : tuple A (succ n) → A
| (tag [] h) := by contradiction | (tag [] h) := by contradiction
| (tag (a::v) h) := a | (tag (a::v) h) := a
definition tail {n : nat} : fixed_list A (succ n) → fixed_list A n definition tail {n : nat} : tuple A (succ n) → tuple A n
| (tag [] h) := by contradiction | (tag [] h) := by contradiction
| (tag (a::v) h) := tag v (succ.inj h) | (tag (a::v) h) := tag v (succ.inj h)
theorem head_cons {n : nat} (a : A) (v : fixed_list A n) : head (a :: v) = a := theorem head_cons {n : nat} (a : A) (v : tuple A n) : head (a :: v) = a :=
by induction v; reflexivity by induction v; reflexivity
theorem tail_cons {n : nat} (a : A) (v : fixed_list A n) : tail (a :: v) = v := theorem tail_cons {n : nat} (a : A) (v : tuple A n) : tail (a :: v) = v :=
by induction v; reflexivity by induction v; reflexivity
theorem head_lcons {n : nat} (a : A) (l : list A) (h : length (a::l) = succ n) : head (tag (a::l) h) = a := theorem head_lcons {n : nat} (a : A) (l : list A) (h : length (a::l) = succ n) : head (tag (a::l) h) = a :=
@ -56,19 +56,19 @@ namespace fixed_list
theorem tail_lcons {n : nat} (a : A) (l : list A) (h : length (a::l) = succ n) : tail (tag (a::l) h) = tag l (succ.inj h) := theorem tail_lcons {n : nat} (a : A) (l : list A) (h : length (a::l) = succ n) : tail (tag (a::l) h) = tag l (succ.inj h) :=
rfl rfl
definition last {n : nat} : fixed_list A (succ n) → A definition last {n : nat} : tuple A (succ n) → A
| (tag l h) := list.last l (ne_nil_of_length_eq_succ h) | (tag l h) := list.last l (ne_nil_of_length_eq_succ h)
theorem eta : ∀ {n : nat} (v : fixed_list A (succ n)), head v :: tail v = v theorem eta : ∀ {n : nat} (v : tuple A (succ n)), head v :: tail v = v
| 0 (tag [] h) := by contradiction | 0 (tag [] h) := by contradiction
| 0 (tag (a::l) h) := rfl | 0 (tag (a::l) h) := rfl
| (n+1) (tag [] h) := by contradiction | (n+1) (tag [] h) := by contradiction
| (n+1) (tag (a::l) h) := rfl | (n+1) (tag (a::l) h) := rfl
definition of_list (l : list A) : fixed_list A (list.length l) := definition of_list (l : list A) : tuple A (list.length l) :=
tag l rfl tag l rfl
definition to_list {n : nat} : fixed_list A n → list A definition to_list {n : nat} : tuple A n → list A
| (tag l h) := l | (tag l h) := l
theorem to_list_of_list (l : list A) : to_list (of_list l) = l := theorem to_list_of_list (l : list A) : to_list (of_list l) = l :=
@ -77,10 +77,10 @@ namespace fixed_list
theorem to_list_nil : to_list nil = ([] : list A) := theorem to_list_nil : to_list nil = ([] : list A) :=
rfl rfl
theorem length_to_list {n : nat} : ∀ (v : fixed_list A n), list.length (to_list v) = n theorem length_to_list {n : nat} : ∀ (v : tuple A n), list.length (to_list v) = n
| (tag l h) := h | (tag l h) := h
theorem heq_of_list_eq {n m} : ∀ {v₁ : fixed_list A n} {v₂ : fixed_list A m}, to_list v₁ = to_list v₂ → n = m → v₁ == v₂ theorem heq_of_list_eq {n m} : ∀ {v₁ : tuple A n} {v₂ : tuple A m}, to_list v₁ = to_list v₂ → n = m → v₁ == v₂
| (tag l₁ h₁) (tag l₂ h₂) e₁ e₂ := begin | (tag l₁ h₁) (tag l₂ h₂) e₁ e₂ := begin
clear heq_of_list_eq, clear heq_of_list_eq,
subst e₂, subst h₁, subst e₂, subst h₁,
@ -88,20 +88,20 @@ namespace fixed_list
subst l₁ subst l₁
end end
theorem list_eq_of_heq {n m} {v₁ : fixed_list A n} {v₂ : fixed_list A m} : v₁ == v₂ → n = m → to_list v₁ = to_list v₂ := theorem list_eq_of_heq {n m} {v₁ : tuple A n} {v₂ : tuple A m} : v₁ == v₂ → n = m → to_list v₁ = to_list v₂ :=
begin begin
intro h₁ h₂, revert v₁ v₂ h₁, intro h₁ h₂, revert v₁ v₂ h₁,
subst n, intro v₁ v₂ h₁, rewrite [heq.to_eq h₁] subst n, intro v₁ v₂ h₁, rewrite [heq.to_eq h₁]
end end
theorem of_list_to_list {n : nat} (v : fixed_list A n) : of_list (to_list v) == v := theorem of_list_to_list {n : nat} (v : tuple A n) : of_list (to_list v) == v :=
begin begin
apply heq_of_list_eq, rewrite to_list_of_list, rewrite length_to_list apply heq_of_list_eq, rewrite to_list_of_list, rewrite length_to_list
end end
/- append -/ /- append -/
definition append {n m : nat} : fixed_list A n → fixed_list A m → fixed_list A (n + m) definition append {n m : nat} : tuple A n → tuple A m → tuple A (n + m)
| (tag l₁ h₁) (tag l₂ h₂) := tag (list.append l₁ l₂) (by rewrite [length_append, h₁, h₂]) | (tag l₁ h₁) (tag l₂ h₂) := tag (list.append l₁ l₂) (by rewrite [length_append, h₁, h₂])
infix ++ := append infix ++ := append
@ -111,40 +111,40 @@ namespace fixed_list
lemma push_eq_rec : ∀ {n m : nat} {l : list A} (h₁ : n = m) (h₂ : length l = n), h₁ ▹ (tag l h₂) = tag l (h₁ ▹ h₂) lemma push_eq_rec : ∀ {n m : nat} {l : list A} (h₁ : n = m) (h₂ : length l = n), h₁ ▹ (tag l h₂) = tag l (h₁ ▹ h₂)
| n n l (eq.refl n) h₂ := rfl | n n l (eq.refl n) h₂ := rfl
theorem append_nil_right {n : nat} (v : fixed_list A n) : v ++ nil = v := theorem append_nil_right {n : nat} (v : tuple A n) : v ++ nil = v :=
induction_on v (λ l n h, by unfold [fixed_list.append, fixed_list.nil]; congruence; apply list.append_nil_right) induction_on v (λ l n h, by unfold [tuple.append, tuple.nil]; congruence; apply list.append_nil_right)
theorem append_nil_left {n : nat} (v : fixed_list A n) : !zero_add ▹ (nil ++ v) = v := theorem append_nil_left {n : nat} (v : tuple A n) : !zero_add ▹ (nil ++ v) = v :=
induction_on v (λ l n h, begin unfold [fixed_list.append, fixed_list.nil], rewrite [push_eq_rec] end) induction_on v (λ l n h, begin unfold [tuple.append, tuple.nil], rewrite [push_eq_rec] end)
theorem append_nil_left_heq {n : nat} (v : fixed_list A n) : nil ++ v == v := theorem append_nil_left_heq {n : nat} (v : tuple A n) : nil ++ v == v :=
heq_of_eq_rec_left !zero_add (append_nil_left v) heq_of_eq_rec_left !zero_add (append_nil_left v)
theorem append.assoc {n₁ n₂ n₃} : ∀ (v₁ : fixed_list A n₁) (v₂ : fixed_list A n₂) (v₃ : fixed_list A n₃), !add.assoc ▹ ((v₁ ++ v₂) ++ v₃) = v₁ ++ (v₂ ++ v₃) theorem append.assoc {n₁ n₂ n₃} : ∀ (v₁ : tuple A n₁) (v₂ : tuple A n₂) (v₃ : tuple A n₃), !add.assoc ▹ ((v₁ ++ v₂) ++ v₃) = v₁ ++ (v₂ ++ v₃)
| (tag l₁ h₁) (tag l₂ h₂) (tag l₃ h₃) := begin | (tag l₁ h₁) (tag l₂ h₂) (tag l₃ h₃) := begin
unfold fixed_list.append, rewrite push_eq_rec, unfold tuple.append, rewrite push_eq_rec,
congruence, congruence,
apply list.append.assoc apply list.append.assoc
end end
theorem append.assoc_heq {n₁ n₂ n₃} (v₁ : fixed_list A n₁) (v₂ : fixed_list A n₂) (v₃ : fixed_list A n₃) : (v₁ ++ v₂) ++ v₃ == v₁ ++ (v₂ ++ v₃) := theorem append.assoc_heq {n₁ n₂ n₃} (v₁ : tuple A n₁) (v₂ : tuple A n₂) (v₃ : tuple A n₃) : (v₁ ++ v₂) ++ v₃ == v₁ ++ (v₂ ++ v₃) :=
heq_of_eq_rec_left !add.assoc (append.assoc v₁ v₂ v₃) heq_of_eq_rec_left !add.assoc (append.assoc v₁ v₂ v₃)
/- reverse -/ /- reverse -/
definition reverse {n : nat} : fixed_list A n → fixed_list A n definition reverse {n : nat} : tuple A n → tuple A n
| (tag l h) := tag (list.reverse l) (by rewrite [length_reverse, h]) | (tag l h) := tag (list.reverse l) (by rewrite [length_reverse, h])
theorem reverse_reverse {n : nat} (v : fixed_list A n) : reverse (reverse v) = v := theorem reverse_reverse {n : nat} (v : tuple A n) : reverse (reverse v) = v :=
induction_on v (λ l n h, begin unfold reverse, congruence, apply list.reverse_reverse end) induction_on v (λ l n h, begin unfold reverse, congruence, apply list.reverse_reverse end)
theorem fixed_list0_eq_nil : ∀ (v : fixed_list A 0), v = nil theorem tuple0_eq_nil : ∀ (v : tuple A 0), v = nil
| (tag [] h) := rfl | (tag [] h) := rfl
| (tag (a::l) h) := by contradiction | (tag (a::l) h) := by contradiction
/- mem -/ /- mem -/
definition mem {n : nat} (a : A) (v : fixed_list A n) : Prop := definition mem {n : nat} (a : A) (v : tuple A n) : Prop :=
a ∈ elt_of v a ∈ elt_of v
notation e ∈ s := mem e s notation e ∈ s := mem e s
@ -153,101 +153,101 @@ namespace fixed_list
theorem not_mem_nil (a : A) : a ∉ nil := theorem not_mem_nil (a : A) : a ∉ nil :=
list.not_mem_nil a list.not_mem_nil a
theorem mem_cons [simp] {n : nat} (a : A) (v : fixed_list A n) : a ∈ a :: v := theorem mem_cons [simp] {n : nat} (a : A) (v : tuple A n) : a ∈ a :: v :=
induction_on v (λ l n h, !list.mem_cons) induction_on v (λ l n h, !list.mem_cons)
theorem mem_cons_of_mem {n : nat} (y : A) {x : A} {v : fixed_list A n} : x ∈ v → x ∈ y :: v := theorem mem_cons_of_mem {n : nat} (y : A) {x : A} {v : tuple A n} : x ∈ v → x ∈ y :: v :=
induction_on v (λ l n h₁ h₂, list.mem_cons_of_mem y h₂) induction_on v (λ l n h₁ h₂, list.mem_cons_of_mem y h₂)
theorem eq_or_mem_of_mem_cons {n : nat} {x y : A} {v : fixed_list A n} : x ∈ y::v → x = y x ∈ v := theorem eq_or_mem_of_mem_cons {n : nat} {x y : A} {v : tuple A n} : x ∈ y::v → x = y x ∈ v :=
induction_on v (λ l n h₁ h₂, eq_or_mem_of_mem_cons h₂) induction_on v (λ l n h₁ h₂, eq_or_mem_of_mem_cons h₂)
theorem mem_singleton {n : nat} {x a : A} : x ∈ (a::nil : fixed_list A 1) → x = a := theorem mem_singleton {n : nat} {x a : A} : x ∈ (a::nil : tuple A 1) → x = a :=
assume h, list.mem_singleton h assume h, list.mem_singleton h
/- map -/ /- map -/
definition map {n : nat} (f : A → B) : fixed_list A n → fixed_list B n definition map {n : nat} (f : A → B) : tuple A n → tuple B n
| (tag l h) := tag (list.map f l) (by clear map; substvars; rewrite length_map) | (tag l h) := tag (list.map f l) (by clear map; substvars; rewrite length_map)
theorem map_nil (f : A → B) : map f nil = nil := theorem map_nil (f : A → B) : map f nil = nil :=
rfl rfl
theorem map_cons {n : nat} (f : A → B) (a : A) (v : fixed_list A n) : map f (a::v) = f a :: map f v := theorem map_cons {n : nat} (f : A → B) (a : A) (v : tuple A n) : map f (a::v) = f a :: map f v :=
by induction v; reflexivity by induction v; reflexivity
theorem map_tag {n : nat} (f : A → B) (l : list A) (h : length l = n) theorem map_tag {n : nat} (f : A → B) (l : list A) (h : length l = n)
: map f (tag l h) = tag (list.map f l) (by substvars; rewrite length_map) := : map f (tag l h) = tag (list.map f l) (by substvars; rewrite length_map) :=
by reflexivity by reflexivity
theorem map_map {n : nat} (g : B → C) (f : A → B) (v : fixed_list A n) : map g (map f v) = map (g ∘ f) v := theorem map_map {n : nat} (g : B → C) (f : A → B) (v : tuple A n) : map g (map f v) = map (g ∘ f) v :=
begin cases v, rewrite *map_tag, apply subtype.eq, apply list.map_map end begin cases v, rewrite *map_tag, apply subtype.eq, apply list.map_map end
theorem map_id {n : nat} (v : fixed_list A n) : map id v = v := theorem map_id {n : nat} (v : tuple A n) : map id v = v :=
begin induction v, unfold map, congruence, apply list.map_id end begin induction v, unfold map, congruence, apply list.map_id end
theorem mem_map {n : nat} {a : A} {v : fixed_list A n} (f : A → B) : a ∈ v → f a ∈ map f v := theorem mem_map {n : nat} {a : A} {v : tuple A n} (f : A → B) : a ∈ v → f a ∈ map f v :=
begin induction v, unfold map, apply list.mem_map end begin induction v, unfold map, apply list.mem_map end
theorem exists_of_mem_map {n : nat} {f : A → B} {b : B} {v : fixed_list A n} : b ∈ map f v → ∃a, a ∈ v ∧ f a = b := theorem exists_of_mem_map {n : nat} {f : A → B} {b : B} {v : tuple A n} : b ∈ map f v → ∃a, a ∈ v ∧ f a = b :=
begin induction v, unfold map, apply list.exists_of_mem_map end begin induction v, unfold map, apply list.exists_of_mem_map end
theorem eq_of_map_const {n : nat} {b₁ b₂ : B} {v : fixed_list A n} : b₁ ∈ map (const A b₂) v → b₁ = b₂ := theorem eq_of_map_const {n : nat} {b₁ b₂ : B} {v : tuple A n} : b₁ ∈ map (const A b₂) v → b₁ = b₂ :=
begin induction v, unfold map, apply list.eq_of_map_const end begin induction v, unfold map, apply list.eq_of_map_const end
/- product -/ /- product -/
definition product {n m : nat} : fixed_list A n → fixed_list B m → fixed_list (A × B) (n * m) definition product {n m : nat} : tuple A n → tuple B m → tuple (A × B) (n * m)
| (tag l₁ h₁) (tag l₂ h₂) := tag (list.product l₁ l₂) (by rewrite [length_product, h₁, h₂]) | (tag l₁ h₁) (tag l₂ h₂) := tag (list.product l₁ l₂) (by rewrite [length_product, h₁, h₂])
theorem nil_product {m : nat} (v : fixed_list B m) : !zero_mul ▹ product (@nil A) v = nil := theorem nil_product {m : nat} (v : tuple B m) : !zero_mul ▹ product (@nil A) v = nil :=
begin induction v, unfold [nil, product], rewrite push_eq_rec end begin induction v, unfold [nil, product], rewrite push_eq_rec end
theorem nil_product_heq {m : nat} (v : fixed_list B m) : product (@nil A) v == (@nil (A × B)) := theorem nil_product_heq {m : nat} (v : tuple B m) : product (@nil A) v == (@nil (A × B)) :=
heq_of_eq_rec_left _ (nil_product v) heq_of_eq_rec_left _ (nil_product v)
theorem product_nil {n : nat} (v : fixed_list A n) : product v (@nil B) = nil := theorem product_nil {n : nat} (v : tuple A n) : product v (@nil B) = nil :=
begin induction v, unfold [nil, product], congruence, apply list.product_nil end begin induction v, unfold [nil, product], congruence, apply list.product_nil end
theorem mem_product {n m : nat} {a : A} {b : B} {v₁ : fixed_list A n} {v₂ : fixed_list B m} : a ∈ v₁ → b ∈ v₂ → (a, b) ∈ product v₁ v₂ := theorem mem_product {n m : nat} {a : A} {b : B} {v₁ : tuple A n} {v₂ : tuple B m} : a ∈ v₁ → b ∈ v₂ → (a, b) ∈ product v₁ v₂ :=
begin cases v₁, cases v₂, unfold product, apply list.mem_product end begin cases v₁, cases v₂, unfold product, apply list.mem_product end
theorem mem_of_mem_product_left {n m : nat} {a : A} {b : B} {v₁ : fixed_list A n} {v₂ : fixed_list B m} : (a, b) ∈ product v₁ v₂ → a ∈ v₁ := theorem mem_of_mem_product_left {n m : nat} {a : A} {b : B} {v₁ : tuple A n} {v₂ : tuple B m} : (a, b) ∈ product v₁ v₂ → a ∈ v₁ :=
begin cases v₁, cases v₂, unfold product, apply list.mem_of_mem_product_left end begin cases v₁, cases v₂, unfold product, apply list.mem_of_mem_product_left end
theorem mem_of_mem_product_right {n m : nat} {a : A} {b : B} {v₁ : fixed_list A n} {v₂ : fixed_list B m} : (a, b) ∈ product v₁ v₂ → b ∈ v₂ := theorem mem_of_mem_product_right {n m : nat} {a : A} {b : B} {v₁ : tuple A n} {v₂ : tuple B m} : (a, b) ∈ product v₁ v₂ → b ∈ v₂ :=
begin cases v₁, cases v₂, unfold product, apply list.mem_of_mem_product_right end begin cases v₁, cases v₂, unfold product, apply list.mem_of_mem_product_right end
/- ith -/ /- ith -/
open fin open fin
definition ith {n : nat} : fixed_list A n → fin n → A definition ith {n : nat} : tuple A n → fin n → A
| (tag l h₁) (mk i h₂) := list.ith l i (by rewrite h₁; exact h₂) | (tag l h₁) (mk i h₂) := list.ith l i (by rewrite h₁; exact h₂)
lemma ith_zero {n : nat} (a : A) (v : fixed_list A n) (h : 0 < succ n) : ith (a::v) (mk 0 h) = a := lemma ith_zero {n : nat} (a : A) (v : tuple A n) (h : 0 < succ n) : ith (a::v) (mk 0 h) = a :=
by induction v; reflexivity by induction v; reflexivity
lemma ith_fin_zero {n : nat} (a : A) (v : fixed_list A n) : ith (a::v) (zero n) = a := lemma ith_fin_zero {n : nat} (a : A) (v : tuple A n) : ith (a::v) (zero n) = a :=
by unfold zero; apply ith_zero by unfold zero; apply ith_zero
lemma ith_succ {n : nat} (a : A) (v : fixed_list A n) (i : nat) (h : succ i < succ n) lemma ith_succ {n : nat} (a : A) (v : tuple A n) (i : nat) (h : succ i < succ n)
: ith (a::v) (mk (succ i) h) = ith v (mk_pred i h) := : ith (a::v) (mk (succ i) h) = ith v (mk_pred i h) :=
by induction v; reflexivity by induction v; reflexivity
lemma ith_fin_succ {n : nat} (a : A) (v : fixed_list A n) (i : fin n) lemma ith_fin_succ {n : nat} (a : A) (v : tuple A n) (i : fin n)
: ith (a::v) (succ i) = ith v i := : ith (a::v) (succ i) = ith v i :=
begin cases i, unfold fin.succ, rewrite ith_succ end begin cases i, unfold fin.succ, rewrite ith_succ end
lemma ith_zero_eq_head {n : nat} (v : fixed_list A (nat.succ n)) : ith v (zero n) = head v := lemma ith_zero_eq_head {n : nat} (v : tuple A (nat.succ n)) : ith v (zero n) = head v :=
by rewrite [-eta v, ith_fin_zero, head_cons] by rewrite [-eta v, ith_fin_zero, head_cons]
lemma ith_succ_eq_ith_tail {n : nat} (v : fixed_list A (nat.succ n)) (i : fin n) : ith v (succ i) = ith (tail v) i := lemma ith_succ_eq_ith_tail {n : nat} (v : tuple A (nat.succ n)) (i : fin n) : ith v (succ i) = ith (tail v) i :=
by rewrite [-eta v, ith_fin_succ, tail_cons] by rewrite [-eta v, ith_fin_succ, tail_cons]
protected lemma ext {n : nat} (v₁ v₂ : fixed_list A n) (h : ∀ i : fin n, ith v₁ i = ith v₂ i) : v₁ = v₂ := protected lemma ext {n : nat} (v₁ v₂ : tuple A n) (h : ∀ i : fin n, ith v₁ i = ith v₂ i) : v₁ = v₂ :=
begin begin
induction n with n ih, induction n with n ih,
rewrite [fixed_list0_eq_nil v₁, fixed_list0_eq_nil v₂], rewrite [tuple0_eq_nil v₁, tuple0_eq_nil v₂],
rewrite [-eta v₁, -eta v₂], congruence, rewrite [-eta v₁, -eta v₂], congruence,
show head v₁ = head v₂, by rewrite [-ith_zero_eq_head, -ith_zero_eq_head]; apply h, show head v₁ = head v₂, by rewrite [-ith_zero_eq_head, -ith_zero_eq_head]; apply h,
have ∀ i : fin n, ith (tail v₁) i = ith (tail v₂) i, from have ∀ i : fin n, ith (tail v₁) i = ith (tail v₂) i, from
@ -257,7 +257,7 @@ namespace fixed_list
/- tabulate -/ /- tabulate -/
definition tabulate : Π {n : nat}, (fin n → A) → fixed_list A n definition tabulate : Π {n : nat}, (fin n → A) → tuple A n
| 0 f := nil | 0 f := nil
| (n+1) f := f (@zero n) :: tabulate (λ i : fin n, f (succ i)) | (n+1) f := f (@zero n) :: tabulate (λ i : fin n, f (succ i))
@ -269,4 +269,4 @@ namespace fixed_list
{unfold tabulate, rewrite ith_zero}, {unfold tabulate, rewrite ith_zero},
{unfold tabulate, rewrite [ith_succ, ih]} {unfold tabulate, rewrite [ith_succ, ih]}
end end
end fixed_list end tuple