I have defined a couple of modules in Coq to build a Byte type from a Bit type, recursively, as a three of pairs. But I hit an issue defining a Numeral Notation for the Byte type.
Here is the code:
Require Import ZArith.
(* bit sequence abstracted interface *)
Module Type Numeric.
Parameter T: Set.
Parameter MAX: T. (* sequence of 1...1 = 2^n - 1 *)
Parameter to: T -> Z. (* conversion to Z *)
Parameter of: Z -> option T. (* conversion from Z *)
End Numeric.
(* a single bit *)
Module Bit.
Inductive bit: Set := bit0 | bit1.
Definition T: Set := bit.
Definition MAX: T := bit1.
Definition to (i: T): Z :=
match i with
| bit0 => 0%Z
| bit1 => 1%Z
end.
Definition of (n: Z): option T :=
match n with
| Z0 => Some bit0
| Zpos xH => Some bit1
| _ => None
end.
End Bit.
(* concatenation of two bit sequences *)
Module ConcatNumeric (m1 m2: Numeric).
Definition T: Set := m1.T * m2.T.
Definition MAX: T := (m1.MAX, m2.MAX).
Definition to (x: T): Z :=
let (x1, x2) := x in
let i1 := m1.to x1 in
let i2 := m2.to x2 in
let base := (m2.to m2.MAX + 1)%Z in
(i1 * base + i2)%Z.
Definition of (i: Z): option T :=
let base := (m2.to m2.MAX + 1)%Z in
let i2 := (i mod base)%Z in
let i1 := (i / base)%Z in
match m1.of i1, m2.of i2 with
| Some z1, Some z2 => Some (z1, z2)
| _, _ => None
end.
End ConcatNumeric.
(* hierarchy defining a byte from bits *)
Module Crumb: Numeric := ConcatNumeric Bit Bit.
Module Nibble: Numeric := ConcatNumeric Crumb Crumb.
Module Byte: Numeric := ConcatNumeric Nibble Nibble.
(* boxing Byte.T in an inductive type to make Numeral Notation happy *)
Inductive u8: Set := u8_box (x: Byte.T).
Definition u8_unbox := fun x => match x with u8_box x => x end.
Definition u8_of := fun i => option_map u8_box (Byte.of i).
Definition u8_to := fun x => Byte.to (u8_unbox x).
(* defines the scope and the Numeral Notation *)
Declare Scope u8_scope.
Delimit Scope u8_scope with u8.
Numeral Notation u8 u8_of u8_to: u8_scope.
(* testing the code *)
Open Scope u8_scope.
Definition x: u8 := 1. (* error here! *)
I am getting this error:
Error: Unexpected non-option term
match Byte.of 1 with
| Some a => Some (u8_box a)
| None => None
end while parsing a numeral notation.
which seems not specific to Numeral Notation but rather a more general issue related to the fact that Byte.of cannot be expanded. Can someone shed some light on what is going on, and if there a way to work around this, which appears to be a limitation?
Coq version 8.11.2
When you write Module Byte: Numeric := Foo, you tell Coq to erase all the definitions from Foo and to keep only the signature of Numeric. This causes Byte.of to lose its body.
In your case, you do not want to restrict the content of Byte to Numeric, but only to document that it is compatible with Numeric. You can do so using Module Byte <: Numeric := Foo.
By the way, instead of putting this documentation on Byte, you could instead move it to ConcatNumeric:
Module ConcatNumeric (m1 m2: Numeric) <: Numeric.
...
End ConcatNumeric.
Module Byte := ConcatNumeric Nibble Nibble.
Related
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.
Following my question here, I have several functions with different types of arguments which I defined the Inductive type formula on them. Is there anyway to use Inductive formula in compute_formula. I am doing this to make proving easier by decreasing the number of constructors that I have to handle in proofs. Thank you.
Fixpoint add (n:type1) (m:type2): type3 :=
match n with
(*body for add*)
end.
Fixpoint mul (n:type1) (m:type4): type5 :=
match n with
(*body for mul*)
end.
Inductive formula : Type :=
| Formula {A B}: type1-> A -> (type1->A->B) -> formula.
(* How should I write this *)
Definition compute_formula {A B} (f: formula) (extraArg:A) : B :=
match f with
|Formula {A B} part1 part2 part3=>
if (A isof type2 && B isof type3) then add part1 part2+extraArg
if (A isof type4 && B isof type5) then mul part1 part2+extraArg
end.
What do you want the output type of compute_formula to be? The way the signature is written, the function would have to be able to compute an element of B no matter what B is. Since this is obviously impossible (what if B is Empty?), I'll show you a different approach.
The idea is to use the formula to get the output type.
Definition output_type (f: formula) :=
match f with
| #Formula _ B _ _ _ => B
end.
Then we can define compute_formula as
Definition compute_formula (f: formula): output_type f :=
match f with
| #Formula _ _ t a func => func t a
end.
A few other things. I'm not sure what you mean with the extraArg part. If you're more specific about what that means I might be able to help you. Also, there isn't (at least outside of tactics) a way to do what you want with A isof type2.
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.
Let's say I have again a small problem with my datatype with an existential quantified component. This time I want to define when two values of type ext are equal.
Inductive ext (A: Set) :=
| ext_ : forall (X: Set), option X -> ext A.
Fail Definition ext_eq (A: Set) (x y: ext A) : Prop :=
match x with
| ext_ _ ox => match y with
| ext_ _ oy => (* only when they have the same types *)
ox = oy
end
end.
What I'd like to do is somehow distinguish between the cases where the existential type is actually same and where it's not. Is this a case for JMeq or is there some other way to accomplish such a case distinction?
I googled a lot, but unfortunately I mostly stumbled upon posts about dependent pattern matching.
I also tried to generate a (boolean) scheme with Scheme Equality for ext, but this wasn't successful because of the type argument.
What I'd like to do is somehow distinguish between the cases where the existential type is actually same and where it's not.
This is not possible as Coq's logic is compatible with the univalence axiom which says that isomorphic types are equal. So even though (unit * unit) and unit are syntactically distinct, they cannot be distinguished by Coq's logic.
A possible work-around is to have a datatype of codes for the types you are interested in and store that as an existential. Something like this:
Inductive Code : Type :=
| Nat : Code
| List : Code -> Code.
Fixpoint meaning (c : Code) := match c with
| Nat => nat
| List c' => list (meaning c')
end.
Inductive ext (A: Set) :=
| ext_ : forall (c: Code), option (meaning c) -> ext A.
Lemma Code_eq_dec : forall (c d : Code), { c = d } + { c <> d }.
Proof.
intros c; induction c; intros d; destruct d.
- left ; reflexivity.
- right ; inversion 1.
- right ; inversion 1.
- destruct (IHc d).
+ left ; congruence.
+ right; inversion 1; contradiction.
Defined.
Definition ext_eq (A: Set) (x y: ext A) : Prop.
refine(
match x with | #ext_ _ c ox =>
match y with | #ext_ _ d oy =>
match Code_eq_dec c d with
| left eq => _
| right neq => False
end end end).
subst; exact (ox = oy).
Defined.
However this obviously limits quite a lot the sort of types you can pack in an ext. Other, more powerful, languages (e.g. equipped with Induction-recursion) would give you more expressive power.
I'm kind of new to Coq.
I'm trying to implement a generic version of insertion sort. I'm implementing is as a module that takes a Comparator as a parameter. This Comparator implements comparison operators (such as is_eq, is_le, is_neq, etc.).
In insertion sort, in order to insert, I must compare two elements in the input list, and based on the result of the comparison, insert the element into the correct location.
My problem is that the implementations of the comparison operators are type -> type -> prop (i need them to be like this for implementation of other types/proofs). I'd rather not create type -> type -> bool versions of the operators if it can be avoided.
Is there any way to convert a True | False prop to a bool for use in a if ... then ... else clause?
The comparator module type:
Module Type ComparatorSig.
Parameter X: Set.
Parameter is_eq : X -> X -> Prop.
Parameter is_le : X -> X -> Prop.
Parameter is_neq : X -> X -> Prop.
Infix "=" := is_eq (at level 70).
Infix "<>" := (~ is_eq) (at level 70).
Infix "<=" := is_le (at level 70).
Parameter eqDec : forall x y : X, { x = y } + { x <> y }.
Axiom is_le_trans : forall (x y z:X), is_le x y -> is_le y z -> is_le x z.
End ComparatorSig.
An implementation for natural numbers:
Module IntComparator <: Comparator.ComparatorSig.
Definition X := nat.
Definition is_le x y := x <= y.
Definition is_eq x y := eq_nat x y.
Definition is_neq x y:= ~ is_eq x y.
Definition eqDec := eq_nat_dec.
Definition is_le_trans := le_trans.
End IntComparator.
The insertion part of insertion sort:
Fixpoint insert (x : IntComparator .X) (l : list IntComparator .X) :=
match l with
| nil => x :: nil
| h :: tl => if IntComparator.is_le x h then x :: h :: tl else h :: (insert x tl)
end.
(obviously, the insert fixpoint doesn't work, since is_le is returns Prop and not bool).
Any help is appreciated.
You seem to be a bit confused about Prop.
is_le x y is of type Prop, and is the statement x is less or equal to y. It is not a proof that this statement is correct. A proof that this statement is correct would be p : is_le x y, an inhabitant of that type (i.e. a witness of that statement's truth).
This is why it does not make much sense to pattern match on IntComparator.is_le x h.
A better interface would be the following:
Module Type ComparatorSig.
Parameter X: Set.
Parameter is_le : X -> X -> Prop.
Parameter is_le_dec : forall x y, { is_le x y } + { ~ is_le x y }.
In particular, the type of is_le_dec is that of a decision procedure for the property is_le, that is, it returns either a proof that x <= y, or a proof that ~ (x <= y). Since this is a type with two constructors, you can leverage the if sugar:
... (if IntComparator.is_le_dec x h then ... else ...) ...
This is, in some sense, an enhanced bool, which returns a witness for what it is trying to decide. The type in question is called sumbool and you can learn about it here:
http://coq.inria.fr/library/Coq.Init.Specif.html#sumbool
In general, it does not make sense to talk about True or False in executing code.
First, because these live in Prop, which means that they cannot be computationally relevant as they will be erased.
Second, because they are not the only inhabitants of Prop. While true and false are the only values of type bool, which implies you can pattern-match, the type Prop contains an infinite number of elements (all the statements you can imagine), thus it makes no sense to try and pattern-match on a element of type Prop.