Tealeaves.Adapters.CategoricalToKleisli.DecoratedMonad

From Tealeaves Require Import
  Classes.Categorical.DecoratedMonad
  Classes.Kleisli.DecoratedMonad
  CategoricalToKleisli.DecoratedFunctor (cobind_dec).

#[local] Generalizable Variables W T.

Import Monoid.Notations.
Import Product.Notations.
Import Kleisli.DecoratedMonad.Notations.

Categorical Decorated Monad to Kleisli Decorated Monad

Derived bindd Operation

Module DerivedOperations.

  #[export] Instance Bindd_Categorical
    (W: Type)
    (T: Type Type)
    `{Map_T: Map T}
    `{Join_T: Join T}
    `{Decorate_WT: Decorate W T}: Bindd W T T :=
  fun A B fjoin (T := T) map (F := T) f dec T.

End DerivedOperations.

Derived Laws

Module DerivedInstances.

  (* Alectryon doesn't like this
     Import CategoricalToKleisli.DecoratedMonad.DerivedOperations.
   *)

  Import DerivedOperations.

  #[local] Generalizable Variables A B C.

  Section with_monad.

    Context
      (T: Type Type)
      `{Categorical.DecoratedMonad.DecoratedMonad W T}.

Identity law

    Lemma bindd_id: (A: Type),
        bindd (ret (T := T) extract) = @id (T A).
    Proof.
      intros. unfold_ops @Bindd_Categorical.
      rewrite <- (fun_map_map (F := T)).
      reassociate <-.
      rewrite (mon_join_map_ret (T := T)).
      reassociate →.
      rewrite (dfun_dec_extract (E := W) (F := T)).
      reflexivity.
    Qed.

Composition law

    Lemma bindd_bindd:
       (A B C: Type) (g: W × B T C) (f: W × A T B),
        bindd g bindd f = bindd (g ⋆5 f).
    Proof.
      intros. unfold bindd at 1 2, Bindd_Categorical.
      (* change (join T ∘ map T ?f) with (bind T f).*)
      do 2 reassociate <-.
      reassociatenear join.
      rewrite (dmon_join (W := W) (T := T)).
      repeat reassociate <-.
      reassociatenear (map f).
      rewrite (fun_map_map (F := T)).
      change (?rest dec T map (F := T) (dec T f) dec T)
        with (rest (dec T map (F := T) (dec T f) dec T)).
      rewrite <- (cobind_dec T).
      reassociate <-.
      change (?g map (shift T) map (cobind (W := prod W) (dec T f)) ?h)
        with (g (map (shift T) map (cobind (W := prod W) (dec T f))) h).
      rewrite (fun_map_map (F := T)).
      unfold bindd.
      change (?h map g join map (shift T cobind (W := prod W) (dec T f)) ?i)
        with (h (map g join map (shift T cobind (W := prod W) (dec T f))) i).
      fequal.
      unfold kc5, bindd, preincr.
      rewrite natural.
      reassociate →. unfold_ops @Map_compose. unfold_compose_in_compose.
      rewrite (fun_map_map (F := T)).
      replace (fun '(w, a)(join (T := T) map (F := T) (g incr w) dec T) (f (w, a)))
        with (join (T := T) (fun '(w, a)(map (F := T) (g incr w) dec T) (f (w, a))))
        by (ext [? ?]; reflexivity).
      reassociate <-.
      #[local] Set Keyed Unification.
      rewrite (mon_join_join (T := T)).
      #[local] Unset Keyed Unification.
      reassociate →.
      fequal. unfold_compose_in_compose.
      rewrite (fun_map_map (F := T)).
      fequal. fequal. ext [w a].
      unfold shift, compose; cbn.
      compose near (dec T (f (w, a))) on left.
      rewrite (fun_map_map (F := T)).
      compose near (dec T (f (w, a))) on left.
      rewrite (fun_map_map (F := T)).
      reflexivity.
    Qed.

Unit law

    Lemma bindd_comp_ret `(f: W × A T B):
      bindd f ret = f pair Ƶ.
    Proof.
      intros. unfold_ops Bindd_Categorical.
      reassociateon left.
      rewrite (dmon_ret (W := W) (T := T)).
      reassociate <- on left.
      reassociatenear (ret (A := W × A)).
      rewrite (natural (G := T) (ϕ := @ret T _)).
      reassociate <-. rewrite (mon_join_ret _).
      reflexivity.
    Qed.

Typeclass Instances

**************************************************************
    #[export] Instance:
      Kleisli.DecoratedMonad.DecoratedRightPreModule W T T :=
      {| kdmod_bindd1 := @bindd_id;
         kdmod_bindd2 := @bindd_bindd;
      |}.

    #[export] Instance:
      Kleisli.DecoratedMonad.DecoratedMonad W T
      :=
      {| kdm_bindd0 := @bindd_comp_ret;
         kdm_monoid := dmon_monoid;
      |}.

  End with_monad.

End DerivedInstances.