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

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.

Related

What does "==>" mean in coq?

I have the following code:
Here is the def of sorted:
Fixpoint sorted (l : list nat) :=
match l with
| [] => true
| x::xs => match xs with
| [] => true
| y :: ys => (x <=? y) && (sorted xs)
end
end.
Here is the def of insert:
Fixpoint insert (x : nat) (l : list nat) :=
match l with
| [] => [x]
| y::ys => if x <=? y then x :: l
else y :: insert x ys
end.
Here is the def of insert_spec:
Definition insert_spec (x : nat) (l : list nat) :=
sorted l ==> sorted (insert x l).
In insert_spec, what does "==>" mean?
It appears that you got the code from Software Foundations' QuickChick guide. Many (if not all) of the notations used in that guide can be found in the QuickChick Reference Manual. There, we find that "==>" is defined as a notation.
Module QcNotation.
Export QcDefaultNotation.
Notation "x ==> y" :=
(implication x y) (at level 55, right associativity)
: Checker_scope.
End QcNotation.
implication is a generic "is this implication true" parameter used by QuickChick.
Parameter implication :
∀ {prop : Type} `{Checkable prop} (b : bool) (p : prop), Checker.
Whenever the first argument is true, QuickChick tests that the second argument evaluates (in whatever context you're using QuickChick in) as true too.
So for your particular piece of code, "==>" is used to say that we want to test that whenever l is sorted, insert x l is sorted too.

How can I create a polymorphic "map xs f" function?

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.

How to express inheritance in Coq?

How can I get the all parents of a element in Coq?
I define a set in Coq as follows:
Inductive Gen : Set :=
| BGen : nat -> nat -> Gen.
There are many instances such as:
Definition g1 = BGen 1 2.
Definition g2 = BGen 2 3.
Now, I want to get the parents element of 3, i.e. [1,2]. I write a function:
Fixpoint parents (c : nat) (l : list Gen) :=
match l with
| [] => []
| (BGen p c') :: l' => if beq_nat c c'
then [p]
else parents c l'
end.
I can only get the direct parent [2] of 3, How can I get the all parents such as [1,2] in this example?
You seem to be asking about how to compute the closure of a function under repeated function application. The key to the problem is to find a way to ensure termination, i.e., a way to determine the maximum number of times the function might be called. In this case, an easy upper bound is List.length l; an element cannot have more transitive-parents than there are generations. Using this insight, we can define a function that takes a list of numbers, and outputs a list of those numbers together with all of their parents, and then we apply this function List.length l times to itself, starting with parents of c:
Require Import Coq.Lists.List. Import ListNotations.
Require Import Coq.Sorting.Mergesort. Import NatSort.
Scheme Equality for nat.
Inductive Gen : Set :=
| BGen : nat -> nat -> Gen.
Definition g1 := BGen 1 2.
Definition g2 := BGen 2 3.
Fixpoint parents (l : list Gen) (c : nat) :=
match l with
| [] => []
| (BGen p c') :: l' => if nat_beq c c'
then [p]
else parents l' c
end.
Fixpoint deduplicate' (ls : list nat) :=
match ls with
| [] => []
| x :: [] => [x]
| x :: ((y :: ys) as xs)
=> if nat_beq x y
then deduplicate' xs
else x :: deduplicate' xs
end.
Definition deduplicate (ls : list nat) := deduplicate' (sort ls).
Definition parents_step (l : list Gen) (cs : list nat) :=
deduplicate (cs ++ List.flat_map (parents l) cs).
Fixpoint all_parents' (l : list Gen) (cs : list nat) (fuel : nat) :=
match fuel with
| 0 => cs
| S fuel'
=> all_parents' l (parents_step l cs) fuel'
end.
Definition all_parents (l : list Gen) (c : nat) :=
deduplicate (all_parents' l (parents l c) (List.length l)).
Definition gs := (g1::g2::nil).
Compute all_parents gs 3. (* [1; 2] *)

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)] *)

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

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.]