I'm using Coq 8.5pl1.
To make a contrived but illustrative example,
(* fix so simpl will automatically unfold. *)
Definition double := fix f n := 2*n.
Theorem contrived n : double (2 + n) = 2 + double (1 + n).
Now, I only want to simplify the arguments to double, and not any part outside of it. (For example, because the rest has already carefully been put into the correct form.)
simpl.
S (S (n + S (S (n + 0)))) = S (S (S (n + S (n + 0))))
This converted the outside (2 + ...) to (S (S ...)) as well as unfolding double.
I can match one of them by doing:
match goal with | |- (double ?A) = _ => simpl A end.
double (S (S n)) = 2 + double (1 + n)
How do I say that I want to simplify all of them? That is, I want to get
double (S (S n)) = 2 + double (S n)
without having to put a separate pattern for each call to double.
I can simplify except for double itself with
remember double as x; simpl; subst x.
double (S (S n)) = S (S (double (S n)))
Opaque/Transparent approach
Combining the results of this answer and this one, we get the following solution:
We use the pattern capability of
simplto narrow down its "action domain", andOpaque/Transparentto forbid (allow resp.) unfolding ofdouble.Custom tactic approach
We can also define a custom tactic for simplifying arguments:
That
let A' := ...construction is needed to protect nested functions from simplification. Here is a simple test:The above results in
Had we used something like
context [function ?A] => simpl Ain the definition ofsimpl_arg_of, we would've gotteninstead.
Arguments directive approach
As suggested by @eponier in comments, we can take advantage of yet another form of
simpl--simpl <qualid>, which the manual defines as:The
Opaque/Transparentapproach doesn't work with it, however we can block unfolding ofdoubleusing theArgumentsdirective: