Section COLA_THEORY.
#[local] Existing Instance direct_product_of_two_Prosets.
#[local] Existing Instance subProset.
#[local] Existing Instance pi_isProset.
Definition infimum_cola {D : Type} {PROSET : isProset D} {COLA : isCola D} (X : ensemble D) : { inf_X : D | is_infimum_of inf_X X } :=
let inf_X : D := proj1_sig (supremum_cola (lowerboundsOf X)) in
@exist D (fun inf_X : D => is_infimum_of inf_X X) inf_X (proj2 (supremum_of_lowerbounds_is_infimum inf_X X) (proj2_sig (supremum_cola (lowerboundsOf X)))).
#[program]
Definition Cola_isLowerSemilattice {D : Type} {PROSET : isProset D} {COLA : isCola D (PROSET := PROSET)} : isLowerSemilattice D (PROSET := PROSET) :=
{| meet_lattice x y := infimum_cola (E.fromList [x; y]); top_lattice := infimum_cola E.empty; |}.
Next Obligation.
cbn beta. destruct (infimum_cola (E.fromList [x1; x2])) as [meet meet_spec]; simpl. s!. rewrite meet_spec. split.
- i; split; done!.
- now i; des; subst.
Qed.
Next Obligation.
destruct (infimum_cola E.empty) as [top top_spec]; simpl. done!.
Qed.
Definition Cola_isLattice {D : Type} {PROSET : isProset D} (COLA : isCola D (PROSET := PROSET)) : isLattice D (PROSET := PROSET) :=
{| Lattice_asUpperSemilattice := Cola_isUpperSemilattice; Lattice_asLowerSemilattice := Cola_isLowerSemilattice; |}.
Definition supremum_of_monotonic_maps {D : Type} {D' : Type} {PROSET : isProset D} {PROSET' : isProset D'} {COLA : isCola D} {COLA' : isCola D'} (F : ensemble `[D -> D']) :=
reify (fun x => supremum_cola (E.image (fun f : `[D -> D'] => proj1_sig f x) F)).

Lemma supremum_of_monotonic_maps_isMonotonic {D : Type} {D' : Type} {PROSET : isProset D} {PROSET' : isProset D'} {COLA : isCola D} {COLA' : isCola D'} (F : ensemble `[D -> D'])
: isMonotonic1 (proj1_sig (supremum_of_monotonic_maps F)).