from collections.abc import Callable, Iterable
from typing import TypeVar, cast, overload

T = TypeVar('T')


@overload
def any_pass(data: T, fns: Iterable[Callable[[T], bool]], /) -> bool: ...


@overload
def any_pass(fns: Iterable[Callable[[T], bool]], /) -> Callable[[T], bool]: ...


def any_pass(
    data: T | Iterable[Callable[[T], bool]],
    predicates: Iterable[Callable[[T], bool]] | None = None,
    /,
) -> bool | Callable[[T], bool]:
    """
    Determines whether any predicate is true for the input data.

    Parameters
    ----------
    data : T
        Input data (positional-only).
    predicates : Iterable[Callable[[T], bool]]
        Predicates to check data against(positional-only).

    Returns
    -------
    bool
        Whether any predicate is true for the input data.

    Examples
    --------
    Data first:
    >>> R.any_pass(9, [R.is_divisible_by(3), R.is_divisible_by(2)])
    True
    >>> R.any_pass(11, [R.is_divisible_by(3), R.is_divisible_by(5)])
    False

    Data last:
    >>> R.any_pass([R.is_divisible_by(3), R.is_divisible_by(2)])(2)
    True
    >>> R.any_pass([R.is_divisible_by(3), R.is_divisible_by(2)])(7)
    False

    """
    if predicates is None:
        data = cast(Iterable[Callable[[T], bool]], data)
        return lambda value: any_pass(value, data)
    data = cast(T, data)
    for fn in predicates:
        if fn(data):
            return True
    return False
