Set Warnings "-extraction-opaque-accessed,-extraction".
Set Warnings "-notation-overridden,-parsing".
Set Bullet Behavior "Strict Subproofs".
(** Apply a function n times *)
Fixpoint appn {A} (f : A -> A) (n : nat) : A ->  A :=
fun x =>
match n with
| 0%nat => x
| S n' => f (appn f n' x)
end.
Infix "^" := appn (at level 30, right associativity) : fun_scope.
(** Instance Hierarchy  GenSized | | Gen   Shrink \    / \  / Arbitrary *)
(** * Generator-related classes *)
(* begin gen_sized_class *)
Class GenSized (A : Type) := { arbitrarySized : nat -> G A }.
(* end gen_sized_class *)
(* begin gen_class *)
Class Gen (A : Type) := { arbitrary : G A }.
(* end gen_class *)
(** Shrink class *)
Class Shrink (A : Type) :=
{ shrink : A -> list A }.
(** Arbitrary Class *)
Class Arbitrary (A : Type) `{Gen A} `{Shrink A}.
(** * Sizes of types *)
Class Sized (A : Type) :=
{ size : A -> nat }.
Class CanonicalSized (A : Type) `{Sized A} :=
{
zeroSized : set A;
succSized : set A -> set A;
zeroSized_spec : zeroSized <--> [ set x : A | size x = 0 ];
succSized_spec :
forall n, succSized [ set x : A | size x <= n ] <--> [ set x : A | size x <= S n ]
}.

(* Specifications: *)
Lemma size_ind (A : Type) `{Hyp : Sized A} :
forall (P : A -> Prop), (forall y, (forall x, size x < size y -> P x) -> P y) -> (forall x, P x).
Lemma size_lfp (A : Type) `{Hyp : CanonicalSized A} :
[set x : A | True ] <--> \bigcup_(s : nat) [set x : A | size x <= s ].
Lemma succ_lfp (A : Type) `{Hyp : CanonicalSized A}
`{Proper _ (respectful set_eq set_eq) succSized} s :
[set x : A | size x <= s ] <-->  (succSized ^ s) zeroSized.