93 lines
2.3 KiB
Python
93 lines
2.3 KiB
Python
from functools import reduce
|
|
|
|
from typing import Tuple, Callable, Any, TypeVar, overload # noqa
|
|
|
|
A = TypeVar("A")
|
|
B = TypeVar("B")
|
|
C = TypeVar("C")
|
|
D = TypeVar("D")
|
|
E = TypeVar("E")
|
|
F = TypeVar("F")
|
|
G = TypeVar("G")
|
|
|
|
|
|
@overload
|
|
def compose() -> Callable[[A], A]: # pylint: disable=function-redefined
|
|
... # pylint: disable=pointless-statement
|
|
|
|
|
|
@overload
|
|
def compose(op1: Callable[[A], B]) -> Callable[[A], B]: # pylint: disable=function-redefined
|
|
... # pylint: disable=pointless-statement
|
|
|
|
|
|
@overload
|
|
def compose(op2: Callable[[B], C], op1: Callable[[A], B]) -> Callable[[A], C]: # pylint: disable=function-redefined
|
|
... # pylint: disable=pointless-statement
|
|
|
|
|
|
@overload
|
|
def compose(
|
|
op3: Callable[[C], D], op2: Callable[[B], C], op1: Callable[[A], B] # pylint: disable=function-redefined
|
|
) -> Callable[[A], D]:
|
|
... # pylint: disable=pointless-statement
|
|
|
|
|
|
@overload
|
|
def compose(
|
|
op4: Callable[[D], E], # pylint: disable=function-redefined
|
|
op3: Callable[[C], D],
|
|
op2: Callable[[B], C],
|
|
op1: Callable[[A], B],
|
|
) -> Callable[[A], E]:
|
|
... # pylint: disable=pointless-statement
|
|
|
|
|
|
@overload
|
|
def compose(
|
|
op5: Callable[[E], F], # pylint: disable=function-redefined
|
|
op4: Callable[[D], E],
|
|
op3: Callable[[C], D],
|
|
op2: Callable[[B], C],
|
|
op1: Callable[[A], B],
|
|
) -> Callable[[A], F]:
|
|
... # pylint: disable=pointless-statement
|
|
|
|
|
|
@overload
|
|
def compose(
|
|
op1: Callable[[A], B], # pylint: disable=function-redefined,too-many-arguments
|
|
op2: Callable[[B], C],
|
|
op3: Callable[[C], D],
|
|
op4: Callable[[D], E],
|
|
op5: Callable[[E], F],
|
|
op6: Callable[[F], G],
|
|
) -> Callable[[A], G]:
|
|
... # pylint: disable=pointless-statement
|
|
|
|
|
|
def compose(*funcs: Callable) -> Callable: # type: ignore
|
|
"""Compose multiple functions right to left.
|
|
|
|
Composes zero or more functions into a functional composition. The
|
|
functions are composed right to left. A composition of zero
|
|
functions gives back the identity function.
|
|
|
|
compose()(x) == x
|
|
compose(f)(x) == f(x)
|
|
compose(g, f)(x) == g(f(x))
|
|
compose(h, g, f)(x) == h(g(f(x)))
|
|
...
|
|
|
|
Returns the composed function.
|
|
"""
|
|
|
|
def _compose(source: Any) -> Any:
|
|
return reduce(lambda acc, f: f(acc), funcs[::-1], source)
|
|
|
|
return _compose
|
|
|
|
|
|
fmap = lambda f, g: compose(f, g) # To force partial application
|
|
|
|
identity = compose() # type: Callable
|