Skip to content

Instantly share code, notes, and snippets.

@antonagestam
Last active February 12, 2021 13:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antonagestam/3df91dfad94ecfaa49f753c9c5450126 to your computer and use it in GitHub Desktop.
Save antonagestam/3df91dfad94ecfaa49f753c9c5450126 to your computer and use it in GitHub Desktop.
Functional composition with cute syntax + typing support.
from __future__ import annotations
from typing import TypeVar, Generic, Callable
Arg = TypeVar("Arg")
Ret = TypeVar("Ret")
NewRet = TypeVar("NewRet")
class Composable(Generic[Arg, Ret]):
def __init__(self, fn: Callable[[Arg], Ret]) -> None:
self.fn = fn
self.__name__ = fn.__name__
def __or__(self, other: Composable[Ret, NewRet]) -> Composable[Arg, NewRet]:
def composed(x: Arg) -> NewRet:
return other(self(x))
composed.__name__ = f"({self} | {other})"
return Composable(composed)
def __call__(self, arg: Arg) -> Ret:
return self.fn(arg)
def __str__(self) -> str:
return self.__name__
def __repr__(self) -> str:
return f"<Composable {self.__name__}>"
@Composable
def add3(n: int) -> int:
return n + 3
@Composable
def add5(n: int) -> int:
return n + 5
@Composable
def mult2(n: int) -> int:
return n * 2
fn = add5 | mult2 | add3 | Composable(str) | Composable(int) | add5 | add3 | mult2
print(f"{fn=}")
print(f"{fn(7)=}")
# pro-tip: try reveal_type(fn(1))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment