Как я могу написать приложение, которое не меняет состояние (на функциональном языке)? - PullRequest
6 голосов
/ 25 января 2009

Я хочу научиться функциональному программированию однажды, но я не понимаю, как я мог бы использовать его для чего-либо, кроме простой математики.

Например: простая функция добавления закладок в веб-браузер должна вызывать какие-то мутации, чтобы в следующий раз, когда пользователь нажимал на закладки, новая закладка находилась в списке.

Ответы [ 6 ]

4 голосов
/ 25 января 2009

Вам не нужно изменяемое состояние для вашего примера. Для «добавить закладку» можно создать новый список закладок, который имеет то же содержимое, что и старый список, но с одной новой записью. Так работает большинство неизменных программ; вместо того, чтобы вносить изменения в существующий граф объектов, вы просто создаете новый граф объектов, который отражает новое состояние мира. Когда все является неизменным, легко разделить большие части графа объектов между «старой» и «новой» версиями.

На один уровень глубже в вашем примере, предположим, что «браузер» - это объект структуры данных со следующей информацией: текущая веб-страница, домашняя страница пользователя и список закладок. Это может быть представлено в памяти как дерево, которое выглядит примерно так:

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 } } }*
}*

Биты, отмеченные '*', являются новыми объектами - в начале избранного находится новый узел связанного списка, содержащий новую строку, а сама структура браузера является новой (так должно быть, поскольку у нее есть новые 'избранное 'указатель).

Вы можете смоделировать все вычисления с сохранением состояния подобным образом, как функции, которые принимают в «предыдущем мире» входные данные и возвращают «следующий мир» в качестве выходных данных; в этом суть государственных монад в таком языке, как Хаскелл.

4 голосов
/ 25 января 2009

Полезному приложению в целом часто приходится менять состояние нескольких вещей, но это не значит, что все или ваши функции должны изменить состояние, чтобы быть полезным.

Монады в функциональном программировании должны выражать операции ввода / вывода (I / O) и изменения состояния без использования языковых функций, которые вызывают побочные эффекты.

Я думаю, что вы думаете только с точки зрения объектно-ориентированного. То, что функция всегда дает один и тот же вывод при одном и том же вводе, не означает, что она не может принимать разные типы ввода (возможно, бесконечные возможности ввода) и производить разные типы вывода.

При функциональном программировании вы имеете дело с неизменяемыми объектами вместо изменяемых. Если вы получаете ввод объекта, вы можете создать новый измененный объект и вернуть его.

Взгляните на эту статью о MapReduce Джоэля о программном обеспечении . Он содержит довольно хороший пример того, почему функция, которая не изменяет состояние, может быть полностью полезной.

3 голосов
/ 25 января 2009

Даже на чисто функциональных языках, таких как Haskell, вам придется манипулировать состоянием. Это делается через монады.

2 голосов
/ 27 января 2009

Многие другие ответы заставят вас спешить использовать монады или некоторые другие экзотические приемы для программирования с использованием изменяемого состояния. Хотя я слышал своими ушами, что редактор отчета Haskell 98 называет Haskell «самым лучшим императивным языком в мире», вам не нужно почти столько изменчивого состояния, сколько предлагают другие ответы. В функциональной программе вы сохраняете свое состояние в параметрах функции .

Например, я только что закончил писать программу на Haskell, которая решает, как сделать резервную копию моей музыки на DVD, чтобы песни с одного и того же альбома записывались на один и тот же DVD, и каждый DVD (кроме последнего) имел по крайней мере 99,9 % полный. Список DVD-дисков и список альбомов, на которые DVD постоянно меняются, но никаких ссылок, монад или других экзотических функций не происходит. Эти значения являются просто параметрами рекурсивной функции.

Чтобы увидеть больше примеров и объяснений, прочитайте очень хороший учебник Джона Хьюза Почему функциональное программирование имеет значение .

2 голосов
/ 25 января 2009

Хороший пример того, как вы справляетесь с «изменчивостью». Предположим, вы реализуете некоторую структуру данных, скажем, дерево AVL, на функциональном языке. В функциях, которые вы реализуете (вставка, удаление и т. Д.), А также во внутренних функциях (поворот и т. Д.), Вы фактически не мутируете данные, а возвращаете мутировали данные.

Базовая система времени выполнения гарантирует, что ваша программа будет эффективно использовать память (например, она выполняет копирование при записи и сборку мусора).

В некоторых частях программы, когда вы действительно меняете мировое состояние (I / O, GUI), существует два подхода.

  • чисто функциональные языки, такие как Haskell, инкапсулируют такие операции в монады (предупреждение: ваша голова может взорваться, читая о них, но не слишком переживайте)
  • другие функциональные языки, такие как OCaml, разрешают изменчивость и побочные эффекты в ваших программах.
0 голосов
/ 27 января 2009

Кроме того, на практике многие приложения, написанные на функциональных языках программирования, фактически используют побочные функции, такие как (set!), Для фактического изменения состояния. Это не теоретически чисто, но, безусловно, выполняет свою работу.

(В частности, я имею в виду популярный потребительский софт, который был написан на основе производной от LISP, но должен был работать в постоянной памяти, поэтому такие вещи, как сборка мусора, должны были выходить в окно.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...