Source code for returns.interfaces.mappable

from abc import abstractmethod
from typing import Callable, ClassVar, Generic, NoReturn, Sequence, TypeVar

from typing_extensions import final

from returns.functions import compose, identity
from returns.primitives.asserts import assert_equal
from returns.primitives.hkt import KindN
from returns.primitives.laws import (
    Law,
    Law1,
    Law3,
    Lawful,
    LawSpecDef,
    law_definition,
)

_FirstType = TypeVar('_FirstType')
_SecondType = TypeVar('_SecondType')
_ThirdType = TypeVar('_ThirdType')
_UpdatedType = TypeVar('_UpdatedType')

_MappableType = TypeVar('_MappableType', bound='MappableN')

# Used in laws:
_NewType1 = TypeVar('_NewType1')
_NewType2 = TypeVar('_NewType2')


[docs]@final class _LawSpec(LawSpecDef): """ Mappable or functor laws. https://en.wikibooks.org/wiki/Haskell/The_Functor_class#The_functor_laws """
[docs] @law_definition def identity_law( mappable: 'MappableN[_FirstType, _SecondType, _ThirdType]', ) -> None: """Mapping identity over a value must return the value unchanged.""" assert_equal(mappable.map(identity), mappable)
[docs] @law_definition def associative_law( mappable: 'MappableN[_FirstType, _SecondType, _ThirdType]', first: Callable[[_FirstType], _NewType1], second: Callable[[_NewType1], _NewType2], ) -> None: """Mapping twice or mapping a composition is the same thing.""" assert_equal( mappable.map(first).map(second), mappable.map(compose(first, second)), )
[docs]class MappableN( Generic[_FirstType, _SecondType, _ThirdType], Lawful['MappableN[_FirstType, _SecondType, _ThirdType]'], ): """ Allows to chain wrapped values in containers with regular functions. Behaves like a functor. See also: - https://en.wikipedia.org/wiki/Functor """ _laws: ClassVar[Sequence[Law]] = ( Law1(_LawSpec.identity_law), Law3(_LawSpec.associative_law), )
[docs] @abstractmethod # noqa: WPS125 def map( # noqa: WPS125 self: _MappableType, function: Callable[[_FirstType], _UpdatedType], ) -> KindN[_MappableType, _UpdatedType, _SecondType, _ThirdType]: """Allows to run a pure function over a container."""
#: Type alias for kinds with one type argument. Mappable1 = MappableN[_FirstType, NoReturn, NoReturn] #: Type alias for kinds with two type arguments. Mappable2 = MappableN[_FirstType, _SecondType, NoReturn] #: Type alias for kinds with three type arguments. Mappable3 = MappableN[_FirstType, _SecondType, _ThirdType]