Source code for fpylib.functors.maybe

from typing import Callable, Generic, Optional

from fpylib.functors.applicative import Applicative
from fpylib.functors.functor import _S, _T
from fpylib.functors.monad import Monad, unit


[docs]class Maybe(Applicative, Monad, Generic[_T]): """ This is a implementation of the Maybe Monad of Haskell. It is a functor, applicative and monad. """
[docs] def unit(self, value: _T) -> "Maybe[_T]": """ Return a Just pr Nothing value based on if the value is None or not. :param value: The value to be checked. :type value: T :return: Just value or Nothing """ return Just(value) if value is not None else Nothing()
[docs] def bind(self, func: Callable[[_T], _S]) -> "Maybe[_S]": """ Return a Just pr Nothing value based on if occur an error or not. :param func: The function to be applied. :type func: Callable[[T], S] :return: Just value or Nothing """ try: value = func(self.get()) if value is None: return Nothing(ValueError("The value is None")) return Just(value) except Exception as e: return Nothing(e)
[docs]class Just(Maybe): def __str__(self) -> str: return f"Just {self.get()}" def __repr__(self) -> str: return f"Just {type(self.get())}"
[docs]class Nothing(Maybe): def __init__(self, *failure: Optional[Exception]) -> None: """ This does nothing. """ object.__setattr__( self, "_Nothing__failure", filter(lambda fail: fail is not None, failure) )
[docs] def fails(self) -> bool: return self.__failure
def __str__(self) -> str: return "Nothing" def __repr__(self) -> str: return f"{self.__str__()} {list(self.__failure)}"
[docs]def maybe_conditioner(func: Callable[..., _T]) -> Callable[..., "Maybe[_T]"]: """ Conditioner for Maybe. :param func: The function to wrap in a Monad. :type func: Callable[..., T] :return: The wrapped function. :rtype: Callable[..., Monad[T]] """ def wrapper(*arg, **kwargs) -> "Maybe[_T]": try: return unit(Maybe, func(*arg, **kwargs)) except Exception as e: return Nothing(e) return wrapper