2

I am looking at this:

Theorem eq_add_1 : forall n m,
  n + m == 1 -> n == 1 /\ m == 0 \/ n == 0 /\ m == 1.
Proof.
intros n m. rewrite one_succ. intro H.
assert (H1 : exists p, n + m == S p) by now exists 0.
apply eq_add_succ in H1. destruct H1 as [[n' H1] | [m' H1]].
left. rewrite H1 in H; rewrite add_succ_l in H; apply succ_inj in H.
apply eq_add_0 in H. destruct H as [H2 H3]; rewrite H2 in H1; now split.
right. rewrite H1 in H; rewrite add_succ_r in H; apply succ_inj in H.
apply eq_add_0 in H. destruct H as [H2 H3]; rewrite H3 in H1; now split.
Qed.

How do I find what the thing like intros or destruct mean exactly, like looking up an implementation (or if not possible, a definition)? What is the way to do this efficiently?

Lance
  • 75,200
  • 93
  • 289
  • 503
  • 1
    I’ve answered the question you asked, but at the present day, I cannot imagine a scenario where finding the exact implementation is helpful; the specifications in the manual are somewhat helpful for expert users. And by “definition” I assume you mean “specification” in this case, otherwise I don’t get the difference between definition and implementation. – Blaisorblade Sep 10 '20 at 08:20
  • related: https://stackoverflow.com/questions/31494291/how-do-you-look-up-where-identifiers-are-defined-in-coq-efficiently – Charlie Parker Mar 04 '22 at 17:15

2 Answers2

3

The answer differs for primitive and user-defined tactics. However, the proof script you show uses almost no user-defined tactics, except now, which is a notation for the easy tactic.

If you're not sure if a tactic is primitive, try both; checking the manual might be the simplest first step.

For user-defined tactics.

For tactics defined as Ltac foo args := body. you can use Print Ltac foo (e.g. Print Ltac easy.). AFAIK, that does not work for tactics defined by Tactic Notation. In both cases, I prefer to look at the sources (which I find via grep).

For primitive tactics

  • There is the Coq reference manual (https://coq.inria.fr/distrib/current/refman/coq-tacindex.html), which does not have complete specification but is usually the closest approximation. It’s not very accessible, so you should first refer to one of the many Coq tutorials or introductions, like Software Foundations.

  • There is the actual Coq implementation, but that’s not very helpful unless you’re a Coq implementer.

Blaisorblade
  • 6,438
  • 1
  • 43
  • 76
  • for a concrete example -- what would I do for `cbn`? I did `Locate cbn` but it said `Locate cbn.`. Thoughts? – Charlie Parker Mar 04 '22 at 17:40
  • @CharlieParker In this case, you can go to https://coq.inria.fr/distrib/current/refman/coq-tacindex.html (linked above) and cbn appears there. I don't think Locate ever helps for tactics. Is there something I could clarify in my answer? (I just clarified a small point, but there's probably more I'm missing). – Blaisorblade Mar 04 '22 at 18:04
  • Hi Blaisor. What about this case. I've been googling like crazy. I want to know what lowercase eval means. e.g. `let x := eval cbn[fact] in fact 10 in change (fact 10) with x.` but I can't find what lowercase eval means. I'm not sure how to improve your answer but hopefully this follow up helps us figure it out :) Context: https://stackoverflow.com/questions/71352757/what-do-the-consecutive-ins-in-coq-do-and-eval-red-idtac-do/71354083#71354083 – Charlie Parker Mar 04 '22 at 18:44
1

As Blaisorblade mentioned, it can be difficult to understand exactly what tactics are doing, and it is easier to look at the reference manual to find out how to use them. However, at a conceptual level, tactics are not that complicated. Via the Curry-Howard correspondence, Coq proofs are represented using the same functional language you use to write regular programs. Tactics like intros or destruct are just metaprograms that write programs in this language.

For instance, suppose that you need to prove A -> B. This means that you need to write a program with a function type A -> B. When you write intros H., Coq builds a partial proof fun (H : A) => ?, where the ? denotes a hole that should have type B. Similarly, destruct adds a match expression to your proof to do case analysis, and asks you to produce proofs for each match branch. As you add more tactics, you keep filling in these holes until you have a complete proof.

The language of Coq is quite minimal, so there is only so much that tactics can do to build a proof: function application and abstraction, constructors, pattern matching, etc. In principle, it would be possible to have only a handful of tactics, one for each syntactic construct in Coq, and this would allow you to build any proof! The reason we don't do this is that using these core constructs directly is too low level, and tactics use automated proof search, unification and other features to simplify the process of writing a proof.

Arthur Azevedo De Amorim
  • 23,012
  • 3
  • 33
  • 39
  • You might add that you can use `Show Proof.` before `Qed.` to show the partial proof term, and `Print eq_add_1.` after to show the complete proof term. – Jasper Hugunin Sep 10 '20 at 16:20
  • for a concrete example -- what would I do for `cbn`? I did `Locate cbn` but it said `Locate cbn.`. Thoughts? – Charlie Parker Mar 04 '22 at 17:41