MathClasses.interfaces.monads
Require Import
abstract_algebra canonical_names.
Require Export
interfaces.functors.
Section ops.
Context (M : Type → Type).
Class MonadReturn := ret: ∀ {A}, A → M A.
Class MonadBind := bind: ∀ {A B}, (A → M B) → M A → M B.
Class MonadJoin := join: ∀ {A}, M (M A) → M A.
End ops.
Arguments ret {M MonadReturn A} _.
Arguments bind {M MonadBind A B} _ _.
Arguments join {M MonadJoin A} _.
Notation "m ≫= f" := (bind f m) (at level 60, right associativity) : mc_scope.
Notation "x ← y ; z" := (y ≫= (λ x : _, z)) (at level 65, next at level 35, right associativity, only parsing) : mc_scope.
Class Monad (M : Type → Type) `{∀ A, Equiv A → Equiv (M A)}
`{MonadReturn M} `{MonadBind M} : Prop :=
{ mon_ret_proper `{Setoid A} :> Proper ((=) ==> (=)) (@ret _ _ A)
; mon_bind_proper `{Setoid A} `{Setoid B} :>
Proper (((=) ==> (=)) ==> (=) ==> (=)) (@bind _ _ A B)
; mon_setoid `{Setoid A} :> Setoid (M A)
; bind_lunit `{Equiv A} `{Setoid B} `{!Setoid_Morphism (f : A → M B)} : bind f ∘ ret = f
; bind_runit `{Setoid A} : bind ret = id
; bind_assoc `{Equiv A} `{Equiv B} `{Setoid C}
`{!Setoid_Morphism (f : B → M C)} `{!Setoid_Morphism (g : A → M B)} :
bind f ∘ bind g = bind (bind f ∘ g) }.
Class StrongMonad (M : Type → Type) `{∀ A, Equiv A → Equiv (M A)}
`{MonadReturn M} `{SFmap M} `{MonadJoin M} : Prop :=
{ smon_ret_proper `{Setoid A} :> Proper ((=) ==> (=)) (@ret _ _ A)
; smon_join_proper `{Setoid A} :> Proper ((=) ==> (=)) (@join _ _ A)
; smon_sfunctor :> SFunctor M
; sfmap_ret `{Equiv A} `{Equiv B} `{!Setoid_Morphism (f : A → B)} :
sfmap f ∘ ret = ret ∘ f
; sfmap_join `{Equiv A} `{Equiv B} `{!Setoid_Morphism (f : A → B)} :
sfmap f ∘ join = join ∘ sfmap (sfmap f)
; join_ret `{Setoid A} :
join ∘ ret = id
; join_sfmap_ret `{Setoid A} :
join ∘ sfmap ret = id
; join_sfmap_join `{Setoid A} :
join ∘ sfmap join = join ∘ join }.
Class FullMonad (M : Type → Type) `{∀ A, Equiv A → Equiv (M A)}
`{MonadReturn M} `{MonadBind M} `{SFmap M} `{MonadJoin M} : Prop :=
{ full_mon_mon :> Monad M
; full_smon :> StrongMonad M
; bind_as_join_sfmap `{Equiv A} `{Setoid B} `{!Setoid_Morphism (f : A → M B)} :
bind f = join ∘ sfmap f }.
abstract_algebra canonical_names.
Require Export
interfaces.functors.
Section ops.
Context (M : Type → Type).
Class MonadReturn := ret: ∀ {A}, A → M A.
Class MonadBind := bind: ∀ {A B}, (A → M B) → M A → M B.
Class MonadJoin := join: ∀ {A}, M (M A) → M A.
End ops.
Arguments ret {M MonadReturn A} _.
Arguments bind {M MonadBind A B} _ _.
Arguments join {M MonadJoin A} _.
Notation "m ≫= f" := (bind f m) (at level 60, right associativity) : mc_scope.
Notation "x ← y ; z" := (y ≫= (λ x : _, z)) (at level 65, next at level 35, right associativity, only parsing) : mc_scope.
Class Monad (M : Type → Type) `{∀ A, Equiv A → Equiv (M A)}
`{MonadReturn M} `{MonadBind M} : Prop :=
{ mon_ret_proper `{Setoid A} :> Proper ((=) ==> (=)) (@ret _ _ A)
; mon_bind_proper `{Setoid A} `{Setoid B} :>
Proper (((=) ==> (=)) ==> (=) ==> (=)) (@bind _ _ A B)
; mon_setoid `{Setoid A} :> Setoid (M A)
; bind_lunit `{Equiv A} `{Setoid B} `{!Setoid_Morphism (f : A → M B)} : bind f ∘ ret = f
; bind_runit `{Setoid A} : bind ret = id
; bind_assoc `{Equiv A} `{Equiv B} `{Setoid C}
`{!Setoid_Morphism (f : B → M C)} `{!Setoid_Morphism (g : A → M B)} :
bind f ∘ bind g = bind (bind f ∘ g) }.
Class StrongMonad (M : Type → Type) `{∀ A, Equiv A → Equiv (M A)}
`{MonadReturn M} `{SFmap M} `{MonadJoin M} : Prop :=
{ smon_ret_proper `{Setoid A} :> Proper ((=) ==> (=)) (@ret _ _ A)
; smon_join_proper `{Setoid A} :> Proper ((=) ==> (=)) (@join _ _ A)
; smon_sfunctor :> SFunctor M
; sfmap_ret `{Equiv A} `{Equiv B} `{!Setoid_Morphism (f : A → B)} :
sfmap f ∘ ret = ret ∘ f
; sfmap_join `{Equiv A} `{Equiv B} `{!Setoid_Morphism (f : A → B)} :
sfmap f ∘ join = join ∘ sfmap (sfmap f)
; join_ret `{Setoid A} :
join ∘ ret = id
; join_sfmap_ret `{Setoid A} :
join ∘ sfmap ret = id
; join_sfmap_join `{Setoid A} :
join ∘ sfmap join = join ∘ join }.
Class FullMonad (M : Type → Type) `{∀ A, Equiv A → Equiv (M A)}
`{MonadReturn M} `{MonadBind M} `{SFmap M} `{MonadJoin M} : Prop :=
{ full_mon_mon :> Monad M
; full_smon :> StrongMonad M
; bind_as_join_sfmap `{Equiv A} `{Setoid B} `{!Setoid_Morphism (f : A → M B)} :
bind f = join ∘ sfmap f }.