Example #1
0
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),
    )

    @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."""
Example #2
0
class SwappableN(
        bimappable.BiMappableN[_FirstType, _SecondType, _ThirdType],
        Lawful['SwappableN[_FirstType, _SecondType, _ThirdType]'],
):
    """Interface that allows swapping first and second type values."""

    _laws: ClassVar[Sequence[Law]] = (Law1(_LawSpec.double_swap_law), )

    @abstractmethod
    def swap(
        self: _SwappableType,
    ) -> KindN[_SwappableType, _SecondType, _FirstType, _ThirdType]:
        """Swaps first and second types in ``SwappableN``."""
Example #3
0
class AltableN(
    Generic[_FirstType, _SecondType, _ThirdType],
    Lawful['AltableN[_FirstType, _SecondType, _ThirdType]'],
):
    """Modifies the second type argument with a pure function."""

    _laws: ClassVar[Sequence[Law]] = (
        Law1(_LawSpec.identity_law),
        Law3(_LawSpec.associative_law),
    )

    @abstractmethod
    def alt(
        self: _AltableType,
        function: Callable[[_SecondType], _UpdatedType],
    ) -> KindN[_AltableType, _FirstType, _UpdatedType, _ThirdType]:
        """Allows to run a pure function over a container."""
Example #4
0
class Equable(Lawful['Equable']):
    """
    Interface for types that can be compared with real values.

    Not all types can, because some don't have the value at a time:
    - ``Future`` has to be awaited to get the value
    - ``Reader`` has to be called to get the value

    """

    _laws: ClassVar[Sequence[Law]] = (
        Law1(_LawSpec.reflexive_law),
        Law2(_LawSpec.symmetry_law),
        Law3(_LawSpec.transitivity_law),
    )

    @abstractmethod
    def equals(self: _EqualType, other: _EqualType) -> bool:
        """Type-safe equality check for values of the same type."""
Example #5
0
class ContainerN(
    ApplicativeN[_FirstType, _SecondType, _ThirdType],
    bindable.BindableN[_FirstType, _SecondType, _ThirdType],
    Lawful['ContainerN[_FirstType, _SecondType, _ThirdType]'],
):
    """
    Handy alias for types with ``.bind``, ``.map``, and ``.apply`` methods.

    Should be a base class for almost any containers you write.

    See also:
        - https://bit.ly/2CTEVov

    """

    _laws: ClassVar[Sequence[Law]] = (
        Law3(_LawSpec.left_identity_law),
        Law1(_LawSpec.right_identity_law),
        Law3(_LawSpec.associative_law),
    )
Example #6
0
class ApplicativeN(
    Generic[_FirstType, _SecondType, _ThirdType],
    Lawful['ApplicativeN'],
):
    """
    Allows to create unit containers from raw values and to apply wrapped funcs.

    See also:
        https://en.wikipedia.org/wiki/Applicative_functor
        http://learnyouahaskell.com/functors-applicative-functors-and-monoids

    """

    _laws: ClassVar[Sequence[Law]] = (
        Law1(_LawSpec.identity),
        Law3(_LawSpec.interchange),
        Law3(_LawSpec.homomorphism),
        Law3(_LawSpec.composition),
    )

    @abstractmethod
    def apply(
        self: _ApplicativeType,
        container: KindN[
            _ApplicativeType,
            Callable[[_FirstType], _UpdatedType],
            _SecondType,
            _ThirdType,
        ],
    ) -> KindN[_ApplicativeType, _UpdatedType, _SecondType, _ThirdType]:
        """Allows to apply a wrapped function over a container."""

    @classmethod
    @abstractmethod
    def from_value(
        cls: Type[_ApplicativeType],  # noqa: N805
        inner_value: _UpdatedType,
    ) -> KindN[_ApplicativeType, _UpdatedType, _SecondType, _ThirdType]:
        """Unit method to create new containers from any raw value."""
Example #7
0
class BiMappableN(
        mappable.MappableN[_FirstType, _SecondType, _ThirdType],
        altable.AltableN[_FirstType, _SecondType, _ThirdType],
        Lawful['BiMappableN[_FirstType, _SecondType, _ThirdType]'],
):
    """
    Allows to change both types of a container at the same time.

    Uses ``.map`` to change first type and ``.alt`` to change second type.

    See also:
        - https://typelevel.org/cats/typeclasses/bifunctor.html

    """

    _laws: ClassVar[Sequence[Law]] = (Law1(_LawSpec.double_swap_law), )

    @abstractmethod
    def swap(
        self: _BiMappableType,
    ) -> KindN[_BiMappableType, _SecondType, _FirstType, _ThirdType]:
        """Swaps first and second types in ``BiMappableN``."""