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