Created
November 30, 2023 21:32
-
-
Save qexat/0f23a14a3ad61572dd6cfa7c82ad104d to your computer and use it in GitHub Desktop.
whatever this is
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from __future__ import annotations | |
| import abc | |
| import collections.abc | |
| import dataclasses | |
| import functools | |
| import typing | |
| T = typing.TypeVar("T") | |
| U = typing.TypeVar("U") | |
| V = typing.TypeVar("V") | |
| W = typing.TypeVar("W") | |
| T_co = typing.TypeVar("T_co", covariant=True) | |
| T_contra = typing.TypeVar("T_contra", contravariant=True) | |
| U_co = typing.TypeVar("U_co", covariant=True) | |
| U_contra = typing.TypeVar("U_contra", contravariant=True) | |
| Ts = typing.TypeVarTuple("Ts") | |
| P = typing.ParamSpec("P") | |
| def compose( | |
| func1: collections.abc.Callable[P, U], | |
| func2: collections.abc.Callable[[U], V], | |
| ) -> collections.abc.Callable[P, V]: | |
| """ | |
| Compose two functions together into one. | |
| """ | |
| def inner(*args: P.args, **kwargs: P.kwargs) -> V: | |
| return func2(func1(*args, **kwargs)) | |
| return inner | |
| @typing.final | |
| @dataclasses.dataclass(slots=True, frozen=True) | |
| class Composable(typing.Generic[P, U]): | |
| """ | |
| Make a function composable with another. | |
| Implements the sugar `>>` operator to bind two functions together. | |
| >>> @Composable | |
| >>> def foo(x: str) -> float: | |
| ... # do stuff | |
| >>> @Composable | |
| >>> def bar(x: float) -> int: | |
| ... # do stuff | |
| >>> foobar = foo >> bar | |
| >>> baz: int = foobar("hello") | |
| """ | |
| func: collections.abc.Callable[P, U] | |
| def __rshift__(self, other: collections.abc.Callable[[U], V]) -> Composable[P, V]: | |
| return Composable(compose(self.func, other)) | |
| # We make sure it is still callable as is | |
| def __call__(self, *args: P.args, **kwargs: P.kwargs) -> U: | |
| return self.func(*args, **kwargs) | |
| @Composable | |
| def partmap( | |
| func: collections.abc.Callable[[T], U], | |
| ) -> Composable[[collections.abc.Iterable[T]], collections.abc.Iterable[U]]: | |
| """ | |
| Create a partial application of the mapped version of `func`. | |
| >>> ords = partmap(ord) | |
| >>> ords("hello") | |
| [104, 101, 108, 108, 111] | |
| """ | |
| @Composable | |
| @functools.wraps(func) | |
| def mapped_func( | |
| iterable: collections.abc.Iterable[T] | |
| ) -> collections.abc.Iterable[U]: | |
| return map(func, iterable) | |
| return mapped_func | |
| @Composable | |
| def withboth( | |
| func: collections.abc.Callable[[*tuple[T, ...]], U], | |
| first_values: collections.abc.Iterable[T], | |
| second_values: collections.abc.Iterable[T], | |
| ) -> tuple[U, U]: | |
| """ | |
| Call `func` on the two sets of values. | |
| """ | |
| return (func(*first_values), func(*second_values)) | |
| @Composable | |
| def withall( | |
| func: collections.abc.Callable[[*tuple[T, ...]], U], | |
| *value_sets: collections.abc.Iterable[T], | |
| ) -> tuple[U, ...]: | |
| """ | |
| Call `func` on all the sets of values. | |
| """ | |
| return tuple(func(*value_set) for value_set in value_sets) | |
| @Composable | |
| def fork( | |
| func1: collections.abc.Callable[[*tuple[T, ...]], U], | |
| func2: collections.abc.Callable[[*tuple[T, ...]], V], | |
| values: collections.abc.Iterable[T], | |
| ) -> tuple[U, V]: | |
| """ | |
| Call two different functions on the same set of values. | |
| """ | |
| return func1(*values), func2(*values) | |
| @Composable | |
| def bracket( | |
| func1: collections.abc.Callable[[*tuple[T, ...]], U], | |
| func2: collections.abc.Callable[[*tuple[V, ...]], W], | |
| first_values: collections.abc.Iterable[T], | |
| second_values: collections.abc.Iterable[V], | |
| ) -> tuple[U, W]: | |
| """ | |
| Call two functions on two distinct sets of values. | |
| """ | |
| return func1(*first_values), func2(*second_values) | |
| @Composable | |
| def packcall(func: collections.abc.Callable[[*Ts], T], args: tuple[*Ts]) -> T: | |
| """ | |
| Call `func` with unpacked `args`. | |
| >>> # equivalent to max(-5, 12, 8) | |
| >>> packcall(max, (-5, 12, 8)) | |
| 12 | |
| """ | |
| return func(*args) | |
| @typing.runtime_checkable | |
| class SupportsAdd(typing.Protocol[T_contra, T_co]): | |
| """ | |
| Trait of implementing the operator `+`. | |
| """ | |
| @abc.abstractmethod | |
| def __add__(self, other: T_contra, /) -> T_co: | |
| pass | |
| @typing.overload | |
| def add() -> ( | |
| collections.abc.Callable[ | |
| [SupportsAdd[typing.Any, T_co]], | |
| collections.abc.Callable[[SupportsAdd[typing.Any, U_co]], T_co | U_co], | |
| ] | |
| ): | |
| pass | |
| @typing.overload | |
| def add( | |
| left: SupportsAdd[typing.Any, T_co], / | |
| ) -> collections.abc.Callable[[SupportsAdd[typing.Any, U_co]], T_co | U_co]: | |
| pass | |
| @typing.overload | |
| def add( | |
| left: SupportsAdd[typing.Any, T_co], | |
| right: SupportsAdd[typing.Any, U_co], | |
| /, | |
| ) -> T_co | U_co: | |
| pass | |
| def add( | |
| left: SupportsAdd[T_contra, T_co] | None = None, | |
| right: SupportsAdd[U_contra, U_co] | None = None, | |
| /, | |
| ) -> ( | |
| T_co | |
| | U_co | |
| | collections.abc.Callable[[SupportsAdd[U_contra, U_co]], T_co | U_co] | |
| | collections.abc.Callable[ | |
| [SupportsAdd[T_contra, T_co]], | |
| collections.abc.Callable[[SupportsAdd[U_contra, U_co]], T_co | U_co], | |
| ] | |
| ): | |
| """ | |
| Add two values together now. Or later. Supports automatically partial | |
| application. | |
| """ | |
| @functools.wraps(add) | |
| def inner( | |
| left: SupportsAdd[T_contra, T_co] | |
| ) -> collections.abc.Callable[[SupportsAdd[U_contra, U_co]], T_co | U_co]: | |
| @functools.wraps(add) | |
| def inner_inner(right: SupportsAdd[U_contra, U_co]) -> T_co | U_co: | |
| return add(left, right) | |
| return inner_inner | |
| if right is None: | |
| if left is None: | |
| return inner | |
| return inner(left) | |
| if left is None: | |
| raise ValueError("left cannot be None if right is not None") | |
| return left + right # type: ignore | |
| print((partmap(ord) >> partmap(hex) >> " ".join)("Hello World!")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment