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.
Related
After unfolding everything I can in an attempt to get rid of symbols I don't want in my induction hypothesis, I am left with:
X: Type
test: X -> bool
x: X
l: list X
IHl: (fix existsb
(X : Type) (test : X -> bool)
(l : list X) {struct l} : bool :=
fold orb (map test l) false) X test l =
negb
((fix forallb
(X : Type) (test : X -> bool)
(l : list X) {struct l} : bool :=
fold andb (map test l) true) X
(fun x : X => negb (test x)) l)
The two fixpoints which wind up embedded should be evaluated as far as I can see since I have already intros'ed their parameters; and if they simply were evaluated with their parameters, my IHl would be perfect.
I am not clear on why these won't evaluate in this case. As the example is from logical foundations, I haven't provided more of my solution hoping that it's enough to ask what tactic can I apply to IHl to cause coq to actually do the rewrite with the arguments that I am looking for.
I guess I don't really understand but it seems my case is fundamentally similar to this question:
Why cannot evaluate a fix-defined expression with an abstract value in Coq?
It seems that the workaround is to destruct l in order to ensure that the cases all start with a constructor, which then eliminates the fixpoints in two redundant cases that make the proof more or less immediate from there.
A post to enlighten me better about why there is no way to get one level of substitution here would be great, as I can't see any reason not to have a tactic that will apply in this circumstance.
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.
The statement of the problem.
Consider this definition of map:
Fixpoint map (xs: list nat): (nat -> nat) -> list nat := match xs with
| nil => fun _ => nil
| x::xs' => fun f => (f x) :: (map xs' f)
end.
It works like this:
Coq < Eval simpl in map (1::2::3::List.nil) (fun x => x + 1).
= 2 :: 3 :: 4 :: nil
: list nat
How can I extend it to work on any types?
For example, in Haskell I can simply write as follows:
map :: forall a b. [a] -> (a -> b) -> [b]
map xs = case xs of
[ ] -> \_ -> [ ]
(x:xs') -> \f -> f x: map xs' f
But in Coq, I do not understand where I could place this forall quantifier.
My efforts.
The syntax reference explains the syntax of Fixpoint thusly:
Fixpoint ident binders {struct ident}? : type? := term
— So evidently there is no place in the syntax for a quantifier that binds a type variable over both binders and type. I tried placing forall here and there by guesswork but I could not make it work.
I can see how the type section could be made polymorphic in the result type of the function parameter without touching the binders section:
Fixpoint map (xs: list nat): forall B, (nat -> B) -> list B := match xs with
| nil => fun _ => nil
| x::xs' => fun f => f x :: (map xs' f)
end.
— But unfortunately this also gives an error, and cryptic enough for me at that:
In environment
map : list nat -> forall B : Type, (nat -> B) -> list B
xs : list nat
T : Type
The term "nil" has type "list ?A" while it is expected to have type
"(nat -> T) -> list T".
So, even for this simpler case I have no solution.
So, what can be done?
In Coq, the Fixpoint command is just a wrapper around the fix term constructor, which allows us to define anonymous recursive functions. A direct definition of map could be given as follows:
Require Import Coq.Lists.List.
Import ListNotations.
Definition map_anon : forall A B, (A -> B) -> list A -> list B :=
fix map A B (f : A -> B) (l : list A) : list B :=
match l with
| [] => []
| x :: l => f x :: map A B f l
end.
This is morally equivalent to the following definition:
Fixpoint map A B (f : A -> B) (l : list A) : list B :=
match l with
| [] => []
| x :: l => f x :: map A B f l
end.
Notice that A and B are bound as regular variables: in Coq, there is no distinction between types and terms, and these declarations causes Coq to infer their types as being Type. No forall quantifier is needed for the definition.
You can list all your arguments, including type arguments, after the name of the function. You'll put any arguments that depend on other arguments after the argument they depend on.
Fixpoint map (A B: Type) (xs: list A) (f: A -> B): list B :=
[...]
If you prefer foralls, you simply need to move everything (except the recursive argument and any arguments it depends on) to after the :.
Fixpoint map (A B: Type) (xs: list A): forall (f: A -> B), list B :=
[...]
Two things to note here. Since nothing after f depends on f, you could use the -> notation. This is purely notation and doesn't have any semantic difference.
Fixpoint map (A B: Type) (xs: list A): (A -> B) -> list B :=
[...]
The other thing to note is that when the arguments are after the : like this, we have to define a function, not just something in list B.
Fixpoint map (A B: Type) (xs: list A): (A -> B) -> list B :=
fun f => [...]
This is why you got the error The term "nil" has type "list ?A" while it is expected to have type "(nat -> T) -> list T".. We needed a function, not just something of type list B, which is what nil is.
I'd like to create a dependent function, but I am running into a type mismatch error on the False_rec term. I'm trying to do something similar to the following:
Definition env A := list A.
Fixpoint zip (xs ys : env nat) (H : length xs = length ys) : env (nat * nat).
Proof.
refine
(match xs, ys with
| [], [] => []
| x :: xs, y :: ys =>
(x, y) :: zip xs ys _
| _, _ => False_rec _ _
end).
...
However, I receive the following error:
The term "False_rec ?P ?f" has type "?P" while it is expected to have type
"env (nat * nat)" (unable to find a well-typed instantiation for
"?P": cannot ensure that "Type" is a subtype of "Set").
The standard list, when it is given a Set, becomes a set itself, but it seems that it does not do so when aliased in this way. For example:
Check (list nat). (* list nat : Set *)
Check (env nat). (* env nat : Type *)
Is there a reason for this mismatch? And is there a way to work around it? (For example, can I convince Coq that (env nat) is a Set? Or can I use a more general False_rec function that operates on Type instead of Set?)
Is there a reason for this mismatch?
Yes. Type is an entity that can contain (big) things that won't fit into Set. E.g. nat fits into Set, but Set does not fit into itself. I think there should be more than one excellent answers on SO explaining this issue.
(For example, can I convince Coq that (env nat) is a Set?
You can use explicit type annotations:
Definition env (A : Set) : Set := list A.
Or can I use a more general False_rec function that operates on Type instead of Set?
Yes, you can. It's called False_rect.
Observe that simple match-expression won't work in your case (regardless of Set/Type business), you will need to use dependent pattern matching. Another possibility is to use proof mode to define your function.
I'm attempting to define and prove correct in Coq a function that efficiently diffs two sorted lists. As it does not always recurse on a structurally smaller term (either the first or second list is smaller), Fixpoint won't accept it, so I'm attempting to use Program Fixpoint instead.
When attempting to prove a property of the function using the tactic simpl or program_simpl, Coq spends minutes computing and then produces a giant term, hundreds of lines long. I was wondering if I'm using Program Fixpoint the wrong way, or alternatively if there are other tactics that should be used instead of simplification when reasoning about it?
I also wondered if it's good practice to include the required properties for correctness in params like this, or would it be better to have a separate wrapper function that takes the correctness properties as params, and make this function just take the two lists to be diffed?
Note that I did try defining a simpler version of make_diff, which only took l1 and l2 as parameters and fixed the type A and relation R, but this still produced a gigantic term when the program_simpl or simpl tactics were applied.
*Edit: my includes are (although they may not all be required here):
Require Import Coq.Sorting.Sorted.
Require Import Coq.Lists.List.
Require Import Coq.Relations.Relation_Definitions.
Require Import Recdef.
Require Import Coq.Program.Wf.
Require Import Coq.Program.Tactics.
The code:
Definition is_decidable (A : Type) (R : relation A) := forall x y, {R x y} + {~(R x y)}.
Definition eq_decidable (A : Type) := forall (x y : A), { x = y } + { ~ (x = y) }.
Inductive diff (X: Type) : Type :=
| add : X -> diff X
| remove : X -> diff X
| update : X -> X -> diff X.
Program Fixpoint make_diff (A : Type)
(R : relation A)
(dec : is_decidable A R)
(eq_dec : eq_decidable A)
(trans : transitive A R)
(lt_neq : (forall x y, R x y -> x <> y))
(l1 l2 : list A)
{measure (length l1 + length l2) } : list (diff A) :=
match l1, l2 with
| nil, nil => nil
| nil, (new_h::new_t) => (add A new_h) :: (make_diff A R dec eq_dec trans lt_neq nil new_t)
| (old_h::old_t), nil => (remove A old_h) :: (make_diff A R dec eq_dec trans lt_neq old_t nil)
| (old_h::old_t) as old_l, (new_h::new_t) as new_l =>
if dec old_h new_h
then (remove A old_h) :: make_diff A R dec eq_dec trans lt_neq old_t new_l
else if eq_dec old_h new_h
then (update A old_h new_h) :: make_diff A R dec eq_dec trans lt_neq old_t new_t
else (add A new_h) :: make_diff A R dec eq_dec trans lt_neq old_l new_t
end.
Next Obligation.
Proof.
simpl.
generalize dependent (length new_t).
generalize dependent (length old_t).
auto with arith.
Defined.
Next Obligation.
Proof.
simpl.
generalize dependent (length new_t).
generalize dependent (length old_t).
auto with arith.
Defined.
In this particular case we can get rid of Program Fixpoint and use plain simple Fixpoint. Since at each recursive call we invoke make_diff either on the tail of the first list or on the tail of the second list, we can nest two fixed-point functions as follows. (I have used the Section mechanism here to avoid passing too many identical arguments)
Require Import Coq.Lists.List.
Import ListNotations.
Require Import Coq.Relations.Relations.
Section Make_diff.
Variable A : Type.
Variable R : relation A.
Variable dec : is_decidable A R.
Variable eq_dec : eq_decidable A.
Variable trans : transitive A R.
Variable lt_neq : forall x y, R x y -> x <> y.
Fixpoint make_diff (l1 l2 : list A) : list (diff A) :=
let fix make_diff2 l2 :=
match l1, l2 with
| nil, nil => nil
| nil, new_h::new_t => (add A new_h) :: make_diff2 new_t
| old_h::old_t, nil => (remove A old_h) :: make_diff old_t nil
| old_h::old_t, new_h::new_t =>
if dec old_h new_h
then (remove A old_h) :: make_diff old_t l2
else if eq_dec old_h new_h
then (update A old_h new_h) :: make_diff old_t new_t
else (add A new_h) :: make_diff2 new_t
end
in make_diff2 l2.
End Make_diff.
Observe that the Section mechanism won't include unused parameters in the resulting signature. Here is a naive test:
(* make the first 2 arguments implicit *)
Arguments make_diff [A R] _ _ _ _.
Require Import Coq.Arith.Arith.
Compute make_diff lt_dec Nat.eq_dec [1;2;3] [4;5;6].
(* = [remove nat 1; remove nat 2; remove nat 3; add nat 4; add nat 5; add nat 6]
: list (diff nat) *)
For anyone who comes across the, a better alternative now is the Equations plugin, which will eventually replace Function and Program Fixpoint.