Skip to content

Instantly share code, notes, and snippets.

@BlueRayi
Created January 14, 2020 08:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BlueRayi/fb999947e8f2a8037e7eea7ff9320f90 to your computer and use it in GitHub Desktop.
Save BlueRayi/fb999947e8f2a8037e7eea7ff9320f90 to your computer and use it in GitHub Desktop.
Maybe in Python
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()
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