2014-09-05 16:45:01 +00:00
|
|
|
|
-- Copyright (c) 2014 Floris van Doorn. All rights reserved.
|
|
|
|
|
-- Released under Apache 2.0 license as described in the file LICENSE.
|
2014-11-12 06:33:47 +00:00
|
|
|
|
-- Author: Floris van Doorn, Leonardo de Moura
|
|
|
|
|
import data.nat.basic data.empty data.prod
|
|
|
|
|
open nat eq.ops prod
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-09-19 23:15:04 +00:00
|
|
|
|
inductive vector (T : Type) : ℕ → Type :=
|
|
|
|
|
nil {} : vector T 0,
|
|
|
|
|
cons : T → ∀{n}, vector T n → vector T (succ n)
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-09-19 23:15:04 +00:00
|
|
|
|
namespace vector
|
2014-10-21 21:08:07 +00:00
|
|
|
|
notation a :: b := cons a b
|
2014-09-05 16:45:01 +00:00
|
|
|
|
notation `[` l:(foldr `,` (h t, cons h t) nil) `]` := l
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
variables {A B C : Type}
|
|
|
|
|
variables {n m : nat}
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
protected definition is_inhabited [instance] (H : inhabited A) (n : nat) : inhabited (vector A n) :=
|
2014-09-08 02:06:03 +00:00
|
|
|
|
nat.rec_on n
|
2014-11-12 06:33:47 +00:00
|
|
|
|
(inhabited.mk nil)
|
2014-09-19 23:15:04 +00:00
|
|
|
|
(λ (n : nat) (iH : inhabited (vector A n)),
|
2014-09-08 02:06:03 +00:00
|
|
|
|
inhabited.destruct H
|
|
|
|
|
(λa, inhabited.destruct iH
|
2014-11-12 06:33:47 +00:00
|
|
|
|
(λv, inhabited.mk (a :: v))))
|
2014-09-08 02:06:03 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem z_cases_on {C : vector A 0 → Type} (v : vector A 0) (Hnil : C nil) : C v :=
|
2014-11-29 07:19:53 +00:00
|
|
|
|
begin
|
|
|
|
|
cases v,
|
|
|
|
|
apply Hnil
|
|
|
|
|
end
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem vector0_eq_nil (v : vector A 0) : v = nil :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
z_cases_on v rfl
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
protected definition destruct (v : vector A (succ n)) {P : Π {n : nat}, vector A (succ n) → Type}
|
2014-11-12 06:33:47 +00:00
|
|
|
|
(H : Π {n : nat} (h : A) (t : vector A n), P (h :: t)) : P v :=
|
2014-11-29 07:19:53 +00:00
|
|
|
|
begin
|
|
|
|
|
cases v with (h', n', t'),
|
|
|
|
|
apply (H h' t')
|
|
|
|
|
end
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
|
|
|
|
definition nz_cases_on := @destruct
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
definition head (v : vector A (succ n)) : A :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
destruct v (λ n h t, h)
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
definition tail (v : vector A (succ n)) : vector A n :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
destruct v (λ n h t, t)
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem head_cons (h : A) (t : vector A n) : head (h :: t) = h :=
|
2014-11-16 04:21:18 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem tail_cons (h : A) (t : vector A n) : tail (h :: t) = t :=
|
2014-11-16 04:21:18 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem eta (v : vector A (succ n)) : head v :: tail v = v :=
|
2014-12-04 05:06:17 +00:00
|
|
|
|
destruct v (λ n h t, rfl)
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
definition last : vector A (succ n) → A :=
|
2014-11-16 04:21:18 +00:00
|
|
|
|
nat.rec_on n
|
|
|
|
|
(λ (v : vector A (succ zero)), head v)
|
|
|
|
|
(λ n₁ r v, r (tail v))
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem last_singleton (a : A) : last (a :: nil) = a :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem last_cons (a : A) (v : vector A (succ n)) : last (a :: v) = last v :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
definition const (n : nat) (a : A) : vector A n :=
|
2014-11-16 04:21:18 +00:00
|
|
|
|
nat.rec_on n
|
|
|
|
|
nil
|
|
|
|
|
(λ n₁ r, a :: r)
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem head_const (n : nat) (a : A) : head (const (succ n) a) = a :=
|
2014-11-16 04:21:18 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem last_const (n : nat) (a : A) : last (const (succ n) a) = a :=
|
2014-11-16 04:21:18 +00:00
|
|
|
|
nat.induction_on n
|
|
|
|
|
rfl
|
|
|
|
|
(λ n₁ ih, ih)
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
definition map (f : A → B) (v : vector A n) : vector B n :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
nat.rec_on n
|
|
|
|
|
(λ v, nil)
|
|
|
|
|
(λ n₁ r v, f (head v) :: r (tail v))
|
|
|
|
|
v
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem map_vnil (f : A → B) : map f nil = nil :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem map_vcons (f : A → B) (h : A) (t : vector A n) : map f (h :: t) = f h :: map f t :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
definition map2 (f : A → B → C) (v₁ : vector A n) (v₂ : vector B n) : vector C n :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
nat.rec_on n
|
|
|
|
|
(λ v₁ v₂, nil)
|
|
|
|
|
(λ n₁ r v₁ v₂, f (head v₁) (head v₂) :: r (tail v₁) (tail v₂))
|
|
|
|
|
v₁ v₂
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem map2_vnil (f : A → B → C) : map2 f nil nil = nil :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem map2_vcons (f : A → B → C) (h₁ : A) (h₂ : B) (t₁ : vector A n) (t₂ : vector B n) :
|
2014-11-12 06:33:47 +00:00
|
|
|
|
map2 f (h₁ :: t₁) (h₂ :: t₂) = f h₁ h₂ :: map2 f t₁ t₂ :=
|
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-18 05:58:42 +00:00
|
|
|
|
definition append (w : vector A n) (v : vector A m) : vector A (n ⊕ m) :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rec_on w
|
|
|
|
|
v
|
2014-11-18 05:58:42 +00:00
|
|
|
|
(λ (a₁ : A) (n₁ : nat) (v₁ : vector A n₁) (r₁ : vector A (n₁ ⊕ m)), a₁ :: r₁)
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
2014-11-18 05:58:42 +00:00
|
|
|
|
theorem append_nil (v : vector A n) : append nil v = v :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-18 05:58:42 +00:00
|
|
|
|
theorem append_cons (h : A) (t : vector A n) (v : vector A m) :
|
|
|
|
|
append (h :: t) v = h :: (append t v) :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
definition unzip : vector (A × B) n → vector A n × vector B n :=
|
2014-11-16 06:19:23 +00:00
|
|
|
|
nat.rec_on n
|
|
|
|
|
(λ v, (nil, nil))
|
|
|
|
|
(λ a r v,
|
|
|
|
|
let t := r (tail v) in
|
|
|
|
|
(pr₁ (head v) :: pr₁ t, pr₂ (head v) :: pr₂ t))
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
definition zip : vector A n → vector B n → vector (A × B) n :=
|
2014-11-16 06:19:23 +00:00
|
|
|
|
nat.rec_on n
|
|
|
|
|
(λ v₁ v₂, nil)
|
|
|
|
|
(λ a r v₁ v₂, (head v₁, head v₂) :: r (tail v₁) (tail v₂))
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem unzip_zip : ∀ (v₁ : vector A n) (v₂ : vector B n), unzip (zip v₁ v₂) = (v₁, v₂) :=
|
2014-11-16 06:19:23 +00:00
|
|
|
|
nat.induction_on n
|
|
|
|
|
(λ (v₁ : vector A zero) (v₂ : vector B zero),
|
|
|
|
|
z_cases_on v₁ (z_cases_on v₂ rfl))
|
|
|
|
|
(λ (n₁ : nat) (ih : ∀ (v₁ : vector A n₁) (v₂ : vector B n₁), unzip (zip v₁ v₂) = (v₁, v₂))
|
|
|
|
|
(v₁ : vector A (succ n₁)) (v₂ : vector B (succ n₁)), calc
|
|
|
|
|
unzip (zip v₁ v₂) = unzip ((head v₁, head v₂) :: zip (tail v₁) (tail v₂)) : rfl
|
|
|
|
|
... = (head v₁ :: pr₁ (unzip (zip (tail v₁) (tail v₂))),
|
|
|
|
|
head v₂ :: pr₂ (unzip (zip (tail v₁) (tail v₂)))) : rfl
|
|
|
|
|
... = (head v₁ :: pr₁ (tail v₁, tail v₂),
|
|
|
|
|
head v₂ :: pr₂ (tail v₁, tail v₂)) : ih
|
|
|
|
|
... = (head v₁ :: tail v₁, head v₂ :: tail v₂) : rfl
|
|
|
|
|
... = (v₁, head v₂ :: tail v₂) : vector.eta
|
|
|
|
|
... = (v₁, v₂) : vector.eta)
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem zip_unzip : ∀ (v : vector (A × B) n), zip (pr₁ (unzip v)) (pr₂ (unzip v)) = v :=
|
2014-11-16 06:19:23 +00:00
|
|
|
|
nat.induction_on n
|
|
|
|
|
(λ (v : vector (A × B) zero),
|
|
|
|
|
z_cases_on v rfl)
|
|
|
|
|
(λ (n₁ : nat) (ih : ∀ v, zip (pr₁ (unzip v)) (pr₂ (unzip v)) = v) (v : vector (A × B) (succ n₁)), calc
|
|
|
|
|
zip (pr₁ (unzip v)) (pr₂ (unzip v)) = zip (pr₁ (head v) :: pr₁ (unzip (tail v)))
|
|
|
|
|
(pr₂ (head v) :: pr₂ (unzip (tail v))) : rfl
|
|
|
|
|
... = (pr₁ (head v), pr₂ (head v)) :: zip (pr₁ (unzip (tail v))) (pr₂ (unzip (tail v))) : rfl
|
|
|
|
|
... = (pr₁ (head v), pr₂ (head v)) :: tail v : ih
|
|
|
|
|
... = head v :: tail v : prod.eta
|
|
|
|
|
... = v : vector.eta)
|
|
|
|
|
|
2014-09-05 16:45:01 +00:00
|
|
|
|
-- Length
|
|
|
|
|
-- ------
|
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
definition length (v : vector A n) :=
|
|
|
|
|
n
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem length_nil : length (@nil A) = 0 :=
|
|
|
|
|
rfl
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem length_cons (a : A) (v : vector A n) : length (a :: v) = succ (length v) :=
|
|
|
|
|
rfl
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem length_append (v₁ : vector A n) (v₂ : vector A m) : length (append v₁ v₂) = length v₁ + length v₂ :=
|
2014-11-18 05:58:42 +00:00
|
|
|
|
calc length (append v₁ v₂) = length v₁ ⊕ length v₂ : rfl
|
|
|
|
|
... = length v₁ + length v₂ : add_eq_addl
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
-- Concat
|
|
|
|
|
-- ------
|
|
|
|
|
definition concat (v : vector A n) (a : A) : vector A (succ n) :=
|
|
|
|
|
vector.rec_on v
|
|
|
|
|
(a :: nil)
|
|
|
|
|
(λ h n t r, h :: r)
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem concat_nil (a : A) : concat nil a = a :: nil :=
|
|
|
|
|
rfl
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem last_concat (v : vector A n) (a : A) : last (concat v a) = a :=
|
|
|
|
|
vector.induction_on v
|
|
|
|
|
rfl
|
|
|
|
|
(λ h n t ih, calc
|
2014-11-29 07:49:17 +00:00
|
|
|
|
last (concat (h :: t) a) = last (concat t a) : rfl
|
2014-11-29 07:19:53 +00:00
|
|
|
|
... = a : ih)
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-09-19 23:15:04 +00:00
|
|
|
|
end vector
|