curry makes it easy to curry functions. If you enable the MyPy plugin, MyPy can also
type check the arguments and return types of curried functions.
The functions returned by
curry support both normal and curried call styles:
from pfun.functions import curry @curry def f(a: int, b: int) -> int: return a + b assert f(2, 2) == 4 assert f(2)(2) == 4
Behind the scenes,
curry simply uses
functools.partial to partially
apply arguments until all required arguments are provided. This means
that when using optional and variadic arguments, there are many different
ways to call a curried function:
@curry def f(a, b='b', c='c'): ... assert f('a', c='c', b='b') == f(b='b')(a='a') == f(c='c')(a='a')(b='b') == ...
To keep things simple, the actual signature of curried functions is simply the original function signature, which allows you to pass curried functions as arguments to functions that expects callbacks:
from typing import Callable from pfun import curry @curry def f(a: int, b: int) -> int: ... def h(g: Callable[[int], int]) - int: ... h(f(1)) # type safe
Because the signature of curried functions is not actually curried, this call will currently issue a false type error:
@curry def f(a: int, b: int) -> int: ... def h(g: Callable[[int], Callable[[int], int]]) -> int: ... h(f) # false type error
If you need to take curried functions as callback arguments, this is a type-safe alternative
from pfun.functions import Curry, curry @curry def f(a: int, b: int) -> int: ... def h(g: Curry[Callable[[int, int], int]]) -> int: ... h(f) # type safe
curry MyPy plugin doesn't support methods. If you want to return a curried function from a method you can use the following workaround:
from pfun.functions import Curry, curry class C: def f(self, x: int) -> Curry[[Callable[[int], int]]]: return curry(lambda y: x + y)
compose makes it easy to compose functions while inferring the resulting type signature with MyPy (if the
pfun MyPy plugin is enabled).
compose composes functions right to left:
from pfun.functions import compose def f(x): ... def g(x): ... h = compose(f, g) # h == lambda x: f(g(x))