In Coq I have
Definition f (s:Unit) : tt=tt := match s with tt => idpath end.
Definition g (p:tt=tt) : Unit := match p with idpath => tt end.
and I would like to prove forall (p:tt=tt), (f o g) p = p.
I want to do it using the path induction described in 1.12.1 in HoTT's book.
It is clear that for the case in which p is idpath, we can prove
assert( (f o g) idpath = idpath).
simpl.
reflexivity.
But how do I use path induction in Coq to package together the whole proof?
The whole proof until now: (What to put instead of admit?)
Require Import HoTT.
Definition f (s:Unit) : tt=tt := match s with tt => idpath end.
Definition g (p:tt=tt) : Unit := match p with idpath => tt end.
Theorem myTheorem : forall (p:tt=tt), (f o g) p = p.
assert( (f o g) idpath = idpath).
simpl.
reflexivity.
admit.
The analog of path induction in Coq is the match construct. Here is how we can use it to define (based) path induction as described in the HoTT book.
Set Implicit Arguments.
Definition J {A} {x : A} (P : forall y, x = y -> Type)
(H : P x eq_refl) : forall y p, P y p :=
fun y p => match p with eq_refl => H end.
The type of this definition says that, whenever we want to prove P y p, where
y : A,
p : x = y, and
P : forall y, x = y -> Type,
it suffices to show that P x eq_refl holds. We can use J to show that your g function is constant. (I have rephrased the definitions to match the ones given by the Coq standard library.)
Definition f (s : unit) : tt = tt := match s with tt => eq_refl end.
Definition g (p : tt = tt) : unit := match p return unit with eq_refl => tt end.
Definition g_tt p : g p = tt :=
J (fun y q => match q return unit with eq_refl => tt end = tt)
eq_refl p.
The tricky part of this proof is finding out what the P parameter of J should be, which is also the case of other proofs that proceed by path induction. Here, I had to unfold the definition of g, because it requires an argument of type tt = tt, whereas the q used above has type tt = y. In any case, you can see that P tt p is definitionally equal to g p = tt, which is what we want to prove.
We can play trick to show that p = eq_refl for any p : tt = tt. Combined with the previous result, it will give exactly what you want.
Definition result (p : tt = tt) : p = eq_refl :=
J (fun y q =>
unit_rect (fun z => tt = z -> Prop)
(fun u => u = eq_refl)
y q)
eq_refl p.
Once again, the crux is the P parameter. We make use of the induction principle for unit, which says that we can define something of type T x (for T : unit -> Type and x : tt) whenever we can find an element of T tt. Recall that the result of this application of J should have type
P tt p
which in this case is just
unit_rect (fun z => tt = z -> Prop)
(fun u => u = eq_refl)
tt p
= (p = eq_refl)
by the computation rules for unit_rect.
Unfortunately, this sort of proof is difficult to replicate with Coq's tactic language, because it often has trouble inferring what P should be. It is often easier to figure out what this value should be yourself and write down the proof term explicitly.
I don't quite understand why, but Coq is also much better at figuring out this annotation if you write down the proof term with match. Compare:
Definition result' (p : tt = tt) : p = eq_refl :=
match p with eq_refl => eq_refl end.
Although this looks much simpler, you will see that the actual term inferred by Coq is much more complicated when you try to print it. Try it!
Edit
Ah, I just realized that you were trying to use the HoTT version of Coq. I don't have that version installed, but I think it shouldn't be too hard to adapt my solution to it.
I realize this question is super old and has long been solved but I do want to note that HoTT path induction is done slightly differently than Arthur's answer prescribes. I think this is helpful to see for two reasons: (i) the way HoTT sets things up is a bit less complicated and (ii) it is more in line with how path induction is actually used in HoTT and so it will be easier to translate into their library. Both of these points are mostly for people like me who come upon this question years later.
First, the symbol equality symbol is redefined in HoTT to denote the path space, which is defined as being the inductive type with one generator refl x for each point in a type A.
So in HoTT we have
Inductive paths {A : UU} (x : A) := A -> UU
| refl : paths a a.
Based path induction is then just the function paths_rect which is automatically generated by the Coq system. Path induction can then be defined as an instance of Based Path induction, as is done in The HoTT Book.
This can all be seen in the UniMath file "Preamble" in the Foundations directory.
Related
Given the definition:
Definition cast (a b:Type) (p:a = b) (x:a) : b :=
match p with
| eq_refl _ => x
end.
I was hoping that the following lemma would be provable:
Lemma cast_cast_is_id : forall (a b:Type) (x:a) (p:a = b) (q:b = a),
cast b a q (cast a b p x) = x.
However, I do not seem to be able to carry out a proof for this. I can destruct p successfully, but cannot destruct q after that. Replacing the lemma's statement with eq_sym p instead of arbitrary q does not help me either it seems.
I fear I have unwittingly stumbled into some subtle point of HoTT.
Can anyone prove this lemma or is it known to be unprovable without further axioms?
I am not completely sure, but it seems to me that what you are trying to prove is no different from forall a (p:a=a), p = eq_refl. If so, you cannot prove it in Coq, unless you know something about a, e.g., decidable equality. In that case, you can use the results on UIP (unicity of identity proofs) from the standard library.
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.
Consider the definition of find in the standard library, which as the type find: forall A : Type, (A -> bool) -> list A -> option A.
Of course, find has to return an option A and not an A because we don't know wether there is a "valid" element in the list.
Now, say I find this definition of find painful, because we have to deal with the option, even when we are sure that such an element exists in the list.
Hence, I'd like to define myFind which additionnaly takes a proof that there is such an element in the list. It would be something like:
Variable A: Type.
Fixpoint myFind
(f: A -> bool)
(l: list A)
(H: exists a, In a l /\ f a = true): A :=
...
If I am not mistaken, such a signature informally says: "Give me a function, a list, and a proof that you have a "valid" element in the list".
My question is: how can I use the hypothesis provided and define my fixpoint ?
What I have in mind is something like:
match l with
| nil => (* Use H to prove this case is not possible *)
| hd :: tl =>
if f hd
then hd
else
(* Use H and the fact that f hd = false
to prove H': exists a, In a tl /\ f a = true *)
myFind f tl H'
end.
An bonus point would be to know whether I can embbed a property about the result directly within the type, for instance in our case, a proof that the return value r is indeed such that f r = true.
We can implement this myFind function by structural recursion over the input list. In the case of empty list the False_rect inductive principle is our friend because it lets us switch from the logical world to the world of computations. In general we cannot destruct proofs of propositions if the type of the term under construction lives in Type, but if we have an inconsistency the system lets us.
We can handle the case of the non-empty input list by using the convoy pattern (there is a number of great answers on Stackoverflow explaining this pattern) and an auxiliary lemma find_not_head.
It might be useful to add that I use the convoy pattern twice in the implementation below: the one on the top level is used to let Coq know the input list is empty in the first match-branch -- observe that the type of H is different in both branches.
From Coq Require Import List.
Import ListNotations.
Set Implicit Arguments.
(* so we can write `f a` instead of `f a = true` *)
Coercion is_true : bool >-> Sortclass.
Section Find.
Variables (A : Type) (f : A -> bool).
(* auxiliary lemma *)
Fact find_not_head h l : f h = false ->
(exists a, In a (h :: l) /\ f a) ->
exists a, In a l /\ f a.
Proof. intros E [a [[contra | H] fa_true]]; [congruence | now exists a]. Qed.
Fixpoint myFind (l : list A) (H : exists a : A, In a l /\ f a) : {r : A | f r} :=
match l with
| [] => fun H : exists a : A, In a [] /\ f a =>
False_rect {r : A | f r}
match H with
| ex_intro _ _ (conj contra _) =>
match contra with end
end
| h :: l => fun H : exists a : A, In a (h :: l) /\ f a =>
(if f h as b return (f h = b -> {r : A | f r})
then fun Efh => exist _ h Efh
else fun Efh => myFind l (find_not_head Efh H)) eq_refl
end H.
End Find.
Here is a simplistic test:
From Coq Require Import Arith.
Section FindTest.
Notation l := [1; 2; 0; 9].
Notation f := (fun n => n =? 0).
Fact H : exists a, In a l /\ f a.
Proof. exists 0; intuition. Qed.
Compute myFind f l H.
(*
= exist (fun r : nat => f r) 0 eq_refl
: {r : nat | f r}
*)
End FindTest.
You can also use Program to help you construct the proof arguments interactively. You fill in as much as you can in the program body and leave _ blanks that you get to fill in later with proof tactics.
Require Import List Program.
Section Find.
Variable A : Type.
Variable test : A -> bool.
Program Fixpoint FIND l (H:exists a, test a = true /\ In a l) : {r | test r = true} :=
match l with
| [] => match (_:False) with end
| a::l' => if dec (test a) then a else FIND l' _
end.
Next Obligation.
firstorder; congruence.
Defined.
End Find.
Program is a little better at not forgetting information when you do case analysis (it knows the convoy pattern) but it is not perfect, hence the use of dec in the if statement.
(Notice how Coq was able to handle the first obligation, to construct a term of type False, all by itself!)
Using this definition of a group:
Structure group :=
{
G :> Set;
id : G;
op : G -> G -> G;
inv : G -> G;
op_assoc_def : forall (x y z : G), op x (op y z) = op (op x y) z;
op_inv_l : forall (x : G), id = op (inv x) x;
op_id_l : forall (x : G), x = op id x
}.
(** Set implicit arguments *)
Arguments id {g}.
Arguments op {g} _ _.
Arguments inv {g} _.
Notation "x # y" := (op x y) (at level 50, left associativity).
And having proven this theorem:
Theorem mult_both_sides (G : group) : forall (a b c : G),
a = b <-> c # a = c # b.
How do I write an Ltac that automates the process of left multiplying a given equality (either the goal itself or a hypothesis) by a given term?
Ideally, using this Ltac in a proof would look like this:
left_mult (arbitrary expression).
left_mult (arbitrary expression) in (hypothesis).
Building on the answer given by larsr, you can use Tactic Notations to write
Tactic Notation "left_mult" uconstr(arbitrary_expression) :=
apply (mult_both_sides _ _ _ arbitrary_expression).
Tactic Notation "left_mult" uconstr(arbitrary_expression) "in" hyp(hypothesis) :=
apply (mult_both_sides _ _ _ arbitrary_expression) in hypothesis.
Using uconstr says "delay typechecking of this term until we plug it into apply". (Other options include constr ("typecheck this at the call site") and open_constr ("typecheck this at the call site and fill in holes with evars").)
Do you really need a specific tactic for this? If you just use apply to this
Goal forall (G:group) (a b c: G), a = b.
intros.
apply (mult_both_sides _ _ _ c).
Now your goal is
G0 : group
a, b, c : G0
============================
c # a = c # b
If you want to modify a hypothesis H, then just do apply ... in H.
In Coq, I'm having problems with applying the rewrite tactic in the following situation:
Section Test.
Hypothesis s t : nat -> nat.
Hypothesis s_ext_eq_t : forall (x : nat), s x = t x.
Definition dummy_s : nat -> nat :=
fun n => match n with
| O => 42
| S np => s np
end.
Definition dummy_t : nat -> nat :=
fun n => match n with
| O => 42
| S np => t np
end.
Goal forall (n : nat), dummy_s n = dummy_t n.
Proof.
intro n. unfold dummy_s. unfold dummy_t.
At that stage, the local context and current goal look as follows:
1 subgoals, subgoal 1 (ID 6)
s : nat -> nat
t : nat -> nat
s_ext_eq_t : forall x : nat, s x = t x
n : nat
============================
match n with
| 0 => 42
| S np => s np
end = match n with
| 0 => 42
| S np => t np
end
Now it should be possible to apply the rewrite tactic to replace the occurence of s np in the goal by t np, thereby making it possible to solve the goal using reflexivity. However,
rewrite s_ext_eq_t.
gives
Toplevel input, characters 0-18:
Error: Found no subterm matching "s ?190" in the current goal.
What am I doing wrong? One can get into a situation where rewrite is applicable via
destruct n.
(* n = 0 *)
reflexivity.
(* n > 0 *)
rewrite s_ext_eq_t.
reflexivity.
Qed.
but in the actual situation I am facing, several such destructs would be necessary, and I wonder whether rewrite or a variant of it is able to do this automatically.
Addendum The above situation naturally occurs when proving that a function defined via well-founded recursion has the desired fixed point property:
Suppose A: Type and that R: A -> A -> Prop is a well-founded relation, i.e. we have Rwf: well_founded R. Then, given a type family P: A -> Type we may construct a section
Fix : forall (x : A), P a
through recursion over R, with the recursion step given as a function
F : forall x:A, (forall y:A, R y x -> P y) -> P x
See https://coq.inria.fr/library/Coq.Init.Wf.html However, to show that Fix indeed has the fixed point property
forall (x : A), Fix x = F (fun (y:A) _ => Fix y)`
we need to provide a witness
F_ext : forall (x:A) (f g:forall y:A, R y x -> P y),
(forall (y:A) (p:R y x), f y p = g y p) -> F f = F g.
i.e. we have to show that F does not use anything else from the given f: forall y:A, R y x -> P y but its values. Of course, in any concrete situation, this should be trivial to verify, but when one tries to prove it, one runs into a situation a minimal example of which I have presented above: One is facing a huge equality of two copies of the code for the recursion step, one time with f and another time with g. Your assumption tells that f and g are extensionally equal, so one should be able to rewrite them. However, in the code for the recursion step, there might be a large number of pattern matchings and new variables that doesn't make sense in the local context, hence it would be (unnecessarily?) quite tedious to destruct dozens of times before being allowed to apply rewrite.
As mentioned in a comment above, it is not possible to perform the rewrite directly on the branch of the match statement, because np is not in scope in the top-level environment. As far as Coq's theory is concerned, a proof of your statement will have to destruct n at some point.
Although I am not aware of any tactics for automating this kind of problem, it is not too hard to come up with some custom ltac code for solving your problem without too much pain:
Ltac solve_eq :=
try reflexivity;
match goal with
| |- match ?x with _ => _ end
= match ?x with _ => _ end =>
destruct x; auto
end.
Goal forall (n : nat), dummy_s n = dummy_t n.
Proof.
intro n. unfold dummy_s. unfold dummy_t.
solve_eq.
Qed.
If your extensional equality results are hypotheses that appear in your context, then solve_eq should be able to solve many goals of this shape; if not, you might have to add extra lemmas to your hint database.