I was going through the book Software foundations to learn Coq and I got stuck on Numbers. In this Type definition
Inductive nat : Type :=
| O : nat
| S : nat -> nat.
How does O becomes 0 when we use it in definition of
Definition pred (n : nat) : nat :=
match n with
| O => O
| S n' => n'
end.
I only understood that O represents natural numbers and S takes a natural number and return another natural number. What I do not get is when our defined nat data type is used in pred definition how does O represent 0? And how does S n' patter match gives us predecessor of n.
The Peano numbers
nat represents the natural numbers via the unary numeral system. The inhabitants (values) of the nat type are O, S O, S (S O), S (S (S O)), ..., S (S (S (S ... O)...).
We interpret the symbol O as the natural number zero. And S represents a single "tick" in unary representation, i.e. we interpret S as a constructor (it has nothing to do with object-oriented programming) which takes a natural number and yields the next natural number.
The predecessor function
pred is actually is not a very well-behaved function in a sense.
First of all, there is no predecessor of zero when we are talking about the natural numbers. But all functions in Coq must return a value, so if we want to keep the type of pred (which is nat -> nat) we must do something about pred O. It feels natural to just return O and get it over with. This gives us the first branch of the pattern-mathing expression (O => O).
Next, what do we return when we call pred on the number representing 1? Let's recall that we write 1 in Coq as S O. This is easy -- pred (S O) should return O. Now let's try 2: pred (S (S O)) should return S O. You see the pattern here? If we have a bunch of S's in front of an O, we strip one S off -- simple as that. The second branch of the pattern-matching expression (S n' => n') does exactly this: it takes a (non-zero) number of the form S n' and turns it into n' (not changing the original, of course).
Let me give an example. Let's calculate the predecessor of the number 3 step-by-step:
pred (S (S (S O)))
Unfold the definition of pred, substitute S (S (S O)) for n:
match S (S (S O)) with
| O => O
| S n' => n'
end
S (S (S O)) has form S n' (it starts with S), so we take the 2nd branch, binding n' to S (S O). How do we check that we didn't make a mistake here? If we substitute the definition of n' into S n' we should get back the original n: S n' = S (S (S O)) = n.
Now, we just return n':
S (S O)
As expected, we got 2 as the result!
Notations
There is a distinction between 0, 0, and O. The first zero (0) is a meta-level numeral for the natural number zero (it's how we designate zero in our metalanguage, e.g. English in this case). 0 is a notation for O, in other words 0 is syntactic sugar for O. As the Coq reference manual says (§1.2.4):
Numerals have no definite semantics in the calculus. They are mere notations that can be bound to objects through the notation mechanism (see Chapter 12 for details). Initially, numerals are bound to Peano’s representation of natural numbers (see 3.1.3).
It's easy to illustrate:
Check 0. (* 0 : nat *)
Check 5. (* 5 : nat *)
Unset Printing Notations. (* Print terms as is, no syntactic sugar *)
Check 0. (* O : nat *)
Check 5. (* S (S (S (S (S O)))) : nat *)
You can overload numerals, here is an example with integers:
Set Printing Notations.
Require Import Coq.ZArith.ZArith.
Open Scope Z.
Check 0. (* 0 : Z *)
Check 5. (* 5 : Z *)
Unset Printing Notations.
Check 0. (* Z0 : Z *)
Check 5. (* Zpos (xI (xO xH)) : Z *)
Upshot: the same notation can be tied to different terms. Coq defines some default notations, e.g. for such ubiquitous things as numbers.
If you wanted to define your own type to represent the natural numbers (my_nat) with possibly different names for O and S (like stop and tick), you'd have to write a plugin to map Coq numerals onto the terms of my_nat (see here).
Related
As elementary as it seems, I can't solve the following problem. There's this inductive type for even naturals and a proven lemma expressing that adding two even numbers yields an even number.
Inductive even : nat -> Prop :=
| O_even : even 0
| plus_2_even : forall n:nat, even n -> even (S (S n)).
Lemma lm_even1: forall n p:nat, even n -> even p -> even (n + p).
I'd like to prove the special case that n + 2 is even:
Lemma lm_even2: forall n: nat, even n -> even (n + 2).
The more general lm_even1 would come handy here but I keep failing with my efforts using apply, rewrite etc. to express that lm_even2 is the same statement with "p = 2". Help would be appreciated.
You might get a better answer if you show us what you've tried (explicitly). There's a short proof with just apply and one or two other basic tactics, but maybe you have a misunderstanding somewhere. Fixing that misunderstanding would be more helpful for you in the long term.
We should start by introducing all the premises. There's a good reason for this that I'll discuss below.
Lemma lm_even2: forall n: nat, even n -> even (n + 2).
Proof.
intros.
Now the proof state is
1 subgoal
n : nat
H : even n
______________________________________(1/1)
even (n + 2)
Now we're in a position to apply lm_even1.. apply term. attempts to unify the type of term with the goal, possibly filling in arguments to term from left to right (if it's some kind of function).
So, for example, apply lm_even1. would first try to unify with the full type
forall n p : nat, even n -> even p -> even (n + p)
Then it'll try with some variable to be determined as the first argument (of type nat):
forall p : nat, even ?n -> even p -> even (?n + p)
Then the same for p: even ?n -> even ?p -> even (?n + ?p). Next, since this is still a function type, it can continue by filling in the argument of type even ?n with some unknown variable: even ?p -> even (?n + ?p) and finally, even (?n + ?p).
The only one of those that could match the goal is the last one: even (?n + ?p) with ?n = n and ?p = 2. If we hadn't introduced the variables, this wouldn't work at all because none of the other types match the original goal.
Lemma lm_even2: forall n: nat, even n -> even (n + 2).
Proof.
intros.
apply lm_even1.
Now the proof state is
2 subgoals
n : nat
H : even n
______________________________________(1/2)
even n
______________________________________(2/2)
even 2
So we have two goals: even n and even 2. Both should be fairly easy to reach using the premises and the definition of even.
I've began learning Coq, and am trying to prove something that seems fairly simple: if a list contains x, then the number of instances of x in that list will be > 0.
I've defined the contains and count functions as follows:
Fixpoint contains (n: nat) (l: list nat) : Prop :=
match l with
| nil => False
| h :: t => if beq_nat h n then True else contains n t
end.
Fixpoint count (n acc: nat) (l: list nat) : nat :=
match l with
| nil => acc
| h :: t => if beq_nat h n then count n (acc + 1) t else count n acc t
end.
I'm trying to prove:
Lemma contains_count_ge1 : forall (n: nat) (l: list nat), contains n l -> (count n 0 l > 0).
I understand the proof will involve unfolding the definitions of count and contains, but then I'd like to say "the list cannot be nil, as contains is true, so there must be an element x in l such that beq_nat h x is true", and I've played around a bit but can't figure out how to use tactics to do this. Any guidance would be greatly appreciated.
ejgallego already gave a great solution to your problem in his answer. I would still like to single out an important point that he left out: in Coq, you must always argue from first principles, and be very pedantic and precise about your proofs.
You argued that the proof should proceed as follows:
The list cannot be nil, as contains is true, so there must be an element x in l such that beq_nat h x is true.
Even though this makes intuitive sense for humans, it is not precise enough for Coq to understand. The problem, as ejgallego's answer shows, is that your informal reasoning conceals a use of induction. Indeed, it is useful to try to expand out your argument in more details even before translating it into tactics. We could proceed like this, for instance:
Let us prove that, for every n : nat and ns : list nat, contains n ns implies count n 0 ns > 0. We proceed by induction on the list ns. If ns = nil, the definition of contains implies that False holds; a contradiction. We are thus left with the case ns = n' :: ns', where we can use the following induction hypothesis: contains n ns' -> count n 0 ns' > 0. There are two sub-cases to consider: whether beq_nat n n' is true or not.
If beq_nat n n' is true, by the definition of count, we see that we just have to show that count n (0 + 1) ns' > 0. Note there isn't a direct way to proceed here. This is because you wrote count tail-recursively, using an accumulator. While this is perfectly reasonable in functional programming, it can making proving properties about count more difficult. In this case, we would need the following auxiliary lemma, also proved by induction: forall n acc ns, count n acc ns = acc + count n 0 ns. I'll let you figure out how to prove this one. But assuming that we have already established it, the goal would reduce to showing that 1 + count n 0 ns' > 0. This is true by simple arithmetic. (There is an even simpler way that does not require an auxiliary lemma, but it would require slightly generalizing the statement you're proving.)
If beq_nat n n' is false, by the definitions of contains and count, we would need to show that contains n ns' implies count n 0 ns' > 0. This is exactly what the induction hypothesis gives us, and we are done.
There are two lessons to be learned here. The first one is that doing formal proofs often requires translating your intuition in formal terms that the system can understand. We know intuitively what it means to have some element occur inside of a list. But if we were to explain what that means more formally, we would resort to some kind of recursive traversal of the list, which would probably turn out to be the very definition of count that you wrote in Coq. And in order to reason about recursion, we need induction. The second lesson is that the way you define things in Coq has important consequences for the proofs you write. ejgallego's solution did not require any auxiliary lemmas beyond those in the standard library, precisely because his definition of count was not tail-recursive.
Well, you pose many questions about basic Coq beyond what is IMO possible to address here. For this particular problem, I would proceed this way (in reality I would use the already provided lemmas in MathComp):
From Coq Require Import PeanoNat Bool List.
Fixpoint contains (n: nat) (l: list nat) : bool :=
match l with
| nil => false
| h :: t => if Nat.eqb h n then true else contains n t
end.
Fixpoint count (n : nat) (l: list nat) : nat :=
match l with
| nil => 0
| h :: t => if Nat.eqb h n then S (count n t) else count n t
end.
Lemma contains_count_ge1 n l : contains n l = true -> count n l > 0.
Proof.
induction l as [|x l IHl]; simpl; [now congruence|].
now destruct (Nat.eqb_spec x n); auto with arith.
Qed.
My "standard" solution:
Lemma test n (l : list nat) : n \in l -> 0 < count_mem n l.
Proof. by rewrite lt0n => /count_memPn/eqP. Qed.
and different definitions of count and contains that may prove useful:
Fixpoint contains (n: nat) (l: list nat) : bool :=
match l with
| nil => false
| h :: t => Nat.eqb h n || contains n t
end.
Fixpoint count (n : nat) (l: list nat) : nat :=
match l with
| nil => 0
| h :: t => Nat.b2n (Nat.eqb h n) + (count n t)
end.
1) I believe that it is possible to use inductive types without pattern matching. (using _rec,_rect,_ind only). It is opaque, complicated, but possible.
2) Is it possible to use coinductive types withous pattern matching?
There exist a function from coinductive type to union of constructors' domains of coinductive type.
Does Coq generate it explicitly?
If yes, how to rewrite 'hd' ?
Section stream.
Variable A : Type.
CoInductive stream : Type :=
| Cons : A -> stream -> stream.
End stream.
Definition hd A (s : stream A) : A :=
match s with
| Cons x _ => x
end.
Although it is possible to use inductive types without directly resorting to pattern matching, this is only superficially true: the _rec, _rect and _ind combinators generated by Coq are all defined in terms of match. For instance:
Print nat_rect.
nat_rect =
fun (P : nat -> Type) (f : P 0) (f0 : forall n : nat, P n -> P (S n)) =>
fix F (n : nat) : P n :=
match n as n0 return (P n0) with
| 0 => f
| S n0 => f0 n0 (F n0)
end
: forall P : nat -> Type,
P 0 -> (forall n : nat, P n -> P (S n)) -> forall n : nat, P n
Furthermore, there are many cases where replacing pattern matching by an eliminator would result in a term with different computational behavior. Consider the following function, which divides a nat by two:
Fixpoint div2 (n : nat) :=
match n with
| 0 | 1 => 0
| S (S n') => S (div2 n')
end.
It is possible to rewrite this function using nat_rec, but the recursive call on n - 2 makes it a bit complicated (try it!).
Now, back to your main question, Coq does not automatically generate similar elimination principles for coinductive types. The Paco library helps deriving more useful principles for reasoning about coinductive data. But as far as I am aware, there is nothing similar for writing plain functions.
It is worth pointing out that your proposed approach is different from what Coq does for inductive data types, in that nat_rect and friends allow writing recursive functions and proofs by induction. One of the reasons providing these combinators is that they are used by the induction tactic. Something of type nat -> unit + nat, which more or less corresponds to what you proposed, wouldn't suffice.
Inspired by another question on StackOverflow, I defined a dense vector to be a vector with option A type elements that only contains Some _ elements, and no None elements.
Require Import Vector.
Section Dense.
Variable A:Type.
Inductive Is_dense : forall n, t (option A) n -> Prop :=
| snil : Is_dense 0 (nil _)
| scons: forall n s, Is_dense n s -> forall a, Is_dense (S n) (cons _ (Some a) _ s).
How can I prove the following two lemmas?
Lemma Is_dense_tl: forall n (s: t (option A) (S n)),
Is_dense (S n) s -> Is_dense n (tl s).
and
Lemma dense_hd: forall n (s: t (option A) (S n)), Is_dense (S n) s -> A.
And also, in the first lemma, when I do inversion s. I get the elements h n' X that were used by s's constructor, but how can I get an equality stating s = cons (option A) h n' X?
Because of type dependency, inversion can't directly generate what you expect, because it is not true in general. However, it is true for a large family of types, whose equality is decidable. In your case, you can apply Eqdep_dec.inj_pair2_eq_dec to get the equality you want, if you provide the fact that equality upon nat is decidable (and it is).
Here is the proof for the first lemma:
Lemma Is_dense_tl: forall n (s: t (option A) (S n)),
Is_dense (S n) s -> Is_dense n (tl s).
Proof.
intros n s hs.
inversion hs; subst; clear hs.
apply Eqdep_dec.inj_pair2_eq_dec in H0.
- now rewrite <- H0; simpl.
- (* insert proof of decidablity *) admit.
Qed.
EDIT: About your comment about the second lemma.
The main difference between your two lemmas is that the first one tries to prove the property Is_dense n (tl s) which lives in Prop, whereas the second one tries to exhibit a term of type A. In short, the former creates a term of sort Prop, the latter a term of sort Type.
To avoid inconsistency in Coq's logic, there is a hierarchy to organize the sorts, which is (not exactly, but to give you the rough idea) Prop: Set Set:Type_0 and Type_n: Type_n+1. On top of this hierarchy is built a type system where the dependent pair (e.g. the type {n: nat | even n } is the type of even natural numbers) is restricted. You can build a Prop from other Prop (e.g. forall p:Prop, p -> p lives in Prop). However you need to be careful when Type is involved. For example, (again, please refer to Coq's documentation for the exact statement) forall n:Type_i, Type_j is of type Type_max(i,j).
This restriction is here to avoid inconsistency (like Russel's paradox) in Coq's type system.
In your case, you are trying to inspect (using inversion) a term of sort Prop (Is_dense (S n) s) to build a term of type A, of sort Type. This is forbidden by the type system. To build a term of sort Type, you need to inspect terms of at least the sort Set. In your example, all you have to do is change the definition of Is_dense to land in Type instead of Prop, and you're good to go.
I am new to Coq and need some help with some of trivial examples to get me started. In particular I am interested in defining some operations of vectors (fixed size lists) using dependent types. I started with Vector package and trying to implement some additional functions. For example I am having difficulty implementing trivial 'take' and 'drop' functions, which take or drop first 'p' elements from the list.
Require Import Vector.
Fixpoint take {A} {n} (p:nat) (a: t A n) : p<=n -> t A p :=
match a return ( p<=n -> t A p) with
| cons A v (S m) => cons (hd v) (take m (tl v)) m
| nil => fun pf => a
end.
The error (in case of nil) is:
The term "a" has type "t A n" while it is expected to have type "t A p".
Could somebody help me with some starting points? Thanks!
I don't understand your approach. You're always returning a non-empty vector when the argument is a non-empty vector, but take must return nil when p=0 regardless of the vector.
Here's one approach to building take. Rather than using the hypothesis p <= n, I express the length of the argument n as a sum of the number p of elements to take and the number of trailing elements m, which is possible iff p <= n. This allows for an easier recursive definition, because (S p') + m is structurally equal to S (p' + m). Note that the discrimination is on the number of elements to take: return nil if taking 0, return cons head new_tail otherwise.
This version of the take function has the desired computational behavior, so all that's left is to define one with the desired proof content. I use the Program feature to do this conveniently: fill in the computational content (trivial, I just need to say that I want to use m = n - p), then complete the proof obligations (which are simple arithmetic).
Require Import Arith.
Require Import Vector.
Fixpoint take_plus {A} {m} (p:nat) : t A (p+m) -> t A p :=
match p return t A (p+m) -> t A p with
| 0 => fun a => nil _
| S p' => fun a => cons A (hd a) _ (take_plus p' (tl a))
end.
Program Definition take A n p (a : t A n) (H : p <= n) : t A p :=
take_plus (m := n - p) p a.
Solve Obligations using auto with arith.
For your newdrop : forall A n p, t A n -> p <= n -> t A (n-p), the following approach works. You need to help Coq by telling it what p and n become in the recursive call.
Program Fixpoint newdrop {A} {n} p : t A n -> p <= n -> t A (n-p) :=
match p return t A n -> p <= n -> t A (n-p) with
| 0 => fun a H => a
| S p' => fun a H => newdrop p' (tl a) (_ : p' <= n - 1)
end.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
I don't know why Solve Obligations using omega. doesn't work but solving each obligation individually works.