Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************)
(* * The Coq Proof Assistant / The Coq Development Team *)
(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
(* <O___,, * (see CREDITS file for the list of authors) *)
(* \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) *)
(************************************************************************)
Reformulation of the Wf module using subsets where possible, providing
the support for Program's treatment of well-founded definitions.
Require Import Coq.Init.Wf. Require Import Coq.Program.Utils. Require Import ProofIrrelevance. Require Import FunctionalExtensionality. Local Open Scope program_scope. Section Well_founded. Variable A : Type. Variable R : A -> A -> Prop. Hypothesis Rwf : well_founded R. Variable P : A -> Type. Variable F_sub : forall x:A, (forall y: { y : A | R y x }, P (proj1_sig y)) -> P x. Fixpoint Fix_F_sub (x : A) (r : Acc R x) : P x := F_sub x (fun y: { y : A | R y x} => Fix_F_sub (proj1_sig y) (Acc_inv r (proj2_sig y))). Definition Fix_sub (x : A) := Fix_F_sub x (Rwf x). Register Fix_sub as program.wf.fix_sub. (* Notation Fix_F := (Fix_F_sub P F_sub) (only parsing). (* alias *) *) (* Definition Fix (x:A) := Fix_F_sub P F_sub x (Rwf x). *) Hypothesis F_ext : forall (x:A) (f g:forall y:{y:A | R y x}, P (`y)), (forall y:{y : A | R y x}, f y = g y) -> F_sub x f = F_sub x g.A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xF_ext:forall (x : A) (f g : forall y : {y : A | R y x}, P (` y)), (forall y : {y : A | R y x}, f y = g y) -> F_sub x f = F_sub x gforall (x : A) (r : Acc R x), F_sub x (fun y : {y : A | R y x} => Fix_F_sub (` y) (Acc_inv r (proj2_sig y))) = Fix_F_sub x rdestruct r using Acc_inv_dep; auto. Qed.A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xF_ext:forall (x : A) (f g : forall y : {y : A | R y x}, P (` y)), (forall y : {y : A | R y x}, f y = g y) -> F_sub x f = F_sub x gforall (x : A) (r : Acc R x), F_sub x (fun y : {y : A | R y x} => Fix_F_sub (` y) (Acc_inv r (proj2_sig y))) = Fix_F_sub x rA:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xF_ext:forall (x : A) (f g : forall y : {y : A | R y x}, P (` y)), (forall y : {y : A | R y x}, f y = g y) -> F_sub x f = F_sub x gforall (x : A) (r s : Acc R x), Fix_F_sub x r = Fix_F_sub x sA:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xF_ext:forall (x : A) (f g : forall y : {y : A | R y x}, P (` y)), (forall y : {y : A | R y x}, f y = g y) -> F_sub x f = F_sub x gforall (x : A) (r s : Acc R x), Fix_F_sub x r = Fix_F_sub x srewrite (proof_irrelevance (Acc R x) r s) ; auto. Qed.A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0F_ext:forall (x0 : A) (f g : forall y : {y : A | R y x0}, P (` y)), (forall y : {y : A | R y x0}, f y = g y) -> F_sub x0 f = F_sub x0 gx:AH:forall y : A, R y x -> Acc R yH0:forall y : A, R y x -> forall r0 s0 : Acc R y, Fix_F_sub y r0 = Fix_F_sub y s0r, s:Acc R xFix_F_sub x r = Fix_F_sub x sA:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xF_ext:forall (x : A) (f g : forall y : {y : A | R y x}, P (` y)), (forall y : {y : A | R y x}, f y = g y) -> F_sub x f = F_sub x gforall x : A, Fix_sub x = F_sub x (fun y : {y : A | R y x} => Fix_sub (` y))A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xF_ext:forall (x : A) (f g : forall y : {y : A | R y x}, P (` y)), (forall y : {y : A | R y x}, f y = g y) -> F_sub x f = F_sub x gforall x : A, Fix_sub x = F_sub x (fun y : {y : A | R y x} => Fix_sub (` y))A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0F_ext:forall (x0 : A) (f g : forall y : {y : A | R y x0}, P (` y)), (forall y : {y : A | R y x0}, f y = g y) -> F_sub x0 f = F_sub x0 gx:AFix_F_sub x (Rwf x) = F_sub x (fun y : {y : A | R y x} => Fix_F_sub (` y) (Rwf (` y)))A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0F_ext:forall (x0 : A) (f g : forall y : {y : A | R y x0}, P (` y)), (forall y : {y : A | R y x0}, f y = g y) -> F_sub x0 f = F_sub x0 gx:AF_sub x (fun y : {y : A | R y x} => Fix_F_sub (` y) (Acc_inv (Rwf x) (proj2_sig y))) = F_sub x (fun y : {y : A | R y x} => Fix_F_sub (` y) (Rwf (` y)))apply Fix_F_inv. Qed.A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x0 : A, (forall y0 : {y0 : A | R y0 x0}, P (` y0)) -> P x0F_ext:forall (x0 : A) (f g : forall y0 : {y0 : A | R y0 x0}, P (` y0)), (forall y0 : {y0 : A | R y0 x0}, f y0 = g y0) -> F_sub x0 f = F_sub x0 gx:Ay:{y0 : A | R y0 x}Fix_F_sub (` y) (Acc_inv (Rwf x) (proj2_sig y)) = Fix_F_sub (` y) (Rwf (` y))A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xF_ext:forall (x : A) (f g : forall y : {y : A | R y x}, P (` y)), (forall y : {y : A | R y x}, f y = g y) -> F_sub x f = F_sub x gforall x : A, Fix_sub x = (let f_sub := F_sub in f_sub x (fun y : {y : A | R y x} => Fix_sub (` y)))exact Fix_eq. Qed. End Well_founded. Require Coq.extraction.Extraction. Extraction Inline Fix_F_sub Fix_sub. Set Implicit Arguments.A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xF_ext:forall (x : A) (f g : forall y : {y : A | R y x}, P (` y)), (forall y : {y : A | R y x}, f y = g y) -> F_sub x f = F_sub x gforall x : A, Fix_sub x = (let f_sub := F_sub in f_sub x (fun y : {y : A | R y x} => Fix_sub (` y)))
Reasoning about well-founded fixpoints on measures.
Section Measure_well_founded. (* Measure relations are well-founded if the underlying relation is well-founded. *) Variables T M: Type. Variable R: M -> M -> Prop. Hypothesis wf: well_founded R. Variable m: T -> M. Definition MR (x y: T): Prop := R (m x) (m y). Register MR as program.wf.mr.T, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mwell_founded MRT, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mwell_founded MRT, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mforall a : T, Acc MR aT, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> M(forall (a : M) (a0 : T), m a0 = a -> Acc MR a0) -> forall a : T, Acc MR aT, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mforall (a : M) (a0 : T), m a0 = a -> Acc MR a0T, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> M(forall (a : M) (a0 : T), m a0 = a -> Acc MR a0) -> forall a : T, Acc MR aapply (H (m a))...T, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> MH:forall (a0 : M) (a1 : T), m a1 = a0 -> Acc MR a1a:TAcc MR aT, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mforall (a : M) (a0 : T), m a0 = a -> Acc MR a0T, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mforall x : M, (forall y : M, R y x -> forall a : T, m a = y -> Acc MR a) -> forall a : T, m a = x -> Acc MR aT, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mx:MH:forall y : M, R y x -> forall a0 : T, m a0 = y -> Acc MR a0a:TH0:m a = xAcc MR aT, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mx:MH:forall y : M, R y x -> forall a0 : T, m a0 = y -> Acc MR a0a:TH0:m a = xforall y : T, MR y a -> Acc MR yT, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mx:MH:forall y0 : M, R y0 x -> forall a0 : T, m a0 = y0 -> Acc MR a0a:TH0:m a = xy:TH1:MR y aAcc MR yT, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mx:MH:forall y0 : M, R y0 x -> forall a0 : T, m a0 = y0 -> Acc MR a0a:TH0:m a = xy:TH1:R (m y) (m a)Acc MR yapply (H (m y))... Defined. End Measure_well_founded. Hint Resolve measure_wf : core. Section Fix_rects. Variable A: Type. Variable P: A -> Type. Variable R : A -> A -> Prop. Variable Rwf : well_founded R. Variable f: forall (x : A), (forall y: { y: A | R y x }, P (proj1_sig y)) -> P x.T, M:TypeR:M -> M -> Propwf:well_founded Rm:T -> Mx:MH:forall y0 : M, R y0 x -> forall a0 : T, m a0 = y0 -> Acc MR a0a:TH0:m a = xy:TH1:R (m y) xAcc MR yA:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0x:Ar:Acc R xFix_F_sub A R P f x r = f (fun y : {y : A | R y x} => Fix_F_sub A R P f (` y) (Acc_inv r (proj2_sig y)))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0x:Ar:Acc R xFix_F_sub A R P f x r = f (fun y : {y : A | R y x} => Fix_F_sub A R P f (` y) (Acc_inv r (proj2_sig y)))case r; auto. Qed. (* Fix_F_sub_rect lets one prove a property of functions defined using Fix_F_sub by showing that property to be invariant over single application of the function body (f in our case). *)A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0x:Ar:Acc R xFix_F_sub A R P f x r = f (fun y : {y : A | R y x} => Fix_F_sub A R P f (` y) (Acc_inv r (proj2_sig y)))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xQ:forall x : A, P x -> Typeinv:forall x : A, (forall y : A, R y x -> forall a : Acc R y, Q y (Fix_F_sub A R P f y a)) -> forall a : Acc R x, Q x (f (fun y : {y : A | R y x} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))forall (x : A) (a : Acc R x), Q x (Fix_F_sub A R P f x a)A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xQ:forall x : A, P x -> Typeinv:forall x : A, (forall y : A, R y x -> forall a : Acc R y, Q y (Fix_F_sub A R P f y a)) -> forall a : Acc R x, Q x (f (fun y : {y : A | R y x} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))forall (x : A) (a : Acc R x), Q x (Fix_F_sub A R P f x a)A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xQ:forall x : A, P x -> Typeinv:forall x : A, (forall y : A, R y x -> forall a : Acc R y, Q y (Fix_F_sub A R P f y a)) -> forall a : Acc R x, Q x (f (fun y : {y : A | R y x} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))R':=fun x : A => forall a : Acc R x, Q x (Fix_F_sub A R P f x a):A -> Typeforall (x : A) (a : Acc R x), Q x (Fix_F_sub A R P f x a)A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xQ:forall x : A, P x -> Typeinv:forall x : A, (forall y : A, R y x -> forall a : Acc R y, Q y (Fix_F_sub A R P f y a)) -> forall a : Acc R x, Q x (f (fun y : {y : A | R y x} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))R':=fun x : A => forall a : Acc R x, Q x (Fix_F_sub A R P f x a):A -> Typeforall x : A, R' xA:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xQ:forall x : A, P x -> Typeinv:forall x : A, (forall y : A, R y x -> forall a : Acc R y, Q y (Fix_F_sub A R P f y a)) -> forall a : Acc R x, Q x (f (fun y : {y : A | R y x} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))R':=fun x : A => forall a : Acc R x, Q x (Fix_F_sub A R P f x a):A -> Typeforall x : A, (forall y : A, R y x -> R' y) -> R' xA:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xQ:forall x : A, P x -> Typeinv:forall x : A, (forall y : A, R y x -> forall a : Acc R y, Q y (Fix_F_sub A R P f y a)) -> forall a : Acc R x, Q x (f (fun y : {y : A | R y x} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))forall x : A, (forall y : A, R y x -> (fun x0 : A => forall a : Acc R x0, Q x0 (Fix_F_sub A R P f x0 a)) y) -> (fun x0 : A => forall a : Acc R x0, Q x0 (Fix_F_sub A R P f x0 a)) xA:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xQ:forall x : A, P x -> Typeinv:forall x : A, (forall y : A, R y x -> forall a : Acc R y, Q y (Fix_F_sub A R P f y a)) -> forall a : Acc R x, Q x (f (fun y : {y : A | R y x} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))forall x : A, (forall y : A, R y x -> forall a : Acc R y, Q y (Fix_F_sub A R P f y a)) -> forall a : Acc R x, Q x (Fix_F_sub A R P f x a)rewrite F_unfold... Qed. (* Let's call f's second parameter its "lowers" function, since it provides it access to results for inputs with a lower measure. In preparation of lemma similar to Fix_F_sub_rect, but for Fix_sub, we first need an extra hypothesis stating that the function body has the same result for different "lowers" functions (g and h below) as long as those produce the same results for lower inputs, regardless of the lt proofs. *) Hypothesis equiv_lowers: forall x0 (g h: forall x: {y: A | R y x0}, P (proj1_sig x)), (forall x p p', g (exist (fun y: A => R y x0) x p) = h (exist (*FIXME shouldn't be needed *) (fun y => R y x0) x p')) -> f g = f h. (* From equiv_lowers, it follows that [Fix_F_sub A R P f x] applications do not not depend on the Acc proofs. *)A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0Q:forall x0 : A, P x0 -> Typeinv:forall x0 : A, (forall y : A, R y x0 -> forall a0 : Acc R y, Q y (Fix_F_sub A R P f y a0)) -> forall a0 : Acc R x0, Q x0 (f (fun y : {y : A | R y x0} => Fix_F_sub A R P f (` y) (Acc_inv a0 (proj2_sig y))))x:AX:forall y : A, R y x -> forall a0 : Acc R y, Q y (Fix_F_sub A R P f y a0)a:Acc R xQ x (Fix_F_sub A R P f x a)A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0equiv_lowers:forall (x0 : A) (g h : forall x1 : {y : A | R y x0}, P (` x1)), (forall (x1 : A) (p p' : R x1 x0), g (exist (fun y : A => R y x0) x1 p) = h (exist (fun y : A => R y x0) x1 p')) -> f g = f hx:Aa, a':Acc R xFix_F_sub A R P f x a = Fix_F_sub A R P f x a'A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0equiv_lowers:forall (x0 : A) (g h : forall x1 : {y : A | R y x0}, P (` x1)), (forall (x1 : A) (p p' : R x1 x0), g (exist (fun y : A => R y x0) x1 p) = h (exist (fun y : A => R y x0) x1 p')) -> f g = f hx:Aa, a':Acc R xFix_F_sub A R P f x a = Fix_F_sub A R P f x a'A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0equiv_lowers:forall (x0 : A) (g h : forall x1 : {y : A | R y x0}, P (` x1)), (forall (x1 : A) (p p' : R x1 x0), g (exist (fun y : A => R y x0) x1 p) = h (exist (fun y : A => R y x0) x1 p')) -> f g = f hx:Aa:Acc R xforall a' : Acc R x, Fix_F_sub A R P f x a = Fix_F_sub A R P f x a'A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0equiv_lowers:forall (x0 : A) (g h : forall x1 : {y : A | R y x0}, P (` x1)), (forall (x1 : A) (p p' : R x1 x0), g (exist (fun y : A => R y x0) x1 p) = h (exist (fun y : A => R y x0) x1 p')) -> f g = f hx:Aa:Acc R x(fun (a0 : A) (p : P a0) => forall a' : Acc R a0, p = Fix_F_sub A R P f a0 a') x (Fix_F_sub A R P f x a)A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0equiv_lowers:forall (x0 : A) (g h : forall x1 : {y : A | R y x0}, P (` x1)), (forall (x1 : A) (p p' : R x1 x0), g (exist (fun y : A => R y x0) x1 p) = h (exist (fun y : A => R y x0) x1 p')) -> f g = f hx:Aa:Acc R xforall x0 : A, (forall y : A, R y x0 -> forall a0 a' : Acc R y, Fix_F_sub A R P f y a0 = Fix_F_sub A R P f y a') -> forall a0 a' : Acc R x0, f (fun y : {y : A | R y x0} => Fix_F_sub A R P f (` y) (Acc_inv a0 (proj2_sig y))) = Fix_F_sub A R P f x0 a'A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1equiv_lowers:forall (x1 : A) (g h : forall x2 : {y : A | R y x1}, P (` x2)), (forall (x2 : A) (p p' : R x2 x1), g (exist (fun y : A => R y x1) x2 p) = h (exist (fun y : A => R y x1) x2 p')) -> f g = f hx:Aa:Acc R xx0:AH:forall y : A, R y x0 -> forall a1 a'0 : Acc R y, Fix_F_sub A R P f y a1 = Fix_F_sub A R P f y a'0a0, a':Acc R x0f (fun y : {y : A | R y x0} => Fix_F_sub A R P f (` y) (Acc_inv a0 (proj2_sig y))) = Fix_F_sub A R P f x0 a'A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1equiv_lowers:forall (x1 : A) (g h : forall x2 : {y : A | R y x1}, P (` x2)), (forall (x2 : A) (p p' : R x2 x1), g (exist (fun y : A => R y x1) x2 p) = h (exist (fun y : A => R y x1) x2 p')) -> f g = f hx:Aa:Acc R xx0:AH:forall y : A, R y x0 -> forall a1 a'0 : Acc R y, Fix_F_sub A R P f y a1 = Fix_F_sub A R P f y a'0a0, a':Acc R x0f (fun y : {y : A | R y x0} => Fix_F_sub A R P f (` y) (Acc_inv a0 (proj2_sig y))) = f (fun y : {y : A | R y x0} => Fix_F_sub A R P f (` y) (Acc_inv a' (proj2_sig y)))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1equiv_lowers:forall (x1 : A) (g h : forall x2 : {y : A | R y x1}, P (` x2)), (forall (x2 : A) (p p' : R x2 x1), g (exist (fun y : A => R y x1) x2 p) = h (exist (fun y : A => R y x1) x2 p')) -> f g = f hx:Aa:Acc R xx0:AH:forall y : A, R y x0 -> forall a1 a'0 : Acc R y, Fix_F_sub A R P f y a1 = Fix_F_sub A R P f y a'0a0, a':Acc R x0forall (x1 : A) (p p' : R x1 x0), Fix_F_sub A R P f (` (exist (fun y : A => R y x0) x1 p)) (Acc_inv a0 (proj2_sig (exist (fun y : A => R y x0) x1 p))) = Fix_F_sub A R P f (` (exist (fun y : A => R y x0) x1 p')) (Acc_inv a' (proj2_sig (exist (fun y : A => R y x0) x1 p')))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x2 : A, (forall y : {y : A | R y x2}, P (` y)) -> P x2equiv_lowers:forall (x2 : A) (g h : forall x3 : {y : A | R y x2}, P (` x3)), (forall (x3 : A) (p0 p'0 : R x3 x2), g (exist (fun y : A => R y x2) x3 p0) = h (exist (fun y : A => R y x2) x3 p'0)) -> f g = f hx:Aa:Acc R xx0:AH:forall y : A, R y x0 -> forall a1 a'0 : Acc R y, Fix_F_sub A R P f y a1 = Fix_F_sub A R P f y a'0a0, a':Acc R x0x1:Ap, p':R x1 x0Fix_F_sub A R P f (` (exist (fun y : A => R y x0) x1 p)) (Acc_inv a0 (proj2_sig (exist (fun y : A => R y x0) x1 p))) = Fix_F_sub A R P f (` (exist (fun y : A => R y x0) x1 p')) (Acc_inv a' (proj2_sig (exist (fun y : A => R y x0) x1 p')))assumption. Qed. (* Finally, Fix_F_rect lets one prove a property of functions defined using Fix_F_sub by showing that property to be invariant over single application of the function body (f). *)A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x2 : A, (forall y : {y : A | R y x2}, P (` y)) -> P x2equiv_lowers:forall (x2 : A) (g h : forall x3 : {y : A | R y x2}, P (` x3)), (forall (x3 : A) (p0 p'0 : R x3 x2), g (exist (fun y : A => R y x2) x3 p0) = h (exist (fun y : A => R y x2) x3 p'0)) -> f g = f hx:Aa:Acc R xx0:AH:forall y : A, R y x0 -> forall a1 a'0 : Acc R y, Fix_F_sub A R P f y a1 = Fix_F_sub A R P f y a'0a0, a':Acc R x0x1:Ap, p':R x1 x0R (` (exist (fun y : A => R y x0) x1 p')) x0A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xequiv_lowers:forall (x0 : A) (g h : forall x : {y : A | R y x0}, P (` x)), (forall (x : A) (p p' : R x x0), g (exist (fun y : A => R y x0) x p) = h (exist (fun y : A => R y x0) x p')) -> f g = f hQ:forall x : A, P x -> Typeinv:forall x : A, (forall y : A, R y x -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x -> Q x (f (fun y : {y : A | R y x} => Fix_sub A R Rwf P f (` y)))forall x : A, Q x (Fix_sub A R Rwf P f x)A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xequiv_lowers:forall (x0 : A) (g h : forall x : {y : A | R y x0}, P (` x)), (forall (x : A) (p p' : R x x0), g (exist (fun y : A => R y x0) x p) = h (exist (fun y : A => R y x0) x p')) -> f g = f hQ:forall x : A, P x -> Typeinv:forall x : A, (forall y : A, R y x -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x -> Q x (f (fun y : {y : A | R y x} => Fix_sub A R Rwf P f (` y)))forall x : A, Q x (Fix_sub A R Rwf P f x)A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P xequiv_lowers:forall (x0 : A) (g h : forall x : {y : A | R y x0}, P (` x)), (forall (x : A) (p p' : R x x0), g (exist (fun y : A => R y x0) x p) = h (exist (fun y : A => R y x0) x p')) -> f g = f hQ:forall x : A, P x -> Typeinv:forall x : A, (forall y : A, R y x -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x -> Q x (f (fun y : {y : A | R y x} => Fix_sub A R Rwf P f (` y)))forall x : A, Q x (Fix_F_sub A R P f x (Rwf x))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0equiv_lowers:forall (x0 : A) (g h : forall x1 : {y : A | R y x0}, P (` x1)), (forall (x1 : A) (p p' : R x1 x0), g (exist (fun y : A => R y x0) x1 p) = h (exist (fun y : A => R y x0) x1 p')) -> f g = f hQ:forall x0 : A, P x0 -> Typeinv:forall x0 : A, (forall y : A, R y x0 -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x0 -> Q x0 (f (fun y : {y : A | R y x0} => Fix_sub A R Rwf P f (` y)))x:AQ x (Fix_F_sub A R P f x (Rwf x))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0equiv_lowers:forall (x0 : A) (g h : forall x1 : {y : A | R y x0}, P (` x1)), (forall (x1 : A) (p p' : R x1 x0), g (exist (fun y : A => R y x0) x1 p) = h (exist (fun y : A => R y x0) x1 p')) -> f g = f hQ:forall x0 : A, P x0 -> Typeinv:forall x0 : A, (forall y : A, R y x0 -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x0 -> Q x0 (f (fun y : {y : A | R y x0} => Fix_sub A R Rwf P f (` y)))x:Aforall x0 : A, (forall y : A, R y x0 -> forall a : Acc R y, Q y (Fix_F_sub A R P f y a)) -> forall a : Acc R x0, Q x0 (f (fun y : {y : A | R y x0} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1equiv_lowers:forall (x1 : A) (g h : forall x2 : {y : A | R y x1}, P (` x2)), (forall (x2 : A) (p p' : R x2 x1), g (exist (fun y : A => R y x1) x2 p) = h (exist (fun y : A => R y x1) x2 p')) -> f g = f hQ:forall x1 : A, P x1 -> Typeinv:forall x1 : A, (forall y : A, R y x1 -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x1 -> Q x1 (f (fun y : {y : A | R y x1} => Fix_sub A R Rwf P f (` y)))x, x0:AX:forall y : A, R y x0 -> forall a0 : Acc R y, Q y (Fix_F_sub A R P f y a0)a:Acc R x0Q x0 (f (fun y : {y : A | R y x0} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1equiv_lowers:forall (x1 : A) (g h : forall x2 : {y : A | R y x1}, P (` x2)), (forall (x2 : A) (p p' : R x2 x1), g (exist (fun y : A => R y x1) x2 p) = h (exist (fun y : A => R y x1) x2 p')) -> f g = f hQ:forall x1 : A, P x1 -> Typeinv:forall x1 : A, (forall y : A, R y x1 -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x1 -> Q x1 (f (fun y : {y : A | R y x1} => Fix_sub A R Rwf P f (` y)))x, x0:AX:forall y : A, R y x0 -> forall a0 : Acc R y, Q y (Fix_F_sub A R P f y a0)a:Acc R x0X0:forall y : A, R y x0 -> Q y (Fix_F_sub A R P f y (Rwf y))Q x0 (f (fun y : {y : A | R y x0} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1equiv_lowers:forall (x1 : A) (g h : forall x2 : {y : A | R y x1}, P (` x2)), (forall (x2 : A) (p p' : R x2 x1), g (exist (fun y : A => R y x1) x2 p) = h (exist (fun y : A => R y x1) x2 p')) -> f g = f hQ:forall x1 : A, P x1 -> Typeinv:forall x1 : A, (forall y : A, R y x1 -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x1 -> Q x1 (f (fun y : {y : A | R y x1} => Fix_sub A R Rwf P f (` y)))x, x0:AX:forall y : A, R y x0 -> forall a0 : Acc R y, Q y (Fix_F_sub A R P f y a0)a:Acc R x0X0:forall y : A, R y x0 -> Q y (Fix_F_sub A R P f y (Rwf y))q:=inv x0 X0 a:Q x0 (f (fun y : {y : A | R y x0} => Fix_sub A R Rwf P f (` y)))Q x0 (f (fun y : {y : A | R y x0} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1equiv_lowers:forall (x1 : A) (g h : forall x2 : {y : A | R y x1}, P (` x2)), (forall (x2 : A) (p p' : R x2 x1), g (exist (fun y : A => R y x1) x2 p) = h (exist (fun y : A => R y x1) x2 p')) -> f g = f hQ:forall x1 : A, P x1 -> Typeinv:forall x1 : A, (forall y : A, R y x1 -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x1 -> Q x1 (f (fun y : {y : A | R y x1} => Fix_sub A R Rwf P f (` y)))x, x0:AX:forall y : A, R y x0 -> forall a0 : Acc R y, Q y (Fix_F_sub A R P f y a0)a:Acc R x0X0:forall y : A, R y x0 -> Q y (Fix_F_sub A R P f y (Rwf y))q:Q x0 (f (fun y : {y : A | R y x0} => Fix_sub A R Rwf P f (` y)))Q x0 (f (fun y : {y : A | R y x0} => Fix_F_sub A R P f (` y) (Acc_inv a (proj2_sig y))))A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1equiv_lowers:forall (x1 : A) (g h : forall x2 : {y : A | R y x1}, P (` x2)), (forall (x2 : A) (p p' : R x2 x1), g (exist (fun y : A => R y x1) x2 p) = h (exist (fun y : A => R y x1) x2 p')) -> f g = f hQ:forall x1 : A, P x1 -> Typeinv:forall x1 : A, (forall y : A, R y x1 -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x1 -> Q x1 (f (fun y : {y : A | R y x1} => Fix_sub A R Rwf P f (` y)))x, x0:AX:forall y : A, R y x0 -> forall a0 : Acc R y, Q y (Fix_F_sub A R P f y a0)a:Acc R x0X0:forall y : A, R y x0 -> Q y (Fix_F_sub A R P f y (Rwf y))q:Q x0 (f (fun y : {y : A | R y x0} => Fix_sub A R Rwf P f (` y)))forall (x1 : A) (p p' : R x1 x0), Fix_F_sub A R P f (` (exist (fun y : A => R y x0) x1 p)) (Rwf (` (exist (fun y : A => R y x0) x1 p))) = Fix_F_sub A R P f (` (exist (fun y : A => R y x0) x1 p')) (Acc_inv a (proj2_sig (exist (fun y : A => R y x0) x1 p')))apply eq_Fix_F_sub. Qed. End Fix_rects.A:TypeP:A -> TypeR:A -> A -> PropRwf:well_founded Rf:forall x2 : A, (forall y : {y : A | R y x2}, P (` y)) -> P x2equiv_lowers:forall (x2 : A) (g h : forall x3 : {y : A | R y x2}, P (` x3)), (forall (x3 : A) (p0 p'0 : R x3 x2), g (exist (fun y : A => R y x2) x3 p0) = h (exist (fun y : A => R y x2) x3 p'0)) -> f g = f hQ:forall x2 : A, P x2 -> Typeinv:forall x2 : A, (forall y : A, R y x2 -> Q y (Fix_sub A R Rwf P f y)) -> Acc R x2 -> Q x2 (f (fun y : {y : A | R y x2} => Fix_sub A R Rwf P f (` y)))x, x0:AX:forall y : A, R y x0 -> forall a0 : Acc R y, Q y (Fix_F_sub A R P f y a0)a:Acc R x0X0:forall y : A, R y x0 -> Q y (Fix_F_sub A R P f y (Rwf y))q:Q x0 (f (fun y : {y : A | R y x0} => Fix_sub A R Rwf P f (` y)))x1:Ap, p':R x1 x0Fix_F_sub A R P f (` (exist (fun y : A => R y x0) x1 p)) (Rwf (` (exist (fun y : A => R y x0) x1 p))) = Fix_F_sub A R P f (` (exist (fun y : A => R y x0) x1 p')) (Acc_inv a (proj2_sig (exist (fun y : A => R y x0) x1 p')))
Tactic to fold a definition based on Fix_measure_sub.
Ltac fold_sub f :=
match goal with
| [ |- ?T ] =>
match T with
context C [ @Fix_sub _ _ _ _ _ ?arg ] =>
let app := context C [ f arg ] in
change app
end
end.
This module provides the fixpoint equation provided one assumes
functional extensionality.
Module WfExtensionality.
The two following lemmas allow to unfold a well-founded fixpoint definition without
restriction using the functional extensionality axiom.
For a function defined with Program using a well-founded order.
forall (A : Type) (R : A -> A -> Prop) (Rwf : well_founded R) (P : A -> Type) (F_sub : forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P x) (x : A), Fix_sub A R Rwf P F_sub x = F_sub x (fun y : {y : A | R y x} => Fix_sub A R Rwf P F_sub (` y))forall (A : Type) (R : A -> A -> Prop) (Rwf : well_founded R) (P : A -> Type) (F_sub : forall x : A, (forall y : {y : A | R y x}, P (` y)) -> P x) (x : A), Fix_sub A R Rwf P F_sub x = F_sub x (fun y : {y : A | R y x} => Fix_sub A R Rwf P F_sub (` y))A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x0 : A, (forall y : {y : A | R y x0}, P (` y)) -> P x0x:Aforall (x0 : A) (f g : forall y : {y : A | R y x0}, P (` y)), (forall y : {y : A | R y x0}, f y = g y) -> F_sub x0 f = F_sub x0 gA:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1x, x0:Af, g:forall y : {y : A | R y x0}, P (` y)H:forall y : {y : A | R y x0}, f y = g yF_sub x0 f = F_sub x0 gA:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1x, x0:Af, g:forall y : {y : A | R y x0}, P (` y)H:forall y : {y : A | R y x0}, f y = g yf = gA:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1x, x0:Af, g:forall y : {y : A | R y x0}, P (` y)H:forall y : {y : A | R y x0}, f y = g yH0:f = gF_sub x0 f = F_sub x0 gextensionality y ; apply H.A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1x, x0:Af, g:forall y : {y : A | R y x0}, P (` y)H:forall y : {y : A | R y x0}, f y = g yf = grewrite H0 ; auto. Qed.A:TypeR:A -> A -> PropRwf:well_founded RP:A -> TypeF_sub:forall x1 : A, (forall y : {y : A | R y x1}, P (` y)) -> P x1x, x0:Af, g:forall y : {y : A | R y x0}, P (` y)H:forall y : {y : A | R y x0}, f y = g yH0:f = gF_sub x0 f = F_sub x0 g
Tactic to unfold once a definition based on Fix_sub.
Ltac unfold_sub f fargs := set (call:=fargs) ; unfold f in call ; unfold call ; clear call ; rewrite fix_sub_eq_ext ; repeat fold_sub f ; simpl proj1_sig. End WfExtensionality.