Skip to content

Useful Functions

curry

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

Currently the 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

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))