Вам не нужно изменяемое состояние для вашего примера. Для «добавить закладку» можно создать новый список закладок, который имеет то же содержимое, что и старый список, но с одной новой записью. Так работает большинство неизменных программ; вместо того, чтобы вносить изменения в существующий граф объектов, вы просто создаете новый граф объектов, который отражает новое состояние мира. Когда все является неизменным, легко разделить большие части графа объектов между «старой» и «новой» версиями.
На один уровень глубже в вашем примере, предположим, что «браузер» - это объект структуры данных со следующей информацией: текущая веб-страница, домашняя страница пользователя и список закладок. Это может быть представлено в памяти как дерево, которое выглядит примерно так:
browser = {
curPage --> "http://current"
homePage --> "http://home"
favorites --> { data --> "http://firstFav"
next --> { data --> "http://secondFav"
next --> null } }
}
Теперь функция AddFavorite будет принимать в качестве входных данных такую структуру данных и возвращать новую структуру данных, такую как
browser = *{
curPage --> "http://current"
homePage --> "http://home"
favorites --> *{ data --> *"http://newFav"*
next --> { data --> "http://firstFav"
next --> { data --> "http://secondFav"
next --> null } } }*
}*
Биты, отмеченные '*', являются новыми объектами - в начале избранного находится новый узел связанного списка, содержащий новую строку, а сама структура браузера является новой (так должно быть, поскольку у нее есть новые 'избранное 'указатель).
Вы можете смоделировать все вычисления с сохранением состояния подобным образом, как функции, которые принимают в «предыдущем мире» входные данные и возвращают «следующий мир» в качестве выходных данных; в этом суть государственных монад в таком языке, как Хаскелл.