from __future__ import (division as _py3_division,
print_function as _py3_print,
absolute_import as _py3_abs_import)
import itertools
from ..lang import sig
from ..lang import H
from ..lang import t
from ..lang import L
from ..lang import build_instance
from ..lang import is_builtin
from ..lang import List
from ..lang import instance
from ..Data.Functor import fmap
from .Applicative import Applicative
[docs]class Monad(Applicative):
"""The Monad class defines the basic operations over a monad, a concept from
a branch of mathematics known as category theory. From the perspective of
a Haskell programmer, however, it is best to think of a monad as an
abstract datatype of actions.
Dependencies:
- `~hask.Control.Applicative.Applicative`:class:
Attributes:
- ``bind``
- ``__rshift__``
Minimal complete definition:
- ``bind``
"""
@classmethod
def make_instance(typeclass, cls, bind):
bind = bind ** (H[(Monad, "m")]/ t("m", "a") >> (H/ "a" >> t("m", "b"))
>> t("m", "b"))
if not is_builtin(cls):
def bind_wrap(s, o):
return Monad[s].bind(s, o)
cls.__rshift__ = bind_wrap
build_instance(Monad, cls, {"bind": bind})
@sig(H[(Monad, "m")]/ t("m", "a") >> (H/ "a" >> t("m", "b")) >> t("m", "b"))
def bind(m, fn):
"""
``bind :: Monad m => m a -> (a -> m b) -> m b``
Monadic bind.
"""
return Monad[m].bind(m, fn)
@sig(H[(Monad, "m")]/ t("m", t("m", "a")) >> t("m", "a"))
def join(m):
"""``join :: Monad m => m (m a) -> m a``
The join function is the conventional monad join operator. It is used to
remove one level of monadic structure, projecting its bound argument into
the outer level.
"""
__id = (lambda x: x) ** (H/ "a" >> "a")
return bind(m, __id)
@sig(H[(Monad, "m")]/ (H/ "a" >> "r") >> t("m", "a") >> t("m", "r"))
def liftM(fn, m):
"""
``liftM :: Monad m => (a1 -> r) -> m a1 -> m r``
Promote a function to a monad.
"""
return fmap(fn, m)
instance(Monad, List).where(
bind = lambda x, fn: L[itertools.chain.from_iterable(fmap(fn, x))]
)