I am doing some exercises about formalizing simply-typed lambda calculus in Coq and would like to automate my proofs using Ltac. While proving progress theorem:
Theorem progress : forall t T,
empty |-- t \in T -> value t \/ exists t', t ==> t'.
I came up with this piece of Ltac code:
Ltac progress_when_stepping :=
(* right, because progress statement places stepping on the right of \/ *)
right;
(* use induction hypotheses *)
repeat
match goal with
| [ H : _ -> value _ \/ exists _, ?t1 ==> _ |- exists _, ?C ?t1 _ ==> _ ] =>
induction H; auto
| [ H : _ -> value _ \/ exists _, ?t2 ==> _, H0 : value ?t1 |-
exists _, ?C ?t1 ?t2 ==> _ ] =>
induction H; auto
| [ H : _ -> value _ \/ exists _, ?t1 ==> _ |- exists _, ?C ?t1 ==> _ ] =>
induction H; auto
end.
==>
denotes a single step of evaluation (via small-step semantics). The intention for each of the match cases is:
However, looking at the behaviour of this code it looks that the third case also matches binary constructors. How do I restrict it to actually match unary constructors only?
The problem is that ?C
matches a term of the form ?C0 ?t0
. You can do some secondary matching to rule out this case.
match goal with
…
| [ H : _ -> value _ \/ exists _, ?t1 ==> _ |- exists _, ?C ?t1 ==> _ ] =>
match C with
| ?C0 ?t0 => fail
| _ => induction H; auto
end
end.