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
simpl
to narrow down its "action domain", andOpaque
/Transparent
to 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 A
in 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
/Transparent
approach doesn't work with it, however we can block unfolding ofdouble
using theArguments
directive: