ExtLib.Structures.Monad
Require Import ExtLib.Core.Any.
Require Import ExtLib.Structures.Functor.
Require Import ExtLib.Structures.Applicative.
Set Implicit Arguments.
Set Strict Implicit.
Set Universe Polymorphism.
Class Monad@{d c} (m : Type@{d} -> Type@{c}) : Type :=
{ ret : forall {t : Type@{d}}, t -> m t
; bind : forall {t u : Type@{d}}, m t -> (t -> m u) -> m u
}.
Section monadic.
Definition liftM@{d c}
{m : Type@{d} -> Type@{c}}
{M : Monad m}
{T U : Type@{d}} (f : T -> U) : m T -> m U :=
fun x => bind x (fun x => ret (f x)).
Definition liftM2@{d c}
{m : Type@{d} -> Type@{c}}
{M : Monad m}
{T U V : Type@{d}} (f : T -> U -> V) : m T -> m U -> m V :=
Eval cbv beta iota zeta delta [ liftM ] in
fun x y => bind x (fun x => liftM (f x) y).
Definition liftM3@{d c}
{m : Type@{d} -> Type@{c}}
{M : Monad m}
{T U V W : Type@{d}} (f : T -> U -> V -> W) : m T -> m U -> m V -> m W :=
Eval cbv beta iota zeta delta [ liftM2 ] in
fun x y z => bind x (fun x => liftM2 (f x) y z).
Definition apM@{d c}
{m : Type@{d} -> Type@{c}}
{M : Monad m}
{A B : Type@{d}} (fM:m (A -> B)) (aM:m A) : m B :=
bind fM (fun f => liftM f aM).
(* Left-to-right composition of Kleisli arrows. *)
Definition mcompose@{c d}
{m:Type@{d}->Type@{c}}
{M: Monad m}
{T U V:Type@{d}}
(f: T -> m U) (g: U -> m V): (T -> m V) :=
fun x => bind (f x) g.
End monadic.
Module MonadBaseNotation.
Delimit Scope monad_scope with monad.
Notation "c >>= f" := (@bind _ _ _ _ c f) (at level 58, left associativity) : monad_scope.
Notation "f =<< c" := (@bind _ _ _ _ c f) (at level 61, right associativity) : monad_scope.
Notation "f >=> g" := (@mcompose _ _ _ _ _ f g) (at level 61, right associativity) : monad_scope.
Notation "e1 ;; e2" := (@bind _ _ _ _ e1%monad (fun _ => e2%monad))%monad
(at level 61, right associativity) : monad_scope.
End MonadBaseNotation.
Module MonadNotation.
Export MonadBaseNotation.
Notation "x <- c1 ;; c2" := (@bind _ _ _ _ c1 (fun x => c2))
(at level 61, c1 at next level, right associativity) : monad_scope.
Notation "' pat <- c1 ;; c2" :=
(@bind _ _ _ _ c1 (fun x => match x with pat => c2 end))
(at level 61, pat pattern, c1 at next level, right associativity) : monad_scope.
End MonadNotation.
Module MonadLetNotation.
Export MonadBaseNotation.
Notation "'let*' x ':=' c1 'in' c2" := (@bind _ _ _ _ c1 (fun x => c2))
(at level 61, c1 at next level, right associativity) : monad_scope.
End MonadLetNotation.
Section Instances.
Universe d c.
Context (m : Type@{d} -> Type@{c}) {M : Monad m}.
Global Instance Functor_Monad@{} : Functor m :=
{ fmap := @liftM _ _ }.
Global Instance Applicative_Monad@{} : Applicative m :=
{ pure := @ret _ _
; ap := @apM _ _
}.
End Instances.
Require Import ExtLib.Structures.Functor.
Require Import ExtLib.Structures.Applicative.
Set Implicit Arguments.
Set Strict Implicit.
Set Universe Polymorphism.
Class Monad@{d c} (m : Type@{d} -> Type@{c}) : Type :=
{ ret : forall {t : Type@{d}}, t -> m t
; bind : forall {t u : Type@{d}}, m t -> (t -> m u) -> m u
}.
Section monadic.
Definition liftM@{d c}
{m : Type@{d} -> Type@{c}}
{M : Monad m}
{T U : Type@{d}} (f : T -> U) : m T -> m U :=
fun x => bind x (fun x => ret (f x)).
Definition liftM2@{d c}
{m : Type@{d} -> Type@{c}}
{M : Monad m}
{T U V : Type@{d}} (f : T -> U -> V) : m T -> m U -> m V :=
Eval cbv beta iota zeta delta [ liftM ] in
fun x y => bind x (fun x => liftM (f x) y).
Definition liftM3@{d c}
{m : Type@{d} -> Type@{c}}
{M : Monad m}
{T U V W : Type@{d}} (f : T -> U -> V -> W) : m T -> m U -> m V -> m W :=
Eval cbv beta iota zeta delta [ liftM2 ] in
fun x y z => bind x (fun x => liftM2 (f x) y z).
Definition apM@{d c}
{m : Type@{d} -> Type@{c}}
{M : Monad m}
{A B : Type@{d}} (fM:m (A -> B)) (aM:m A) : m B :=
bind fM (fun f => liftM f aM).
(* Left-to-right composition of Kleisli arrows. *)
Definition mcompose@{c d}
{m:Type@{d}->Type@{c}}
{M: Monad m}
{T U V:Type@{d}}
(f: T -> m U) (g: U -> m V): (T -> m V) :=
fun x => bind (f x) g.
End monadic.
Module MonadBaseNotation.
Delimit Scope monad_scope with monad.
Notation "c >>= f" := (@bind _ _ _ _ c f) (at level 58, left associativity) : monad_scope.
Notation "f =<< c" := (@bind _ _ _ _ c f) (at level 61, right associativity) : monad_scope.
Notation "f >=> g" := (@mcompose _ _ _ _ _ f g) (at level 61, right associativity) : monad_scope.
Notation "e1 ;; e2" := (@bind _ _ _ _ e1%monad (fun _ => e2%monad))%monad
(at level 61, right associativity) : monad_scope.
End MonadBaseNotation.
Module MonadNotation.
Export MonadBaseNotation.
Notation "x <- c1 ;; c2" := (@bind _ _ _ _ c1 (fun x => c2))
(at level 61, c1 at next level, right associativity) : monad_scope.
Notation "' pat <- c1 ;; c2" :=
(@bind _ _ _ _ c1 (fun x => match x with pat => c2 end))
(at level 61, pat pattern, c1 at next level, right associativity) : monad_scope.
End MonadNotation.
Module MonadLetNotation.
Export MonadBaseNotation.
Notation "'let*' x ':=' c1 'in' c2" := (@bind _ _ _ _ c1 (fun x => c2))
(at level 61, c1 at next level, right associativity) : monad_scope.
End MonadLetNotation.
Section Instances.
Universe d c.
Context (m : Type@{d} -> Type@{c}) {M : Monad m}.
Global Instance Functor_Monad@{} : Functor m :=
{ fmap := @liftM _ _ }.
Global Instance Applicative_Monad@{} : Applicative m :=
{ pure := @ret _ _
; ap := @apM _ _
}.
End Instances.