Section BasicFacts.
Context {m : Type -> Type}.
Context {EqM : EqM m}.
Context {Mm : Monad m}.
Context {EqMP : @EqMProps m _ EqM}.
Context {ML : @MonadLaws m EqM Mm}.
Instance Proper_Kleisli_apply {a b} :
Proper (eq2 ==> eq ==> eqm) (@Kleisli_apply m a b).
Global Instance Functor_pure
: Functor Fun (Kleisli m) (fun x => x) (@pure m _).
Global Instance Proper_cat_Kleisli {a b c}
: @Proper (Kleisli m a b -> Kleisli m b c -> _)
(eq2 ==> eq2 ==> eq2) cat.
Local Opaque bind ret eqm.
Global Instance CatAssoc_Kleisli : CatAssoc (Kleisli m).
(** *** [id_ktree] respect identity laws *)
Global Instance CatIdL_Kleisli : CatIdL (Kleisli m).
Global Instance CatIdR_Kleisli : CatIdR (Kleisli m).
Global Instance Category_Kleisli : Category (Kleisli m).
Global Instance InitialObject_Kleisli : InitialObject (Kleisli m) void.
(** *** [pure] is well-behaved *)
(* SAZ: not sure about the naming conventions here. *)
Global Instance Proper_pure {A B} :
Proper (eq2 ==> eq2) (@pure _ _ A B).
Fact compose_pure {A B C} (ab : A -> B) (bc : B -> C) :
(pure ab >>> pure bc ⩯ pure (ab >>> bc))%cat.
Fact compose_pure_l {A B C D} (f: A -> B) (g: B -> C) (k: Kleisli m C D) :
(pure f >>> (pure g >>> k) ⩯ pure (g ∘ f) >>> k)%cat.
Fact compose_pure_r {A B C D} (f: B -> C) (g: C -> D) (k: Kleisli m A B) :
((k >>> pure f) >>> pure g ⩯ k >>> pure (g ∘ f))%cat.
Fact pure_cat {A B C}: forall (f:A -> B) (bc: Kleisli m B C),
pure f >>> bc ⩯ fun a => bc (f a).
Fact cat_pure {A B C}: forall (ab: Kleisli m A B) (g:B -> C),
(ab >>> pure g)
⩯ (map g ab).

Lemma pure_swap {A B}:
@pure _ _ (A+B) _ swap ⩯ swap.