Why does this Coq Definition fail? Coq Namespace error for Inductive Type - coq

I have the following Inductive Type and a test function:
Inductive parameter : Type :=
| Nop
| OneP : forall A, A -> parameter
| TwoP : forall (A : Type) (r : nat) (b : A), parameter
.
Check (TwoP nat 1 5).
Definition test (p : parameter) : option (nat * nat) :=
match p with
| TwoP nat x y => Some (x, y)
| _ => None
end.
The test function fails with the error:
The term "Some (x, y)" has type "option (Datatypes.nat * nat)"
while it is expected to have type "option (Datatypes.nat * Datatypes.nat)".
I don't understand why my definition does not work. Is there a difference between nat and Datataypes.nat ?
Any help would be appreciated. Thanks!

In Coq, it is not possible to test what a type is. Consider the following program:
Definition is_nat (A : Type) : bool :=
match A with
| nat => true
| _ => false
end.
If you try to run this, Coq tells you that the last branch is redundant, and rejects the definition. The issue is that nat is taken to be a variable name, not the nat data type from the standard library. Therefore, the first branch matches every type A, and the last branch is redundant. In your example, the pattern nat ends up masking the data type nat, which is why you end up seeing the qualified name Datatypes.nat.
One way of solving this issue is to use a type of codes instead of Type. For instance:
Inductive type : Type :=
| Bool
| Nat.
Definition type_denote t : Type :=
match t with
| Bool => bool
| Nat => nat
end.
Coercion type_denote : type >-> Sortclass.
Inductive parameter : Type :=
| Nop
| OneP : forall (A : type), A -> parameter
| TwoP : forall (A : type) (r : nat) (b : A), parameter
.
Check (TwoP Nat 1 5).
Definition test (p : parameter) : option (nat * nat) :=
match p with
| TwoP Nat x y => Some (x, y)
| _ => None
end.
There are two issues with this solution. First, it requires you to anticipate all types that you will need in parameter, and add those in the definition of type. Second, it forces you to program with dependent types, which can be hard to manipulate. It might be possible to refactor your definitions to avoid the problem of type matching altogether, although there is no one-size-fits-all solution -- it depends on your application.

Related

What does the term "?T#{x:=t}", or a type with a question mark and at sign surrounding it mean in Coq?

I'm trying to write a function which removes the zeros from a list. Here is the first try of my implementation.
Require Import Nat.
Require Import List.
Fixpoint shrink (x : list nat) list nat := (* Mistake! Needs a : list nat *)
match x with
| nil => nil
| h :: t => if h =? 0 then shrink t else (h :: shrink t)
end.
However, I get this error:
Error:
In environment
shrink : forall (x : Datatypes.list Datatypes.nat)
(list0 : ?T) (nat : ?T0#{list:=list0}),
Datatypes.list ?T1#{x:=x; list:=list0; x1:=x}
x : list nat
list : ?T
nat : ?T0
h : Datatypes.nat
t : Datatypes.list Datatypes.nat
The term "shrink t" has type
"forall (list0 : ?T#{x:=t}) (nat : ?T0#{x:=t; list:=list0}),
Datatypes.list ?T1#{x:=t; list:=list0; x1:=t}"
while it is expected to have type "Datatypes.list ?T1#{x1:=h :: t}".
The correct function implementation is this:
Fixpoint shrink (x : list nat) : list nat :=
match x with
| nil => nil
| h :: t => if h =? 0 then shrink t else (h :: shrink t)
end.
But how am I supposed to interpret the error, in particular (list0 : ?T#{x:=t})? In particular,
Why is it list0 instead of list?
What does ? mean before the T?
What does the #{ ... } mean after the T?
For your first point, this is just a printing thing but essentially local variables names are just hints for Coq and it may not respect them to avoid confusion. Here it's probably because of the list := list0 we see later.
Letters preceded by ? are existential variables or evars, used for unification. Here it doesn't know what the type of list0 should be because you did not give any, but it knows it has to be something. So for now it's ?T and it will try to figure out later what it should be by looking at its uses.
For nat it's the same, but it also knows it might depend on some list and in this case its value should be list0 so it does the instantiation ?T0{list:=list0}. This notation is for substitution in evars.
I invite you to look at the documentation of evars in the manual to know more.

How to write boolean comparsion function in Coq

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] *)

Retrieving constraints from GADT to ensure exhaustion of pattern matching in Coq

Let's define two helper types:
Inductive AB : Set := A | B.
Inductive XY : Set := X | Y.
Then two other types that depend on XY and AB
Inductive Wrapped : AB -> XY -> Set :=
| W : forall (ab : AB) (xy : XY), Wrapped ab xy
| WW : forall (ab : AB), Wrapped ab (match ab with A => X | B => Y end)
.
Inductive Wrapper : XY -> Set :=
WrapW : forall (xy : XY), Wrapped A xy -> Wrapper xy.
Note the WW constructor – it can only be value of types Wrapped A X and Wrapped B Y.
Now I would like to pattern match on Wrapper Y:
Definition test (wr : Wrapper Y): nat :=
match wr with
| WrapW Y w =>
match w with
| W A Y => 27
end
end.
but I get error
Error: Non exhaustive pattern-matching: no clause found for pattern WW _
Why does it happen? Wrapper forces contained Wrapped to be A version, the type signature forces Y and WW constructor forbids being A and Y simultaneously. I don't understand why this case is being even considered, while I am forced to check it which seems to be impossible.
How to workaround this situation?
Let's simplify:
Inductive MyTy : Set -> Type :=
MkMyTy : forall (A : Set), A -> MyTy A.
Definition extract (m : MyTy nat) : nat :=
match m with MkMyTy _ x => S x end.
This fails:
The term "x" has type "S" while it is expected to have type "nat".
wat.
This is because I said
Inductive MyTy : Set -> Type
This made the first argument to MyTy an index of MyTy, as opposed to a parameter. An inductive type with a parameter may look like this:
Inductive list (A : Type) : Type :=
| nil : list A
| cons : A -> list A -> list A.
Parameters are named on the left of the :, and are not forall-d in the definition of each constructor. (They are still present in the constructors' types outside of the definition: cons : forall (A : Type), A -> list A -> list A.) If I make the Set a parameter of MyTy, then extract can be defined:
Inductive MyTy (A : Set) : Type :=
MkMyTy : A -> MyTy A.
Definition extract (m : MyTy nat) : nat :=
match m with MkMyTy _ x => S x end.
The reason for this is that, on the inside, a match ignores anything you know about the indices of the scrutinee from the outside. (Or, rather, the underlying match expression in Gallina ignores the indices. When you write a match in the source code, Coq tries to convert it into the primitive form while incorporating information from the indices, but it often fails.) The fact that m : MyTy nat in the first version of extract simply did not matter. Instead, the match gave me S : Set (the name was automatically chosen by Coq) and x : S, as per the constructor MkMyTy, with no mention of nat. Meanwhile, because MyTy has a parameter in the second version, I actually get x : nat. The _ is really a placeholder this time; it is mandatory to write it as _, because there's nothing to match, and you can Set Asymmetric Patterns to make it disappear.
The reason we distinguish between parameters and indices is because parameters have a lot of restrictions—most notably, if I is an inductive type with parameters, then the parameters must appear as variables in the return type of each constructor:
Inductive F (A : Set) : Set := MkF : list A -> F (list A).
(* ^--------^ BAD: must appear as F A *)
In your problem, we should make parameters where we can. E.g. the match wr with Wrap Y w => _ end bit is wrong, because the XY argument to Wrapper is an index, so the fact that wr : Wrapper Y is ignored; you would need to handle the Wrap X w case too. Coq hasn't gotten around to telling you that.
Inductive Wrapped (ab : AB) : XY -> Set :=
| W : forall (xy : XY), Wrapped ab xy
| WW : Wrapped ab (match ab with A => X | B => Y end).
Inductive Wrapper (xy : XY) : Set := WrapW : Wrapped A xy -> Wrapper xy.
And now your test compiles (almost):
Definition test (wr : Wrapper Y): nat :=
match wr with
| WrapW _ w => (* mandatory _ *)
match w with
| W _ Y => 27 (* mandatory _ *)
end
end.
because having the parameters gives Coq enough information for its match-elaboration to use information from Wrapped's index. If you issue Print test., you can see that there's a bit of hoop-jumping to pass information about the index Y through the primitive matchs which would otherwise ignore it. See the reference manual for more information.
The solution turned out to be simple but tricky:
Definition test (wr : Wrapper Y): nat.
refine (match wr with
| WrapW Y w =>
match w in Wrapped ab xy return ab = A -> xy = Y -> nat with
| W A Y => fun _ _ => 27
| _ => fun _ _ => _
end eq_refl eq_refl
end);
[ | |destruct a]; congruence.
Defined.
The issue was that Coq didn't infer some necessary invariants to realize that WW case is ridiculous. I had to explicitly give it a proof for it.
In this solution I changed match to return a function that takes two proofs and brings them to the context of our actual result:
ab is apparently A
xy is apparently Y
I have covered real cases ignoring these assumptions, and I deferred "bad" cases to be proven false later which turned to be trivial. I was forced to pass the eq_refls manually, but it worked and does not look that bad.

Coinduction on Coq, type mismatch

I've been trying out coinductive types and decided to define coinductive versions of the natural numbers and the vectors (lists with their size in the type). I defined them and the infinite number as so:
CoInductive conat : Set :=
| cozero : conat
| cosuc : conat -> conat.
CoInductive covec (A : Set) : conat -> Set :=
| conil : covec A cozero
| cocons : forall (n : conat), A -> covec A n -> covec A (cosuc n).
CoFixpoint infnum : conat := cosuc infnum.
It all worked except for the definition I gave for an infinite covector
CoFixpoint ones : covec nat infnum := cocons 1 ones.
which gave the following type mismatch
Error:
In environment
ones : covec nat infnum
The term "cocons 1 ones" has type "covec nat (cosuc infnum)" while it is expected to have type
"covec nat infnum".
I thought the compiler would accept this definition since, by definition, infnum = cosuc infnum. How can I make the compiler understand these expressions are the same?
The standard way to solve this issue is described in Adam Chlipala's CPDT (see the chapter on Coinduction).
Definition frob (c : conat) :=
match c with
| cozero => cozero
| cosuc c' => cosuc c'
end.
Lemma frob_eq (c : conat) : c = frob c.
Proof. now destruct c. Qed.
You can use the above definitions like so:
CoFixpoint ones : covec nat infnum.
Proof. rewrite frob_eq; exact (cocons 1 ones). Defined.
or, perhaps, in a bit more readable way:
Require Import Coq.Program.Tactics.
Program CoFixpoint ones : covec nat infnum := cocons 1 ones.
Next Obligation. now rewrite frob_eq. Qed.

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. :)