def types_unify(a, b):
    try:
        a = a.get_repr()
        b = b.get_repr()
        if isinstance(a, TypeVar):
            a.union(b)
        elif isinstance(b, TypeVar):
            b.union(a)
        elif (isinstance(a, TypeConstant) and isinstance(b, TypeConstant)):
            if (a != b):
                raise UnifiactionError('Different basic types')
        elif (isinstance(a, TypeTuple) and isinstance(b, TypeTuple)):
            if (len(a.args) != len(b.args)):
                raise UnifiactionError('Tuples size mismatch')
            for (a, b) in zip(a.args, b.args):
                types_unify(a, b)
        elif (isinstance(a, TypeArrow) and isinstance(b, TypeArrow)):
            types_unify(a.left, b.left)
            types_unify(a.right, b.right)
        else:
            raise UnifiactionError('Different kinds')
    except UnifiactionError as e:
        e.add(a, b)
        raise
def types_unify(a, b):
    try:
        a = a.get_repr()
        b = b.get_repr()
        if isinstance(a, TypeVar):
            a.union(b)
        elif isinstance(b, TypeVar):
            b.union(a)
        elif (isinstance(a, TypeConstant) and isinstance(b, TypeConstant)):
            if (a != b):
                raise UnifiactionError('Different basic types')
        elif (isinstance(a, TypeTuple) and isinstance(b, TypeTuple)):
            if (len(a.args) != len(b.args)):
                raise UnifiactionError('Tuples size mismatch')
            for (a, b) in zip(a.args, b.args):
                types_unify(a, b)
        elif (isinstance(a, TypeArrow) and isinstance(b, TypeArrow)):
            types_unify(a.left, b.left)
            types_unify(a.right, b.right)
        else:
            raise UnifiactionError('Different kinds')
    except UnifiactionError as e:
        e.add(a, b)
        raise