>>> from Redy.ADT.Core import match, data, P
    >>> from Redy.ADT.traits import ConsInd, Discrete
    >>> @data
    >>> class List(ConsInd, Discrete):
    >>>     # ConsInd(index following constructing)
    >>>     #    |-> Ind;
    >>>     # Discrete
    >>>     #    |-> Im(Immutable), Eq
    >>>     Nil : ...
    >>>     Cons: lambda head, tail: ...
    >>> lst = List.Cons(2, List.Cons(1, List.Nil))
    >>> mode_lst = P[List.Cons, P, P[List.Cons, 1]]
    >>> if match(mode_lst,  lst):
    >>>     assert mode_lst == [List.Cons, 2, [List.Cons, 1]]

def match(mode_lst: list, obj: 'object that has __destruct__ method'):
    """
    >>> from Redy.ADT.Core import match, data, P
    >>> from Redy.ADT.traits import ConsInd, Discrete
    >>> @data
    >>> class List(ConsInd, Discrete):
    >>>     # ConsInd(index following constructing)
    >>>     #    |-> Ind;
    >>>     # Discrete
    >>>     #    |-> Im(Immutable), Eq
    >>>     Nil : ...
    >>>     Cons: lambda head, tail: ...
    >>> lst = List.Cons(2, List.Cons(1, List.Nil))
    >>> mode_lst = P[List.Cons, P, P[List.Cons, 1]]
    >>> if match(mode_lst,  lst):
    >>>     assert mode_lst == [List.Cons, 2, [List.Cons, 1]]
    """
    # noinspection PyUnresolvedReferences
    try:
        # noinspection PyUnresolvedReferences
        structure = obj.__destruct__()
    except AttributeError:
        return False
    n = len(mode_lst)
    if n > len(structure):
        return False

    for i in range(n):
        mode = mode_lst[i]
        # noinspection PyUnresolvedReferences
        elem = obj[i]
        if isinstance(mode, PatternList):
            if not match(mode, elem):
                return False
        elif mode is P:
            # noinspection PyUnresolvedReferences
            mode_lst[i] = elem
        elif mode is any:
            pass
        elif mode != elem:
            return False

    return True