lean4-htt/tmp/eqns/matchArrayLit.lean
2020-03-13 06:39:13 -07:00

193 lines
7.4 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

universes u v
namespace Experiment1
inductive ArrayLitMatch (α : Type u)
| sz0 {} : ArrayLitMatch
| sz1 (a₁ : α) : ArrayLitMatch
| sz2 (a₁ a₂ : α) : ArrayLitMatch
| sz3 (a₁ a₂ a₃ : α) : ArrayLitMatch
| other {} : ArrayLitMatch
def matchArrayLit {α : Type u} (a : Array α) : ArrayLitMatch α :=
if a.size = 0 then
ArrayLitMatch.sz0
else if h : a.size = 1 then
ArrayLitMatch.sz1 (a.getLit 0 h (ofDecideEqTrue rfl))
else if h : a.size = 2 then
ArrayLitMatch.sz2 (a.getLit 0 h (ofDecideEqTrue rfl)) (a.getLit 1 h (ofDecideEqTrue rfl))
else if h : a.size = 3 then
ArrayLitMatch.sz3 (a.getLit 0 h (ofDecideEqTrue rfl)) (a.getLit 1 h (ofDecideEqTrue rfl)) (a.getLit 2 h (ofDecideEqTrue rfl))
else
ArrayLitMatch.other
def matchArrayLit.eq0 {α : Type u} : matchArrayLit (#[] : Array α) = ArrayLitMatch.sz0 :=
rfl
def matchArrayLit.eq1 {α : Type u} (a₁ : α) : matchArrayLit #[a₁] = ArrayLitMatch.sz1 a₁ :=
rfl
def matchArrayLit.eq2 {α : Type u} (a₁ a₂ : α) : matchArrayLit #[a₁, a₂] = ArrayLitMatch.sz2 a₁ a₂ :=
rfl
def matchArrayLit.eq3 {α : Type u} (a₁ a₂ a₃ : α) : matchArrayLit #[a₁, a₂, a₃] = ArrayLitMatch.sz3 a₁ a₂ a₃ :=
rfl
def matchArrayLit.eq4 {α : Type u} (a₁ a₂ a₃ a₄ : α) : matchArrayLit #[a₁, a₂, a₃, a₄] = ArrayLitMatch.other :=
rfl
end Experiment1
def toListLitAux {α : Type u} (a : Array α) (n : Nat) (hsz : a.size = n) : ∀ (i : Nat), i ≤ a.size → List α → List α
| 0, hi, acc => acc
| (i+1), hi, acc => toListLitAux i (Nat.leOfSuccLe hi) (a.getLit i hsz (Nat.ltOfLtOfEq (Nat.ltOfLtOfLe (Nat.ltSuccSelf i) hi) hsz) :: acc)
def toArrayLit {α : Type u} (a : Array α) (n : Nat) (hsz : a.size = n) : Array α :=
List.toArray $ toListLitAux a n hsz n (hsz ▸ Nat.leRefl _) []
theorem toArrayLitEq {α : Type u} (a : Array α) (n : Nat) (hsz : a.size = n) : a = toArrayLit a n hsz :=
-- TODO: this is painful to prove without proper automation
sorry
/-
First, we need to prove
∀ i j acc, i ≤ a.size → (toListLitAux a n hsz (i+1) hi acc).index j = if j < i then a.getLit j hsz _ else acc.index (j - i)
by induction
Base case is trivial
(j : Nat) (acc : List α) (hi : 0 ≤ a.size)
|- (toListLitAux a n hsz 0 hi acc).index j = if j < 0 then a.getLit j hsz _ else acc.index (j - 0)
... |- acc.index j = acc.index j
Induction
(j : Nat) (acc : List α) (hi : i+1 ≤ a.size)
|- (toListLitAux a n hsz (i+1) hi acc).index j = if j < i + 1 then a.getLit j hsz _ else acc.index (j - (i + 1))
... |- (toListLitAux a n hsz i hi' (a.getLit i hsz _ :: acc)).index j = if j < i + 1 then a.getLit j hsz _ else acc.index (j - (i + 1)) * by def
... |- if j < i then a.getLit j hsz _ else (a.getLit i hsz _ :: acc).index (j-i) * by induction hypothesis
=
if j < i + 1 then a.getLit j hsz _ else acc.index (j - (i + 1))
If j < i, then both are a.getLit j hsz _
If j = i, then lhs reduces else-branch to (a.getLit i hsz _) and rhs is then-brachn (a.getLit i hsz _)
If j >= i + 1, we use
- j - i >= 1 > 0
- (a::as).index k = as.index (k-1) If k > 0
- j - (i + 1) = (j - i) - 1
Then lhs = (a.getLit i hsz _ :: acc).index (j-i) = acc.index (j-i-1) = acc.index (j-(i+1)) = rhs
With this proof, we have
∀ j, j < n → (toListLitAux a n hsz n _ []).index j = a.getLit j hsz _
We also need
- (toListLitAux a n hsz n _ []).length = n
- j < n -> (List.toArray as).getLit j _ _ = as.index j
Then using Array.extLit, we have that a = List.toArray $ toListLitAux a n hsz n _ []
-/
theorem Array.eqLitOfSize0 {α : Type u} (a : Array α) (hsz : a.size = 0) : a = #[] :=
toArrayLitEq a 0 hsz
/-
Array.ext a #[] h (fun i h₁ h₂ => absurd h₂ (Nat.notLtZero _))
-/
theorem Array.eqLitOfSize1 {α : Type u} (a : Array α) (hsz : a.size = 1) : a = #[a.getLit 0 hsz (ofDecideEqTrue rfl)] :=
toArrayLitEq a 1 hsz
/-
Array.extLit a #[a.getLit 0 hsz (ofDecideEqTrue rfl)] hsz rfl $ fun i =>
match i with
| 0 => fun hi => rfl
| (n+1) => fun hi =>
have n < 0 from hi;
absurd this (Nat.notLtZero _)
-/
theorem Array.eqLitOfSize2 {α : Type u} (a : Array α) (hsz : a.size = 2) : a = #[a.getLit 0 hsz (ofDecideEqTrue rfl), a.getLit 1 hsz (ofDecideEqTrue rfl)] :=
toArrayLitEq a 2 hsz
/-
Array.extLit a #[a.getLit 0 hsz (ofDecideEqTrue rfl), a.getLit 1 hsz (ofDecideEqTrue rfl)] hsz rfl $ fun i =>
match i with
| 0 => fun hi => rfl
| 1 => fun hi => rfl
| (n+2) => fun hi =>
have n < 0 from hi;
absurd this (Nat.notLtZero _)
-/
theorem Array.eqLitOfSize3 {α : Type u} (a : Array α) (hsz : a.size = 3) :
a = #[a.getLit 0 hsz (ofDecideEqTrue rfl), a.getLit 1 hsz (ofDecideEqTrue rfl), a.getLit 2 hsz (ofDecideEqTrue rfl)] :=
toArrayLitEq a 3 hsz
/-
Array.extLit a #[a.getLit 0 hsz (ofDecideEqTrue rfl), a.getLit 1 hsz (ofDecideEqTrue rfl), a.getLit 2 hsz (ofDecideEqTrue rfl)] hsz rfl $ fun i =>
match i with
| 0 => fun hi => rfl
| 1 => fun hi => rfl
| 2 => fun hi => rfl
| (n+3) => fun hi =>
have n < 0 from hi;
absurd this (Nat.notLtZero _)
-/
/-
Matcher for the following patterns
```
| #[] => _
| #[a₁] => _
| #[a₁, a₂, a₃] => _
| a => _
``` -/
def matchArrayLit {α : Type u} (C : Array α → Sort v) (a : Array α)
(h₁ : Unit → C #[])
(h₂ : ∀ a₁, C #[a₁])
(h₃ : ∀ a₁ a₂ a₃, C #[a₁, a₂, a₃])
(h₄ : ∀ a, C a)
: C a :=
if h : a.size = 0 then
@Eq.rec _ _ (fun x _ => C x) (h₁ ()) _ (toArrayLitEq a 0 h).symm
else if h : a.size = 1 then
@Eq.rec _ _ (fun x _ => C x) (h₂ (a.getLit 0 h (ofDecideEqTrue rfl))) _ (toArrayLitEq a 1 h).symm
else if h : a.size = 3 then
@Eq.rec _ _ (fun x _ => C x) (h₃ (a.getLit 0 h (ofDecideEqTrue rfl)) (a.getLit 1 h (ofDecideEqTrue rfl)) (a.getLit 2 h (ofDecideEqTrue rfl))) _ (toArrayLitEq a 3 h).symm
else
h₄ a
/- Equational lemmas that should be generated automatically. -/
theorem matchArrayLit.eq1 {α : Type u} (C : Array α → Sort v)
(h₁ : Unit → C #[])
(h₂ : ∀ a₁, C #[a₁])
(h₃ : ∀ a₁ a₂ a₃, C #[a₁, a₂, a₃])
(h₄ : ∀ a, C a)
: matchArrayLit C #[] h₁ h₂ h₃ h₄ = h₁ () :=
rfl
theorem matchArrayLit.eq2 {α : Type u} (C : Array α → Sort v)
(h₁ : Unit → C #[])
(h₂ : ∀ a₁, C #[a₁])
(h₃ : ∀ a₁ a₂ a₃, C #[a₁, a₂, a₃])
(h₄ : ∀ a, C a)
(a₁ : α)
: matchArrayLit C #[a₁] h₁ h₂ h₃ h₄ = h₂ a₁ :=
rfl
theorem matchArrayLit.eq3 {α : Type u} (C : Array α → Sort v)
(h₁ : Unit → C #[])
(h₂ : ∀ a₁, C #[a₁])
(h₃ : ∀ a₁ a₂ a₃, C #[a₁, a₂, a₃])
(h₄ : ∀ a, C a)
(a₁ a₂ a₃ : α)
: matchArrayLit C #[a₁, a₂, a₃] h₁ h₂ h₃ h₄ = h₃ a₁ a₂ a₃ :=
rfl
theorem matchArrayLit.eq4 {α : Type u} (C : Array α → Sort v)
(h₁ : Unit → C #[])
(h₂ : ∀ a₁, C #[a₁])
(h₃ : ∀ a₁ a₂ a₃, C #[a₁, a₂, a₃])
(h₄ : ∀ a, C a)
(a : Array α)
(n₁ : a.size ≠ 0) (n₂ : a.size ≠ 1) (n₃ : a.size ≠ 3)
: matchArrayLit C a h₁ h₂ h₃ h₄ = h₄ a :=
match a, n₁, n₂, n₃ with
| ⟨0, _⟩, n₁, _, _ => absurd rfl n₁
| ⟨1, _⟩, _, n₂, _ => absurd rfl n₂
| ⟨2, _⟩, _, _, _ => rfl
| ⟨3, _⟩, _, _, n₃ => absurd rfl n₃
| ⟨n+4, _⟩, _, _, _ => rfl