public ConsPStack<E> with(int index, E element) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException();

        if (index == 0)
            return objectEquals(first, element) ? this : new ConsPStack<E>(element, rest);

        ConsPStack<E> newRest = rest.with(index - 1, element);
        return newRest == rest ? this : new ConsPStack<E>(first, newRest);
    }