How to write boolean comparsion function in Coq - boolean

I'm trying to remove all integers that are greater than 7 from a list as follows
filter (fun n => n > 7).
However I get the following error
The term "n > 7" has type "Prop" while it is expected to have type "bool".
I am new to Coq, how can I fix it?

The problem is that #List.filter nat expects a function of type nat -> bool but you supplied a function of type nat -> Prop. Here, #List.filter nat is List.filter applied to the type argument nat. One difference between bool and Prop is that bool is decidable while Prop is not: there are propositions P such that neither P nor ~P are known; one can always determine whether something is true or false.
In order to resolve this situation, you need to write a function of type nat -> bool that returns true when applied to an argument greater than 7 and false otherwise. You can take advantage of the fact that the standard library defines boolean comparison functions over the natural numbers. I would also suggest reading the first volume of Software Foundations to familiarize yourself with Coq. It is more accessible and easy-going than some other prominent introductions (it was used in a program verification course at my university that presupposed little functional programming experience).
Here is a minimal example using only the builtin list type and notations:
Require Import Coq.Lists.List.
Import ListNotations.
Fixpoint filterb {A : Type} (f : A -> bool) (xs : list A) : list A :=
match xs with
| [] => []
| x :: xs => if f x then x :: filterb f xs else filterb f xs
end.
Fixpoint ltb (n m : nat) : bool :=
match n, m with
| n , 0 => false
| 0 , S m => true
| S n, S m => ltb n m
end.
Eval compute in (filterb (fun n => ltb 7 n) [5;6;7;8;9]).
(* = [8;9] *)

Related

How can I match on a specific value in Coq?

I'm trying to implement a function that simply counts the number of occurrences of some nat in a bag (just a synonym for a list).
This is what I want to do, but it doesn't work:
Require Import Coq.Lists.List.
Import ListNotations.
Definition bag := list nat.
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => O
| v :: t => S (count v t)
| _ :: t => count v t
end.
Coq says that the final clause is redundant, i.e., it just treats v as a name for the head instead of the specific v that is passed to the call of count. Is there any way to pattern match on values passed as function arguments? If not, how should I instead write the function?
I got this to work:
Fixpoint count (v:nat) (s:bag) : nat :=
match s with
| nil => O
| h :: t => if (beq_nat v h) then S (count v t) else count v t
end.
But I don't like it. I'd rather pattern match if possible.
Pattern matching is a different construction from equality, meant to discriminate data encoded in form of "inductives", as standard in functional programming.
In particular, pattern matching falls short in many cases, such as when you need potentially infinite patterns.
That being said, a more sensible type for count is the one available in the math-comp library:
count : forall T : Type, pred T -> seq T -> nat
Fixpoint count s := if s is x :: s' then a x + count s' else 0.
You can then build your function as count (pred1 x) where pred1 : forall T : eqType, T -> pred T , that is to say, the unary equality predicate for a fixed element of a type with decidable (computable) equality; pred1 x y <-> x = y.
I found in another exercise that it's OK to open up a match clause on the output of a function. In that case, it was "evenb" from "Basics". In this case, try "eqb".
Well, as v doesn't work in the match, I thought that maybe I could ask whether the head of the list was equal to v. And yes, it worked. This is the code:
Fixpoint count (v : nat) (s : bag) : nat :=
match s with
| nil => 0
| x :: t =>
match x =? v with
| true => S ( count v t )
| false => count v t
end
end.

How does the discriminate tactic work?

I was curious about how the discriminate tactic works behind the curtain. Therefore I did some experiments.
First a simple Inductive definition:
Inductive AB:=A|B.
Then a simple lemma which can be proved by the discriminate tactic:
Lemma l1: A=B -> False.
intro.
discriminate.
Defined.
Let's see what the proof looks like:
Print l1.
l1 =
fun H : A = B =>
(fun H0 : False => False_ind False H0)
(eq_ind A
(fun e : AB => match e with
| A => True
| B => False
end) I B H)
: A = B -> False
This looks rather complicated and I do not understand what is happening here. Therefore I tried to prove the same lemma more explicitly:
Lemma l2: A=B -> False.
apply (fun e:(A=B) => match e with end).
Defined.
Let's again see what Coq has made with this:
Print l2.
l2 =
fun e : A = B =>
match
e as e0 in (_ = a)
return
(match a as x return (A = x -> Type) with
| A => fun _ : A = A => IDProp
| B => fun _ : A = B => False
end e0)
with
| eq_refl => idProp
end
: A = B -> False
Now I am totally confused. This is still more complicated.
Can anyone explain what is going on here?
Let's go over this l1 term and describe every part of it.
l1 : A = B -> False
l1 is an implication, hence by Curry-Howard correspondence it's an abstraction (function):
fun H : A = B =>
Now we need to construct the body of our abstraction, which must have type False. The discriminate tactic chooses to implement the body as an application f x, where f = fun H0 : False => False_ind False H0 and it's just a wrapper around the induction principle for False, which says that if you have a proof of False, you can get a proof of any proposition you want (False_ind : forall P : Prop, False -> P):
(fun H0 : False => False_ind False H0)
(eq_ind A
(fun e : AB => match e with
| A => True
| B => False
end) I B H)
If we perform one step of beta-reduction, we'll simplify the above into
False_ind False
(eq_ind A
(fun e : AB => match e with
| A => True
| B => False
end) I B H)
The first argument to False_ind is the type of the term we are building. If you were to prove A = B -> True, it would have been False_ind True (eq_ind A ...).
By the way, it's easy to see that we can simplify our body further - for False_ind to work it needs to be provided with a proof of False, but that's exactly what we are trying to construct here! Thus, we can get rid of False_ind completely, getting the following:
eq_ind A
(fun e : AB => match e with
| A => True
| B => False
end) I B H
eq_ind is the induction principle for equality, saying that equals can be substituted for equals:
eq_ind : forall (A : Type) (x : A) (P : A -> Prop),
P x -> forall y : A, x = y -> P y
In other words, if one has a proof of P x, then for all y equal to x, P y holds.
Now, let's create step-by-step a proof of False using eq_ind (in the end we should obtain the eq_ind A (fun e : AB ...) term).
We start, of course, with eq_ind, then we apply it to some x - let's use A for that purpose. Next, we need the predicate P. One important thing to keep in mind while writing P down is that we must be able to prove P x. This goal is easy to achieve - we are going to use the True proposition, which has a trivial proof. Another thing to remember is the proposition we are trying to prove (False) - we should be returning it if the input parameter is not A.
With all the above the predicate almost writes itself:
fun x : AB => match x with
| A => True
| B => False
end
We have the first two arguments for eq_ind and we need three more: the proof for the branch where x is A, which is the proof of True, i.e. I. Some y, which will lead us to the proposition we want to get proof of, i.e. B, and a proof that A = B, which is called H at the very beginning of this answer. Stacking these upon each other we get
eq_ind A
(fun x : AB => match x with
| A => True
| B => False
end)
I
B
H
And this is exactly what discriminate gave us (modulo some wrapping).
Another answer focuses on the discriminate part, I will focus on the manual proof. You tried:
Lemma l2: A=B -> False.
apply (fun e:(A=B) => match e with end).
Defined.
What should be noted and makes me often uncomfortable using Coq is that Coq accepts ill-defined definitions that it internally rewrites into well-typed terms. This allows to be less verbose, since Coq adds itself some parts. But on the other hand, Coq manipulates a different term than the one we entered.
This is the case for your proof. Naturally, the pattern-matching on e should involve the constructor eq_refl which is the single constructor of the eq type. Here, Coq detects that the equality is not inhabited and thus understands how to modify your code, but what you entered is not a proper pattern-matching.
Two ingredients can help understand what is going on here:
the definition of eq
the full pattern-matching syntax, with as, in and return terms
First, we can look at the definition of eq.
Inductive eq {A : Type} (x : A) : A -> Prop := eq_refl : x = x.
Note that this definition is different from the one that seems more natural (in any case, more symmetric).
Inductive eq {A : Type} : A -> A -> Prop := eq_refl : forall (x:A), x = x.
This is really important that eq is defined with the first definition and not the second. In particular, for our problem, what is important is that, in x = y, x is a parameter while y is an index. That is to say, x is constant across all the constructors while y can be different in each constructor. You have the same difference with the type Vector.t. The type of the elements of a vector will not change if you add an element, that's why it is implemented as a parameter. Its size, however, can change, that's why it is implemented as an index.
Now, let us look at the extended pattern-matching syntax. I give here a very brief explanation of what I have understood. Do not hesitate to look at the reference manual for safer information. The return clause can help specify a return type that will be different for each branch. That clause can use the variables defined in the as and in clauses of the pattern-matching, which binds respectively the matched term and the type indices. The return clause will both be interpreted in the context of each branch, substituting the variables of as and in using this context, to type-check the branches one by one, and be used to type the match from an external point of view.
Here is a contrived example with an as clause:
Definition test n :=
match n as n0 return (match n0 with | 0 => nat | S _ => bool end) with
| 0 => 17
| _ => true
end.
Depending on the value of n, we are not returning the same type. The type of test is forall n : nat, match n with | 0 => nat | S _ => bool end. But when Coq can decide in which case of the match we are, it can simplify the type. For example:
Definition test2 n : bool := test (S n).
Here, Coq knows that, whatever is n, S n given to test will result as something of type bool.
For equality, we can do something similar, this time using the in clause.
Definition test3 (e:A=B) : False :=
match e in (_ = c) return (match c with | B => False | _ => True end) with
| eq_refl => I
end.
What's going on here ? Essentially, Coq type-checks separately the branches of the match and the match itself. In the only branch eq_refl, c is equal to A (because of the definition of eq_refl which instantiates the index with the same value as the parameter), therefore we claimed we returned some value of type True, here I. But when seen from an external point of view, c is equal to B (because e is of type A=B), and this time the return clause claims that the match returns some value of type False. We use here the capability of Coq to simplify pattern-matching in types that we have just seen with test2. Note that we used True in the other cases than B, but we don't need True in particular. We only need some inhabited type, such that we can return something in the eq_refl branch.
Going back to the strange term produced by Coq, the method used by Coq does something similar, but on this example, certainly more complicated. In particular, Coq often uses types IDProp inhabited by idProp when it needs useless types and terms. They correspond to True and I used just above.
Finally, I give the link of a discussion on coq-club that really helped me understand how extended pattern-matching is typed in Coq.

Inductive definition for family of types

I have been struggling on this for a while now. I have an inductive type:
Definition char := nat.
Definition string := list char.
Inductive Exp : Set :=
| Lit : char -> Exp
| And : Exp -> Exp -> Exp
| Or : Exp -> Exp -> Exp
| Many: Exp -> Exp
from which I define a family of types inductively:
Inductive Language : Exp -> Set :=
| LangLit : forall c:char, Language (Lit c)
| LangAnd : forall r1 r2: Exp, Language(r1) -> Language(r2) -> Language(And r1 r2)
| LangOrLeft : forall r1 r2: Exp, Language(r1) -> Language(Or r1 r2)
| LangOrRight : forall r1 r2: Exp, Language(r2) -> Language(Or r1 r2)
| LangEmpty : forall r: Exp, Language (Many r)
| LangMany : forall r: Exp, Language (Many r) -> Language r -> Language (Many r).
The rational here is that given a regular expression r:Exp I am attempting to represent the language associated with r as a type Language r, and I am doing so with a single inductive definition.
I would like to prove:
Lemma L1 : forall (c:char)(x:Language (Lit c)),
x = LangLit c.
(In other words, the type Language (Lit c) has only one element, i.e. the language of the regular expression 'c' is made of the single string "c". Of course I need to define some semantics converting elements of Language r to string)
Now the specifics of this problem are not important and simply serve to motivate my question: let us use nat instead of Exp and let us define a type List n which represents the lists of length n:
Parameter A:Set.
Inductive List : nat -> Set :=
| ListNil : List 0
| ListCons : forall (n:nat), A -> List n -> List (S n).
Here again I am using a single inductive definition to define a family of types List n.
I would like to prove:
Lemma L2: forall (x: List 0),
x = ListNil.
(in other words, the type List 0 has only one element).
I have run out of ideas on this one.
Normally when attempting to prove (negative) results with inductive types (or predicates), I would use the elim tactic (having made sure all the relevant hypothesis are inside my goal (generalize) and only variables occur in the type constructors). But elim is no good in this case.
If you are willing to accept more than just the basic logic of Coq, you can just use the dependent destruction tactic, available in the Program library (I've taken the liberty of rephrasing your last example in terms of standard-library vectors):
Require Coq.Vectors.Vector.
Require Import Program.
Lemma l0 A (v : Vector.t A 0) : v = #Vector.nil A.
Proof.
now dependent destruction v.
Qed.
If you inspect the term, you'll see that this tactic relied on the JMeq_eq axiom to get the proof to go through:
Print Assumptions l0.
Axioms:
JMeq_eq : forall (A : Type) (x y : A), x ~= y -> x = y
Fortunately, it is possible to prove l0 without having to resort to features outside of Coq's basic logic, by making a small change to the statement of the previous lemma.
Lemma l0_gen A n (v : Vector.t A n) :
match n return Vector.t A n -> Prop with
| 0 => fun v => v = #Vector.nil A
| _ => fun _ => True
end v.
Proof.
now destruct v.
Qed.
Lemma l0' A (v : Vector.t A 0) : v = #Vector.nil A.
Proof.
exact (l0_gen A 0 v).
Qed.
We can see that this new proof does not require any additional axioms:
Print Assumptions l0'.
Closed under the global context
What happened here? The problem, roughly speaking, is that in Coq we cannot perform case analysis on terms of dependent types whose indices have a specific shape (such as 0, in your case) directly. Instead, we must prove a more general statement where the problematic indices are replaced by variables. This is exactly what the l0_gen lemma is doing. Notice how we had to make the match on n return a function that abstracts on v. This is another instance of what is known as "convoy pattern". Had we written
match n with
| 0 => v = #Vector.nil A
| _ => True
end.
Coq would see the v in the 0 branch as having type Vector.t A n, making that branch ill-typed.
Coming up with such generalizations is one of the big pains of doing dependently typed programming in Coq. Other systems, such as Agda, make it possible to write this kind of code with much less effort, but it was only recently shown that this can be done without relying on the extra axioms that Coq wanted to avoid including in its basic theory. We can only hope that this will be simplified in future versions.

Counting number of different elements in a list in Coq

I'm trying to write a function that takes a list of natural numbers and returns as output the amount of different elements in it. For example, if I have the list [1,2,2,4,1], my function DifElem should output "3". I've tried many things, the closest I've gotten is this:
Fixpoint DifElem (l : list nat) : nat :=
match l with
| [] => 0
| m::tm =>
let n := listWidth tm in
if (~ In m tm) then S n else n
end.
My logic is this: if m is not in the tail of the list then add one to the counter. If it is, do not add to the counter, so I'll only be counting once: when it's the last time it appears. I get the error:
Error: The term "~ In m tm" has type "Prop"
which is not a (co-)inductive type.
In is part of Coq's list standard library Coq.Lists.List. It is defined there as:
Fixpoint In (a:A) (l:list A) : Prop :=
match l with
| [] => False
| b :: m => b = a \/ In a m
end.
I think I don't understand well enough how to use If then statements in definitions, Coq's documentation was not helpful enough.
I also tried this definition with nodup from the same library:
Definition Width (A : list nat ) := length (nodup ( A ) ).
In this case what I get as error is:
The term "A" has type "list nat" while it is expected to have
type "forall x y : ?A0, {x = y} + {x <> y}".
And I'm quiet confused as to what's going on here. I'd appreciate your help to solve this issue.
You seem to be confusing propositions (Prop) and booleans (bool). I'll try to explain in simple terms: a proposition is something you prove (according to Martin-Lof's interpretation it is a set of proofs), and a boolean is a datatype which can hold only 2 values (true / false). Booleans can be useful in computations, when there are only two possible outcomes and no addition information is not needed. You can find more on this topic in this answer by #Ptival or a thorough section on this in the Software Foundations book by B.C. Pierce et al. (see Propositions and Booleans section).
Actually, nodup is the way to go here, but Coq wants you to provide a way of deciding on equality of the elements of the input list. If you take a look at the definition of nodup:
Hypothesis decA: forall x y : A, {x = y} + {x <> y}.
Fixpoint nodup (l : list A) : list A :=
match l with
| [] => []
| x::xs => if in_dec decA x xs then nodup xs else x::(nodup xs)
end.
you'll notice a hypothesis decA, which becomes an additional argument to the nodup function, so you need to pass eq_nat_dec (decidable equality fot nats), for example, like this: nodup eq_nat_dec l.
So, here is a possible solution:
Require Import Coq.Arith.Arith.
Require Import Coq.Lists.List.
Import ListNotations.
Definition count_uniques (l : list nat) : nat :=
length (nodup eq_nat_dec l).
Eval compute in count_uniques [1; 2; 2; 4; 1].
(* = 3 : nat *)
Note: The nodup function works since Coq v8.5.
In addition to Anton's solution using the standard library I'd like to remark that mathcomp provides specially good support for this use case along with a quite complete theory on count and uniq. Your function becomes:
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.
Definition count_uniques (T : eqType) (s : seq T) := size (undup s).
In fact, I think the count_uniques name is redundant, I'd prefer to directly use size (undup s) where needed.
Using sets:
Require Import MSets.
Require List. Import ListNotations.
Module NatSet := Make Nat_as_OT.
Definition no_dup l := List.fold_left (fun s x => NatSet.add x s) l NatSet.empty.
Definition count_uniques l := NatSet.cardinal (no_dup l).
Eval compute in count_uniques [1; 2; 2; 4; 1].

Function of comparison coq

I want to make a function of natural numbers comparison in coq
I declare a Set of invariant contain sup, inf, egal
Inductive invr:Type:=inf | sup | egal.
And I define a function comparaison
Definition comparaison (inv:invr)(a b:nat):bool:=
match invr with
|inf => if (a < b) then true else false
|sup => if (a > b) then true else false
|egal=> if (a = b) then true else false
end.
But it does not work! Thanks for your response.
You are trying to match type (set) invr with its constructors values instead of variable inv, so you get an error
The term "invr" has type "Set" while it is expected to have type
"invr".
You need to do the matching for inv, not invr
Definition comparaison (inv:invr)(a b:nat):bool:=
match inv with
|inf => if (a < b) then true else false
|sup => if (a > b) then true else false
|egal=> if (a = b) then true else false
end.
Also make sure that you have <, >, = notations are defined to return bool, because by default they return Prop, which can't be used in if/else. So you need to use beq_nat, and leb from Arith.
Simplified final version (removed redundant if/else branches).
Require Import Coq.Arith.Arith.
Inductive invr : Type:= inf | sup | egal.
Definition comparaison (inv:invr)(a b:nat):bool:=
match inv with
|inf => leb a b
|sup => leb b a
|egal=> beq_nat a b
end.
This is a typical beginner mistake.
< stands for lt, which has type:
lt : nat -> nat -> Prop
That is, a < b is just a proposition, not a procedure that computes whether a is less than b!
The same goes for equality.
What you want to use is a function that computes the truth of these propositions, either as a boolean or as a richer type:
In the library Arith:
beq_nat: nat -> nat -> bool
leb: nat -> nat -> bool
(* or the more informative versions which return proofs of what they decide *)
eq_nat_dec: forall n m : nat, {n = m} + {n <> m}
lt_dec: forall n m : nat, {n < m} + {~ n < m}
So the following is a valid expression:
if beq_nat a b then true else false
Also note that the following is a valid expression equivalent to the precedent one (since beq_nat returns a bool):
beq_nat a b