RelationClasses versus CRelationClasses - coq

The Coq standard library has two subsets of classes modules, one anchored in Coq.Classes.RelationClasses and the other in Coq.Classes.CRelationClasses. The latter seems to have been added more recently (2012).
I must be missing something obvious as they both look very similar to me.
What is the reason they exist?

The key difference is in the type of relations they support:
(* RelationClasses, actually defined in Relation_Definitions *)
Definition relation (A : Type) := A -> A -> Prop.
(* CRelationClasses *)
Definition crelation (A : Type) := A -> A -> Type.

In addition to crelation producing a Type instead of a Prop, another key difference is that crelation is universe polymorphic, but relation is not.
Require Import Relation_Definitions.
Require Import Coq.Classes.CRelationClasses.
Set Printing Universes.
Print relation.
(*
relation =
fun A : Type#{Coq.Relations.Relation_Definitions.1} => A -> A -> Prop
: Type#{Coq.Relations.Relation_Definitions.1} ->
Type#{max(Set+1,Coq.Relations.Relation_Definitions.1)}
*)
Print crelation.
(*
crelation#{u u0} =
fun A : Type#{u} => A -> A -> Type#{u0}
: Type#{u} -> Type#{max(u,u0+1)}
(* u u0 |= *)
*)
Check (fun (R: crelation (Type -> Type)) => R crelation).
Fail Check (fun (R: relation (Type -> Type)) => R relation).
(*
The command has indeed failed with message:
In environment
R : relation (Type#{test.7} -> Type#{test.8})
The term "relation" has type
"Type#{Coq.Relations.Relation_Definitions.1} ->
Type#{max(Set+1,Coq.Relations.Relation_Definitions.1)}"
while it is expected to have type "Type#{test.7} -> Type#{test.8}"
(universe inconsistency: Cannot enforce Coq.Relations.Relation_Definitions.1
<= test.8 because test.8 < Coq.Relations.Relation_Definitions.1).
*)

Related

how to create a polymorphe couple such as "( a : type A, b : type B ) " in lambda-calculus

I am working on a project in Lambda-calculus and i am trying to code polymorphe couple with coqide
but a have a problem coding the constructor that respect the type pprod
Definition pprod : Set -> Set -> Set := fun A B => forall T : Set , (A -> B -> T) -> T.
I have a problem with pcpl
Definition pcpl : Set -> Set -> pprod :=
fun A B T : Set => fun (a : A) (b : B) => fun k : A -> B -> T => k a b.
this is the error i get :
The term "pprod" has type "Set -> Set -> Set"
which should be Set, Prop or Type.
The problem is that you are quantifying over Set, so the resulting product type cannot be of type Set, but of a larger type Type. So your definition should look like
Definition pprod : Set -> Set -> Type := fun A B => forall T : Set , (A -> B -> T) -> T.
the constructor for products should look like
Definition pcpl (A : Set) (B : Set) : A -> B -> pprod A B :=
fun (a : A) (b : B) => fun T : Set => fun k : A -> B -> T => k a b.
An alternative way to approach this is to use the polymorphic types in Coq, namely the types in Prop:
Definition pprod : Prop -> Prop -> Prop :=
fun A B => forall T : Prop , (A -> B -> T) -> T.
Definition pcpl (A : Prop) (B : Prop) : A -> B -> pprod A B :=
fun (a : A) (b : B) => fun T : Prop => fun k : A -> B -> T => k a b.
Note the universes in Coq are a bit confusing. See What is different between Set and Type in Coq? for details.
I'm going to take this opportunity to advertise the new Proof Assistants stack exchange.

Is the %hint annotation imported/Dec and auto annotation?

I have a datatype that depends on a predicate P : a -> Type, meaning that some of its data constructors refer have an implicit P x as argument. I would like idris to be able to automatically infer this implicit. For this, I annotated the implicit with the keyword auto and I wrote a function isP : (x : a) -> Dec (P x) with a %hint annotation before the type declaration. Namely, something like:
module P
P : a -> Type
%hint
isP : (x : a) -> Dec (P x)
and in a separate file
module Main
import P
data Foo : Type where
Bar : (x : a) -> .{auto prf : P x} -> Foo
That said, I can't declare values of said Foo type because Idris claims the it can't infer prf.
Is this because prf has type P x instead of Dec (P x) or is it because the %hint flag does not get imported?
In either case, how can I get Idris to use a Dec value to try to find an implicit?
The %hint flag is imported, as you guess, it's because Dec (P x) is different than P x.
There's a trick though, you can use this datatype:
data IsYes : prop -> Type where
SoTrue : IsYes (Yes prop)
(basically, you define a type that holds a Yes for a given property)
and then you can use default instead of auto to check if the property holds:
data Foo : Type where
Bar : (x : a) -> .{default SoTrue prf : IsYes (isP x)} -> Foo
Note: with this trick, you don't even need %hint anymore, you just check the outcome of isP at compile time.

How does the induction principle for the singleton type unit in Coq work?

I was going through Adam Chlipala's book on Coq and it defined the inductive type:
Inductive unit : Set :=
| tt.
I was trying to understand its induction principle:
Check unit_ind.
(* unit_ind
: forall P : unit -> Prop, P tt -> forall u : unit, P u *)
I am not sure if I understand what the output of Coq means.
1) So check gives me a look at the type of "objects" right? So unit_ind has type:
forall P : unit -> Prop, P tt -> forall u : unit, P u
Right?
2) How does one read that type? I am having trouble understanding where to put the parenthesis or something...For the first thing before the comma, it doesn't make sense to me to read it as:
IF "for all P of type unit" THEN " Prop "
since the hypothesis is not really something true or false. So I assume the real way to real the first thing is this way:
forall P : (unit -> Prop), ...
so P is just a function of type unit to prop. Is this correct?
I wish this was correct but under that interpretation I don't know how to read the part after the first comma:
P tt -> forall u : unit, P u
I would have expected all the quantifications of variables in existence to be defined at the beginning of the proposition but thats not how its done, so I am not sure what is going on...
Can someone help me read this proposition both formally and intuitively? I also want to understand conceptually what it's trying to say and not only get bugged down by the details of it.
Let me put some extra (not really necessary) parentheses:
forall P : unit -> Prop, P tt -> (forall u : unit, P u)
I would translate it as "For any predicate P over the unit type, if P holds of tt, then P holds of any term of type unit".
Intuitively, since tt is the only value of type unit, it makes sense to only prove P for this unique value.
You can check if this intuition works for you by trying to interpret the induction principle for the bool type in the same manner.
Check bool_ind.
bool_ind
: forall P : bool -> Prop, P true -> P false -> (forall b : bool, P b)

How to capture parameters under universal quantification (using Modules? Sections?)

I am wondering how best to handle this sort of situation in Coq:
Suppose I need to define and prove a number of things about an arbitrary structure (for the purposes of this discussion, let's say a set with a binary relation). Of course, I can always supply the set and relation as arguments for each such definition/proof:
Inductive star (X : Set) (R : X -> X -> Prop) := ...
Lemma star_trans (X : Set) (R : X -> X -> Prop) : ...
Naturally, this gets tiresome after a while. What I would like to do is have X and R as parameters locally within some demarcated area of code like so:
Parameter X : Set.
Parameter R : X -> X -> Prop.
Inductive star := ...
Lemma star_trans : ...
in such a way that the definitions and theorems, when used outside this area of code, capture X and R under universal quantification in order to give them the proper type. For instance, Check star should yield star : forall X : Set, (X -> X -> Prop) -> X -> X -> Prop.
I figured that this might be what modules are for, but I can't figure out how to use them for this situation.
This is exactly what the "Section mechanism" does: see https://coq.inria.fr/distrib/current/refman/Reference-Manual004.html#Section .
Section rel_star.
Variables (X : Set) (R : X -> X -> Prop).
Inductive star := ...
Lemma star_trans: ...
End rel_star.

Coq type error when matching with type family

I’m trying to re-implement an example from CPDT from memory. I wrote:
Inductive myType : Set := MyNat | MyBool.
Definition typeDenote (t : myType) : Set :=
match t with
| MyNat => nat
| MyBool => bool
end.
Inductive unaryOp : myType -> myType -> Set :=
| Twice : unaryOp MyNat MyNat.
Definition twice (n:nat) : nat := n + n.
Definition tunaryDenote (a b : myType) (t : unaryOp a b)
: typeDenote a -> typeDenote b :=
match t with
| Twice => twice
end.
The resulting error is:
Toplevel input, characters 125-130
> | Twice => twice
> ^^^^^
Error: In environment
a : myType
b : myType
t : unaryOp a b
The term "twice" has type "nat -> nat" while it is expected to have type
"forall H : typeDenote ?141, typeDenote ?142"
I don’t understand this error message. I would think that once the match on Twice : unaryOp MyNat MyNat succeeds, Coq infers that a and b are MyNats, and thus typeDenote a -> typeDenote b ≡ nat -> nat, making twice a perfectly fine candidate for the return value. Where’d I go wrong?
Just like #AntonTrunov said, it is typechecked without any issue on my Coq 8.5pl1. However if you need to add some extra annotations for your version to accept the function, you want to have a look at this section of the manual to figure out what to do.
My guess is that you want to have a match ... in ... return ... with to say that the return type should be refined by the information obtained by matching t at the type unaryOp a b (indeed: a and b will take concrete values in the Twice branch).
This is the definition you get using that technique:
Definition tunaryDenote (a b : myType) (t : unaryOp a b)
: typeDenote a -> typeDenote b :=
match t in unaryOp a b return typeDenote a -> typeDenote b with
| Twice => twice
end.
I think that the answer is that Coq's type inference is limited, and does not do the reasoning you want it to do.
Coq's type inference does not do arbitrary calculation but simple unification. It looks at twice, understand that it is nat->nat and concludes that it is not (syntactically) of the form typeDenote a -> TypeDenote b.
If it was doing calculation, it was likely to be non-terminating, since its type system is very sophisticated so you can encode non-trivial computation there.
I tried a newer version of Coq, and like others have said, it typechecks without issue on Coq 8.5. :)