Coq, true datatype - coq

So I have this problem:
In environment
n : nat
The term "true" has type "Datatypes.bool" while it is expected to have type
"bool".
I have no idea what does it mean.
trying to prove:
Theorem eqb_0_l : forall n:nat,
0 =? n = true -> n = 0.

I guess you are working with Software Foundations - which has at least in the introductory chapters its own definition of bool. If you Require modules from both, Software Foundations and the Coq standard library, you easily end up with multiple definitions of bool, nat, ... .
The solution is to not Require anything from the Coq standard library in the introductory chapters from Software Foundations. Only Require modules which come with SF.
SF does this so because it explains how to define nat and bool and how to prove basic lemmas about these taypes. This can't be done without actually defining them, which leads to the mentioned problems.

Related

Proving technology of Coq's kernel

Isabelle bases its kernel proof power in resolution coupled with higher-order unification.
How are theorems proven by Coq's kernel?
The question arises from reading Paulson's "The foundation of a generic theorem prover":
Propositions-as-types could consume excessive space; and what would take the place of Huet's unification procedure for higher-order logic?
There are two kinds of technology in most provers: the "proving" part (responsible for building a proof, since it is often too tedious for the user) and the "checking" part (responsible for verifying that a proof is well-formed and matches a given theorem statement). In both Isabelle and Coq, the kernel is only responsible for the "checking" part.
In the case of Coq, the propositions-as-types paradigm is indeed used for checking proofs. In other words, a proof is a lambda-term of the Calculus of Inductive Constructions (CIC) whose type is compared to the theorem statement seen as a type.
How are theorems proven by Coq's kernel?
As explained above, theorems are not proven by Coq's kernel, only checked.
That check is done as usual with type checking: If the term is an application, check (recursively) that the arguments has the right type, and that the function return type matches the type. For example, to prove that a + f(b) has type nat, you must check that plus has type nat -> nat -> nat, that f has type A -> nat, that a has type nat and b has type A.
The proof has to be constructed by the user. The proof itself is a lambda term. The theorem proposition is the type of the lambda term.
Because it may be difficult to create the right lambda term directly, Coq does not force the user to write the whole term in one go. One can instead leave "holes" in the term to be filled in later, either by hand or with tactics. Tactics are small programs that try to fill in a piece of the proof (which may or may not be the right piece...).
Once the entire lambda term has been constructed, the proof is checked by Coq by checking that the lambda term really has the type of the proposition that one wishes to prove.

How to set implicit parameters for constructor

Playing with nostutter excersizes I found another odd behaviour. Here is the code:
Inductive nostutter {X:Type} : list X -> Prop :=
| ns_nil : nostutter []
| ns_one : forall (x : X), nostutter [x]
| ns_cons: forall (x : X) (h : X) (t : list X), nostutter (h::t) -> x <> h -> nostutter (x::h::t).
Example test_nostutter_manual: not (nostutter [3;1;1;4]).
Proof.
intro.
inversion_clear H.
inversion_clear H0.
unfold not in H2.
(* We are here *)
specialize (H2 eq_refl).
apply H2.
Qed.
Status after unfold is this:
1 subgoal (ID 229)
H1 : 3 <> 1
H : nostutter [1; 4]
H2 : 1 = 1 -> False
============================
False
When I run specialize (H2 eq_refl). inside IndProp.v that loads other Logical foundations files, it works. Somehow it understands that it needs to put "1" as a parameter. Header of IndProp.v is this:
Set Warnings "-notation-overridden,-parsing".
From LF Require Export Logic.
Require Import String.
Require Coq.omega.Omega.
When I move the code into another file "nostutter.v", this same code gives an expected error:
The term "eq_refl" has type "RelationClasses.Reflexive Logic.eq" while
it is expected to have type "1 = 1".
Header of nostutter.v:
Set Warnings "-notation-overridden,-parsing".
Require Import List.
Import ListNotations.
Require Import PeanoNat.
Import Nat.
Local Open Scope nat_scope.
I have to explicitly add a parameter to eq_refl: specialize (H2 (eq_refl 1)).
I think it's not related specifically to specialize. What is it? How to fix?
The problem is importing PeanoNat.Nat.
When you import PeanoNat, the module type Nat comes into scope, so importing Nat brings in PeanoNat.Nat. If you meant to import Coq.Init.Nat, you'll either have to import it before importing PeanoNat, or import it with Import Init.Nat..
Why does importing PeanoNat.Nat cause trouble in this case?
Arith/PeanoNat.v (static link) contains the module1 Nat. Inside that module, we find2 the unusual looking line
Include NBasicProp <+ UsualMinMaxLogicalProperties <+ UsualMinMaxDecProperties.
All this means is that each of NBasicProp, UsualMinMaxLogicalProperties and UsualMinMaxDecProperties are included, which in turn means that everything defined in those modules is included in the current module. Separating this line out into three Include commands, we can figure out which one is redefining eq_refl. It turns out to be NBasicProp, which is found in this file (static link). We're not quite there yet: the redefinition of eq_refl isn't here. However, we see the definition of NBasicProp in terms of NMaxMinProp.
This leads us to NMaxMin.v, which in turn leads us to NSub.v, which leads us to NMulOrder.v, which leads us to NAddOrder.v, which leads us to NOrder.v, which leads us to NAdd.v, which leads us to NBase.v, ...
I'll cut to the chase here. Eventually we end up in Structures/Equality.v (static link) with the module BackportEq which finally gives us our redefinition of eq_refl.
Module BackportEq (E:Eq)(F:IsEq E) <: IsEqOrig E.
Definition eq_refl := #Equivalence_Reflexive _ _ F.eq_equiv.
Definition eq_sym := #Equivalence_Symmetric _ _ F.eq_equiv.
Definition eq_trans := #Equivalence_Transitive _ _ F.eq_equiv.
End BackportEq.
The way this is defined, eq_refl (without any arguments) has type Reflexive eq, where Reflexive is the class
Class Reflexive (R : relation A) :=
reflexivity : forall x : A, R x x.
(found in Classes/RelationClasses.v)
So that means that we'll always need to supply an extra argument to get something of type x = x. There are no implicit arguments defined here.
Why is importing modules like PeanoNat.Nat generally a bad idea?
If the wild goose chase above wasn't convincing enough, let me just say that modules like this one, which extend and import other modules and module types, are often not meant to be imported. They often have short names (like N, Z or Nat) so any theorem you want to use from them is easily accessible without having to type out a long name. They usually have a long chain of imports and thus contain a vast number of items. If you import them, now that vast number of items is polluting your global namespace. As you saw with eq_refl, that can cause unexpected behavior with what you thought was a familiar constant.
Most of the modules encountered in this adventure are of the "module type/functor" variety. Suffice to say, they're difficult to understand fully, but a short guide can be found here.
My sleuthing was done by opening files in CoqIDE and running the command Locate eq_refl. (or better yet, ctrl+shift+L) after anything that might import from elsewhere. Locate can also tell you where a constant was imported from. I wish there were an easier way to see the path of imports in module types, but I don't think so. You could guess that we'd end up in Coq.Classes.RelationClasses based on the type of the overwritten eq_refl, but that isn't as precise.

refining types with modules and typeclasses

I'm not very familiar with modules or typeclasses in Coq, but based on my basic understanding of them, I believe I have a problem where I should use them.
I want to define a sum function that adds all the elements of a polymorphic list t. It should only work when the type of elements of the list (t) has some definition for plus_function and plus_id_element. The definition of sum I'd like to write would be something like this:
Fixpoint sum {t : Type} (l : list t) :=
match l with
| Nil => plus_id_element t
| Cons x xs => ((plus_function t) x (sum xs))
end.
I don't know what's the usual way to achieve something like this in Coq. I believe in Idris, for example, one would replace t by an interface/typeclass that defines plus_function and plus_id_element. Although typeclasses exist in Coq, I haven't seen them used very often and I believe people usually use modules instead to achieve something similar. I'm not sure if I'm mixing unrelated concepts. Are modules and typeclasses useful for this problem? What would be the recommended approach?
Indeed typeclasses were designed for this exact task, but then you face the hard problem of designing the particular class hierarchy that will fit your problem well.
Coq doesn't provide a standard hierarchy of mathematical operators, and there are many delicate trade-offs in building one with regard to the choice of classes, operators, and axioms.
I thus recommend starting from a mature development such as the MathComp library. MathComp is based on "Canonical Structures" which are a similar notion to type classes, and provides quite a few ready to use classes. The Packaging Mathematical Structures" paper contains more details, but the basic idea is that types pack their operators. For example, if you want to reason about abelian modules you can use the zmodType structure:
From mathcomp Require Import all_ssreflect all_algebra.
Open Scope ring_scope.
Definition sum (A: zmodType) (s : seq A) := foldr +%R 0 s.
to define the sum over a list of elements of the abelian group A. Even better, don't define you own sum operator and just use the one provided by the library: \sum_(x <- s) x:
Lemma eq_sum (A: zmodType) (s : seq A) : sum s = \sum_(x <- s) x.
Proof. by rewrite unlock. Qed.

General Advice about When to Use Prop and When to use bool

I am formalizing a grammar which is essentially one over boolean expressions. In coq, you can get boolean-like things in Prop or more explicitly in bool.
So for example, I could write:
true && true
Or
True /\ True
The problem is that in proofs (which is what I really care about) I can do a case analysis in domain bool, but in Prop this is not possible (since all members are not enumerable, I suppose). Giving up this tactic and similar rewriting tactics seems like a huge drawback even for very simple proofs.
In general, what situations would one choose Prop over bool for formalizing? I realize this is a broad question, but I feel like this is not addressed in the Coq manual sufficiently. I am interested in real world experience people have had going down both routes.
There are lots of different opinions on this. My personal take is that you are often better off not making this choice: it makes sense to have two versions of a property, one in Prop, the other one in bool.
Why would you want this? As you pointed out, booleans support case analysis in proofs and functions, which general propositions do not. However, Prop is more convenient to use in certain cases. Suppose you have a type T with finitely many values. We can write a procedure
all : (T -> bool) -> bool
that decides whether a boolean property P : T -> bool holds of all elements of T. Imagine that we know that all P = true, for some property P. We might want to use this fact to conclude that P x = true for some value x. To do this, we need to prove a lemma about all:
allP : forall P : T -> bool,
all P = true <-> (forall x : T, P x = true)
This lemma connects two different formulations of the same property: a boolean one and a propositional one. When reasoning about all in a proof, we can invoke allP to convert freely between the two. We can also have different conversion lemmas:
allPn : forall P,
all P = false <-> (exists x, P x = false)
In fact, we are free to choose any Coq proposition whatsoever to relate to a boolean computation (as long, of course, as we can prove that the two are logically equivalent). For instance, if we would like to have a custom induction principle associated with a boolean property, we can look for an equivalent formulation as an inductively defined proposition.
The Mathematical Components library is a good example of development that follows this style. Indeed, because it is so pervasive there, the library provides a special view mechanism for writing conversion lemmas like the one above and applying them. In plain Coq, we can also use the rewrite tactic to apply logical equivalences more conveniently.
Of course, there are many situations where it does not make sense to have two formulations of the same property. Sometimes, you are forced to use Prop, because the property you care about is undecidable. Sometimes, you might feel that you wouldn't gain anything by writing your property in Prop, and may keep it only as a boolean.
In addition to the Software Foundations chapter linked above, this answer discusses the difference between bool and Prop in more depth.

How do you define an ordered pair in Coq?

I am a programmer, but an ultra-newbie to Coq, and have tried to figure out the tutorials without much success. My question is very simple: How does one define an ordered pair (of natural numbers) in Coq?
Here was my attempt:
Variable node1 : nat.
Variable node2 : nat.
Inductive edge : type := node1 -> node2.
(Note that "edge" is the name I am using for ordered pair.) The third line gives a syntax error, suggesting that I need a '.' in the sentence somewhere.
I don't know what to do. Any help would be great! (Also, is there a tutorial that helps teach very basic Coq concepts better than the ones that are easily seen given a Google search for "Coq Tutorial" ?)
You can do this simply enough by just using a Coq definition:
Definition ordered_pair := (nat * nat) % type.
This introduces ordered_pair as a synonym for (nat * nat) % type (note that the % type is required to get Coq to interpret * in the scope of types, rather than naturals). The real power is in the use of *:
Inductive prod (A B:Type) : Type :=
pair : A -> B -> prod A B.
(From http://coq.inria.fr/stdlib/Coq.Init.Datatypes.html)
You get all the necessary elimination principles, etc... from there.