Delimit Scope omegacat_scope with omegacat.
Local Open Scope omegacat_scope.
(** Since we can't eliminate prop to define functors in a simple way, we redefine the notion of le (less than or equal) for natural numbers in Type (Tle).  We show that le implies Tle (and vise versa).  What follows are some properties of Tle. *)
Inductive Tle (n : nat) : nat → Type :=
| Tle_n : Tle n n
| Tle_S : ∀ m, Tle n m → Tle n (S m)
.
Hint Constructors Tle.
Notation "n ≤ m" := (Tle n m) : omegacat_scope.
Definition Tle_addS (n m : nat) : n ≤ m → S n ≤ S m.
Definition Tle_trans (n m t : nat) : n ≤ m → m ≤ t → n ≤ t.
(** Tle is decidable. This is crutial in conversion from le to Tle. *)
Definition Tle_dec (n m : nat) : (n ≤ m) + ((n ≤ m) → False).
(** This is prety straightforward. *)
Definition Tle_le {n m : nat} : n ≤ m → le n m.
(** The contrapositive of conversion from le to Tle. *)
Definition NTle_Nle {n m : nat} : (n ≤ m → False) → (le n m → False).
(** This is the actual conversion from le to Tle.  Here, the trick is that we use decidability of Tle. In case the relation holds, we have the proof. In case it does not, we can refute the le relation.  Hence, this conversion is (as expected) does not preform an explicit elimination of le (as it is impossible) and hence is not computationally simplifiable. *)
Definition le_Tle {n m : nat} : le n m → n ≤ m.
(** Natural numbers form a preorder with le (less than or equal relation). *)
Definition OmegaPreOrder :=
{|
PreOrder_car := nat : Type;
PreOrder_rel := Tle : _ → _ → Type;
PreOrder_rel_isProp :=
fun _ _ h h' => Tle_is_HProp h h';
PreOrder_refl := Tle_n;
PreOrder_trans := Tle_trans
|}.
(** The pre-order category ω. *)
Definition OmegaCat : Category := PreOrder_Cat OmegaPreOrder.
Notation "'ω'" := (OmegaCat) : omegacat_scope.
(** Given a map f from natural numbers to objects of a category C and a map from (f (S n) –≻ f n), we construct a functor from ωᵒᵖ to C. *)
(** This is the arrow map of the functor being constructed. *)
Local Fixpoint FA_fx {C : Category}
(OOF_O : nat → C)
(OOF_A : ∀ n, ((OOF_O (S n)) –≻ (OOF_O n))%morphism)
(n m : nat) (h : Tle n m)
{struct h} : (OOF_O m –≻ OOF_O n)%morphism
:=
match h in _ ≤ w return
(OOF_O w –≻ OOF_O n)%morphism
with
| Tle_n _ =>
id (OOF_O n)
| Tle_S _ m' H' =>
((FA_fx OOF_O OOF_A _ _ H') ∘ (OOF_A m'))%morphism
end
.
(** This is the the functor described above. *)
Program Definition OmegaCat_Op_Func {C : Category}
(OOF_O : nat → C)
(OOF_A : ∀ n, ((OOF_O (S n)) –≻ (OOF_O n))%morphism)
: ((ω^op) –≻ C)%functor :=
{|
FO := OOF_O;
FA := fun m n h => FA_fx OOF_O OOF_A _ _ h
|}
.
Next Obligation.
(** Similar functor from ω to C. *)
Definition OmegaCat_Func {C : Category}
(OMF_O : nat → C)
(OMF_A : ∀ n, ((OMF_O n) –≻ (OMF_O (S n)))%morphism)
: (OmegaCat –≻ C)%functor
:= (@OmegaCat_Op_Func (C^op) OMF_O OMF_A)^op.

(** Any functor from ω to C is freely generated by its object map and the image of the arrow map under (le_S _ _ (le_n n)) (proof of (le n (S n))). *)
Lemma OmegaCat_Func_unique {C : Category} (F : (ω –≻ C)%functor) :
F = OmegaCat_Func (FO F) (fun n => FA F (Tle_S _ _ (Tle_n n))).