Source code for monad.types.monad

# -*- coding: utf-8 -*-
# Copyright (c) 2012-2014, Philip Xu <pyx@xrefactor.com>
# License: BSD New, see LICENSE for details.
"""monad.types.monad - The Monad Class."""

from . import Applicative
from ..utils import identity


[docs]class Unit(object): """Descriptor that always return the owner monad, used for ``unit``.""" # pylint: disable = too-few-public-methods def __get__(self, instance, cls): """Returns the owner monad.""" return cls
[docs]class Monad(Applicative): """The Monad Class. Implements bind operator ``>>`` and inverted bind operator ``<<`` as syntactic sugar. It is equivalent to ``(>>=)`` and ``(=<<)`` in haskell, not to be confused with ``(>>)`` and ``(<<)`` in haskell. As python treats assignments as statements, there is no way we can overload ``>>=`` as a chainable bind, be it directly overloaded through ``__irshift__``, or derived by python itself through ``__rshift__``. The default implementations of ``bind``, ``fmap`` and ``join`` are mutual recursive, subclasses should at least either overload ``bind``, or ``fmap`` and ``join``, or all of them for better performance. """ # Bind Operators def __rshift__(self, function): """The bind operator ``>>``""" if not callable(function): return NotImplemented return self.bind(function) def __rlshift__(self, function): """The inverted bind operator ``<<``""" if not callable(function): return NotImplemented return self.bind(function) def __repr__(self): return '{cls}({value})'.format( cls=type(self).__name__, value=repr(self.value))
[docs] def bind(self, function): """The bind operation. ``function`` is a function that maps from the underlying value to a monadic type, something like signature ``f :: a -> M a`` in haskell's term. The default implementation defines ``bind`` in terms of ``fmap`` and ``join``. """ return self.fmap(function).join()
[docs] def fmap(self, function): """The fmap operation. The default implementation defines ``fmap`` in terms of ``bind`` and ``unit``. """ # pylint: disable = star-args return self.bind( lambda *args, **kwargs: self.unit(function(*args, **kwargs)) )
[docs] def join(self): """The join operation. The default implementation defines ``join`` in terms of ``bind`` and ``identity`` function. """ return self.bind(identity)
#: The ``unit`` of monad. unit = Unit()