Is it possible to turn a context pattern into a Gallina function? - coq

In Ltac, a context pattern can be used to build an Ltac-level function which accepts a Gallina term and constructs a Gallina term by filling in a hole. I would like to reify this function and use it at the level of Gallina, rather than Ltac.
E.g., the following code works using meta-variables rather than context patterns.
Variables
(A : Set)
(P : A -> Prop)
(a : A)
(H : forall Q: A -> Prop, Q a).
Goal (P a).
match goal with
| |- ?P a => exact (H P)
end.
Qed.
But the following code does not work because I cannot bring the variable x into scope before filling in the pattern:
Goal (P a).
match goal with
| |- context C[a] => let y := context C[x] in exact (H (fun x => y))
end.
(* The reference x was not found in the current
environment. *)
Nor does the following work because I cannot use Ltac within Gallina:
Goal (P a).
match goal with
| |- context C[a] => let y := exact (H (fun x => context C[x]))
end.
(* Syntax error... *)
But the following code shows that my context pattern works like I think it should:
Goal (P a).
match goal with
| |- context C[a] => let y := context C[a] in idtac y
end.
(* (P a) *)
While this example is trivial because the goal is a single application, in general I want to use context patterns to match significantly more complex goals and then use those patterns to build Gallina functions. Can this be done?

Use ltac:(...)
match goal with
| |- context C[a] => exact (H (fun x => ltac:(let y := context C[x] in exact y)))
end.
ltac:(...) can replace any Gallina term. The expected type of that hole becomes the goal for the contained tactic expression, which is executed to produce a new Gallina term to fill the hole.

Related

Induction on a datatype with non-uniform type parameters produces ill-typed terms

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.

Prove existential quantifier using Coq

Assuming we have an inductive data structure and some predicate over it:
Inductive A : EClass :=
X | Y .
Definition P (a: A) : bool :=
match a with
X => true
| Y => false
end.
Then, I formulate a theorem to say there exists an element a such that P a returns true:
Theorem test :
exists a: A, P a.
There are probably various ways of doing it, I am thinking how to use case analysis to prove it, in my mind, it works something like this:
remember there are 2 ways A can be constructed
try each way one by one, stop if we find a witness such that P a holds.
My Coq code looks like:
evar (a: A). (* introduce a candidate to manipulate *)
destruct a eqn: case_A. (* case analysis *)
- (* case where a = X *)
exists a.
rewrite case_A.
done.
- (* case where a = Y *)
(* stuck *)
My question is that,
is my prove strategy logically flawed?
if not, my Coq is the problem, how can I convey to Coq that my job is done is I find one witness? might be I should not destruct?
Thanks!
Yes, your proof is flawed! All that you need is to provide the witness first:
Inductive A := X | Y .
Definition P (a: A) : bool := match a with X => true | Y => false end.
Theorem test : exists a: A, P a = true.
Proof. now exists X. Qed.
If you do case analysis first, you'll get into a dead-end.
Here is a rough framework that demonstrates how you might program a Coq tactic to try all elements of a finite type as witnesses.
(* Typeclass to register an enumeration of elements of a type. *)
Class Enumeration (A:Type) :=
enumerate : list A.
Arguments enumerate A [Enumeration].
(* Typeclass to register decision procedures to determine whether
a given proposition is true or false. *)
Class Decision (P:Prop) :=
decide : {P} + {~P}.
Arguments decide P [Decision].
(* Given a Coq list l, execute tactic t on every element of
l until we get a success. *)
Ltac try_list l t :=
match (eval hnf in l) with
| #cons _ ?hd ?tl => (t hd || try_list tl t)
end.
(* Tactic for "proof by reflection": use a decision procedure, and
if it returns "true", then extract the proof from the result. *)
Ltac by_decision :=
match goal with
|- ?P => let res := (eval hnf in (decide P)) in
match res with
| left ?p => exact p
end
end.
(* Combination to try to prove an (exists x:A, P) goal by trying
to prove P by reflection for each element in an enumeration of A. *)
Ltac try_enumerate :=
match goal with
|- #ex ?A ?P =>
try_list (enumerate A)
ltac:(fun x => exists x; by_decision)
end.
(* Demonstration on your example *)
Inductive A := X | Y.
Instance A_enum : Enumeration A :=
cons X (cons Y nil).
Instance bool_eq_dec : forall x y:bool,
Decision (x = y).
Proof.
intros. red. decide equality.
Defined.
Definition P (a:A) : bool :=
match a with
| X => true
| Y => false
end.
Goal exists a:A, P a = true.
Proof.
try_enumerate.
Qed.

Incorrect elimination of X in the inductive type "or":

I am trying to define a relatively simple function on Coq:
(* Preliminaries *)
Require Import Vector.
Definition Vnth {A:Type} {n} (v : Vector.t A n) : forall i, i < n -> A. admit. Defined.
(* Problematic definition below *)
Definition VnthIndexMapped {A:Type}
{i o:nat}
(x: Vector.t (option A) i)
(f': nat -> option nat)
(f'_spec: forall x, x<o ->
(forall z,(((f' x) = Some z) -> z < i)) \/
(f' x = None))
(n:nat) (np: n<o)
: option A
:=
match (f' n) as fn, (f'_spec n np) return f' n = fn -> option A with
| None, _ => fun _ => None
| Some z, or_introl zc1 => fun p => Vnth x z (zc1 z p)
| Some z, or_intror _ => fun _ => None (* impossible case *)
end.
And getting the following error:
Error:
Incorrect elimination of "f'_spec n np" in the inductive type "or":
the return type has sort "Type" while it should be "Prop".
Elimination of an inductive object of sort Prop
is not allowed on a predicate in sort Type
because proofs can be eliminated only to build proofs.
I think I understand the reason for this limitation, but I am having difficulty coming up with a workaround. How something like this could be implemented? Basically I have a function f' for which I have a separate proof that values less than 'o' it either returns None or a (Some z) where z is less than i and I am trying to use it in my definition.
There are two approaches to a problem like this: the easy way and the hard way.
The easy way is to think whether you're doing anything more complicated than you have to. In this case, if you look carefully, you will see that your f'_spec is equivalent to the following statement, which avoids \/:
Lemma f'_spec_equiv i o (f': nat -> option nat) :
(forall x, x<o ->
(forall z,(((f' x) = Some z) -> z < i)) \/
(f' x = None))
<-> (forall x, x<o -> forall z,(((f' x) = Some z) -> z < i)).
Proof.
split.
- intros f'_spec x Hx z Hf.
destruct (f'_spec _ Hx); eauto; congruence.
- intros f'_spec x Hx.
left. eauto.
Qed.
Thus, you could have rephrased the type of f'_spec in VnthIndexedMapped and used the proof directly.
Of course, sometimes there's no way of making things simpler. Then you need to follow the hard way, and try to understand the nitty-gritty details of Coq to make it accept what you want.
As Vinz pointed out, you usually (there are exceptions) can't eliminate the proof of proposition to construct something computational. However, you can eliminate a proof to construct another proof, and maybe that proof gives you what need. For instance, you can write this:
Definition VnthIndexMapped {A:Type}
{i o:nat}
(x: Vector.t (option A) i)
(f': nat -> option nat)
(f'_spec: forall x, x<o ->
(forall z,(((f' x) = Some z) -> z < i)) \/
(f' x = None))
(n:nat) (np: n<o)
: option A
:=
match (f' n) as fn return f' n = fn -> option A with
| None => fun _ => None
| Some z => fun p =>
let p' := proj1 (f'_spec_equiv i o f') f'_spec n np z p in
Vnth x z p'
end eq_refl.
This definition uses the proof that both formulations of f'_spec are equivalent, but the same idea would apply if they weren't, and you had some lemma allowing you to go from one to the other.
I personally don't like this style very much, as it is hard to use and lends itself to programs that are complicated to read. But it can have its uses...
The issue is that you want to build a term by inspecting the content of f'_spec. This disjunction lives in Prop, so it can only build other Prop. You want to build more, something in Type. Therefore you need a version of disjunction that lives at least in Set (more generally in Type). I advise you replace your Foo \/ Bar statement with the usage of sumbool, which uses the notation {Foo}+{Bar}.

Unfold anonymous function in Coq proof

I am stuck trying to prove something in Coq that involves the use of a type class.
The specific type class is almost identical to this Functor type class: https://gist.github.com/aztek/2911378
My instance looks like this:
Instance ListFunctor : Functor list := { fmap := map }.
(* Proof stuff here *)
Defined.
map is the map over lists from the standard library.
The "proof" I am doing is basically just a unit test:
Example list_map_test : fmap (fun x => x + 1) (1::2::3::nil) = (2::3::4::nil).
My goal looks like this and I am stuck:
(let (fmap0, _, _) := ListFunctor in fmap0) nat nat
(fun x : nat => x + 1) (1 :: 2 :: 3 :: nil) = 2 :: 3 :: 4 :: nil
Coq destructured the instance to get fmap0 and then applied the resulting anonymous function with the args nat nat (fun x : nat => x + 1) (1 :: 2 :: 3 :: nil).
As the next step in my proof, I would like to unfold fmap0 or the anonymous function.
How can I do this? I cannot do unfold fmap0.
My expectation was that fmap0 is the standard lib map because that is what I gave to the instance.
I was able to destruct the instance myself, but this shows the abstract version of fmap0 and not the implementation that was given when instantiating the type class.
What am I doing wrong?
If f is an anonymous function (that is, something of the form fun x => expr), then simpl should be enough. If it is an identifier and you cannot unfold it, then either (1) it is a local variable bound in your context, or (2) it is a global definition defined via Qed. In the latter case, just remove the Qed from your definition, replacing it by Defined. In the former case, I would guess that you should have tried to unfold or simplify expr1 so that Coq can have access to the actual definition of f (this, in turn, might require removing Qeds from other global definitions).
I don't know exactly why, but if you simplify directly the goal
1 subgoal
______________________________________(1/1)
fmap (λ x : nat, (x + 1)%nat) (1 :: 2 :: 3 :: [ ]) = 2 :: 3 :: 4 :: [ ]
using simpl or cbv for example, you get your instance of map (in fact you get the result of map S applied to 1 :: 2 :: 3 :: [] hence the goal becomes trivial). I don't know why unfolding fmap or destructing the ListFunctor yields a generic fmap0.

Proof of Paper, Scissor, Rock as Monoid Instance in Coq

So while learning Coq I did a simple example with the game paper, scissor, rock. I defined a data type.
Inductive PSR : Set := paper | scissor | rock.
And three functions:
Definition me (elem: PSR) : PSR := elem.
Definition beats (elem: PSR) : PSR :=
match elem with
| paper => scissor
| rock => paper
| scissor => rock
end.
Definition beatenBy (elem: PSR) : PSR :=
match elem with
| paper => rock
| rock => scissor
| scissor => paper
end.
I also define composition (although this should be somewhere in the standard library)
Definition compose {A B C} (g : B -> C) (f : A -> B) : (A -> C) :=
fun x : A => g (f x).
I implement the class monoid as described here
Class Monoid {A : Type} (dot : A -> A -> A) (unit : A) : Type := {
dot_assoc : forall x y z:A,
dot x (dot y z)= dot (dot x y) z;
unit_left : forall x,
dot unit x = x;
unit_right : forall x,
dot x unit = x
}.
I finally managed to prove that you can PSR forms a monoid under compose as + and me as 1
Instance MSPR : Monoid compose me.
split.
intros. reflexivity.
intros. reflexivity.
intros. reflexivity.
Qed.
Question
Why does the proof of Instance MSPR : Monoid compose me. work just by applying intros and reflexivity? Honestly, I did split and intros knowing what I was doing, but after intros I got something like
3 subgoal
x : PSR -> PSR
y : PSR -> PSR
z : PSR -> PSR
______________________________________(1/3)
compose x (compose y z) = compose (compose x y) z
tried apply compose. but it didn't work. Magically reflexivity. solved it but I don't know why.
Side Note
This worked wonderfully, if you define power like this
Fixpoint power {A dot one} {M : #Monoid A dot one}(a:A)(n:nat) :=
match n with 0 % nat => one
| S p => dot a (power a p)
end.
then Compute (power beats 2) paper. yields
= rock
: PSR
which did this beats (beats paper) = beats scissor = rock !!!
The reflexivity principle in Coq is actually more powerful than than mere syntactic equality, as one could expect. Roughly speaking, Coq considers to be equal any two things that can be simplified to the same value. Simplification here is taken in a slightly more restrictive sense than in algebra, for instance, where one is allowed to manipulate formulas according to algebraic laws. Instead, Coq comes with a fixed set of computation rules that describe how programs compute. In your example, simplifying the expression would yield
compose x (fun a => y (z a)) = compose (fun a => x (y a)) z
fun a => x (y (z a)) = fun a => x (y (z a))
Where "fun" is Coq's notation for an anonymous function, I.e. a function without a name. Since these two things are equal, reflexivity suffices. The same idea apllies to the other goals.
After the intros, you can do unfold compose to ask Coq to only unfold compose definition, you will see that both side of the equality are syntactically the same, thus reflexivity manages to solve your goal (reflexivity can "see" through definitions).
The question remains: why are they the same: See Arthur's answer for that ;)
V.