Local Open Scope functor_scope.
Section GenProd_Eq_Complete.
Context {C : Category}.
Local Ltac ElimUnit := repeat match goal with [H : unit |- _] => destruct H end.
Section GenProd_Eq_Limits.
Context {J : Category}.
Context {OProd : ∀ (map : J → C), (Π map)%object}
{HProd : ∀ (map : (Arrow J) → C), (Π map)%object}
{Eqs : Has_Equalizers C}
.
Section Limits_Exist.
Context (D : J –≻ C).
Local Notation DTarg := (fun f => (D _o (Targ f))%object) (only parsing).
Local Notation DF := Discr_Func (only parsing).
Local Notation OPR := (OProd (D _o)%object) (only parsing).
Local Notation HPR := (HProd DTarg) (only parsing).
Program Definition Projs_Cone : Cone (DF DTarg) :=
{|
cone_apex := Const_Func 1 (OPR _o tt);
cone_edge := {|Trans := fun f => Trans (cone_edge OPR) (Targ f)|}
|}.
Definition Projs : (OPR –≻ HPR)%morphism :=
Trans (LRKE_morph_ex HPR Projs_Cone) tt.
Program Definition D_imgs_Cone : Cone (DF DTarg) :=
{|
cone_apex := Const_Func 1 (OPR _o tt);
cone_edge :=
{|
Trans :=
fun f =>
(D _a (Arr f) ∘ (Trans (cone_edge OPR) (Orig f)))%morphism
|}
|}.
Definition D_imgs : (OPR –≻ HPR)%morphism :=
Trans (LRKE_morph_ex HPR D_imgs_Cone) tt.
Program Definition Lim_Cone : Cone D :=
{|
cone_apex := Const_Func 1 (Eqs _ _ Projs D_imgs);
cone_edge :=
{|Trans :=
fun d => ((Trans (cone_edge OPR) d)
∘ (equalizer_morph (Eqs _ _ Projs D_imgs)))%morphism
|}
|}.
Next Obligation.
Next Obligation.
Section Every_Cone_Equalizes.
Context (Cn : Cone D).
Local Hint Extern 1 => progress cbn.
Program Definition Cone_to_DF_DCone : Cone (DF (D _o)%object) :=
{|
cone_apex := Cn;
cone_edge :=
@NatTrans_compose
_ _
(Cn ∘ (Functor_To_1_Cat (Discr_Cat J)))
(Discr_Func ((Cn ∘ (Functor_To_1_Cat J))%functor _o)%object) _
{|Trans := fun _ => id |} (Discretize (cone_edge Cn))
|}.
Definition From_Cone_to_OPR : (Cn –≻ OPR)%morphism :=
Trans (LRKE_morph_ex OPR Cone_to_DF_DCone) tt.
Program Definition Cone_to_DF_DTrag_Cone : Cone (DF DTarg) :=
{|
cone_apex := Cn;
cone_edge := {|Trans :=
fun c => Trans (Discretize (cone_edge Cn)) (Targ c)|}
|}.
Program Definition Cone_Morph_From_Cone_to_DF_DTrag_Cone_to_HPR_1 :
Cone_Morph _ Cone_to_DF_DTrag_Cone HPR :=
{|
cone_morph :=
{|Trans :=
fun f =>
match f as u return (((Cn _o) u)%object –≻ (_ u))%morphism
with
| tt => (Projs ∘ From_Cone_to_OPR)%morphism
end
|}
|}.
Next Obligation.
Next Obligation.
Next Obligation.
Program Definition Cone_Morph_From_Cone_to_DF_DTrag_Cone_to_HPR_2 :
Cone_Morph _ Cone_to_DF_DTrag_Cone HPR :=
{|
cone_morph :=
{|Trans :=
fun f =>
match f as u return (((Cn _o)%object u) –≻ (_ u))%morphism
with
| tt => (D_imgs ∘ From_Cone_to_OPR)%morphism
end
|}
|}.
Next Obligation.
Next Obligation.
Next Obligation.

Lemma From_Cone_to_Obj_Prod_Equalizes :
(Projs ∘ From_Cone_to_OPR = D_imgs ∘ From_Cone_to_OPR)%morphism.