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.
Related
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.
I was able to create a ComRingMixin, but when I try to declare this type as a canonical ring, Coq complains:
x : phantom (GRing.Zmodule.class_of ?bT) (GRing.Zmodule.class ?bT)
The term "x" has type "phantom (GRing.Zmodule.class_of ?bT) (GRing.Zmodule.class ?bT)"
while it is expected to have type "phantom (GRing.Zmodule.class_of 'I_n) ?b".
This is what I have so far, I was able to define the operations and instantiate the abelian group mixin as well as the canonical declaration, but for the ring, my code fails.
From mathcomp Require Import all_ssreflect all_algebra.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Import GRing.Theory.
Open Scope ring_scope.
Section Zn.
Variables n :nat.
Axiom one_lt_n : (1 < n)%N.
Axiom z_lt_n : (0 < n)%N.
Lemma mod_lt_n : forall (x : nat), ((x %% n)%N < n)%N.
Proof.
move=> x0; rewrite ltn_mod; by exact: z_lt_n.
Qed.
Definition mulmod (a b : 'I_n) : 'I_n := Ordinal (mod_lt_n (((a*b)%N %% n)%N)).
Definition addmod (a b : 'I_n) : 'I_n := Ordinal (mod_lt_n (((a+b)%N %% n)%N)).
Definition oppmod (x : 'I_n) : 'I_n := Ordinal (mod_lt_n (n - x)%N).
Lemma addmodC : commutative addmod. Admitted.
Lemma addmod0 : left_id (Ordinal z_lt_n) addmod. Admitted.
Lemma oppmodK : involutive oppmod. Admitted.
Lemma addmodA : associative addmod. Admitted.
Lemma addmodN : left_inverse (Ordinal z_lt_n) oppmod addmod. Admitted.
Definition Mixin := ZmodMixin addmodA addmodC addmod0 addmodN.
Canonical ordn_ZmodType := ZmodType 'I_n Mixin.
Lemma mulmodA : associative mulmod. Admitted.
Lemma mulmodC : commutative mulmod. Admitted.
Lemma mulmod1 : left_id (Ordinal one_lt_n) mulmod. Admitted.
Lemma mulmod_addl : left_distributive mulmod addmod. Admitted.
Lemma one_neq_0_ord : (Ordinal one_lt_n) != Ordinal z_lt_n. Proof. by []. Qed.
Definition mcommixin := #ComRingMixin ordn_ZmodType (Ordinal one_lt_n) mulmod mulmodA mulmodC mulmod1 mulmod_addl one_neq_0_ord.
Canonical ordnRing := RingType 'I_n mcommixin.
Canonical ordncomRing := ComRingType int intRing.mulzC.
What am i doing wrong? I'm basing myself on http://www-sop.inria.fr/teams/marelle/advanced-coq-17/lesson5.html.
The problem is that ssralg already declares ordinal as a zmodType instance. There can only be one canonical instance of a structure per head symbol, so your declaration of ordn_ZmodType is effectively ignored.
One solution around it is to introduce a local synonym in this section and use it to define the canonical structures:
(* ... *)
Definition foo := 'I_n.
(* ... *)
Definition ordn_ZmodType := ZmodType foo Mixin.
(* ... *)
Canonical ordnRing := RingType foo mcommixin. (* This now works *)
The other solution is to use the ringType instance defined in MathComp for ordinal. The catch is that it is only defined for types of the form 'I_n.+2.
In principle, one could also have declared these instances assuming the same axioms on n as you did, but this would make the inference of canonical structures more difficult.
Check fun n => [ringType of 'I_n.+2].
(* ... : nat -> ringType *)
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.
I've been using Coq for a very short time and I still bump into walls with some things. I've defined a set with a Record construction. Now I need to do some pattern matching to use it, but I'm having issues properly using it. First, these are my elements.
Inductive element : Set :=
| empty : element
.
.
.
| fun_m : element -> element -> element
| n_fun : nat -> element -> element
.
I pick the elements with certain characteristic to make a subset of them the next way:
Inductive esp_char : elements -> Prop :=
| esp1 : esp_char empty
| esp2 : forall (n : nat )(E : element), esp_char E -> esp_char (n_fun n E).
Record especial : Set := mk_esp{ E : element ; C : (esp_char E)}.
Now, I need to use definition and fix point on the 'especial' elements, just the two that I picked. I have read the documentation on Record and what I get is that I'd need to do something like this:
Fixpoint Size (E : especial): nat :=
match E with
|{|E := empty |} => 0
|{|E := n_fun n E0|} => (Size E0) + 1
end.
Of course this tells me that I'm missing everything on the inductive part of elements so I add {|E := _ |}=> 0, or anything, just to make the induction full. Even doing this, I then find this problem:
|{|E := n_fun n E0|} => (Size E0) + 1
Error:
In environment
Size : especial -> nat
E : especial
f : element
i : esp_char f
n : nat
E0 : element
The term "E0" has type "element" while it is expected to have type "especial".
What I have been unable to do is fix that last thing, I have a lemma proving that if n_fun n E0 is 'especial' then E0 is especial, but I can't build it as so inside the Fixpoint. I also defined the size for "all elements" and then just picked the "especial" ones in a definition, but I want to be able to do direct pattern matching directly on the set "especial". Thank you for your input.
EDIT: Forgot to mention that I also have a coercion to always send especial to elements.
EDIT: This is the approach I had before posting:
Fixpoint ElementSize (E : element): nat :=
match E with
| n_fun n E0 => (ElementSize E0) + 1
| _ => 0
end.
Definition Size (E : especial) := ElementSize E.
I'd have tried to do:
Lemma mk_especial_proof n E : esp_char (n_fun n E) -> esp_char E.
Proof. now intros U; inversion U. Qed.
Fixpoint Size (E : especial): nat :=
match E with
|{|E := empty |} => 0
|{|E := n_fun n E0; C := P |} => (Size (mk_esp E0 (mk_especial_proof _ _ P))) + 1
|{|E := fun_m E1 E2 |} => 0
end.
However this will fail the termination check. I'm not familiar with how to overcome this problem with records. I'd definitively follow the approach I mentioned in the comments (using a fixpoint over the base datatype).
EDIT: Added single fixpoint solution.
Fixpoint size_e e :=
match e with
| empty => 0
| fun_m e1 e2 => 0
| n_fun _ e => 1 + size_e e
end.
Definition size_esp e := size_e (E e).
I reduced your example to this, but you can easily go back to your definition. We have a set, and a subset defined by an inductive predicate. Often one uses sigma types for this, with the notation {b | Small b}, but it is actually the same as the Record definition used in your example, so never mind :-).
Inductive Big : Set := (* a big set *)
| A
| B (b0 b1:Big)
| C (b: Big).
Inductive Small : Big -> Prop := (* a subset *)
| A' : Small A
| C' (b:Big) : Small b -> Small (C b).
Record small := mk_small { b:Big ; P:Small b }.
Here is a solution.
Lemma Small_lemma: forall b, Small (C b) -> Small b.
Proof. intros b H; now inversion H. Qed.
Fixpoint size (b : Big) : Small b -> nat :=
match b with
| A => fun _ => 0
| B _ _ => fun _ => 0
| C b' => fun H => 1 + size b' (Small_lemma _ H)
end.
Definition Size (s:small) : nat :=
let (b,H) := s in size b H.
To be able to use the hypothesis H in the match-branches, it is sent into the branch as a function argument. Otherwise the destruction of b is not performed on the H term, and Coq can't prove that we do a structural recursion on H.
In file SemiRing.v I defined some classes:
(** Setoids. *)
Class Setoid := {
s_typ :> Type;
s_eq : relation s_typ;
s_eq_Equiv : Equivalence s_eq }.
Existing Instance s_eq_Equiv.
Module Import Setoid_Notations.
Infix "==" := s_eq.
End Setoid_Notations.
Instance Leibniz_Setoid (A : Type) : Setoid.
Proof.
apply Build_Setoid with (s_eq := #eq A). constructor. fo. fo.
unfold Transitive. apply eq_trans.
Defined.
(** Setoids with decidable equivalence. *)
Class Decidable_Setoid := {
ds_setoid :> Setoid;
ds_eq_dec : forall x y, {s_eq x y} + {~s_eq x y} }.
Class SemiRing := {
sr_ds :> Decidable_Setoid;
sr_0 : s_typ;
sr_1 : s_typ;
sr_add : s_typ -> s_typ -> s_typ;
sr_add_eq : Proper (s_eq ==> s_eq ==> s_eq) sr_add;
sr_mul : s_typ -> s_typ -> s_typ;
sr_mul_eq : Proper (s_eq ==> s_eq ==> s_eq) sr_mul;
sr_th : semi_ring_theory sr_0 sr_1 sr_add sr_mul s_eq }.
Then I define a NSemiRing.v is an instance of SemiRing for natural numbers.
Require Import SemiRing.
Instance Nat_as_Setoid : Setoid := Leibniz_Setoid nat. (*Where A = nat *)
Instance Nat_as_DS : Decidable_Setoid.
Proof.
apply Build_Decidable_Setoid with (ds_setoid := Nat_as_Setoid).
apply eq_nat_dec.
Defined.
Instance Nat_as_SR : SemiRing.
Proof.
apply Build_SemiRing with (sr_ds := Nat_as_DS) (sr_0 := 0) (sr_1 := 1)
(sr_add := plus) (sr_mul := mult).
class. class. constructor; intros; simpl; try ring. refl.
Defined.
My question is:
I want to have a lemma for example:
Lemma Aadd_0_r (n: nat) : n + 0 = n.
Proof. ... Qed.
How can I add or make this lemma Aadd_0_r of type nat see as one of the field of Nat_as_SR of type SemiRing?
That in another file I import NSemiRing:
Require Import NSemiRing.
Context {S: SemiRing}. Import Setoid_Notations.
For example, if I have a lemma that have the form of :
Lemma add_zero_r (n: s_typ): n + 0 == n.
Where I want "s_typ" is automatically recognize as type "nat" and I can call the Lemma Aadd_0_r to prove this lemma.
Doesn't just Proof. apply Aadd_0_r. Qed. finish the proof?
If you turn off notations and unfold all the definitions your goal reduces to Aadd_0_r.