Converting to Fin Type in Coq - coq

Can anyone tell me why the following projection function in COQ doesn't work?
Require Import Vector.
Require Import Fin.
Definition Proj {n:nat}{p:nat}(x:t p+{(exists m : nat, n=p+m)}):=
match x with
inleft y => y
|_ => F1
end.
I get the following error:
Error:
In environment
n : nat
p : nat
x : t p + {(exists m : nat, n = p + m)}
e : exists m : nat, n = p + m
The term "F1" has type "t (S ?6 (* [n, p, x, e, e] *))"
while it is expected to have type "t p".
On the other hand, using concrete values for p works fine:
Require Import Vector.
Require Import Fin.
Definition Proj {n:nat}(x:t 3 + {(exists m : nat, n=3+m)}):=
match x with
inleft y => y
|_ => F1
end.
Eval compute in (Proj (of_nat 2 3)) = FS (FS F1): t 3.

I'm assuming that you want Proj to return a value of type t p. That is impossible for p = 0 (because t 0 is the empty set), and that's why you cannot implement Proj for arbitrary p. If you extend you function to take a proof that p is not equal to 0, then you can implement it as follows. Read Adam's CPDT Chapter on Dependent Types to understand what is going on here.
Definition Proj {n:nat} {p:nat} (x:t p+{(exists m : nat, n=p+m)}) : p <> 0 -> t p :=
match x with
| inleft y => fun _ => y
| _ => match p with
| 0 => fun h => False_rect _ (h eq_refl)
| S _ => fun _ => F1
end
end.

Related

Error when referencing type variable from another file

I am working upon formalization of groups theory in coq. I have 2 files:
groups.v - contains definitions and theorems for groups
groups_Z.v - contains theorems and definitions for Z group.
groups.v:
Require Import Coq.Setoids.Setoid.
Require Import Coq.Lists.List.
Require Import PeanoNat.
Class Semigroup G : Type :=
{
mult : G -> G -> G;
assoc : forall x y z:G,
mult x (mult y z) = mult (mult x y) z
}.
Class Monoid G `{Hsemi: Semigroup G} : Type :=
{
e : G;
left_id : forall x:G, mult e x = x;
}.
Class Group G `{Hmono: Monoid G} : Type :=
{
inv : G -> G;
left_inv : forall x:G, mult (inv x) x = e;
}.
Declare Scope group_scope.
Infix "*" := mult (at level 40, left associativity) : group_scope.
Open Scope group_scope.
Section Group_theorems.
Parameter G: Type.
Context `{Hgr: Group G}.
(* More theorems follow *)
Fixpoint pow (a: G) (n: nat) {struct n} : G :=
match n with
| 0 => e
| S n' => a * (pow a n')
end.
Notation "a ** b" := (pow a b) (at level 35, right associativity).
End Group_theorems.
Close Scope group_scope.
groups_Z.v:
Add LoadPath ".".
Require Import groups.
Require Import ZArith.
Open Scope group_scope.
Section Z_Groups.
Parameter G: Type.
Context `{Hgr: Group G}.
Definition pow_z (a: groups.G) (z: Z) : G :=
match z with
| Z0 => e
| Zpos x => pow a (Pos.to_nat x)
| Zneg x => inv (pow a (Pos.to_nat x))
end.
Notation "a ** b" := (pow_z a b) (at level 35, right associativity).
End Z_groups.
Close Scope group_scope.
The attempt to define pow_z fails with message:
The term "pow a (Pos.to_nat x)" has type "groups.G" while it is
expected to have type "G".
If we use the different signature: Definition pow_z (a: G) (z: Z) : G
instead of Definition pow_z (a: groups.G) (z: Z) : G.
then it gives another error:
The term "a" has type "G" while it is expected to have type
"groups.G".
How to fix this?
In Coq, the command Parameter G : Type declares a global constant, which is akin to axiomatizing the existence of an abstract Type G : Type. From a theoretical point of view, this should be ok as this axiom is trivially realizable, but I think you meant Variable G : Type to denote a local variable instead.
The errors messages of Coq follow from there because you declare two global constants named G, one in each module. As soon as the second one is declared, the first one is designated by groups.G by Coq (it's the shortest name that disambiguates this constant from others). Now pow operates on and returns a groups.G, while you require pow_z returns a G (which in file groups_Z.v at this location means groups_Z.G, and is different from groups.G).
NB: Group theory has been developed several times in Coq, and if you want to do anything else than experimenting with the system, I would advise you work on top of existing libraries. For example the mathematical components library has a finite group library.
I changed Parameter G: Type. to Variable G: Type in both files and pow_z definition to this:
Definition pow_z (a: G) (z: Z) : G :=
match z with
| Z0 => e
| Zpos x => pow G a (Pos.to_nat x)
| Zneg x => inv (pow G a (Pos.to_nat x))
end.

How to get the type of a subterm when you're building a match

My general question is: is there an easy way to incrementally build up a definition in Coq when I'm not familiar with the type of what I'm working with?
Consider one definition of the natural numbers in Coq, from Coq.Narith.BinNat
Definition discr n : { p:positive | n = pos p } + { n = 0 }.
Now, to me it's a little confusing what this term looks like. Suppose I'm trying to extract this positive p from the definition. My first try failed:
Require Import Coq.Narith.BinNat.
Fail Definition NToPos (x : N) : positive :=
match N.discr x with
| inright HO => 1
| inleft Hpos => Hpos
end.
(*
Error:
In environment
x : N
Hpos : {p : positive | x = N.pos p}
The term "Hpos" has type "{p : positive | x = N.pos p}"
while it is expected to have type "positive".
*)
Well... okay. Now I know my basic misunderstanding is with the notation {p : positive | x = N.pos p}, but where do I go from here?
My question is, is there a better way to understand a definition such as N.discr? What I think I want is the following:
Definition NToPos (x : N) : positive :=
match N.discr x with
| inright HO => 1
| inleft Hpos => (* Please tell me how to further destruct Hpos *)
end.
In general, to decipher a notation, you can ask something like
Locate "{ x | p }".
In this case, this figures out what { p : positive | n = pos p } means (you replace the "replaceable" parts of the notation with (meta)variables). It gives
Notation "{ x | P }" := sig (fun x => P)
Now the name sig can be used to get more information.
Print sig.
(*
Inductive sig (A : Type) (P : A -> Prop) : Type :=
exist : forall x : A,
P x -> {x : A | P x}
Arguments exist [A]%type_scope _%function_scope
*)
Which tells you that you need to match Hpos against exist _ p Hpos (the Arguments say that A is implicit and that P is explicit, but P (as a parameter) is already fixed by the type of the scrutinee and must be ignored, and the remaining arguments, x : A and the P x, need to be named).
Alternatively,
Unset Printing Notations. (* In CoqIDE, you're told to set this from the view menu instead *)
Check N.discr.
(* Shows you that the notation stands for sig *)
And then continue as before.
I eventually figured this out by checking Print N.discr and observing:
N.discr =
fun n : N =>
match n as n0 return ({p : positive | n0 = N.pos p} + {n0 = 0%N}) with
| 0%N => inright eq_refl
| N.pos p =>
inleft (exist (fun p0 : positive => N.pos p = N.pos p0) p eq_refl)
end
: forall n : N, {p : positive | n = N.pos p} + {n = 0%N}
and seeing that the case I want is exist (fun p0 : positive => N.pos p = N.pos p0) p eq_refl. Then, exist is the key function. From that I was able to correctly guess inleft (exists p Hpos) would work:
Definition NToPos (x : N) : positive :=
match N.discr x with
| inright HO => 1
| inleft (exist p Hpos) => p
end.

How can I compare (equality) of two elements of same Set in Coq?

Inductive ty: Set :=
| I
| O.
Definition f (x: ty) (y: ty): nat :=
if x = y then 0 else 1.
I want the function f to compare two terms of type ty but it does not compile and I see this error:
The term x = y has type Prop which is not a (co-)inductive type.
You need to prove that equality is decidable for ty (which can be done automatically using decide equality) and then use that definition in the if ... then ... else ... statement. Concretely:
Inductive ty: Set :=
| I
| O.
Definition ty_eq_dec : forall (x y : ty), { x = y } + { x <> y }.
Proof.
decide equality.
Defined.
Definition f (x: ty) (y: ty): nat :=
if ty_eq_dec x y then 0 else 1.
You can use match to compare the elements of inductive data types.
Definition f x y := match x,y with I, I | O, O => 0 | _,_ => 1 end.
decide equality is a more general tactic and works for infinite sets, but it is good to know that it is match that is doing the real work.

Messing around with category theory

Motivation: I am attempting to study category theory while creating a Coq formalization of the ideas I find in whatever textbook I follow. In order to make this formalization as simple as possible, I figured I should identify objects with their identity arrow, so a category can be reduced to a set (class, type) of arrows X with a source mapping s:X->X, target mapping t:X->X, and composition mapping product : X -> X -> option X which is a partial mapping defined for t f = s g. Obviously the structure (X,s,t,product) should follow various properties. For the sake of clarity, I am spelling out the formalization I chose below, but there is no need to follow it I think in order to read my question:
Record Category {A:Type} : Type := category
{ source : A -> A
; target : A -> A
; product: A -> A -> option A
; proof_of_ss : forall f:A, source (source f) = source f
; proof_of_ts : forall f:A, target (source f) = source f
; proof_of_tt : forall f:A, target (target f) = target f
; proof_of_st : forall f:A, source (target f) = target f
; proof_of_dom: forall f g:A, target f = source g <-> product f g <> None
; proof_of_src: forall f g h:A, product f g = Some h -> source h = source f
; proof_of_tgt: forall f g h:A, product f g = Some h -> target h = target g
; proof_of_idl: forall a f:A,
a = source a ->
a = target a ->
a = source f ->
product a f = Some f
; proof_of_idr: forall a f:A,
a = source a ->
a = target a ->
a = target f ->
product f a = Some f
; proof_of_asc:
forall f g h fg gh:A,
product f g = Some fg ->
product g h = Some gh ->
product fg h = product f gh
}
.
I have no idea how practical this is and how far it will take me. I see this as an opportunity to learn category theory and Coq at the same time.
Problem: My first objective was to create a 'Category' which would resemble as much as possible the category Set. In a set theoretic framework, I would probably consider the class of triplets (a,b,f) where f is a map with domain a and range a subset of b. With this in mind I tried:
Record Arrow : Type := arrow
{ dom : Type
; cod : Type
; arr : dom -> cod
}
.
So that Arrow becomes my base type on which I could attempt building a structure of category. I start embedding Type into Arrow:
Definition id (a : Type) : Arrow := arrow a a (fun x => x).
which allows me to define the source and target mappings:
Definition domain (f:Arrow) : Arrow := id (dom f).
Definition codomain (f:Arrow) : Arrow := id (cod f).
Then I move on to defining a composition on Arrow:
Definition compose (f g: Arrow) : option Arrow :=
match f with
| arrow a b f' =>
match g with
| arrow b' c g' =>
match b with
| b' => Some (arrow a c (fun x => (g' (f' x))))
| _ => None
end
end
end.
However, this code is illegal as I get the error:
The term "f' x" has type "b" while it is expected to have type "b'".
Question: I have the feeling I am not going to get away with this, My using Type naively would take me to some sort of Russel paradox which Coq will not allow me to do. However, just in case, is there a way to define compose on Arrow?
Your encoding does not work in plain Coq because of the constructive nature of the theory: it is not possible to compare two sets for equality. If you absolutely want to follow this approach, Daniel's comment sketches a solution: you need to assume a strong classical principle to be able to check whether the endpoints of two arrows match, and then manipulate an equality proof to make Coq accept the definition.
Another approach is to have separate types for arrows and objects, and use type dependency to express the compatibility requirement on arrow endpoints. This definition requires only three axioms, and considerably simplifies the construction of categories:
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Record category : Type := Category {
obj : Type;
hom : obj -> obj -> Type;
id : forall {X}, hom X X;
comp : forall X Y Z, hom X Y -> hom Y Z -> hom X Z;
(* Axioms *)
idL : forall X Y (f : hom X Y), comp id f = f;
idR : forall X Y (f : hom X Y), comp f id = f;
assoc : forall X Y Z W
(f : hom X Y) (g : hom Y Z) (h : hom Z W),
comp f (comp g h) = comp (comp f g) h
}.
We can now define the category of sets and ask Coq to automatically prove the axioms for us.
Require Import Coq.Program.Tactics.
Program Definition Sets : category := {|
obj := Type;
hom X Y := X -> Y;
id X := fun x => x;
comp X Y Z f g := fun x => g (f x)
|}.
(This does not lead to any circularity paradoxes, because of Coq's universe mechanism: Coq understands that the Type used in this definition is actually smaller than the one used to define category.)
This encoding is sometimes inconvenient due to the lack of extensionality in Coq's theory, because it prevents certain axioms from holding. Consider the category of groups, for example, where the morphisms are functions that commute with the group operations. A reasonable definition for these morphisms could be as follows (assuming that there is some type group representing groups, with * denotes multiplication and 1 denotes the neutral element).
Record group_morphism (X Y : group) : Type := {
mor : X -> Y;
mor_1 : mor 1 = 1;
mor_m : forall x1 x2, mor (x1 * x2) = mor x1 * mor x2
}.
The problem is that the properties mor_1 and mor_m interfere with the notion of equality for elements of group_morphism, making the proofs for associativity and identity that worked for Sets break. There are two solutions:
Adopt extra axioms into the theory so that the required properties still go through. In the above example, you would need proof irrelevance:
proof_irrelevance : forall (P : Prop) (p q : P), p = q.
Change the category axioms so that the identities are valid up to some equivalence relation specific to that category, instead of the plain Coq equality. This approach is followed here, for example.

Morphism - Setoid on non-convertible terms in Coq

I have the following function in Coq. Now I want to define an instance as below. In my case, equivalence [==] on type [nat] is defined but not on [StringMap.t String.t]. Please if you solve the Instace SC_Proper. Thanks.
Definition SC (u: nat) (zm: StringMap.t String.t):
StringMap.t String.t :=
match u with
| S p => match p with
| 2 => zm
| _ =>
match StringMap.find "S" zm with
| Some k => StringMap.empty
| _ => zm
end
end
| O => zm
end.
Instance SC_Proper
: Proper (equiv ==> equiv ==> equiv) SC.
Proof with o.
repeat red. intros u u' Hu zm1 zm2 Hzm.
Admitted.