lean4-htt/tests/playground/partial_eq_lemma.lean
Leonardo de Moura 829a50ccf7 test(tests/playground/partial_eq_lemma): partial equation lemmas
@kha I added this example as a template for what the equation compiler
will have to do. The plan is:
- We can use `partial` to define any function if the result type is
inhabited.
- If the result type is of the form `Partial a`, the equation compiler
generates lemmas of the form:

```
theorem fooEq args : terminates (foo args) → foo args = lhs
```
The new test contains an example.
2019-03-26 18:06:04 -07:00

78 lines
4 KiB
Text
Raw Permalink 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
inductive Partial (α : Type u)
| val (a : α) : Partial
| bot {} : Partial
def terminates {α : Type u} (p : Partial α) : Prop := p ≠ Partial.bot
def fooAux (s : String) (c : Char) : Nat → String.Pos → Partial String.Pos
| 0 i := Partial.bot
| (Nat.succ k) i :=
if s.atEnd i then Partial.val i
else if s.get i == c then Partial.val i
else fooAux k (s.next i)
theorem fooAuxEqSucc (s : String) (c : Char) : ∀ (k : Nat) (i : String.Pos), terminates (fooAux s c k i) → fooAux s c k.succ i = fooAux s c k i
| 0 i ht := absurd rfl ht
| (Nat.succ k) i ht :=
show (fooAux s c k.succ.succ i = fooAux s c k.succ i), from
Decidable.byCases
(λ h : s.atEnd i,
have h₁ : fooAux s c (k.succ.succ) i = Partial.val i, from ifPos h,
have h₂ : fooAux s c k.succ i = Partial.val i, from ifPos h,
Eq.trans h₁ h₂.symm)
(λ h : ¬ s.atEnd i,
Decidable.byCases
(λ h' : s.get i == c,
have h₁ : fooAux s c (k.succ.succ) i = Partial.val i, from Eq.trans (ifNeg h) (ifPos h'),
have h₂ : fooAux s c k.succ i = Partial.val i, from Eq.trans (ifNeg h) (ifPos h'),
Eq.trans h₁ h₂.symm)
(λ h' : ¬ s.get i == c,
have h₁ : fooAux s c (k.succ.succ) i = fooAux s c k.succ (s.next i), from Eq.trans (ifNeg h) (ifNeg h'),
have h₂ : fooAux s c k.succ i = fooAux s c k (s.next i), from Eq.trans (ifNeg h) (ifNeg h'),
have h₃ : fooAux s c k (s.next i) ≠ Partial.bot, from h₂ ▸ ht,
have ih : fooAux s c k.succ (s.next i) = fooAux s c k (s.next i), from fooAuxEqSucc k _ h₃,
Eq.trans h₁ (Eq.trans ih h₂.symm)))
theorem fooAuxTermSucc (s : String) (c : Char) (k : Nat) (i : String.Pos)
(h₁ : terminates (fooAux s c k.succ i)) (h₂ : ¬ (s.atEnd i)) (h₃ : ¬ (s.get i == c)) : terminates (fooAux s c k (s.next i)) :=
have (fooAux s c k.succ i) = fooAux s c k (s.next i), from Eq.trans (ifNeg h₂) (ifNeg h₃),
this ▸ h₁
constant bigNat : Nat := 1000000
def foo (s : String) (c : Char) (i : String.Pos) : Partial String.Pos :=
fooAux s c bigNat i
theorem fooEq (s : String) (c : Char) (i : String.Pos) :
terminates (foo s c i) →
foo s c i = if s.atEnd i then Partial.val i
else if s.get i == c then Partial.val i
else foo s c (s.next i) :=
show terminates (fooAux s c bigNat i) → fooAux s c bigNat i = (if s.atEnd i then Partial.val i
else if s.get i == c then Partial.val i
else fooAux s c bigNat (s.next i)), from
Nat.casesOn bigNat
(λ h : fooAux s c 0 i ≠ Partial.bot, absurd rfl h)
(λ N h,
have h₁ : fooAux s c N.succ i = (if s.atEnd i then Partial.val i
else if s.get i == c then Partial.val i
else fooAux s c N (s.next i)), from rfl,
Decidable.byCases
(λ c₁ : s.atEnd i,
have aux₁ : fooAux s c N.succ i = Partial.val i, from ifPos c₁,
have aux₂ : ite (String.atEnd s i) (Partial.val i)
(ite (String.get s i == c) (Partial.val i) (fooAux s c (Nat.succ N) (String.next s i))) = Partial.val i, from ifPos c₁,
Eq.trans aux₁ aux₂.symm)
(λ c₁ : ¬ s.atEnd i,
Decidable.byCases
(λ c₂ : s.get i == c,
have aux₁ : fooAux s c N.succ i = Partial.val i, from Eq.trans (ifNeg c₁) (ifPos c₂),
have aux₂ : ite (String.atEnd s i) (Partial.val i)
(ite (String.get s i == c) (Partial.val i) (fooAux s c (Nat.succ N) (String.next s i))) = Partial.val i, from Eq.trans (ifNeg c₁) (ifPos c₂),
Eq.trans aux₁ aux₂.symm)
(λ c₂ : ¬ s.get i == c,
have h₂ : terminates (fooAux s c N (s.next i)), from fooAuxTermSucc _ _ _ _ h c₁ c₂,
have h₃ : fooAux s c N (s.next i) = fooAux s c N.succ (s.next i), from (fooAuxEqSucc _ _ _ _ h₂).symm,
h₃ ▸ h₁)))