Functools Module

Functional programming utilities.

This module provides utility functions for functional programming patterns, including function composition, folding, currying, and more.

The F class serves as a namespace for these utilities, providing static methods that can be used throughout your functional code.

F Class

class katharos.functools.F[source]

Bases: object

Namespace for utility functions.

All functions are static and can be called without instantiating the class.

static compose(f)[source]

Compose two functions.

Parameters:

f (Callable[[TypeVar(B)], TypeVar(C)]) – A function from B to C.

Return type:

Callable[[Callable[[TypeVar(A)], TypeVar(B)]], Callable[[TypeVar(A)], TypeVar(C)]]

Returns:

A function that takes a function from A to B and returns a function from A to C.

Examples

>>> inc = lambda x: x + 1
>>> double = lambda x: x * 2
>>> inc_then_double = F.compose(double)(inc)
>>> inc_then_double(5)
12
static id(x)[source]

Identity function.

Parameters:

x (TypeVar(A)) – Input value.

Return type:

TypeVar(A)

Returns:

The same value x.

Examples

>>> F.id(42)
42
>>> F.id("hello")
'hello'
static foldr(f, acc, xs)[source]

Right fold a function over an iterable.

Parameters:
Return type:

TypeVar(B)

Returns:

The accumulator value after applying f to each element of xs.

Examples

>>> F.foldr(lambda x, acc: acc + [x], [], [1, 2, 3])
[3, 2, 1]
>>> F.foldr(lambda x, acc: f"({x}+{acc})", "0", [1, 2, 3])
'(1+(2+(3+0)))'
static foldl(f, acc, xs)[source]

Left fold a function over an iterable.

Parameters:
Return type:

TypeVar(B)

Returns:

The accumulator value after applying f to each element of xs.

Examples

>>> F.foldl(lambda acc, x: acc + x, 0, [1, 2, 3])
6
>>> F.foldl(lambda acc, x: f"({acc}+{x})", "0", [1, 2, 3])
'(((0+1)+2)+3)'
static sigma(xs)[source]

Combine all elements of a non-empty list using the semigroup operation.

Parameters:

xs (NonEmptyList[TypeVar(A, bound= Semigroup)]) – A non-empty list of semigroup elements.

Return type:

TypeVar(A, bound= Semigroup)

Returns:

The result of combining all elements using the semigroup’s @ operator.

Examples

>>> from katharos.types.list import NonEmptyList
>>> from katharos.types.monoid import Sum
>>> F.sigma(NonEmptyList(Sum(1), [Sum(2), Sum(3)]))
Sum(6)
static curry(f)[source]
Overloads:
  • f (Callable[[A], R]) → Callable[[A], R]

  • f (Callable[[A, B], R]) → Callable[[A], Callable[[B], R]]

  • f (Callable[[A, B, C], R]) → Callable[[A], Callable[[B], Callable[[C], R]]]

  • f (Callable[…, Any]) → Callable[…, Any]

Transform a multi-argument function into a curried version.

Currying converts a function that takes multiple arguments into a sequence of functions, each taking a single argument. Supports both positional and keyword arguments, and several arguments may be supplied in one step.

The original function is invoked as soon as every parameter without a default is bound. Consequently, parameters with defaults (as well as *args/**kwargs) can only be overridden in the step that completes the call — not in a later step, because there is no later step.

Parameters:

f (Callable[..., Any]) – A function to curry.

Returns:

A curried version of the function.

Raises:

TypeError – If an argument does not match the function’s signature, or a keyword argument is supplied more than once.

Return type:

Callable[[…], Any]

Examples

>>> def add(x: int, y: int, z: int) -> int:
...     return x + y + z
>>> curried_add = F.curry(add)
>>> curried_add(1)(2)(3)
6
>>> add_one = curried_add(1)
>>> add_one(2)(3)
6
>>> curried_add(x=1)(y=2)(z=3)
6
>>> curried_add(1, y=2)(z=3)
6

Parameters with defaults need not be supplied; the call fires once all required parameters are bound:

>>> def greet(name: str, greeting: str = "hi") -> str:
...     return f"{greeting} {name}"
>>> F.curry(greet)("bob")
'hi bob'
>>> F.curry(greet)("bob", greeting="hello")
'hello bob'

Supplying the same keyword twice is an error, as in a plain call:

>>> curried_add(x=1)(x=2, y=2, z=3)
Traceback (most recent call last):
    ...
TypeError: f.add() got multiple values for keyword argument 'x'
static lift_a2(f, fa, fb)[source]

Lift a binary function into an applicative context.

Applies a two-argument function to the values held inside two applicatives of the same type, combining their contexts.

Parameters:
Return type:

Applicative[TypeVar(App, bound= Applicative), TypeVar(C)]

Returns:

An applicative containing the result of applying f to the two wrapped values.

Examples

>>> from katharos.types.maybe import Maybe
>>> F.lift_a2(lambda x, y: x + y, Maybe.Just(2), Maybe.Just(3))
Just(5)
>>> F.lift_a2(lambda x, y: x + y, Maybe.Just(2), Maybe.Nothing())
Nothing()
static lift_a3(f, fa, fb, fc)[source]

Lift a ternary function into an applicative context.

Applies a three-argument function to the values held inside three applicatives of the same type, combining their contexts.

Parameters:
Return type:

Applicative[TypeVar(App, bound= Applicative), TypeVar(D)]

Returns:

An applicative containing the result of applying f to the three wrapped values.

Examples

>>> from katharos.types.maybe import Maybe
>>> F.lift_a3(
...     lambda x, y, z: x + y + z,
...     Maybe.Just(1),
...     Maybe.Just(2),
...     Maybe.Just(3),
... )
Just(6)
>>> F.lift_a3(
...     lambda x, y, z: x + y + z,
...     Maybe.Just(1),
...     Maybe.Nothing(),
...     Maybe.Just(3),
... )
Nothing()