Source code for categories.maybe

from typing import Any, Callable, Generic, Type, TypeVar

from categories import applicative, functor, mappend
from categories import monad, monoid
from categories import semigroup, sappend


A = TypeVar('A')
B = TypeVar('B')
M = TypeVar('M', bound='Maybe')


[docs]class Maybe(Generic[A]): _JUST_TYPE = 'Just' # type: str _NOTHING_TYPE = 'Nothing' # type: str def __init__(self, type: str, value: A = None) -> None: self.type = type if self.type == self._JUST_TYPE: self.value = value def __repr__(self) -> str: return ('Nothing' if self.type == self._NOTHING_TYPE else 'Just({})'.format(repr(self.value))) def __eq__(self, other) -> bool: if isinstance(other, type(self)): return (self.type == other.type and self.__dict__ == other.__dict__) else: return False
[docs] def match(self, constructor) -> bool: if self.type == self._NOTHING_TYPE: return constructor == self.nothing else: return constructor == self.just
[docs] @classmethod def just(cls: Type, value: A) -> M: return cls(cls._JUST_TYPE, value)
[docs] @classmethod def nothing(cls: Type) -> M: return cls(cls._NOTHING_TYPE)
Just = Maybe.just # type: Callable[[A], Maybe[A]] Nothing = Maybe.nothing # type: Callable[[], Maybe[A]] def _mappend(a: Maybe[A], b: Maybe[A]) -> Maybe[A]: if a == Nothing(): return b elif b == Nothing(): return a else: return Just(mappend(a.value, b.value)) def _sappend(a: Maybe[A], b: Maybe[A]) -> Maybe[A]: if a.match(Nothing): return b elif b.match(Nothing): return a else: return Just(sappend(a.value, b.value)) def _fmap(f: Callable, x: Maybe[A])-> Maybe[B]: return Just(f(x.value)) if x.match(Just) else Nothing() def _apply(f, x: Maybe[A]) -> Maybe[B]: if f.match(Just) and x.match(Just): return Just(f.value(x.value)) else: return Nothing() def _bind(m: Maybe[A], f: Callable[[Any], Maybe[B]]) -> Maybe[B]: if m.match(Nothing): return Nothing() else: return f(m.value) functor.instance(Maybe, _fmap) semigroup.instance(Maybe, _sappend) monoid.instance(Maybe, lambda: Nothing(), _mappend) applicative.instance(Maybe, Just, _apply) monad.instance(Maybe, Just, _bind)
[docs]def maybe(default: B, f: Callable, x: Maybe[A]) -> B: """ Given a default value, a function, and a Maybe object, return the default if the Maybe object is Nothing, otherwise call the function with the value in the Maybe object, call the function on it, and return the result. :param default: This is the value that gets returned if ``x`` is Nothing :param f: When x matches Just, this function is called on the value in x, and the result is returned :param x: a Maybe object :returns: Whatever type ``default`` or the return type of ``f`` is """ if x.match(Just): return f(x.value) else: return default