Say I have a tactic normalize
which proves a = ?x
where x
is a normalization of a
(e.g. how ring
would prove 2a - a = a
). How could I use ltac to use this to normalize all subterms (of the proper type) of my goal?
In pseudoltac I think it would look something like
repeat match goal with
| _ |- context[ ?a : A ] => progress (setoid_)replace a with (normalized a)
end.
but I'm unsure how to make it work.
I don't know how to do this in ltac, but for ring we have ring_simplify which should do what you want for ring
Though I am actually unable to do what you want with it
Yes I also realized that ring_simplify does exactly what I want (over rings), but I need it for a different 'simplifier' (aac_normalise
from AAC Tactics)
If you can easily generate the equalities, then using rewrite
might be suitable?
That can match on subterms easily
https://coq.inria.fr/refman/proofs/writing-proofs/rewriting.html?highlight=rewrite#coq:tacn.rewrite
I agree, but generating the equalities is the problem; I want ltac to figure these out (by normalization)
You can do something like this:
Require Import ZArith.
Open Scope Z_scope.
Goal forall a b c:Z,
(a + b + c) ^ 2 =
a * a + b ^ 2 + c * c + 2 * a * b + 2 * a * c + 2 * b * c.
intros.
eassert (H : (a + b + c) ^ 2 = _) by (ring_simplify; reflexivity).
rewrite H.
Now you just need to find the subterms that you want to simplify
That part I am not sure how to do
This should also work for aac_normalise from looking at the doc but I haven't tried it
Though maybe @Karl Palmskog knows about it since he is a maintainer
I think the question here is about Ltac. AAC_tactics does almost all the work at the OCaml level (using type class information)
Hmm well you can match on abstract [P ?a ?b]
for whatever connective P
and have a few cases like this. I am not sure how to enforce what the type of ?a
and ?b
are however.
For instance, in the integers, I might look at sub expressions of +
*
-
etc.
Then when you have the term you want to normalize you can do the eassert
like I did above and rewrite with it.
Thanks @Ali Caglayan , I got it to work using eassert
(though I'm afraid my implementation checks all subterms at the moment, I guess adding a check for operators as you mentioned would help if speed becomes an issue)
I think this is best achieved by writing a tactic which goes recursively through the term and returns an equality between the original term and the normalized term. The main obstacle for this in Ltac1 are the heuristics which decide if a tactic returns a term or a tactic. In Ltac2 this is easier to do. Note that in term matches the head symbol can be a variable, so typically you need only a few cases in a match (depending on what Gallina constructs you want to dig into or leave untouched).
Benjamin Salling Hvass has marked this topic as resolved.
Last updated: Jan 31 2023 at 12:01 UTC