typesafe-monads/monads/maybe.py

70 lines
1.7 KiB
Python
Raw Normal View History

2018-10-11 05:26:00 +00:00
from __future__ import annotations
from typing import Any, Callable, Generic, Optional, TypeVar
from .monad import Monad
T = TypeVar("T")
S = TypeVar("S")
E = TypeVar("E")
class Maybe(Monad[T]):
def __init__(self) -> None:
raise NotImplementedError
@classmethod
def unit(cls, value: T) -> Maybe[T]:
return Just(value)
def bind(self, function: Callable[[T], Maybe[S]]) -> Maybe[S]:
if isinstance(self, Just):
return function(self.value)
else:
new: Maybe[S] = Nothing()
return new
def fmap(self, function: Callable[[T], S]) -> Maybe[S]:
if isinstance(self, Just):
return Just(function(self.value))
else:
new: Maybe[S] = Nothing()
return new
def withDefault(self, default: T) -> T:
if isinstance(self, Just):
return self.value
else:
return default
__rshift__ = bind
__mul__ = __rmul__ = fmap
class Just(Maybe[T]):
def __init__(self, value: T) -> None:
self.value = value
def __eq__(self, other: object):
return isinstance(other, Just) and self.value == other.value
2018-10-11 05:26:00 +00:00
def __repr__(self) -> str:
return f"<Just {self.value}>"
class Nothing(Maybe[T]):
def __init__(self) -> None:
...
def __eq__(self, other: object):
return isinstance(other, Nothing)
2018-10-11 05:26:00 +00:00
def __repr__(self) -> str:
return "<Nothing>"
def maybe(value: T, predicate: Optional[Callable[[T], bool]] = None) -> Maybe[T]:
predicate = predicate or (lambda x: x is not None)
if predicate(value):
return Just(value)
else:
return Nothing()