Section PACO.
#[local] Hint Resolve le_join_lattice_introl le_join_lattice_intror join_lattice_le_intro bot_lattice_le_intro : core.
Context {A : Type}.
Let D : Type := ensemble A.
#[local]
Instance ensemble_isUpperSemilattice : isUpperSemilattice D :=
{ join_lattice := @E.union A
; bot_lattice := @E.empty A
; join_lattice_spec := union_join_lattice_spec
; bot_lattice_spec := empty_bot_lattice_spec
}.
Variant paco' {paco_F : D -> D} (F : D -> D) (X : D) : D :=
| mk_paco' (WITNESS : D)
(INCL : WITNESS \subseteq join_lattice X (paco_F X))
: F WITNESS \subseteq paco' F X.
#[global]
Instance ensemble_isCoLa : isCola D :=
fun Xs : ensemble D => @exist D (fun sup_Xs : D => is_supremum_of sup_Xs Xs) (E.unions Xs) (unions_is_supremum Xs).
#[projections(primitive)]
CoInductive paco (F : D -> D) (X : D) (z : A) : Prop :=
Fold_paco { unfold_paco : z \in paco' (paco_F := paco F) F X }.

Theorem paco_fold (F : D -> D) (Y : D)
: F (join_lattice Y (paco F Y)) \subseteq paco F Y.