I'm new to Coq. I've been working through Pierce's Logical Foundations. My interest is a bit out-of-scope of this excellent text as I want to get up-and-running with some math problems.
One of the first things I tried with reals (the R type) was this:
Compute exp 1.
Which sent Coq into an infinite loop. Can this be computed? Is the definition of exp only for proofs?
Doing:
Print exp.
Print proj1_sig.
Print exist_exp.
Yields:
exp = fun x : R => proj1_sig (exist_exp x)
: R -> R
Argument scope is [R_scope]
proj1_sig =
fun (A : Type) (P : A -> Prop) (e : {x : A | P x}) => let (a, _) := e in a
: forall (A : Type) (P : A -> Prop), {x : A | P x} -> A
Arguments A, P are implicit
Argument scopes are [type_scope function_scope _]
exist_exp =
fun x : R =>
(fun H : {l : R | infinite_sum (fun n : nat => (/ INR (fact n) * x ^ n)%R) l}
=> H)
(Alembert_C3 (fun n : nat => (/ INR (fact n))%R) x exp_cof_no_R0
Alembert_exp)
: forall x : R, {l : R | exp_in x l}
Good grief!! How can I learn all of this?!
The thing to understand is that compute asks Coq to put exp 1 into a form that is normal with respect to the rules of its lambda-calculus. So, Coq is not entering an infinite loop. It is just that the normal form of exp 1 is so large that Coq takes a very long time to compute it (and display it).
In practice, no one is ever interested in the normal form of exp 1. So, what are you trying to compute? If you are only interested in computing guaranteed approximations of exp 1, I suggest looking at the CoRN or CoqInterval libraries.
If you just want to see the definition of exp, then your Print approach is fine. It shows that exp is defined as the limit of the traditional power series. It looks a bit ugly, because the definition also embeds the proof that it is convergent for any real number.
Related
Assume P: nat -> T -> Prop is a proposition that for any given t: T,
either there exists a k: nat such that P holds for all numbers greater than or equal to k and no number less than k.
or P k t is false for all k : nat.
I want to define min_k : T -> nat + undef to be the minimum number k such that P k t holds, and undef otherwise.
Is that even possible? I tried to define something like
Definition halts (t : T) := exists k : nat, P k t.
Or maybe
Definition halts (t : T) := exists! k : nat, (~ P k t /\ P (S k) t).
and then use it like
Definition min_k (t : T) := match halts T with
| True => ??
| False => undef
end.
but I don't know how to go further from there.
Any ideas would be appreciated.
You can't match on a Prop. If you want to do case analysis then you need something in Type, typically bool or something like sumbool or sumor. In other words, you can do what you want as long as you have a pretty strong hypothesis.
Variable T : Type.
Variable P : nat -> T -> Prop.
Hypothesis PProperty : forall (t : T),
{k : nat | forall n, (k <= n -> P n t) /\ (n < k -> ~ P n t)}
+
{forall k, ~ P k t}.
Definition min_k (t : T) : option nat :=
match PProperty t with
| inleft kH => Some (proj1_sig kH)
| inright _ => None
end.
Crucially, this wouldn't have worked if PProperty was a Prop disjunction, i.e., if it was of the form _ \/ _ instead of the form _ + { _ }.
By the way, the idiomatic way of describing foo + undef in Coq is to use option foo, which is what I did above, but you can adapt it as you wish.
In addition to Ana's excellent answer, I think it is worth pointing out that option nat is essentially the same thing as {k : nat | ...} + {forall k, ~ P k t} if you erase the proofs of the latter type: in the first case (Some or inleft), you get a natural number out; in the second (None or inright) you get nothing at all.
So i was doing an exercise for learning coq. and I was trying to defind a type according to this encoding:
forall X.(X -> X) -> X -> X;`and this is from Alonzo Church(he proposed an encoding for natural number) as below:
0 , f:x:x
1 , f:x:fx
2 , f:x:f(fx)
3 , f:x:f(f(fx))
.....
n , f:x:fnx:
My code is like below:
Definition nat := forall X : Type, (X -> X) -> X -> X.
And the exercise require me to define expressions zero,one,two and three that encode the corresponding numbers as elements of nat:
Below is what I thought it will be
Definition zero : nat :=
fun (X : Type) (f : X -> X) (x : X) => x.
Definition one : nat :=
fun (X : Type) (f : X -> X) (x : X) => f x.
Definition two : nat :=
fun (X : Type) (f : X -> X) (x : X) => f (f x).
Definition three : nat :=
fun (X:Type)(f: X -> X)(x: X) => f ( f ( f x )).
My question is I need to prove that the plus n one = succ n. and the n is my defined type Nat
I have a succ function defined as below:
Definition succ (n : nat) : nat :=
fun (X : Type) (f : X -> X) (x : X) => f (n X f x).
my plus function defined as below:
Definition plus (n m : nat) : nat :=
fun (X : Type) (f : X -> X) (x : X) => (n X f (m X f x)).
The thing is when I tried to prove plus n one = succ n, I stuck in the middle and have no idea how to prove.
code as below:
Theorem plus_succ: forall (n : nat),
plus n one = succ n.
Proof.
intros.
1 subgoal
n : nat
______________________________________(1/1)
plus n one = succ n
and there's no way I can do inversion or any other tactic...(I am new to Coq, I've learnt list,poly,induction and tactics so far)
So that brings me to the thought that probably one, two or maybe all of my definition I defined above are not accurate.
Tons of appreciation if anyone can help me or give me some hints! Thankssss!
Using Church encodings in Coq is not a bad idea per-se, but you won't be able to say much about the inhabitants of this type (beside constructing some of them as you did).
The first issue is that inhabitants of this Church encoding are functions, and you will be able to show that two functions are equal in pure Coq only if they compute to the same value (up to unfolding, beta-reductions, reductions of match and fixes).
This is not the case for plus n one and succ n: you have on the lhs fun X f x => f (n X f x) and on the rhs fun X f x => n X f (f x). What you could hope to prove is forall (X : type) (f : X -> X) (x : X), f (n X f x) = n X f (f x), and you would then need to use functional extensionality, an axiom stating that the equality between functions is determined by the value of the functions at each point of their domain (see Coq.Logic.FunctionalExtensionality in the stdlib for more details on that point). This axiom is frequently assumed, but it is not innocent either (e.g. it does block computations).
The second issue you will run into is that you expect the inhabitants of nat = forall X, (X -> X) -> X -> X to be functions parametric in their first argument X : Type, but there is nothing actually enforcing that. Indeed, you can construct non-parametric inhabitants if you assume additional axioms, for instance excluded-middle. In pure Coq (without any axiom), there are results due to Bernardy and Lasson that show that indeed all inhabitants of your type nat are parametric, however you cannot internalize this result. And without parametricity, you have no bullets to prove equations such as f (n X f x) = n X f (f x).
So your troubles come from these two issues:
in absence of functional extensionality, the equalities that you can prove between functions are quite limited, and
you are not able in pure Coq to express internally that a quantification over types is parametric.
If you want to learn more about these issues on parametricity and what can still be achieved using Church encodings (or variants of these), I would recommend having a look at Chlipala's Parametric Higher-Order Abstract Syntax.
I'm working towards formalising Free Selective Applicative Functors in Coq, but struggling with proofs by induction for inductive data types with non-uniform type parameters.
Let me give a bit of an introduction on the datatype I'm dealing with.
In Haskell, we encode Free Selective Functors as a GADT:
data Select f a where
Pure :: a -> Select f a
Select :: Select f (Either a b) -> f (a -> b) -> Select f b
The crucial thing here is the existential type variable b in the second data constructor.
We can translate this definition to Coq:
Inductive Select (F : Type -> Type) (A : Set) : Set :=
Pure : A -> Select F A
| MkSelect : forall (B : Set), Select F (B + A) -> F (B -> A) -> Select F A.
As a side note, I use the -impredicative-set option to encode it.
Coq generates the following induction principle for this datatype:
Select_ind :
forall (F : Type -> Type) (P : forall A : Set, Select F A -> Prop),
(forall (A : Set) (a : A), P A (Pure a)) ->
(forall (A B : Set) (s : Select F (B + A)), P (B + A)%type s ->
forall f0 : F (B -> A), P A (MkSelect s f0)) ->
forall (A : Set) (s : Select F A), P A s
Here, the interesting bit is the predicate P : forall A : Set, Select F A -> Prop which is parametrised not only in the expression, but also in the expressions type parameter. As I understand, the induction principle has this particular form because of the first argument of the MkSelect constructor of type Select F (B + A).
Now, I would like to prove statements like the third Applicative law for the defined datatype:
Theorem Select_Applicative_law3
`{FunctorLaws F} :
forall (A B : Set) (u : Select F (A -> B)) (y : A),
u <*> pure y = pure (fun f => f y) <*> u.
Which involve values of type Select F (A -> B), i.e. expressions containing functions. However,
calling induction on variables of such types produces ill-typed terms. Consider an oversimplified example of an equality that can be trivially proved by reflexivity, but can't be proved using induction:
Lemma Select_induction_fail `{Functor F} :
forall (A B : Set) (a : A) (x : Select F (A -> B)),
Select_map (fun f => f a) x = Select_map (fun f => f a) x.
Proof.
induction x.
Coq complains with the error:
Error: Abstracting over the terms "P" and "x" leads to a term
fun (P0 : Set) (x0 : Select F P0) =>
Select_map (fun f : P0 => f a) x0 = Select_map (fun f : P0 => f a) x0
which is ill-typed.
Reason is: Illegal application (Non-functional construction):
The expression "f" of type "P0" cannot be applied to the term
"a" : "A"
Here, Coq can't construct the predicate abstracted over the type variable because the reversed function application from the statement becomes ill-typed.
My question is, how do I use induction on my datatype? I can't see a way how to modify the induction principle in such a way so the predicate would not abstract the type. I tried to use dependent induction, but it has been producing inductive hypothesis constrained by equalities similar to (A -> B -> C) = (X + (A -> B -> C)) which I think would not be possible to instantiate.
Please see the complete example on GitHub: https://github.com/tuura/selective-theory-coq/blob/impredicative-set/src/Control/Selective/RigidImpredSetMinimal.v
UPDATE:
Following the discussio in the gist I have tried to carry out proofs by induction on depth of expression. Unfortunately, this path was not very fruitful since the induction hypothesis I get in theorems similar to Select_Applicative_law3 appear to be unusable. I will leave this problem for now and will give it a try later.
Li-yao, many thanks again for helping me to improve my understanding!
Proofs by induction are motivated by recursive definitions. So to know what to apply induction to, look for Fixpoints.
Your Fixpoints most likely work on terms indexed by single type variables Select F A, that's exactly where you want to use induction, not at the toplevel of the goal.
A Fixpoint on terms indexed by function types A -> B is useless since no subterms of any Select term are indexed by function types. For the same reason, induction is useless on such terms.
Here I think the strong type discipline actually forces you to work everything out on paper before trying to do anything in Coq (which is a good thing in my opinion). Try to do the proof on paper, without even worrying about types; explicitly write down the predicate(s) you want to prove by induction. Here's a template to see what I mean:
By induction on u, we will show
u <*> pure x = pure (fun f => f x) <*> u
(* Dummy induction predicate for the sake of example. *)
(* Find the right one. *)
(* It may use quantifiers... *)
Base case (set u = Pure f). Prove:
Pure f <*> pure x = pure (fun f => f x) <*> Pure f
Induction step (set u = MkSelect v h). Prove:
MkSelect v h <*> pure x = pure (fun f => f x) <*> MkSelect v h
assuming the induction hypothesis for the subterm v (set u = v):
v <*> pure x = pure (fun f => f x) <*> v
Notice in particular that the last equation is ill-typed, but you can still run along with it to do equational reasoning. Regardless, it will likely turn out that there is no way to apply that hypothesis after simplifying the goal.
If you really need to use Coq to do some exploration, there is a trick, consisting in erasing the problematic type parameter (and all terms that depend on it). Depending on your familiarity with Coq, this tip may turn out to be more confusing than anything. So be careful.
The terms will still have the same recursive structure. Keep in mind that the proof should also follow the same structure, because the point is to add more types on top afterwards, so you should avoid shortcuts that rely on the lack of types if you can.
(* Replace all A and B by unit. *)
Inductive Select_ (F : unit -> Type) : Set :=
| Pure_ : unit -> Select_ F
| MkSelect_ : Select_ F -> F tt -> Select_ F
.
Arguments Pure_ {F}.
Arguments MkSelect_ {F}.
(* Example translating Select_map. The Functor f constraint gets replaced with a dummy function argument. *)
(* forall A B, (A -> B) -> (F A -> F B) *)
Fixpoint Select_map_ {F : unit -> Type} (fmap : forall t, unit -> (F t -> F t)) (f : unit -> unit) (v : Select_ F) : Select_ F :=
match v with
| Pure_ a => Pure_ (f a)
| MkSelect_ w h => MkSelect_ (Select_map_ fmap f w) (fmap _ tt h)
end.
With that, you can try to prove this trimmed down version of the functor laws for example:
Select_map_ fmap f (Select_map_ fmap g v) = Select_map_ fmap (fun x => f (g x)) v
(* Original theorem:
Select_map f (Select_map g v) = Select_map (fun x => f (g x)) v
*)
The point is that removing the parameter avoids the associated typing problems, so you can try to use induction naively to see how things (don't) work out.
I'm trying to use Equations package to define a function over vectors in Coq. The minimum code that shows the problem that I will describe is available at the following gist.
My idea is to code a function that does a lookup on a "proof" that some type holds for all elements of a vector, which has a standard definition:
Inductive vec (A : Type) : nat -> Type :=
| VNil : vec A 0
| VCons : forall n, A -> vec A n -> vec A (S n).
Using the previous type, I had defined the following (also standard) lookup operation (using Equations):
Equations vlookup {A}{n}(i : fin n) (v : vec A n) : A :=
vlookup FZero (VCons x _) := x ;
vlookup (FSucc ix) (VCons _ xs) := vlookup ix xs.
Now, the trouble begins. I want to define the type of "proofs" that some
property holds for all elements in a vector. The following inductive type does this job:
Inductive vforall {A : Type}(P : A -> Type) : forall n, vec A n -> Type :=
| VFNil : vforall P _ VNil
| VFCons : forall n x xs,
P x -> vforall P n xs -> vforall P (S n) (VCons x xs).
Finally, the function that I want to define is
Equations vforall_lookup
{n}
{A : Type}
{P : A -> Type}
{xs : vec A n}
(idx : fin n) :
vforall P xs -> P (vlookup idx xs) :=
vforall_lookup FZero (VFCons _ _ pf _) := pf ;
vforall_lookup (FSucc ix) (VFCons _ _ _ ps) := vforall_lookup ix ps.
At leas to me, this definition make sense and it should type check. But, Equations had showed the following warning and left me with a proof obligation in which I had no idea on how to finish it.
The message presented after the definition of the previous function is:
Warning:
In environment
eos : end_of_section
fix_0 : forall (n : nat) (A : Type) (P : A -> Type) (xs : vec A n)
(idx : fin n) (v : vforall P xs),
vforall_lookup_ind n A P xs idx v (vforall_lookup idx v)
A : Type
P : A -> Type
n0 : nat
x : A
xs0 : vec A n0
idx : fin n0
p : P x
v : vforall P xs0
Unable to unify "VFCons P n0 x xs0 p v" with "v".
The obligation left is
Obligation 1 of vforall_lookup_ind_fun:
(forall (n : nat) (A : Type) (P : A -> Type) (xs : vec A n)
(idx : fin n) (v : vforall P xs),
vforall_lookup_ind n A P xs idx v (vforall_lookup idx v)).
Later, after looking at a similar definition in Agda standard library, I realised that the previous function definition is missing a case for the empty vector:
lookup : ∀ {a p} {A : Set a} {P : A → Set p} {k} {xs : Vec A k} →
(i : Fin k) → All P xs → P (Vec.lookup i xs)
lookup () []
lookup zero (px ∷ pxs) = px
lookup (suc i) (px ∷ pxs) = lookup i pxs
My question is, how can I specify that, for the empty vector case, the right hand side should be empty, i.e. a contradiction? The Equations manual shows an example for equality but I could adapt it to this case. Any idea on what am I doing wrong?
I think I finally understood what is going on in this example by looking closely at the obligation generated.
The definition is correct, and it is accepted (you can use vforall_lookup without solving the obligation). What fails to be generated is the induction principle associated to the function.
More precisely, Equations generates the right induction principle in three steps (this is detailed in the reference manual) in section "Elimination principle":
it generates the graph of the function (in my version of Equations it is called vforall_lookup_graph, in previous versions it was called vforall_lookup_ind). I am not sure that I fully understand what it is. Intuitively, it reflects the structure of the body of the function. In any case, it is a key component to generate the induction principle.
it proves that the function respects this graph (in a lemma called vforall_lookup_graph_correct or vforall_lookup_ind_fun);
it combines the last two results to generate the induction principle associated to the function (this lemma is called vforall_lookup_elim in all versions).
In your case, the graph was correctly generated but Equations was not able to prove automatically that the function respects its graph (step 2), so it is left to you.
Let's give it a try!
Next Obligation.
induction v.
- inversion idx.
- dependent elimination idx.
(* a powerful destruct provided by Equations
that correctly working with dependent types
*)
+ constructor.
+ constructor.
Coq rejects the last call to constructor with the error
Unable to unify "VFCons P n1 x xs p v" with "v".
This really looks like the error obtained in the first place, so I think the automatic resolution reached this same point and failed. Does this mean that we took a wrong path? Let's look closer at the goal before the second constructor.
We have to prove
vforall_lookup_graph (S n1) A P (VCons x xs) (FSucc f) (VFCons P n1 x xs p v) (vforall_lookup (FSucc f) (VFCons P n1 x xs p v))
while the type of vforall_lookup_graph_equation_2, the second constructor of vforall_lookup_graph_equation is
forall (n : nat) (A : Type) (P : A -> Type) (x : A) (xs0 : vec A n) (f : fin n) (p : P x) (v : vforall P xs0),
vforall_lookup_graph n A P xs0 f v (vforall_lookup f v) -> vforall_lookup_graph (S n) A P (VCons x xs0) (FSucc f) (VFCons P n x xs0 p v) (vforall_lookup f v)
The difference lies in the calls to vforall_lookup. In the first case, we have
vforall_lookup (FSucc f) (VFCons P n1 x xs p v)
and in the second case
vforall_lookup f v
But these are identical by definition of vforall_lookup! But by default the unification fails to recognize that. We need to help it a bit. We can either give the value of some argument, e.g.
apply (vforall_lookup_graph_equation_2 n0).
or we can use exact or refine that unify more aggressively than apply since they are given the whole term and not only its head
refine (vforall_lookup_graph_equation_2 _ _ _ _ _ _ _ _ _).
We can conclude easily by the induction hypothesis. This gives the following proof
Next Obligation.
induction v.
- inversion idx.
- dependent elimination idx.
+ constructor.
+ (* IHv is the induction hypothesis *)
exact (vforall_lookup_graph_equation_2 _ _ _ _ _ _ _ _ (IHv _)).
Defined.
Since I like doing proofs with dependent types by hand, I can't help giving a proof that does not use dependent elimination.
Next Obligation.
induction v.
- inversion idx.
- revert dependent xs.
refine (
match idx as id in fin k return
match k return fin k -> Type with
| 0 => fun _ => IDProp
| S n => fun _ => _
end id
with
| FZero => _
| FSucc f => _
end); intros.
+ constructor.
+ exact (vforall_lookup_graph_equation_2 _ _ _ _ _ _ _ _ (IHv _)).
Defined.
I am new to Coq and need some help with some of trivial examples to get me started. In particular I am interested in defining some operations of vectors (fixed size lists) using dependent types. I started with Vector package and trying to implement some additional functions. For example I am having difficulty implementing trivial 'take' and 'drop' functions, which take or drop first 'p' elements from the list.
Require Import Vector.
Fixpoint take {A} {n} (p:nat) (a: t A n) : p<=n -> t A p :=
match a return ( p<=n -> t A p) with
| cons A v (S m) => cons (hd v) (take m (tl v)) m
| nil => fun pf => a
end.
The error (in case of nil) is:
The term "a" has type "t A n" while it is expected to have type "t A p".
Could somebody help me with some starting points? Thanks!
I don't understand your approach. You're always returning a non-empty vector when the argument is a non-empty vector, but take must return nil when p=0 regardless of the vector.
Here's one approach to building take. Rather than using the hypothesis p <= n, I express the length of the argument n as a sum of the number p of elements to take and the number of trailing elements m, which is possible iff p <= n. This allows for an easier recursive definition, because (S p') + m is structurally equal to S (p' + m). Note that the discrimination is on the number of elements to take: return nil if taking 0, return cons head new_tail otherwise.
This version of the take function has the desired computational behavior, so all that's left is to define one with the desired proof content. I use the Program feature to do this conveniently: fill in the computational content (trivial, I just need to say that I want to use m = n - p), then complete the proof obligations (which are simple arithmetic).
Require Import Arith.
Require Import Vector.
Fixpoint take_plus {A} {m} (p:nat) : t A (p+m) -> t A p :=
match p return t A (p+m) -> t A p with
| 0 => fun a => nil _
| S p' => fun a => cons A (hd a) _ (take_plus p' (tl a))
end.
Program Definition take A n p (a : t A n) (H : p <= n) : t A p :=
take_plus (m := n - p) p a.
Solve Obligations using auto with arith.
For your newdrop : forall A n p, t A n -> p <= n -> t A (n-p), the following approach works. You need to help Coq by telling it what p and n become in the recursive call.
Program Fixpoint newdrop {A} {n} p : t A n -> p <= n -> t A (n-p) :=
match p return t A n -> p <= n -> t A (n-p) with
| 0 => fun a H => a
| S p' => fun a H => newdrop p' (tl a) (_ : p' <= n - 1)
end.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
I don't know why Solve Obligations using omega. doesn't work but solving each obligation individually works.