Say I want to have a tactic to clear multiple hypothesis at once, to do something like clear_multiple H1, H2, H3.. I tried to do that using pairs, like the following:
Ltac clear_multiple arg :=
match arg with
| (?f, ?s) => clear s; clear_multiple f
| ?f => clear f
end.
But then, the problem is that I have to place parenthesis to have a Prod:
Variable A: Prop.
Goal A -> A -> A -> True.
intros.
clear_multiple (H, H0, H1).
My question is, how to do that without using Prods ?
I checked this question, but it is not exactly what I want, since the number of arguments I want is not known.
You might like to know that the clear tactic can take multiple arguments, so you do not need to define a new tactic: you can just write clear H H0 H1.
Of course, you might want to define such n-ary tactics for other tasks. Coq has a tactic notation mechanism that supports such definitions. Unfortunately, they are not too powerful: you can only pass a list of arguments of a certain kind to a tactic that expects multiple arguments (like clear); I don't think it can give you a list that you can iterate on programmatically.
Related
Here I mean axiom as what we can define with the Axiom keyword in Coq Gallina, not with such command-line argument passing to Coq.
I know some axioms make Coq inconsistent. However, AFAIK they don't make Coq Turing complete. In my rough understanding, it's because they don't offer any additional computational behavior.
Is there one that makes Coq turning complete? If not, could you give a more concrete explanation of why it's impossible?
The answer to your question largely depends on where you want your functions defined in Coq to compute. In general, there is no problem to encode arbitrary partial functions in Coq using for instance step-indexing, see Mc Bride's "Turing completeness, totally free" for more details.
But you will only be able to evaluate these functions up to a specified finite bound in Coq.
If the goal is to write formally verified programs that could use arbitrary recursion and run them outside of Coq, then you don't need axioms, you can use the Extraction mechanism and its proof-erasure semantics as shown by the following example of an unbounded while loop:
Inductive Loop : Prop := Wrap : Loop -> Loop.
Notation next := (fun l => match l with Wrap l' => l' end).
Definition while {A : Type} (f : A -> A * bool) : Loop -> A -> A :=
fix aux (l : Loop) (a : A) {struct l} :=
let '(x, b) := f a in
if b then aux (next l) x else x.
Require Extraction.
Recursive Extraction while.
with extraction result:
type bool =
| True
| False
type ('a, 'b) prod =
| Pair of 'a * 'b
(** val while0 : ('a1 -> ('a1, bool) prod) -> 'a1 -> 'a1 **)
let rec while0 f x =
let Pair (x0, b) = f x in (match b with
| True -> while0 f x0
| False -> x0)
Note that the function while requires a proof of termination in Coq that is erased once it is turned to ocaml.
Finally, as you explain, you would need to extend Coq's computational reduction machinery if you wanted evaluation of partial functions to stay inside Coq. There is no general mechanism providing this feature at the moment (even though there is a coq enhancement proposal to add rewriting rules). It might be possible to abuse definitional UIP to evaluate partial functions. In all cases, adding the possibility to evaluate partial functions inside Coq, making it part of the conversion, automatically entails that the theory itself because undecidable (the proof assistant may fail to return a typechecking result).
I have a hard time finding the available rewrite rules for my situation. As I don't want to bother you with each rewrite question, I was wondering do you have some tips for finding suitable rewrite rules?
Do you have any tips on how to solve and or search for rewriting the following example:
1 subgoal
H: P
H0: Q
__________
R
And say I have Lemma Join: P /\ Q = R
In order to do this rewrite, I suppose I need to get H and H0 first rewritten into P /\ Q.
So how would you solve or find the rewrite rules for such a case?
Another example
H: a <= b
____________
b < a
I am confident there should exists some commutativity rewrite rule for this, but how can I best find this rule?
Many thanks in advance!
First a tip so you don't run into this problem later: Don't confuse equality of types for logical equivalence. What you usually mean in your first example above is that P/\Q <-> R, not that the type P/\Q is definitionally the same type as R.
With regards to your question about finding lemmas in the library; yes, it is very important to be able to find things there. Coq's Search command lets you find all (Required) lemmas that contain a certain pattern somewhere in it, or some particular string. The latter is useful because the library tends to have a somewhat predicable naming scheme, for instance the names for lemmas about decidability often contains then string "dec", commutativity lemmas often are called something with "comm" etc.
Try for example to search for decidability lemmas about integers, i.e. lemmas that have the term Z somewhere inside them, and the name contains the string "dec".
Require Import ZArith.
Search "dec" Z.
Back to your question; in your case you want to find a lemma that ends with "something and something", so you can use the pattern ( _ /\ _ )
Search ( _ /\ _ ).
However, you get awfully many hits, because many lemmas ends with "something and something".
In your particular case, you perhaps want to narrow the search to
Search (?a -> ?b -> ?a /\ ?b).
but be careful when you are using pattern variables, because perhaps the lemma you was looking for had the arguments in the other order.
In this particular case you found the lemma
conj: forall [A B : Prop], A -> B -> A /\ B
which is not really a lemma but the actual constructor for the inductive type. It is just a function. And remember, every theorem/lemma etc. in type theory is "just a function". Even rewriting is just function application.
Anyway, take seriously the task of learning to find lemmas, and to read the output from Search. It will help you a lot.
Btw, the pattern matching syntax is like the term syntax but with holes or variables, which you will also use when you are writing Ltac tactics, so it is useful to know for many reasons.
How can I apply rewrite -> targetting only a sub-expression? For example, consider this theorem:
Parameter add : nat -> nat -> nat.
Axiom comm : forall a b, add a b = add b a.
Theorem t1 : forall a b : nat,
(add (add a b) (add a (add a b))) =
(add (add a b) (add a (add b a))).
Intuitively, it requires commuting only one (add a b) sub-expression, but if I do rewrite -> (comm a b), it rewrites all the occurrences. How can I target a particular sub-expression?
This is a case where the ssreflect matching facilities will usually be more convenient than "at" [I'd dare to say sub-term rewrites are often a cause of people switching to ssreflect's rewrite]. In particular:
rewrite {pos}[pat]lemma will select occurrences pos of pattern pat to rewrite,
pat can be a contextual pattern that may allow you improve the robustness of your scripts.
You can target a specific occurrence with the rewrite tactic using the suffix at N. Occurrences are numbered from 1 in left-to-right order. You can rewrite multiple occurrencess by separating their indices with spaces. You need Require Import Setoid. The at suffix is also available with some other tactics that target occurrences of a term, including many tactics that perform conversions (change, unfold, fold, etc.), set, destruct, etc.
intros.
rewrite -> (comm a b) at 2.
rewrite -> (comm _ _).
reflexivity.
There are other possible approaches, especially if all you need is to apply equalities. The congruence tactic can find what to rewrite and apply symmetry and transitivity on its own, but you need to prime it by adding all equivalences to the context (in the form of universally-quantified equalities), it won't query hint databases.
assert (Comm := comm).
congruence.
To get more automation, Hint Rewrite creates a database of theorems which the tactic autorewrite will try applying. For more advanced automation, look up generalized rewriting with setoids, which I'm not sufficiently familiar with to expound on.
I am trying to understand the exact meaning of the : (colon) in Coq/ssreflect proofs in terms of non-ssreflect Coq.
I read that it has something to do with moving things to the goal (like generalize??) and is the opposite of =>, which move things to the hypotheses. However, I often find it confusing because proofs work either way with or without the :. Below is an example from a tutorial:
Lemma tmirror_leaf2 t : tmirror (tmirror t) = Leaf -> t = Leaf.
Proof.
move=> e.
by apply: (tmirror_leaf (tmirror_leaf e)).
Qed.
where,
tmirror_leaf
: forall t, tmirror t = Leaf -> t = Leaf
is a lemma that says if the mirror of a tree is a leaf, then the tree is a leaf.
I don't understand why we need the : here and not merely do the Coq apply. In fact, if I remove the :, it works just fine. Why does it make a difference?
Indeed, apply: H1 ... Hn is to all effects equivalent to move: H1 .. Hn; apply. A more interesting use of apply is apply/H and its variations, which can interpret views.
I think I found the answer while reading the SSReflect documentation. Essentially, ssr has redefined tactics like apply such that it operates on the first variable of the goal instead of something in the context. That's why the : is used in apply: XX. in the ssr way (which is equivalent to move: XX; apply.), and it also works if : is omitted as that is the traditional Coq way.
Quoting the documentation:
Furthermore, SSReflect redefines the basic Coq tactics case, elim, and
apply so that they can take better advantage of ':' and '=>'. These
Coq tactics require an argument from the context but operate on the
goal. Their SSReflect counterparts use the first variable or constant
of the goal instead, so they are "purely deductive":
they do not use or change the proof context. There is no loss since
`:' can readily be used to supply the required variable.
The documentation for Coq carries the general admonition not to rely on the builtin naming mechanism, but select one's own names, lest the changes in the naming mechanism render past proofs invalid.
When considering expressions of the form remember Expr as v, we set the variable v to the expression Expr. But the name of the assumption is selected automatically, and is something like Heqv, so we have:
Heqv: v = Expr
How can I select my own name instead of Heqv? I can always rename it to whatever I like using the rename command, but that doesn't keep my proofs independent of the hypothetical future changes in the builtin naming mechanism in Coq.
If you may get rid of the separate equality, try set (name := val). Use unfold instead of rewrite to get the value back in place.
If you need the equality for more than the rewrite <-, I know of no built in tactic that does this. You can do it manually, though, or build a tactic / notation. I just threw this together. (Note: I'm not an expert, this might be done more easily.)
Tactic Notation "remember_as_eq" constr(expr) ident(vname) ident(eqname) :=
let v := fresh in
let HHelp := fresh in
set (v := expr);
(assert (HHelp : sigT (fun x => x = v)) by ( apply (existT _ v); reflexivity));
inversion HHelp as [vname eqname];
unfold v in *; clear v HHelp;
rewrite <- eqname in *.
Use as remember_as_eq (2+2) four Heqfour to get the same result as with remember (2+2) as four.
Note: Updated to handle more cases, the old version failed on some combinations of value and goal type. Leave a comment if you find another case that works with rewrite but not this one.