I am learning Coq and I encountered an issue : how can I switch from that context
HA : A
HABC : A -> B -> C
to this one ?
HA : B -> C
I tried apply and rewrite tactics but it did not work.
Thank you for your help !
You need to apply HABC to HA to yield a witness of B -> C, which, by the way, it would make more sense to name HBC than HA, already used. Using ssreflect, you could write:
From mathcomp Require Import all_ssreflect.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Lemma foo A B C (HA : A) (HABC : A -> B -> C) : false.
Proof.
have HBC := HABC HA.
If you want to keep the HA name, one way to do it would be to replace the have with
have {HA} HA := HABC HA.
where the {HA} clears HA from the environment so that you can reuse the HA name right way for the result of the application.
Related
I am trying to apply the addf_div theorem from math-comp's ssralg to the following:
1 / a%:R + 1 / a%:R. I want to show that this is 2 / a%:R, but addf_div is over fieldTypes and can't be applied. Is there a way to apply addf_div to the goal.
Here, a is a nat.
I'm not at all an expert with ssralg, but I managed to get this direct proof, which I'm pretty sure can be very simplified.
From mathcomp Require Import all_ssreflect all_algebra.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Open Scope ring_scope.
Import GRing.Theory.
Variable (R : numFieldType).
Variable (a : nat).
Definition a' : R := a%:R.
Lemma foo : 1 / a' + 1 / a' = 2%:R / a'.
Proof. by rewrite -mulrDr -mulr2n mulrnAr -mulrnAl. Qed.
Note that addf_div can be used inside the proof too, but using it doesn't seem to be making the proof simpler.
I'm fairly new to Coq, and was doing some Katas on CodeWars for fun and learning.
I'm stuck with one of them and want to hear some ideas from you.
So, I have:
Record iso (A B : Set) : Set :=
bijection {
A_to_B : A -> B;
B_to_A : B -> A;
A_B_A : forall a : A, B_to_A (A_to_B a) = a;
B_A_B : forall b : B, A_to_B (B_to_A b) = b
}.
(* nat_plus_nat : a set having size(nat) more elements than nat. (provided in preloaded) *)
Inductive nat_plus_nat : Set := left (n : nat) | right (n : nat).
Theorem nat_iso_natpnat : iso nat nat_plus_nat.
I have and idea, but I can't implement it, and I don't know if it's feasible. Basically, I want to map every odd nat to one constructor(left, for example) and every even nat to another(right, for example). Will this work? If no, how can it be done?
Right now I'm stuck with the fact, that A_to_B defined as fun n => if odd n then left n else right n and B_to_A defined as fun n => match n with | left n' => n' | right n' => n' end won't give me enough facts to eliminate some cases.
You need to do the math correctly first: find two functions that are inverse of each other.
You initial intent is correct: odd numbers to one side, even numbers to the other side, but what you store on each side should cover all the natural numbers, so you will probably have to divide by 2 somewhere.
For Coq usage, You should load the Arith package, by starting with the following line:
Require Import Arith.
This way, you can benefit from existing functions, like Nat.div2 and Nat.even and all the existing theorems about them. To find the relevant theorems, I suggest commands like:
Search Nat.even 2.
Search Nat.div2.
Last hint: proving properties of Nat.div2 by induction is rather difficult for beginners. Try to use the existing theorems as much as possible. If you choose to perform a proof by induction concerning div2, go look in the sources in file theories/Arith/Div2.v : the author of that file designed a specific induction theorem called ìnd_0_1_SS just for that purpose.
I can define the following inductive type:
Inductive T : Type -> Type :=
| c1 : forall (A : Type), A -> T A
| c2 : T unit.
But then the command Check (c1 (T nat)) fails with the message: The term T nat has type Type#{max(Set, Top.3+1)} while it is expected to have type Type#{Top.3} (universe inconsistency).
How can I tweak the above inductive definition so that c1 (T nat) does not cause a universe inconsistency, and without setting universe polymorphism on?
The following works, but I would prefer a solution without adding equality:
Inductive T (A : Type) : Type :=
| c1 : A -> T A
| c2' : A = unit -> T A.
Definition c2 : T unit := c2' unit eq_refl.
Check (c1 (T nat)).
(*
c1 (T nat)
: T nat -> T (T nat)
*)
Let me first answer the question of why we get the universe inconsistency in the first place.
Universe inconsistencies are the errors that Coq reports to avoid proofs of False via Russell's paradox, which results from considering the set of all sets which do not contain themselves.
There's a variant which is more convenient to formalize in type theory called Hurken's Paradox; see Coq.Logic.Hurkens for more details. There is a specialization of Hurken's paradox which proves that no type can retract to a smaller type. That is, given
U := Type#{u}
A : U
down : U -> A
up : A -> U
up_down : forall (X:U), up (down X) = X
we can prove False.
This is almost exactly the setup of your Inductive type. Annotating your type with universes, you start with
Inductive T : Type#{i} -> Type#{j} :=
| c1 : forall (A : Type#{i}), A -> T A
| c2 : T unit.
Note that we can invert this inductive; we may write
Definition c1' (A : Type#{i}) (v : T A) : A
:= match v with
| c1 A x => x
| c2 => tt
end.
Lemma c1'_c1 (A : Type#{i}) : forall v, c1' A (c1 A v) = v.
Proof. reflexivity. Qed.
Suppose, for a moment, that c1 (T nat) typechecked. Since T nat : Type#{j}, this would require j <= i. If it gave us that j < i, then we would be set. We could write c1 Type#{j}. And this is exactly the setup for the variant of Hurken's that I mentioned above! We could define
u = j
U := Type#{j}
A := T Type#{j}
down : U -> A := c1 Type#{j}
up : A -> U := c1' Type#{j}
up_down := c1'_c1 Type#{j}
and hence prove False.
Coq needs to implement a rule for avoiding this paradox. As described here, the rule is that for each (non-parameter) argument to a constructor of an inductive, if the type of the argument has a sort in universe u, then the universe of the inductive is constrained to be >= u. In this case, this is stricter than Coq needs to be. As mentioned by SkySkimmer here, Coq could recognize arguments which appear directly in locations which are indices of the inductive, and disregard those in the same way that it disregards parameters.
So, to finally answer your question, I believe the following are your only options:
You can Set Universe Polymorphism so that in T (T nat), your two Ts take different universe arguments. (Equivalently, you can write Polymorphic Inductive.)
You can take advantage of how Coq treats parameters of inductive types specially, which mandates using equality in your case. (The requirement of using equality is a general property of going from indexed inductive types to parameterized inductives types---from moving arguments from after the : to before it.)
You can pass Coq the flag -type-in-type to entirely disable universe checking.
You can fix bug #7929, which I reported as part of digging into this question, to make Coq handle arguments of constructors which appear in index-position in the inductive in the same way it handles parameters of inductive types.
(You can find another edge case of the system, and manage to trick Coq into ignoring the universes you want to slip past it, and probably find a proof of False in the process. (Possibly involving module subtyping, see, e.g., this recent bug in modules with universes.))
In Coq Tutorial, section 1.3.1 and 1.3.2, there are two elim applications:
The first one:
1 subgoal
A : Prop
B : Prop
C : Prop
H : A /\ B
============================
B /\ A
after applying elim H,
Coq < elim H.
1 subgoal
A : Prop
B : Prop
C : Prop
H : A /\ B
============================
A -> B -> B /\ A
The second one:
1 subgoal
H : A \/ B
============================
B \/ A
After applying elim H,
Coq < elim H.
2 subgoals
H : A \/ B
============================
A -> B \/ A
subgoal 2 is:
B -> B \/ A
There are three questions. First, in the second example, I don't understand what inference rule (or, logical identity) is applied to the goal to generate the two subgoals. It is clear to me for the first example, though.
The second question, according to the manual of Coq, elim is related to inductive types. Therefore, it appears that elim cannot be applied here at all, because I feel that there are no inductive types in the two examples (forgive me for not knowing the definition of inductive types). Why can elim be applied here?
Third, what does elim do in general? The two examples here don't show a common pattern for elim. The official manual seems to be designed for very advanced users, since they define a term upon several other terms that are defined by even more terms, and their language is ambiguous.
Thank you so much for answering!
Jian, first let me note that the manual is open source and available at https://github.com/coq/coq ; if you feel that the wording / definition order could be improved please open an issue there or feel free to submit a pull request.
Regarding your questions, I think you would benefit from reading some more comprehensive introduction to Coq such as "Coq'art", "Software Foundations" or "Programs and Proofs" among others.
In particular, the elim tactic tries to apply the so called "elimination principle" for a particular type. It is called elimination because in a sense, the rule allows you to "get rid" of that particular object, allowing you to continue on the proof [I recommend reading Dummett for a more throughout discussion of the origins of logical connectives]
In particular, the elimination rule for the ∨ connective is usually written by logicians as follows:
A B
⋮ ⋮
A ∨ B C C
────────────────
C
that is to say, if we can derive C independently from A and B, then we can derive it from A ∨ B. This looks obvious, doesn't it?
Going back to Coq, it turns out that this rule has a computational interpretation thanks to the "Curry-Howard-Kolmogorov" equivalence. In fact, Coq doesn't provide most of the standard logical connectives as a built in, but it allow us to define them by means of "Inductive" datatypes, similar to those in Haskell or OCaml.
In particular, the definition of ∨ is:
Inductive or (A B : Prop) : Prop :=
| or_introl : A -> A \/ B
| or_intror : B -> A \/ B
that is to say, or A B is the piece of data that either contains an A or a B, together with a "tag", that allows us to "match" to know which one do we really have.
Now, the "elimination principle for or" has type:
or_ind : forall A B P : Prop, (A -> P) -> (B -> P) -> A \/ B -> P
The great thing of Coq is that such principle is not a "built-in", just a regular program! Think, could you write the code of the or_ind function? I'll give you a hint:
Definition or_ind A B P (hA : A -> P) (hB : B -> P) (orW : A \/ B) :=
match orW with
| or_introl aW => ?
| or_intror bW => ?
end.
Once this function is defined, all that elim does, is to apply it, properly instantiating the variable P.
Exercise: solve your second example using apply and ord_ind instead of elim. Good luck!
The Eval compute command does not always evaluate to a simple expression.
Consider the code:
Require Import Coq.Lists.List.
Require Import Coq.Arith.Peano_dec.
Import ListNotations.
Inductive I : Set := a : nat -> I | b : nat -> nat -> I.
Lemma I_eq_dec : forall x y : I, {x = y}+{x <> y}.
Proof.
repeat decide equality.
Qed.
And, if I execute the following command:
Eval compute in (if (In_dec eq_nat_dec 10 [3;4;5]) then 1 else 2).
Coq tells me that the result is 2. However, when I execute the following expression:
Eval compute in (if (In_dec I_eq_dec (a 2) [(a 1);(a 2)]) then 1 else 2).
I get a long expression where the In-predicate seems to be unfolded, but no result is given.
What do I have to change to obtain the answer 1 in the last Eval compute line ?
In Coq there are two terminator commands for proof scripts: Qed and Defined. The difference between them is that the former creates opaque terms, which cannot be unfolded, even by Eval compute. The latter creates transparent terms, which can then be unfolded as usual. Thus, you just have to put Defined in the place of Qed.:
Require Import Coq.Lists.List.
Require Import Coq.Arith.Peano_dec.
Import ListNotations.
Inductive I : Set := a : nat -> I | b : nat -> nat -> I.
Lemma I_eq_dec : forall x y : I, {x = y}+{x <> y}.
Proof.
repeat decide equality.
Defined.
Eval compute in (if (In_dec I_eq_dec (a 2) [(a 1);(a 2)]) then 1 else 2).
I personally find the sumbool type {A} + {B} not very nice for expressing decidable propositions, precisely because proofs and computation are too tangled together; in particular, proofs affect how terms reduce. I find it better to follow the Ssreflect style, separate proofs and computation and relate them via a special predicate:
Inductive reflect (P : Prop) : bool -> Set :=
| ReflectT of P : reflect P true
| ReflectF of ~ P : reflect P false.
this gives a convenient way for saying that a boolean computation returns true iff some property is true. Ssreflect provides support for conveniently switching between the computational boolean view and the logical view.
If you want to evaluate your proofs, you need to make them transparent. You do that by finishing them with the Defined command. The Qed command makes them opaque, meaning it discards their computational content.