(************************************************************************)
(*         *      The Rocq Prover / The Rocq Development Team           *)
(*  v      *         Copyright INRIA, CNRS and contributors             *)
(* <O___,, * (see version control and CREDITS file for authors & dates) *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)
(*                      Evgeny Makarov, INRIA, 2007                     *)
(************************************************************************)
(** This file defined the strong (course-of-value, well-founded) recursion and proves its properties *)
Require Export NSub.
Ltac f_equiv' := repeat (repeat f_equiv; try intros ? ? ?; auto).
Module NStrongRecProp (Import N : NAxiomsRecSig').
Include NSubProp N.
Section StrongRecursion.
Variable A : Type.
Variable Aeq : relation A.
Variable Aeq_equiv : Equivalence Aeq.
(** [strong_rec] allows defining a recursive function [phi] given by an equation [phi(n) = F(phi)(n)] where recursive calls to [phi] in [F] are made on strictly lower numbers than [n].  For [strong_rec a F n]: - Parameter [a:A] is a default value used internally, it has no effect on the final result. - Parameter [F:(N->A)->N->A] is the step function: [F f n] should return [phi(n)] when [f] is a function that coincide with [phi] for numbers strictly less than [n]. *)
Definition strong_rec (a : A) (f : (N.t -> A) -> N.t -> A) (n : N.t) : A :=
recursion (fun _ => a) (fun _ => f) (S n) n.
(** For convenience, we use in proofs an intermediate definition between [recursion] and [strong_rec]. *)
Definition strong_rec0 (a : A) (f : (N.t -> A) -> N.t -> A) : N.t -> N.t -> A :=
recursion (fun _ => a) (fun _ => f).

Lemma strong_rec_alt : forall a f n,
strong_rec a f n = strong_rec0 a f (S n) n.