The simpl
tactic unfolds expressions like 2 + a
to "match trees" which doesn't seem simple at all. For example:
Goal forall i:Z, ((fun x => x + i) 3 = i + 3).
simpl.
Leads to:
forall i : Z,
match i with
| 0 => 3
| Z.pos y' =>
Z.pos
match y' with
| q~1 =>
match q with
| q0~1 => (Pos.succ q0)~1
| q0~0 => (Pos.succ q0)~0
| 1 => 3
end~0
| q~0 =>
match q with
| q0~1 => (Pos.succ q0)~0
| q0~0 => q0~1
| 1 => 2
end~1
| 1 => 4
end
| Z.neg y' => Z.pos_sub 3 y'
end = i + 3
How to avoid such complications with simpl
tactic?
This particular goal can be solved with omega
, but if it is a bit more sophisticated, omega fails, and i have to resort to something like: replace (2 + a) with (a + 2); simpl; replace (a + 2) with (2 + a)
.
You can control definition unfolding with the
Transparent
andOpaque
commands. In your example, you should be able to say something likeAlternatively, the
Arguments
command can be used to instruct thesimpl
tactic to avoid simplifying terms in certain contexts. E.g.does the trick for me in your case. What this particular variant does is to avoid simplifying a term when a big, ugly
match
would appear in head position after doing so (what you saw in your example). There are other variants too, however.Finally, just for completeness, the Ssreflect library provides nice infrastructure for making certain definitions opaque locally. So you could say something like
meaning "lock
Z.add
, so that it won't simplify, then simplify the remaining of the expression (the/=
switch), then unlock the definition again (-lock
)".You can tweak how the simpl tactic behaves so you get less matches.
Read more about it here.
Otherwise you can use other tactics that allow you to choose how to reduce.
cbn beta
, for example.