Overload a given callable object to be used with ``|`` operator
    overloading.

    This is especially used for composing a pipeline of
    transformation over a single data set.

    Arguments:
        fn (function): target function to decorate.

    Raises:
        TypeError: if function or coroutine function is not provided.

    Returns:
        function: decorated function

def overload(fn):
    """
    Overload a given callable object to be used with ``|`` operator
    overloading.

    This is especially used for composing a pipeline of
    transformation over a single data set.

    Arguments:
        fn (function): target function to decorate.

    Raises:
        TypeError: if function or coroutine function is not provided.

    Returns:
        function: decorated function
    """
    if not isfunction(fn):
        raise TypeError('paco: fn must be a callable object')

    spec = getargspec(fn)
    args = spec.args
    if not spec.varargs and (len(args) < 2 or args[1] != 'iterable'):
        raise ValueError('paco: invalid function signature or arity')

    @functools.wraps(fn)
    def decorator(*args, **kw):
        # Check function arity
        if len(args) < 2:
            return PipeOverloader(fn, args, kw)
        # Otherwise, behave like a normal wrapper
        return fn(*args, **kw)

    return decorator