similar to depth_profile but reports types

    Args:
        sequence (?):
        compress_homogenous (bool): (default = True)

    Returns:
        str: level_type_str

    CommandLine:
        python -m utool.util_list --test-list_type_profile
        python3 -m utool.util_list --test-list_type_profile

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_list import *  # NOQA
        >>> import numpy as np
        >>> sequence = [[1, 2], np.array([1, 2, 3], dtype=np.int32), (np.array([1, 2, 3], dtype=np.int32),)]
        >>> compress_homogenous = True
        >>> level_type_str = list_type_profile(sequence, compress_homogenous)
        >>> result = ('level_type_str = %s' % (str(level_type_str),))
        >>> print(result)
        level_type_str = list(list(int*2), ndarray[int32], tuple(ndarray[int32]*1))

def list_type_profile(sequence, compress_homogenous=True, with_dtype=True):
    """
    similar to depth_profile but reports types

    Args:
        sequence (?):
        compress_homogenous (bool): (default = True)

    Returns:
        str: level_type_str

    CommandLine:
        python -m utool.util_list --test-list_type_profile
        python3 -m utool.util_list --test-list_type_profile

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_list import *  # NOQA
        >>> import numpy as np
        >>> sequence = [[1, 2], np.array([1, 2, 3], dtype=np.int32), (np.array([1, 2, 3], dtype=np.int32),)]
        >>> compress_homogenous = True
        >>> level_type_str = list_type_profile(sequence, compress_homogenous)
        >>> result = ('level_type_str = %s' % (str(level_type_str),))
        >>> print(result)
        level_type_str = list(list(int*2), ndarray[int32], tuple(ndarray[int32]*1))
    """
    # For a pure bottom level list return the length
    #if not any(map(util_type.is_listlike, sequence)) or (isinstance(sequence, np.ndarray) and sequence.dtype != object):
    if not util_type.is_listlike(sequence) or (isinstance(sequence, np.ndarray) and sequence.dtype != object):
        typename = str(type(sequence)).replace('<type \'', '').replace('\'>', '')
        if six.PY3:
            typename = str(type(sequence)).replace('<class \'', '').replace('\'>', '')
        if with_dtype and typename == 'numpy.ndarray':
            typename = typename.replace('numpy.', '')
            typename += '[%s]' % (sequence.dtype,)

        level_type_str = typename
        return level_type_str
    if len(sequence) == 0:
        return ''

    level_type_list = []
    for item in sequence:
        #if util_type.is_listlike(item):
        item_type_profile = list_type_profile(item, with_dtype=with_dtype)
        level_type_list.append(item_type_profile)

    if compress_homogenous:
        # removes redudant information by returning a type and number
        if allsame(level_type_list):
            type_ = level_type_list[0]
            level_type_str = str(type_) + '*' + str(len(level_type_list))
        else:
            level_type_str = ', '.join(level_type_list)
    typename = str(type(sequence)).replace('<type \'', '').replace('\'>', '')
    if six.PY3:
        typename = str(type(sequence)).replace('<class \'', '').replace('\'>', '')
    level_type_str = typename + '(' + str(level_type_str) + ')'
    return level_type_str