How to get the type of a subterm when you're building a match - coq

My general question is: is there an easy way to incrementally build up a definition in Coq when I'm not familiar with the type of what I'm working with?
Consider one definition of the natural numbers in Coq, from Coq.Narith.BinNat
Definition discr n : { p:positive | n = pos p } + { n = 0 }.
Now, to me it's a little confusing what this term looks like. Suppose I'm trying to extract this positive p from the definition. My first try failed:
Require Import Coq.Narith.BinNat.
Fail Definition NToPos (x : N) : positive :=
match N.discr x with
| inright HO => 1
| inleft Hpos => Hpos
end.
(*
Error:
In environment
x : N
Hpos : {p : positive | x = N.pos p}
The term "Hpos" has type "{p : positive | x = N.pos p}"
while it is expected to have type "positive".
*)
Well... okay. Now I know my basic misunderstanding is with the notation {p : positive | x = N.pos p}, but where do I go from here?
My question is, is there a better way to understand a definition such as N.discr? What I think I want is the following:
Definition NToPos (x : N) : positive :=
match N.discr x with
| inright HO => 1
| inleft Hpos => (* Please tell me how to further destruct Hpos *)
end.

In general, to decipher a notation, you can ask something like
Locate "{ x | p }".
In this case, this figures out what { p : positive | n = pos p } means (you replace the "replaceable" parts of the notation with (meta)variables). It gives
Notation "{ x | P }" := sig (fun x => P)
Now the name sig can be used to get more information.
Print sig.
(*
Inductive sig (A : Type) (P : A -> Prop) : Type :=
exist : forall x : A,
P x -> {x : A | P x}
Arguments exist [A]%type_scope _%function_scope
*)
Which tells you that you need to match Hpos against exist _ p Hpos (the Arguments say that A is implicit and that P is explicit, but P (as a parameter) is already fixed by the type of the scrutinee and must be ignored, and the remaining arguments, x : A and the P x, need to be named).
Alternatively,
Unset Printing Notations. (* In CoqIDE, you're told to set this from the view menu instead *)
Check N.discr.
(* Shows you that the notation stands for sig *)
And then continue as before.

I eventually figured this out by checking Print N.discr and observing:
N.discr =
fun n : N =>
match n as n0 return ({p : positive | n0 = N.pos p} + {n0 = 0%N}) with
| 0%N => inright eq_refl
| N.pos p =>
inleft (exist (fun p0 : positive => N.pos p = N.pos p0) p eq_refl)
end
: forall n : N, {p : positive | n = N.pos p} + {n = 0%N}
and seeing that the case I want is exist (fun p0 : positive => N.pos p = N.pos p0) p eq_refl. Then, exist is the key function. From that I was able to correctly guess inleft (exists p Hpos) would work:
Definition NToPos (x : N) : positive :=
match N.discr x with
| inright HO => 1
| inleft (exist p Hpos) => p
end.

Related

Beta expansion in coq: can I make a term into a function, abstracting over another given term?

I want to rewrite a term, as a function in a sort of beta expansion (inverse of beta reduction).
So, for example in the term a + 1 = RHS I would like to replace it as (fun x => x + 1) a = RHS. Obviously, the two terms are equal by betta reduction, but I can't figure out how to automate it.
The tactic pattern comes very close to what I want, except it only applies to a full goal, and I can't see how I would use it in a term inside an equality.
Similarly, I thought I could use the context holes. Here is my best attempt
Ltac betaExpansion term a:=
let T:= type of a in
match term with
context hole [a] =>
idtac hole;
let f:= fun x => context hole [x] in
remember ( fun x:T => f x ) as f'
end.
Goal forall a: nat, a + 1 = 0.
intros a.
match goal with
|- ?LHS = _ =>
betaExpansion LHS a (*Error: Variable f should be bound to a term but is bound to a tacvalue.*)
end.
This obviously fails, because f is a tacvalue when I really need a normal value. Can I somehow evaluate the expression to make it a value?
You should have a look at the pattern tactic. pattern t replaced all occurrences of t in the goal by a beta expanded variable.
You may also use the change ... with ... at tactic.
Goal forall (a:nat) , a+1 = 2* (a+1) - (a+1).
intro x; change (x+1) with ((fun z => z) (x+1)) at 1 3.
(*
x : nat
============================
(fun z : nat => z) (x + 1) = 2 * (x + 1) - (fun z : nat => z) (x + 1)
*)
Or, more automatically
Ltac betaexp term i :=
let x := fresh "x" in
let T := type of term in
change term with ((fun x : T => x) term) at i.
Goal forall (a:nat) , a+1 = a+1 .
intro x; betaexp (x+1) ltac:(1).

Coq - Assign expression to variable

First and foremost, I'm not yet very familiar with Coq lingo, so I will use terms like e.g. 'expression' and 'variable' loosely, but they are probably not the correct Coq terms.
I'm trying to prove the following subgoal of a Theorem.
1 goal
b : bag
v, b' : nat
b'' : natlist
B : b = b' :: b''
IHb'' : b = b'' -> count v (add v b'') = count v b'' + 1
______________________________________(1/1)
S match v =? b' with
| true => S (count v b'')
| false => count v b''
end = match v =? b' with
| true => S (count v b'')
| false => count v b''
end + 1
You can ignore S and + 1, I'm basically looking for a way to assign
match v =? b' with
| true => S (count v b'')
| false => count v b''
end
to a variable of type nat because it occurs on both sides of the equation.
How can I do this? Or do I need to go through destroying v and b' and proving all cases separately?
Here are two possibilities. There may well be better ones.
You can use set to give a name to a term. All the occurrences of that term are replaced by the variable.
set (x := match v =? b' with
| true => S (count v b'')
| false => count v b''
end).
Sometimes you need to hide the definition of the variable, and only remember it as an equality that you invoke on demand. For that, use remember.
You can match the goal against a pattern using the context form of match goal and give a name to whatever's inside that pattern.
match goal with |- context [S ?_x = ?_x + 1] => set (x := _x) end.
If this is your real goal and not a simplified example, it's a simple arithmetic statement and you can just call lia and let Coq figure it out.
Require Import Lia.
…
lia.
Besides Gilles's suggestions you can use the ssreflect set to achieve this, in at least two ways illustrated here:
Require Import Arith ssreflect.
Variables v b' b'' : nat.
Variable count : nat -> nat -> nat.
Goal
S match v =? b' with
| true => S (count v b'')
| false => count v b''
end
= match v =? b' with
| true => S (count v b'')
| false => count v b''
end + 1.
Proof.
set t := (X in S X = X + _).
Undo.
set t := match _ with true => _ | false => _ end.
Abort.
The latter one also works with the regular set but it needs brackets:
set (t := match _ with true => _ | false => _ end).

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.

Converting to Fin Type in Coq

Can anyone tell me why the following projection function in COQ doesn't work?
Require Import Vector.
Require Import Fin.
Definition Proj {n:nat}{p:nat}(x:t p+{(exists m : nat, n=p+m)}):=
match x with
inleft y => y
|_ => F1
end.
I get the following error:
Error:
In environment
n : nat
p : nat
x : t p + {(exists m : nat, n = p + m)}
e : exists m : nat, n = p + m
The term "F1" has type "t (S ?6 (* [n, p, x, e, e] *))"
while it is expected to have type "t p".
On the other hand, using concrete values for p works fine:
Require Import Vector.
Require Import Fin.
Definition Proj {n:nat}(x:t 3 + {(exists m : nat, n=3+m)}):=
match x with
inleft y => y
|_ => F1
end.
Eval compute in (Proj (of_nat 2 3)) = FS (FS F1): t 3.
I'm assuming that you want Proj to return a value of type t p. That is impossible for p = 0 (because t 0 is the empty set), and that's why you cannot implement Proj for arbitrary p. If you extend you function to take a proof that p is not equal to 0, then you can implement it as follows. Read Adam's CPDT Chapter on Dependent Types to understand what is going on here.
Definition Proj {n:nat} {p:nat} (x:t p+{(exists m : nat, n=p+m)}) : p <> 0 -> t p :=
match x with
| inleft y => fun _ => y
| _ => match p with
| 0 => fun h => False_rect _ (h eq_refl)
| S _ => fun _ => F1
end
end.

Using sets as hyphotesis and goal in COQ

How exactly could a proof like the following be completed?
1 subgoals
IHt1 : {t' : some_type | something_using t'}
IHt2 : {t' : some_type | something_else_using t'}
______________________________________(1/1)
{t' : some_type | another_thing_involving t'}
I do understand that the {x|P x} notation is a shorthand for the sig definition but I really cannot understand how to use it.
{x : D | P x} is intuitively speaking the subset of the domain D containing the elements that satisfy the predicate P. As a proposition, it is true if that subset is non-empty, i.e. if there is a witness x0 in D such that P x0 is true.
An object of type {x : D | P x} is a pair containing an element x0 : D and a proof of P x0. This is visible when you look at the definition of {x : D | P x}, which is syntactic sugar for sig (fun x:D => P x)
Inductive sig (D:Type) (P:D -> Prop) : Type :=
exist : forall x:D, P x -> sig P.
The type of the constructor is a dependent pair type; the first element of the pair has the type D and the second element has the type P x in which x is the first element.
To make use of a hypothesis of the form {x : D | P x}, the most basic way is to use the destruct tactic to break it down into its two components: a witness x0 : D and a proof H : P x0.
destruct IHt1.
1 subgoals
t' : some_type
H : something_using t'
IHt2 : {t'0 : some_type | something_else_using t'0}
______________________________________(1/1)
{t'0 : some_type | another_thing_involving t'0}
To prove a goal of the form {x : D | P x}, the most basic is to use the exist tactic to introduce the intended witness. This leaves one subgoal which is to prove that the witness has the desired property.
exists u.
⋮
______________________________________(1/1)
another_thing_involving u