Using functions in definitions - coq

I'm modeling a program in which users can choose from different operators and functions for writing queries (i.e. formulas) for the system. For showing these operators, here I defined add and mul functions and used nat datatype, instead of my program's functions and datatypes. How should I define formula that enables me to use it in definition compute_formula. I'm a bit stuck at solving this issue. Thank you.
Fixpoint add n m :=
match n with
| 0 => m
| S p => S (p + m)
end
where "n + m" := (add n m) : nat_scope.
Fixpoint mul n m :=
match n with
| 0 => 0
| S p => m + p * m
end
where "n * m" := (mul n m) : nat_scope.
Definition formula : Set :=
nat-> nat -> ?operators_add_mull ->formula.
Definition compute_formula (f: formula) : nat :=
match f with
|firstnumber,secondnumber, ?operators_add_mull =>
?operators_add_mull firstnumber secondnumber
end.

First, your syntax for defining a data type is not quite right: you need to use the Inductive keyword:
Inductive formula : Set :=
| Formula : nat -> nat -> ?operators_add_mul -> formula.
It remains to figure out what the arguments to the Formula constructor should be. The Coq function type -> is a type like any other, and we can use it as the third argument:
Inductive formula : Set :=
| Formula : nat -> nat -> (nat -> nat -> nat) -> formula.
After defining this data type, you can write an expression like Formula 3 5 add, which denotes the addition of 3 and 5. To inspect the formula data type, you need to write match using the Formula constructor:
Definition compute_formula (f : formula) : nat :=
match f with
| Formula n m f => f n m
end.

Related

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.

Inductive definition for family of types

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.

Confused about pattern matching in Record constructions in Coq

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.

Coordinates in Coq

I apologize if this is obviously posted somewhere, but I have been trying Google search and SO search and found nothing on this yet.
Part A.
Is there a standard library for defining coordinates/vectors and points in R^2 and R^3 in Coq? I pretty much want to do standard stuff, like adding vectors, cross products, scaling, etc.
If not, how is this for a start:
Require Import Coq.Reals.Reals.
Inductive Coordinate2 : Type := Point2: R -> R -> Coordinate2.
Definition R2plus (u:Coordinate2) (v:Coordinate2) : Coordinate2 :=
match u, v with
| (Point2 ux uy),(Point2 vx vy)=>(Point2 ((ux+vx)%R) ((uy+vy)%R))
end.
(* etc. *)
Notation "x + y" := (R2plus x y).
Also, why when I run:
Eval compute in ((2%R) < (3%R))%R.
Do I get
= (2 < 3)%R
: Prop
rather than
True
or something?
Part B.
Is this even a good idea? I want to build an algorithm which computes some things using real numbers, and prove the algorithm correct in Coq. Is Coq.Reals.Reals the right thing to be using, or is it really too abstract?
Instead of defining Coordinate2 you could also use (R * R)%type, list R, or t R 2, where t A n, defined in Vector, is a list of size n.
You might want to give your notations a scope and a delimiting key to avoid clashes with other notations.
Notation "x + y" := (R2plus x y) : r2_scope.
Delimit Scope r2_scope with R2.
Eval compute in ((Point2 0 1) + (Point2 2 3))%R2.
Prop, Set, and Type are sorts, which means something of type Prop might be defined inductively.
For example, for the nats, le is defined as
Inductive le : nat -> nat -> Prop :=
| le_n : forall n, le n n
| le_S : forall n m : nat, le n m -> le n (S m).
2 <= 2 is true because it's inhabited by le_n 2
2 <= 3 is true because it's inhabited by le_S 2 2 (le_n 2)
2 <= 4 is true because it's inhabited by le_S 2 3 (le_S 2 2 (le_n 2))
3 <= 2 is false because it's not inhabited
For 2 <= 3 to reduce to True, le would have to be defined like, for example,
Fixpoint le (n m : nat) : Prop :=
match n with
| 0 => True
| S n =>
match m with
| 0 => False
| S m => le n m
end
end.
Coq's definition of Rplus and Rlt are actually axioms. To check the definition of something use the Print command.
To answer part B, I guess it depends on how well you understand mathematical analysis and the various ways of defining the reals. If you're more familiar with numerical methods, you might want to use the rationals instead.