>>> from Redy.Collections import Traversal, Flow
    >>> lst: Iterable[int] = [0, 1, 2, 3, 4, 5, 6]
    >>> x = Flow(lst)[Traversal.chunk_by(lambda x: x // 3)]
    >>> assert list(x.unbox) == [[0, 1, 2], [3, 4, 5], [6]]
    >>> x = Flow([])[Traversal.chunk_by(lambda x: x)]
    >>> assert list(x.unbox) == []

def chunk_by(fn: Callable[[T], object]):
    """
    >>> from Redy.Collections import Traversal, Flow
    >>> lst: Iterable[int] = [0, 1, 2, 3, 4, 5, 6]
    >>> x = Flow(lst)[Traversal.chunk_by(lambda x: x // 3)]
    >>> assert list(x.unbox) == [[0, 1, 2], [3, 4, 5], [6]]
    >>> x = Flow([])[Traversal.chunk_by(lambda x: x)]
    >>> assert list(x.unbox) == []
    """

    def inner(seq: ActualIterable[T]) -> ActualIterable[ActualIterable[T]]:
        seq = iter(seq)
        try:
            head = next(seq)
        except StopIteration:
            return iter(seq)

        current_status = fn(head)
        group = [head]
        for each in seq:
            status = fn(each)
            if status != current_status:
                yield group
                group = [each]
            else:
                group.append(each)
            current_status = status
        if group:
            yield group

    return inner