When is the first input to `list_rec` not a constant function? - coq

The list_rec function has the type:
list_rec
: forall (A : Type) (P : list A -> Set),
P nil ->
(forall (a : A) (l : list A), P l -> P (a :: l)%list) ->
forall l : list A, P l
In all of the examples I've come up with, P is just a constant function that ignores the input list and returns the same type no matter what. For example, P might be fun _ : list A => nat or fun _ : list A => list B. What are some use cases for making the output of P dependent on the input? Why is the type of P list A -> Set instead of just Set?

We can, for example, use list_rec with a non-constant P function to implement a function that converts a list to a vector (a length-indexed list).
Require List Vector.
Import List.ListNotations Vector.VectorNotations.
Set Implicit Arguments.
Section VecExample.
Variable A : Set.
Definition P (xs : list A) : Set := Vector.t A (length xs).
Definition list_to_vector : forall xs : list A, Vector.t A (length xs) :=
list_rec P [] (fun x _ vtail => x :: vtail).
End VecExample.
You can compare it with the standard definition of the Vector.of_list function, which does exactly the same (t means Vector.t in the following code), using explicit recursion instead of hiding it behind a recursion principle:
Fixpoint of_list {A} (l : list A) : t A (length l) :=
match l as l' return t A (length l') with
|Datatypes.nil => []
|(h :: tail)%list => (h :: (of_list tail))
end.
A simple test:
Eval compute in list_to_vector [1;2;3].
Eval compute in Vector.of_list [1;2;3].
Both function calls return the same result:
= [1; 2; 3]
: Vector.t nat (length [1; 2; 3])

Try to prove s ++ [] = s.
[Hint: Define P as fun s => s ++ [] = s.]

Related

Is it possible to make Coq accept a class of Fixpoint functions if we provide proofs of argument size reduction?

I have trees of arbitrary arity, with the following type:
Inductive Tree : Set :=
| Node : list Tree -> Tree.
I can easily create a number of Fixpoint functions such as the following one:
Fixpoint nodecount (tree: Tree ) : nat :=
match tree with
| Node trs => S (sum (map nodecount trs))
end.
but none of the following 'filter' type, even in trivial cases such as this one :
Function nodecount' (tree: Tree ) : nat :=
match tree with
| Node trs => S (sum (map nodecount' ( filter ( fun x => true) trs)))
end.
Whatever the function behind the filter is, the compiler rejects the function as ill-formed.
Is there a way to provide Coq with a proof that this class of filter functions actually produces well-behaved terms, so that any member of this class of fixpoints is allowed ?
Thank you for your help !
One solution is to use mapfilter : (A -> option B) -> list A -> list B instead of filter and a separate map. You also need to be careful in defining mapfilter so that the function argument is not part of the fix arguments.
This works because after unfolding mapfilter in nodecount', the recursive call to nodecount' will be syntactically a subterm of the input tree.
Definition mapfilter {A B : Type} (f : A -> option B) : list A -> list B :=
fix mapfilter_f (xs : list A) : list B :=
match xs with
| nil => nil
| x :: xs => match f x with
| Some y => y :: mapfilter_f xs
| None => mapfilter_f xs
end
end.
Fixpoint nodecount' (p : Tree -> bool) (tree: Tree ) : nat :=
match tree with
| Node trs => S (sum (mapfilter (fun x => if p x then Some (nodecount' p x) else None) trs))
end.
Alternatively you can directly write the list recursion into the tree one:
Fixpoint nodecount (f : Tree -> bool) (t : Tree) : nat :=
if (f t) then
match t with
| Node l =>
(fix iter l1 :=
match l1 with
| nil => 1
| (a :: l2)%list => nodecount f a + iter l2
end) l
end
else 0.

Transform casual list into dependently typed list in Coq

I have following definition of list in Coq:
Variable A : Set.
Variable P : A -> Prop.
Hypothesis P_dec : forall x, {P x}+{~(P x)}.
Inductive plist : nat -> Set :=
pnil : plist O
| pcons : A -> forall n, plist n -> plist n
| pconsp : forall (a:A) n, plist n -> P a -> plist (S n)
.
It describes "list of elements of type A where at least n of them fulfill predicate P".
My task is to create function that will convert casual list into plist (with maximum possible n). My attempt was to first count all elements that match P and then set the output type according to the result:
Fixpoint pcount (l : list A) : nat :=
match l with
| nil => O
| h::t => if P_dec h then S(pcount t) else pcount t
end.
Fixpoint plistIn (l : list A) : (plist (pcount l)) :=
match l with
| nil => pnil
| h::t => match P_dec h with
| left proof => pconsp h _ (plistIn t) proof
| right _ => pcons h _ (plistIn t)
end
end.
However, I get an error in the line with left proof:
Error:
In environment
A : Set
P : A -> Prop
P_dec : forall x : A, {P x} + {~ P x}
plistIn : forall l : list A, plist (pcount l)
l : list A
h : A
t : list A
proof : P h
The term "pconsp h (pcount t) (plistIn t) proof" has type
"plist (S (pcount t))" while it is expected to have type
"plist (pcount (h :: t))".
The problem is that Coq cannot see that S (pcount t) equals pcount (h :: t) knowing that P h, which was already proven. I cannot let Coq know this truth.
How to define this function correctly? Is it even possible to do so?
You can use dependent pattern-matching, as the result type plist (pcount (h :: t)) depends on whether P_dec h is left or right.
Below, the keyword as introduces a new variable p, and return tells the type of the whole match expression, parameterized by p.
Fixpoint plistIn (l : list A) : (plist (pcount l)) :=
match l with
| nil => pnil
| h::t => match P_dec h as p return plist (if p then _ else _) with
| left proof => pconsp h (pcount t) (plistIn t) proof
| right _ => pcons h _ (plistIn t)
end
end.
The type plist (if p then _ else _) must be equal to plist (pcount (h :: t)) when substituting p := P_dec h. Then in each branch, say left proof, you need to produce plist (if left proof then _ else _) (which reduces to the left branch).
It's a bit magical that Coq can infer what goes in the underscores here, but to be safe you can always spell it out: if p then S (pcount t) else pcount t (which is meant to exactly match the definition of pcount).

Coq polymorphic function without explicit type

I have an "enumerate" function written in the Coq term language (what is it called?). This function is kind of annoying to use because it requires that A (the type of an element in the list l) be explicitly provided whenever the enumerate function is used. Is there a way to avoid needing to explicitly pass A as a parameter?
(* [a, b] -> [(0,a), (1,b)] *)
Fixpoint enumerate (A : Type) (l : list A) : list (nat * A) :=
let empty : (list (nat * A)) := nil in
let incr_pair xy := match xy with
| (x, y) => ((S x), y)
end in
match l with
| nil => empty
| (x :: xs) => (O, x) :: (map incr_pair (enumerate A xs))
end.
I want to be able to write something like
Fixpoint enumerate (l : list A) : list (nat * A) := ...
Possibly with some additional syntax identifying what exactly A is.
Put arguments in brackets to make them implicit by default (see section 2.7.4 here). Also, you should probably write this function in a non-quadratic way with a nat accumulator.
Require Import Lists.List.
Import ListNotations.
Fixpoint enumerate_from {A : Type} (n : nat) (l : list A) : list (nat * A) :=
match l with
| [] => []
| x :: xs => (n, x) :: enumerate_from (S n) xs
end.
Definition enumerate {A} l : list (nat * A) := enumerate_from 0 l.
Compute (enumerate [3; 4; 5]). (* prints [(0, 3); (1, 4); (2, 5)] *)

Why do Coq recursion principles pass along both the substructure and the result of the recursive call?

After examining a few different recursion principles generated for different recursive data types, I noticed that in the recursive case, substructures are passed along with the result of the recursive call on the substructure.
For example, doing Print list_rect gives:
list_rect =
fun (A : Type) (P : list A -> Type) (f : P nil)
(f0 : forall (a : A) (l : list A), P l -> P (a :: l)%list) =>
fix F (l : list A) : P l :=
match l as l0 return (P l0) with
| nil => f
| (y :: l0)%list => f0 y l0 (F l0)
end
: forall (A : Type) (P : list A -> Type),
P nil ->
(forall (a : A) (l : list A), P l -> P (a :: l)%list) ->
forall l : list A, P l
In the pattern match, the cons case looks like (y :: l0)%list => f0 y l0 (F l0). Why does f0 take both l0 and the result of recursively calling F on l0? What are situations when you need access to the tail of the list when you've already computed the result of calling F on it?
As soon as you need the induction hypothesis, you need the tail of the list because it appears in its type: to write P l, l needs to be in scope.
Now if you weren't bothered about types, a good reason to have both the tail of the list and the recursive call is efficiency: computing the tail is linear in the size of the list but grabbing it on the way is constant time. The prototypical example of this type of issue is the definition of the predecessor function for unary natural numbers when you only have access to the iterator and not the recursor.

How to find length of list of pair

I have calculated the length of list by function (length).Now I want to find the length of a list of pairs (natprod) and make a list from the first element of each pair in the list. I have a problem in calculating the length of a list of pair, because there is no nil/[] at the end of lists which may be used for termination of loop.
An example to clear my point would be [(2,5)(1,5)(3,7)]->[2,1,3].
Please guide me.
Fixpoint length (l: natlist) : nat :=
match l with
| [] => O
| _ :: l' => S (length l')
end.
There is a [] is every list, including lists of pairs.
You don't need to compute the length of the list however...
What you're looking for is the map function.
Basically map f [x1 ; ... ; xn] is [f x1 ; ... ; f xn].
Its type would be map : forall {A B : Type} (f : A -> B) (l : list A), list B.
Or if you really want to stick to your natprod, natlist and so on:
map : (natprod -> nat) -> list natprod -> natlist...
Fixpoint map {A B : Type} (f : A -> B) (l : list A) : list B :=
match l with
| [] => []
| x :: l => f x :: map f l
end.
In your case you want to map the snd function which returns the second element of a pair: map snd l.