Source code for monad.types.maybe

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

from . import MonadPlus, Null
from ..mixins import ContextManager, Ord


[docs]class Maybe(MonadPlus, ContextManager, Ord): """The Maybe Monad. Representing values/computations that may fail. >>> Just(42) Just(42) >>> Just([1, 2, 3]) Just([1, 2, 3]) >>> Just(Nothing) Just(Nothing) >>> Just(Just(2)) Just(Just(2)) >>> isinstance(Just(1), Maybe) True >>> isinstance(Nothing, Maybe) True >>> saving = 100 >>> spend = lambda cost: Nothing if cost > saving else Just(saving - cost) >>> spend(90) Just(10) >>> spend(120) Nothing >>> safe_div = lambda a, b: Nothing if b == 0 else Just(a / b) >>> safe_div(12.0, 6) Just(2.0) >>> safe_div(12.0, 0) Nothing Bind operation with ``>>`` >>> inc = lambda n: Just(n + 1) if isinstance(n, int) else Nothing >>> Just(0) Just(0) >>> Just(0) >> inc Just(1) >>> Just(0) >> inc >> inc Just(2) >>> Just('zero') >> inc Nothing Comparison with ``==``, as long as what's wrapped inside are comparable. >>> Just(42) == Just(42) True >>> Just(42) == Nothing False >>> Nothing == Nothing True """
[docs] @classmethod def from_value(cls, value): """Wraps ``value`` in a :class:`Maybe` monad. Returns a :class:`Just` if the value is evaluated as true. :data:`Nothing` otherwise. """ return cls.unit(value) if value else Nothing
[docs] def bind(self, function): """The bind operation of :class:`Maybe`. Applies function to the value if and only if this is a :class:`Just`. """ return Nothing if self is Nothing else function(self.value)
def __bool__(self): return self is not Nothing __nonzero__ = __bool__ def __repr__(self): """Customized Show.""" if self is Nothing: return 'Nothing' else: return 'Just({})'.format(repr(self.value)) def __iter__(self): if self is not Nothing: yield self.value # Customized Ord logic def __lt__(self, monad): """Override to handle special case: Nothing.""" if self is Nothing and monad is Nothing: return False elif self is Nothing: # Nothing is less than something. return True elif monad is Nothing: # self is not Nothing and monad is Nothing here return False else: # Test normally return super(Maybe, self).__lt__(monad) # MonadPlus operation
[docs] def plus(self, monad): return self or monad
# pylint: disable = invalid-name Just = Maybe #: The :class:`Maybe` that represents nothing, a singleton, like ``None``. Nothing = Maybe(Null) Maybe.zero = Nothing # pylint: enable = invalid-name