Stream: Coq users

Topic: Rewrite with equal parameters of phantom type

view this post on Zulip William Spencer (Mar 02 2024 at 18:03):

I'm working with a matrix (phantom) type

Definition Matrix (n m : nat) := nat -> nat -> C.

This makes it awkward to use a number of rewrite lemmas: often, the dimensions will not definitionally match, despite being equal (a * b vs b * a, say). As these are not true dependent types, this can be be resolved by replacing the appropriate dimensions, but it makes for unreadable (and fragile) proofs with lots of replace (a*b) with (b*a) by lia or even worse assert (H: a*b=b*a) by lia; rewrite H at 1 4 5; clear H to get Coq to unify the dimensions given in lemmas with the goal.

On a per-lemma basis, this is not so hard to resolve: you can write a tactic that matches the goal against a generic form of the statement of the lemma and assert each of the equalities. For example:

Lemma kron_comm_mul_inv_mat_equiv : forall p q : nat,
@mat_equiv (p*q) (p*q)
  (@Mmult (p*q) (p*q) (p*q)
     (kron_comm p q) (kron_comm q p)) (Matrix.I (p*q)).
(* Hard to use, often one of the `p*q`'s will be a `q*p`. This rewrites effectively: *)
Ltac rewrite_kron_comm_lem :=
  match goal with
  |- context[@Mmult ?n ?m ?o (kron_comm ?t' ?s') (kron_comm ?s'' ?t'')] =>
    (* idtac n m o t' s' s'' t''; *)
    replace s'' with s' by lia;  replace t'' with t' by lia;
    replace n with (t'*s')%nat by lia;   replace m with (t'*s')%nat by lia;
    replace o with (t'*s')%nat by lia;
    replace (@Mmult n m o (kron_comm t' s') (kron_comm s' t'))
      with (@Mmult (t'*s') (t'*s') (t'*s') (kron_comm t' s') (kron_comm s' t'))
      by (f_equal;lia);
    rewrite (kron_comm_mul_inv_mat_equiv t' s')

(This has not been prepared to also work in hypotheses, nor have I checked it closely, but to illustrate the point.)
This is a solution, but not really effective. What I would like is some sort of "strong rewrite" tactic that performs some version of this on its own. I have not had success writing it, though. I am quite happy to use Ltac, and willing to learn another tool (Ltac2, ML, etc.) if that is necessary, but would appreciate some guidance on the issue.

  1. Is there such a tactic already? I couldn't find one, but also have no idea what search terms would work.
  2. In trying to write an Ltac to do this, I found myself wanting to generate patterns in an Ltac. Is this possible, and how?
  3. Is there another tool with capabilities that would enable me to do this without too much work? (i.e. not reimplementing matching, for example) If so, what is a good resource to learn that tool?

Thanks for any advice - apologies for the rather open-ended question(s), and let me know if there's anything I can clarify!

view this post on Zulip Meven Lennon-Bertrand (Mar 04 2024 at 16:14):

Does the tactic applys_eq here do something like what you'd like?

view this post on Zulip Li-yao (Mar 05 2024 at 18:09):

Another idea is to reformulate the lemma with more variables, so that rewrite is more likely to match in the first place, generating equality obligations instead:

forall p q pq1 pq2 pq3 pq4,
  pq1 = p * q -> pq2 = p * q -> pq3 = p * q -> pq4 = p * q ->
  @mat_equiv (p*q) (p*q)
    (@Mmul pq1 pq2 pq3 (...) (...)) (Matrix.I pq4)

Last updated: Jun 23 2024 at 04:03 UTC