MathClasses.categories.product

Require Import
  abstract_algebra ChoiceFacts interfaces.functors
  theory.categories categories.categories.


Section object.
  Context {I: Type} (O: I Type)
    `{ i, Arrows (O i)}
    `{ i (x y: O i), Equiv (x y)}
    `{ i, CatId (O i)} `{ i, CatComp (O i)}
    `{ i, Category (O i)}.

  Definition Object := i, O i.
  Global Instance pa: Arrows Object := λ x y, i, x i y i.   Global Instance: CatId Object := λ _ _, cat_id.
  Global Instance: CatComp Object := λ _ _ _ d e i, d i e i.
  Definition e (x y: Object): Equiv (x y) := λ f g, i, f i = g i.
End object.

Hint Extern 0 (Equiv (_ _)) ⇒ eapply @e : typeclass_instances.

Section contents.
  Context {I: Type} (O: I Type)
    `{ i, Arrows (O i)}
    `{ i (x y: O i), Equiv (x y)}
    `{ i, CatId (O i)} `{ i, CatComp (O i)}
    `{ i, Category (O i)}.

  Global Instance: x y: Object O, Setoid (x y) := _.

  Global Instance: Category (Object O).
  Proof with try reflexivity.
   constructor. apply _.
      intros ? ? ? x y E x' y' F i.
      change (x i x' i = y i y' i).
      rewrite (E i), (F i)...
     repeat intro. apply comp_assoc.
    repeat intro. apply id_l.    repeat intro. apply id_r.
  Qed.

  Let product_object := categories.object (Object O).

  Notation ith_obj i := (categories.object (O i)).

  Program Definition project i: categories.object (Object O) ith_obj i :=
    @categories.arrow _ _ (λ d, d i) (λ _ _ a, a i) _.
  Next Obligation. Proof.    constructor; intros; try reflexivity; try apply _.
   constructor; try apply _.
   intros ? ? E. apply E.
  Qed.

  Section factors.

    Variables (C: categories.Object) (X: i, C ith_obj i).

    Let ith_functor i := categories.Functor_inst _ _ (X i).

    Program Definition factor: C product_object
      := @categories.arrow _ _ (λ (c: C) i, X i c) (λ (x y: C) (c: x y) i, fmap (X i) c) _.
    Next Obligation. Proof with try reflexivity; intuition.      constructor; intros; try apply _.
       constructor; try apply _.
       intros ? ? E ?.
       change (fmap (X i) x = fmap (X i) y).
       rewrite E...
      intro. unfold fmap at 1. rewrite preserves_id... destruct X...
     intro. unfold fmap at 1. rewrite preserves_comp... destruct X...
    Qed.   End factors.


  Global Instance mono (X Y: Object O): (a: X Y), ( i, @Mono _ _ (H0 _) (H2 i) _ _ (a i)) Mono a.
  Proof. firstorder. Qed.
End contents.