Lecture 9: Recursive functions in Coq

(credits: Benjamin Gregoire)

Recursive datatypes

4  Datatypes are described by several cases: the constructors

4  Each constructor is presented as a function

4  Output type: the datatype

4  Inputs: they correpond to several fields

4  Some inputs are in the datatype: recursion

4  Usually one constructor has no inputs in the datatype (i.e. base cases)

4  Programming function with the datatype as input

4  Use Match ... with ... end

4  As many cases as there are constructors

4  One pattern variable for each non parameter constructor argument

An example of recursive datatype

4 An example of datatype used to describe a programming language

An example of recursive function

4 Note the recursive calls made on tl and tr

4 The recursive call should be done on strict sub-term

4 This ensure the termination of recursive functions

Why termination is important

An Ocaml function:

# let rec loop x =loop x;; val f : 'a -> 'b = <fun>

Assume we can do such a definition in Coq: Fixpoint loop (x:?) : ? := loop x.

Now add type information for x: Fixpoint loop (x:nat) : ? := loop x.

Now add type information for the result (assume B:Type): Fixpoint loop (x:nat) : B := loop x.

4 The function loop has type nat -> B

4 We have used B but we can use any type

Use False instead of bool:

Fixpoint loop (x:nat) : False := loop x.

4 Now the function loop has type nat -> False

4 Did you see the problem?

4 What is the type of loop 0 ?

loop 0 : False

4 We can proof False without hypothesis, the logical system is incoherent (everything is provable)

The termination of recursive functions is one of the component

which ensure the logical consistency of Coq

We should live with it .. .

An example of recursive function: fact

Recursive call should be made on strict sub-term:

An example of recursive function: div2

Recursive call can be done on not immediate sub-terms:

A sub-term of strict sub-term is a strict sub-term

More general recursion

4 It is possible to have recursive calls on results of functions

4 All cases must return a strict sub-term

4 strict sub-terms may be obtained by apply functions on strict sub-terms

4 Only constraint is that functions must return sub-terms not necessarily strict.

4 Checked by looking at all cases

Example of function that returns a sub-term

4 in case O value is n, a (non-strict) sub-term of n

4 in case S p value is n a sub-term of n

Recursive function using pred

The same trick can be played with minus which returns a sub-term of its first argument, to define euclidian division

Mutual recursion

It is possible to define function by mutual recursion:

Lexicographic order

Sometimes termination functions is ensured by a lexicographic order on arguments (Ocaml):

let rec merge l1 l2 =

match l1, l2 with

| [], _ -> l2

| _, [] -> l1

| x1::l1', x2::l2' ->

if x1 <= x2 then

x1 :: merge l1' l2
else

x2 :: merge l1 l2';;

There are two recursive calls merge l1' l2 and merge l1 l2'

Solution in Coq: internal recursion

Coq also makes it possible to describe anonymous recursive functions. Sometimes, it is necessary to use them for difficult recursion patterns.

Another solution (Hugo Herbelin)

More general recursion

4 Constraint of structural recursion too cumbersome

4 Sometimes a characteristic decreases, but structural recursion is not available

4 General solution provided by well-founded recursion

4 Intermediate solution provided by the command Function

Example using Function: fact on Z

Integers have a more complex structure than natural numbers

4 x 1 is not a structural sub-term of x

4 for instance 3 is Zpos (xI xH) and 2 is Zpos (xO xH)

4 Makes more efficient computation possible

Now, we prove explicitely that something decreases

Merge again

Well-founded Relations

Partial order over a set of elements such that the minimal elements are accessible

Elements whose all predecessors are accessible become accessible

A relation is well founded if all elements are accessible.

It is possible to define functions by recursion on the accessibility proof of an element (Function is based on this)

Proving that some relation is well-founded

Coq's Standard Library provides us with some useful examples of well-founded relations :

4 The predicate lt over nat (but you can use measure instead)

4 The predicate Zwf c, which is the restriction of < to the interval [c, ∞] of Z.

More example : log10

log10 can also be defined using measure

Proving properties on recursive functions

Usually a property on a recursive function can be proved using an induction on the recursive argument.

Sometime we need some generalization before starting the induction (see the example div2_le).

Proof techniques for recursive function

4  Specific reasoning tool for each function

4  Usable like an induction principle

4 Requires a special induction tactic

4  Cases correspond to behavior cases of function

4  Hypotheses are provided for each test performed

4  Induction hypotheses are provided for recursive calls

Example of functional induction

Second example of functional induction

Proof techniques for mutual fixpoints

Properties on mutual fixpoints should be generally proved

simultaneously.

Example:

Solution 1: prove both in one shot

Use the lemma to prove the two disjoint lemmas:

Solution 2: use mutual lemmas

This is a way to define a mutual fixpoint in proof mode.

Prove for function defined using Function

Among the few lemmas that are generated by Function, the lemma log10_equation has the following statement, which expresses the intention of the original definition :

Functional Scheme

A functional scheme for function defined using Function is also automatically generated (no need to use Functional Scheme)

So, you can use functional induction .. .

Proofs about uncurrified functions

4 Induction principles work for variables, no composite expressions

4 All references to sub-components must be explicit references to the argument

4 Two solutions to make references explicit (see the proofs)

4  use projectors

4 add equalities

Generating its own induction principle

Sometime, the generated induction principle is not what you need.

You have to build your own induction principle