63 lines
1.7 KiB
Python
63 lines
1.7 KiB
Python
from functools import partial
|
|
from typing import TypeVar, Generic, Callable
|
|
|
|
from .typing import Functor, Monad, Applicative
|
|
|
|
|
|
TSource = TypeVar('TSource')
|
|
TResult = TypeVar('TResult')
|
|
|
|
|
|
class Identity(Generic[TSource]):
|
|
"""Identity monad.
|
|
|
|
The Identity monad is the simplest monad, which attaches no
|
|
information to values.
|
|
"""
|
|
def __init__(self, value: TSource) -> None:
|
|
self._value = value
|
|
|
|
@classmethod
|
|
def unit(cls, value: TSource) -> 'Identity[TSource]':
|
|
"""Initialize a new identity."""
|
|
return Identity(value)
|
|
|
|
def map(self, mapper: Callable[[TSource], TResult]) -> 'Identity[TResult]':
|
|
"""Map a function over wrapped values."""
|
|
result = mapper(self._value)
|
|
return Identity(result)
|
|
|
|
def bind(self, func: Callable[[TSource], 'Identity[TResult]']) -> 'Identity[TResult]':
|
|
return func(self._value)
|
|
|
|
@classmethod
|
|
def pure(cls, value: TSource):
|
|
return Identity(value)
|
|
|
|
def apply(self: 'Identity[Callable[[TSource], TResult]]', something: 'Identity[TSource]') -> 'Identity[TResult]':
|
|
def mapper(other_value):
|
|
try:
|
|
return self._value(other_value)
|
|
except TypeError:
|
|
return partial(self._value, other_value)
|
|
return something.map(mapper)
|
|
|
|
def run(self) -> TSource:
|
|
return self._value
|
|
|
|
def __call__(self) -> TSource:
|
|
return self.run()
|
|
|
|
def __eq__(self, other) -> bool:
|
|
return self._value == other()
|
|
|
|
def __str__(self) -> str:
|
|
return "Identity(%s)" % self._value
|
|
|
|
def __repr__(self) -> str:
|
|
return str(self)
|
|
|
|
|
|
assert isinstance(Identity, Functor)
|
|
assert isinstance(Identity, Applicative)
|
|
assert isinstance(Identity, Monad)
|