Zulip Chat Archive
Stream: new members
Topic: Lean infering wrong induction hypothesis
Do Nhat Minh (Jun 15 2019 at 18:48):
I'm proving the following theorem in Lean.
theorem progress {t T} (ht : has_type context.empty t T) : value t ∨ ∃t', t -+> t' := begin induction t, case tm.var: { exact false.elim (var_not_has_type_empty_context ht) }, case tm.abs: { exact or.inl v_abs }, case tm.app: t₁ t₂ ih₁ ih₂ { sorry, }, case tm.tru: { exact or.inl v_tru }, case tm.fls: { exact or.inl v_fls }, case tm.tst: t₁ t₂ t₃ ih₁ ih₂ ih₃ { sorry, }, end
If I remove sorry
in case tm.app
, Lean tells me that ih₁
has type has_type context.empty t₁ T -> value t₁ ∨ ∃t', t₁ -+> t'
, which is wrong.
The definitions for ty
, tm
, value
, and has_type
can be found here.
Can anyone please give me a hint on how to proceed?
Kenny Lau (Jun 15 2019 at 19:01):
why is it wrong?
Kenny Lau (Jun 15 2019 at 19:03):
inductive tm : Type | var : string -> tm | app : tm -> tm -> tm | abs : string -> ty -> tm -> tm | tru : tm | fls : tm | tst : tm -> tm -> tm -> tm
in particular | app : tm -> tm -> tm
, so case tm.app
reads "t
is now tm.app t1 t2
where t1
and t2
satisfy the proposition, and we prove that t
also satisfies the proposition"
Kenny Lau (Jun 15 2019 at 19:03):
the proposition of course being has_type context.empty t T -> value t or exists t', t -+> t'
Do Nhat Minh (Jun 15 2019 at 19:04):
it should have type has_type context.empty t₁ (arrow T₁ T₂) -> value t₁ ∨ ∃t', t₁ -+> t'
Do Nhat Minh (Jun 15 2019 at 19:04):
how should I change the definition of tm
to make that happen?
Kenny Lau (Jun 15 2019 at 19:05):
you should induct on ht
instead
Do Nhat Minh (Jun 15 2019 at 19:06):
I'm translating the definition in Coq found here to Lean and I'm not doing a good job at it
Do Nhat Minh (Jun 15 2019 at 19:08):
induction on ht
also gives me wrong hypotheses, such as a new context
(named ht_context
) for case has_type.t_var
Do Nhat Minh (Jun 15 2019 at 19:10):
(deleted)
Kenny Lau (Jun 15 2019 at 19:20):
theorem progress {t T} (ht : has_type context.empty t T) : value t ∨ ∃t', t -+> t' := begin revert ht, generalize he : context.empty = e, intro ht, induction ht, case has_type.t_var : e s t ht { rw ← he at ht, cases ht }, case has_type.t_abs : { left, constructor }, case has_type.t_app : e t₁ t₂ m₁ m₂ h₁ h₂ h₃ h₄ { sorry }, case has_type.t_tru : { left, constructor }, case has_type.t_fls : { left, constructor }, case has_type.t_tst : { sorry } end
Do Nhat Minh (Jun 15 2019 at 19:25):
Could you please explain what revert and generalize does?
Marc Huisinga (Jun 15 2019 at 19:27):
revert and generalize are also explained here: https://leanprover.github.io/theorem_proving_in_lean/tactics.html#basic-tactics
Kenny Lau (Jun 15 2019 at 19:30):
@Do Nhat Minh you can compare the state before and after those tactics
Kenny Lau (Jun 15 2019 at 19:31):
theorem progress {t T} (ht : has_type context.empty t T) : value t ∨ ∃t', t -+> t' := begin /- state 1 -/ revert ht, /- state 2 -/ generalize he : context.empty = e, /- state 3 -/ intro ht, induction ht, case has_type.t_var : e s t ht { rw ← he at ht, cases ht }, case has_type.t_abs : { left, constructor }, case has_type.t_app : e t₁ t₂ m₁ m₂ h₁ h₂ h₃ h₄ { sorry }, case has_type.t_tru : { left, constructor }, case has_type.t_fls : { left, constructor }, case has_type.t_tst : { sorry } end
Kenny Lau (Jun 15 2019 at 19:31):
state 1:
1 goal t : tm, T : ty, ht : has_type context.empty t T ⊢ value t ∨ ∃ (t' : tm), t -+> t'
state 2:
1 goal t : tm, T : ty ⊢ has_type context.empty t T → (value t ∨ ∃ (t' : tm), t -+> t')
state 3:
1 goal t : tm, T : ty, e : context, he : context.empty = e ⊢ has_type e t T → (value t ∨ ∃ (t' : tm), t -+> t')
Kenny Lau (Jun 15 2019 at 20:02):
theorem progress {t T} (ht : has_type context.empty t T) : value t ∨ ∃t', t -+> t' := begin revert ht, generalize he : context.empty = e, intro ht, induction ht, case has_type.t_var : e s t ht { rw ← he at ht, cases ht }, case has_type.t_abs : { left, constructor }, case has_type.t_app : e t₁ t₂ m₁ m₂ h₁ h₂ h₃ h₄ { cases h₃ he with h₅ h₅, cases h₄ he with h₆ h₆, { cases h₅; cases h₁, right, existsi _, exact step.st_appabs h₆ }, { cases h₆ with t' h₆, right, existsi _, exact step.st_app2 h₅ h₆ }, { cases h₅ with t' h₅, right, existsi _, exact step.st_app1 h₅ } }, case has_type.t_tru : { left, constructor }, case has_type.t_fls : { left, constructor }, case has_type.t_tst : e y t₁ t₂ t₃ h₁ h₂ h₃ h₄ h₅ h₆ { sorry } end
Do Nhat Minh (Jun 16 2019 at 04:43):
Thanks, @Kenny Lau !
Do Nhat Minh (Jun 16 2019 at 04:43):
That helps!
Do Nhat Minh (Jun 16 2019 at 04:43):
Thanks for the pointer, @Marc Huisinga
Do Nhat Minh (Jun 16 2019 at 04:44):
I've read the whole book but the explanation for generalize
is not clear to me
Mario Carneiro (Jun 16 2019 at 05:45):
If you want to prove P foo
, it suffices to prove \forall x, P x
. generalize : foo = x
will do that. Similarly, it suffices to prove \forall x, foo = x -> P x
, and generalize h : foo = x
will do that (introducing x
and h : foo = x
).
Do Nhat Minh (Jun 16 2019 at 14:42):
That really helps! Thanks, @Mario Carneiro !
Last updated: Dec 20 2023 at 11:08 UTC