Created
January 14, 2020 08:35
-
-
Save BlueRayi/fb999947e8f2a8037e7eea7ff9320f90 to your computer and use it in GitHub Desktop.
Maybe in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from abc import ABCMeta, abstractmethod | |
from collections.abc import Container, Sized, Iterator | |
from typing import TypeVar, Generic | |
T = TypeVar('T') | |
class NullpoError(Exception): | |
def __init__(self, message): | |
self.message = message | |
class Fanctor(Generic[T], metaclass=ABCMeta): | |
@abstractmethod | |
def map(self, f): | |
pass | |
class Applicative(Generic[T], metaclass=ABCMeta): | |
@abstractmethod | |
def lift(self, f): | |
pass | |
class Monad(Fanctor, Generic[T], metaclass=ABCMeta): | |
@classmethod | |
@abstractmethod | |
def pure(cls, x): | |
pass | |
@classmethod | |
@abstractmethod | |
def join(cls, m): | |
pass | |
def bind(self, f): | |
cls = type(self) | |
return cls.join(self.map(f)) | |
class Maybe(Container, Sized, Monad, Applicative, Generic[T], metaclass=ABCMeta): | |
@property | |
@abstractmethod | |
def has_value(self): | |
pass | |
@abstractmethod | |
def __eq__(self, other): | |
pass | |
@property | |
@abstractmethod | |
def depth(self): | |
pass | |
def __iter__(self): | |
return MaybeIterator(self) | |
@property | |
@abstractmethod | |
def i(self): | |
pass | |
@property | |
@abstractmethod | |
def q(self): | |
pass | |
@abstractmethod | |
def __rshift__(self, other): | |
pass | |
@abstractmethod | |
def __repr__(self): | |
pass | |
@abstractmethod | |
def __str__(self): | |
pass | |
@abstractmethod | |
def __contains__(self, item): | |
pass | |
@abstractmethod | |
def to_native(self): | |
pass | |
@abstractmethod | |
def __call__(self, *args, **kwargs): | |
pass | |
class Something(Maybe, Generic[T]): | |
def __init__(self, value): | |
self.__value = value | |
@classmethod | |
def pure(cls, x): | |
return cls(x) | |
def map(self, f): | |
cls = type(self) | |
return cls(f(self.__value)) | |
@classmethod | |
def join(cls, m): | |
if isinstance(m.__value, Maybe): | |
return m.__value | |
else: | |
return m | |
def lift(self, m): | |
return self.bind(m.__value) | |
@property | |
def has_value(self): | |
return True | |
def __eq__(self, other): | |
return isinstance(other, Something) and self.__value == other.__value | |
@property | |
def depth(self): | |
if isinstance(self.__value, Maybe): | |
return self.__value.depth + 1 | |
else: | |
return 1 | |
@property | |
def i(self): | |
return self.__value | |
@property | |
def q(self): | |
return SomethingSNO(self.__value) | |
def __rshift__(self, other): | |
cls = type(self) | |
if isinstance(other, Maybe): | |
if self.depth < other.depth: | |
return Something(self) >> other | |
elif self.depth > other.depth: | |
return self.__value >> other | |
else: | |
return self | |
else: | |
return (self >> cls(other)).__value | |
def __repr__(self): | |
return 'just({})'.format(repr(self.__value)) | |
def __str__(self): | |
return 'Just {}'.format(str(self.__value)) | |
def __len__(self): | |
return 1 | |
def __contains__(self, item): | |
try: | |
return self.__value == item | |
except TypeError: | |
return False | |
def to_native(self): | |
if isinstance(self.__value, Maybe): | |
return self.__value.to_native | |
else: | |
return self.__value | |
def __call__(self, *args, **kwargs): | |
cls = type(self) | |
return cls(self.__value(*args, **kwargs)) | |
class Nothing(Maybe, Generic[T]): | |
__instance = None | |
@classmethod | |
def __new__(cls, *args, **kwargs): | |
if cls.__instance is None: | |
cls.__instance = super(Nothing, cls).__new__(cls) | |
return cls.__instance | |
@classmethod | |
def pure(cls, x): | |
return cls.__instance | |
def map(self, f): | |
cls = type(self) | |
return cls.__instance | |
@classmethod | |
def join(cls, m): | |
return cls.__instance | |
def lift(self, m): | |
cls = type(self) | |
return cls.__instance | |
@property | |
def has_value(self): | |
return False | |
def __eq__(self, other): | |
return isinstance(other, Nothing) | |
@property | |
def depth(self): | |
return 1 | |
@property | |
def i(self): | |
raise NullpoError('it GOT no value.') | |
@property | |
def q(self): | |
return NothingSNO() | |
def __rshift__(self, other): | |
return other | |
def __repr__(self): | |
return 'nothing' | |
def __str__(self): | |
return 'Nothing' | |
def __len__(self): | |
return 0 | |
def __contains__(self, item): | |
return False | |
def to_native(self): | |
return None | |
def __call__(self, *args, **kwargs): | |
cls = type(self) | |
return cls.__instance | |
Nothing() | |
class MaybeIterator(Iterator, Generic[T]): | |
def __init__(self, m): | |
self.__m = m | |
def __iter__(self): | |
return self | |
def __next__(self): | |
if self.__m: | |
value = self.__m.i | |
self.__m = Nothing() | |
return value | |
else: | |
raise StopIteration() | |
class SafeNavigationOperator(metaclass=ABCMeta): | |
@abstractmethod | |
def __getattr__(self, attr_name): | |
pass | |
@abstractmethod | |
def __getitem__(self, key): | |
pass | |
class SomethingSNO(SafeNavigationOperator): | |
def __init__(self, value): | |
self.__value = value | |
def __getattr__(self, attr_name): | |
return just(getattr(self.__value, attr_name)) | |
def __getitem__(self, key): | |
return just(self.__value[key]) | |
class NothingSNO(SafeNavigationOperator): | |
__instance = None | |
@classmethod | |
def __new__(cls, *args, **kwargs): | |
if cls.__instance is None: | |
cls.__instance = super(NothingSNO, cls).__new__(cls) | |
return cls.__instance | |
def __getattr__(self, attr_name): | |
return nothing | |
def __getitem__(self, key): | |
return nothing | |
NothingSNO() | |
def just(x): | |
return Something(x) | |
nothing: Nothing = Nothing() | |
def dep(m): | |
if isinstance(m, Maybe): | |
return m.depth | |
else: | |
return 0 | |
def join(m): | |
return type(m).join(m) | |
def do(*params): | |
if all(params): | |
return lambda f: just(f(*(param.i for param in params))) | |
else: | |
return lambda f: nothing | |
def maybe_from(x): | |
if isinstance(x, Maybe): | |
return x | |
else: | |
if x is not None: | |
return Something(x) | |
else: | |
return Nothing() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
from abc import ABCMeta, abstractmethod | |
from collections.abc import Container, Hashable, Sized, Iterator | |
from typing import TypeVar, Generic, Callable, Optional, Any | |
T = TypeVar('T') | |
S = TypeVar('S') | |
class NullpoError(Exception): | |
def __init__(self: NullpoError, message: Any) -> None: | |
... | |
class Fanctor(Generic[T], metaclass=ABCMeta): | |
@abstractmethod | |
def map(self: Fanctor[T], f: Callable[[T], S]) -> Fanctor[S]: | |
... | |
class Applicative(Generic[T], metaclass=ABCMeta): | |
@abstractmethod | |
def lift(self: Applicative[T], f: Applicative[Callable[[T], S]]) -> Applicative[S]: | |
... | |
class Monad(Fanctor, Generic[T], metaclass=ABCMeta): | |
@abstractmethod | |
def map(self: Monad[T], f: Callable[[T], S]) -> Monad[S]: | |
... | |
@classmethod | |
@abstractmethod | |
def pure(cls: type, x: S) -> Monad[S]: | |
... | |
@classmethod | |
@abstractmethod | |
def join(cls: type, m: Monad[Monad[S]]) -> Monad[S]: | |
... | |
def bind(self: Monad[T], f: Callable[[T], Monad[S]]) -> Monad[S]: | |
... | |
class Maybe(Container, Sized, Monad, Applicative, Generic[T], metaclass=ABCMeta): | |
@classmethod | |
@abstractmethod | |
def pure(cls: type, x: S) -> Maybe[S]: | |
... | |
@abstractmethod | |
def map(self: Maybe[T], f: Callable[[T], S]) -> Maybe[S]: | |
... | |
@classmethod | |
@abstractmethod | |
def join(cls: type, m: Monad[Monad[S]]) -> Maybe[S]: | |
... | |
def bind(self: Maybe[T], f: Callable[[T], Monad[S]]) -> Maybe[S]: | |
... | |
@abstractmethod | |
def lift(self: Maybe[T], m: Applicative[Callable[[T], S]]) -> Maybe[S]: | |
... | |
@property | |
@abstractmethod | |
def has_value(self: Maybe[T]) -> bool: | |
... | |
def __eq__(self: Maybe[T], other: S) -> bool: | |
... | |
@property | |
@abstractmethod | |
def depth(self: Maybe[T]) -> int: | |
... | |
def __iter__(self: Maybe[T]) -> MaybeIterator[T]: | |
... | |
@property | |
@abstractmethod | |
def i(self: Maybe[T]) -> T: | |
... | |
@property | |
@abstractmethod | |
def q(self: Maybe[T]) -> SafeNavigationOperator: | |
... | |
@abstractmethod | |
def __rshift__(self: Maybe[T], other: S) -> S: | |
... | |
@abstractmethod | |
def __repr__(self: Maybe[T])-> str: | |
... | |
@abstractmethod | |
def __str__(self: Maybe[T]) -> str: | |
... | |
@abstractmethod | |
def __contains__(self: Maybe[T], item: Any) -> bool: | |
... | |
@abstractmethod | |
def to_native(self: Maybe[T]) -> Any: | |
... | |
@abstractmethod | |
def __call__(self: Maybe[Callable[..., S]], *args, **kwargs) -> Maybe[S]: | |
... | |
class Something(Maybe, Generic[T]): | |
def __init__(self: Something[T], value: T) -> None: | |
... | |
@classmethod | |
def pure(cls: type, x: S) -> Maybe[S]: | |
... | |
def map(self: Something[T], f: Callable[[T], S]) -> Maybe[S]: | |
... | |
@classmethod | |
def join(cls: type, m: Monad[Monad[S]]) -> Maybe[S]: | |
... | |
def bind(self: Something[T], f: Callable[[T], Monad[S]]) -> Maybe[S]: | |
... | |
def lift(self: Something[T], m: Applicative[Callable[[T], S]]) -> Maybe[S]: | |
... | |
@property | |
def has_value(self: Something[T]) -> bool: | |
... | |
def __eq__(self: Something[T], other: S) -> bool: | |
... | |
@property | |
def depth(self: Something[T]) -> int: | |
... | |
@property | |
def i(self: Something[T]) -> T: | |
... | |
@property | |
def q(self: Something[T]) -> SomethingSNO: | |
... | |
def __rshift__(self: Something[T], other: S) -> S: | |
... | |
def __repr__(self: Something[T]) -> str: | |
... | |
def __str__(self: Something[T]) -> str: | |
... | |
def __len__(self: Something[T]) -> int: | |
... | |
def __contains__(self: Something[T], item: Any) -> bool: | |
... | |
def to_native(self: Something[T]) -> T: | |
... | |
def __call__(self: Something[Callable[..., S]], *args, **kwargs) -> Maybe[S]: | |
... | |
class Nothing(Maybe, Generic[T]): | |
def __init__(self: Nothing[T]) -> None: | |
... | |
@classmethod | |
def __new__(cls: type, *args, **kwargs) -> Nothing[S]: | |
... | |
@classmethod | |
def pure(cls: type, x: S) -> Maybe[S]: | |
... | |
def map(self: Nothing[T], f: Callable[[T], S]) -> Maybe[S]: | |
... | |
@classmethod | |
def join(cls: type, m: Monad[Monad[S]]) -> Maybe[S]: | |
... | |
def bind(self: Nothing[T], f: Callable[[T], Monad[S]]) -> Maybe[S]: | |
... | |
def lift(self: Nothing[T], m: Applicative[Callable[[T], S]]) -> Maybe[S]: | |
... | |
@property | |
def has_value(self: Nothing[T]) -> bool: | |
... | |
def __eq__(self: Nothing[T], other: Any) -> bool: | |
... | |
@property | |
def depth(self: Nothing[T]) -> int: | |
... | |
@property | |
def i(self: Nothing[T]) -> T: | |
... | |
@property | |
def q(self: Nothing[T]) -> NothingSNO: | |
... | |
def __rshift__(self: Nothing[T], other: S) -> S: | |
... | |
def __repr__(self: Nothing[T]) -> str: | |
... | |
def __str__(self: Nothing[T]) -> str: | |
... | |
def __len__(self: Nothing[T]) -> int: | |
... | |
def __contains__(self: Nothing[T], item: Any) -> bool: | |
... | |
def to_native(self: Nothing[T]) -> T: | |
... | |
def __call__(self: Nothing[Callable[..., S]], *args, **kwargs) -> Maybe[S]: | |
... | |
class MaybeIterator(Iterator, Generic[T]): | |
def __init__(self: MaybeIterator[T], m: Maybe[T]) -> None: | |
... | |
def __iter__(self: MaybeIterator[T]) -> MaybeIterator[T]: | |
... | |
def __next__(self: MaybeIterator[T]) -> T: | |
... | |
class SafeNavigationOperator(metaclass=ABCMeta): | |
@abstractmethod | |
def __getattr__(self: SafeNavigationOperator, attr_name: str) -> Maybe: | |
... | |
@abstractmethod | |
def __getitem__(self: SafeNavigationOperator, key: Hashable) -> Maybe: | |
... | |
class SomethingSNO(SafeNavigationOperator): | |
def __init__(self: SomethingSNO, value: Any) -> None: | |
... | |
def __getattr__(self: SomethingSNO, attr_name: str) -> Maybe: | |
... | |
def __getitem__(self: SomethingSNO, key: Hashable) -> Maybe: | |
... | |
class NothingSNO(SafeNavigationOperator): | |
def __init__(self: NothingSNO) -> None: | |
... | |
@classmethod | |
def __new__(cls: type, *args, **kwargs) -> NothingSNO: | |
... | |
def __getattr__(self: NothingSNO, attr_name: str) -> Maybe: | |
... | |
def __getitem__(self: NothingSNO, key: Hashable) -> Maybe: | |
... | |
def just(x: T) -> Something[T]: | |
... | |
nothing: Nothing = ... | |
def dep(m: Any) -> int: | |
... | |
def join(m: Maybe[Maybe[T]]) -> Maybe[T]: | |
... | |
def do(*params: tuple) -> Callable[Callable[..., S], Maybe[S]]: | |
... | |
def maybe_from(x: Optional[T]) -> Maybe[T]: | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment