Функциональное реактивное программирование - Functional reactive programming

Функциональное реактивное программирование ( FRP ) - это парадигма программирования для реактивного программирования ( асинхронное программирование потока данных ) с использованием строительных блоков функционального программирования (например, отображение , сокращение , фильтр ). FRP использовался для программирования графических пользовательских интерфейсов (GUI), робототехники , игр и музыки, чтобы упростить эти проблемы путем явного моделирования времени.

Составы FRP

Исходную формулировку функционального реактивного программирования можно найти в статье ICFP 97 «Функциональная реактивная анимация» Конала Эллиотта и Пола Худака .

С момента своего появления в 1997 году FRP принял множество форм. Одна ось разнообразия - дискретная и непрерывная семантика. Другая ось - это то, как системы FRP могут быть изменены динамически.

Непрерывный

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

  • Значения моделирования, которые изменяются с течением времени, называются «поведением», а затем «сигналами».
  • Моделирование « событий », которые происходят в дискретные моменты времени.
  • Система может быть изменена в ответ на события, обычно называемые «переключением».
  • Отделение деталей оценки, таких как частота дискретизации, от реактивной модели.

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

Дискретный

Формулировки, такие как Event-Driven FRP и версии Elm до 0.17, требуют, чтобы обновления были дискретными и управляемыми событиями. Эти формулировки подтолкнули к практическому использованию FRP с упором на семантику, которая имеет простой API, который может быть эффективно реализован в таких настройках, как робототехника или в веб-браузере.

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

Интерактивный FRP

Было указано, что обычная модель FRP, от входов до выходов, плохо подходит для интерактивных программ. Отсутствие возможности «запускать» программы в сопоставлении от входов к выходам может означать, что необходимо использовать одно из следующих решений:

  • Создайте структуру данных действий, которые появляются как выходы. Действия должны выполняться внешним интерпретатором или средой. Это наследует все трудности исходной системы потокового ввода-вывода Haskell.
  • Используйте Arrowized FRP и вставьте стрелки, которые способны выполнять действия. Действия также могут иметь идентификаторы, что позволяет им, например, поддерживать отдельные изменяемые хранилища. Это подход, используемый библиотекой Fudgets и, в более общем смысле, Monadic Stream Functions.
  • Новый подход состоит в том, чтобы разрешить выполнение действий сейчас (в монаде ввода-вывода), но отложить получение их результатов на более позднее время. Это использует взаимодействие между монадами Event и IO и совместимо с FRP, более ориентированным на выражения:
planNow :: Event (IO a) -> IO (Event a)

Проблемы реализации

Существует два типа систем FRP: push-based и pull-based. Системы на основе push-уведомлений принимают события и проталкивают их через сигнальную сеть для достижения результата. Системы на основе вытягивания ждут, пока не потребуется результат, и работают в обратном направлении по сети, чтобы получить требуемое значение.

Некоторые системы FRP, такие как Yampa, используют выборку, при которой образцы извлекаются сигнальной сетью. У этого подхода есть недостаток: сеть должна ждать до продолжительности одного шага вычислений, чтобы узнать об изменениях на входе. Выборка является примером FRP на основе извлечения.

Библиотеки Reactive и Etage на Hackage представили подход, называемый push-pull FRP. В этом подходе, это событие создается только тогда, когда требуется следующее событие в чисто определенном потоке (таком как список фиксированных событий с указанием времени). Эти чисто определенные потоки действуют как ленивые списки в Haskell. Это половина, основанная на притяжении. Половина на основе push используется, когда вводятся внешние по отношению к системе события. Внешние события отправляются потребителям, чтобы они могли узнать о событии в тот момент, когда оно было выпущено.

Реализации

  • Yampa - это эффективная реализация на чистом Haskell с стрелками, с поддержкой SDL, SDL2, OpenGL и HTML DOM.
  • Язык программирования Elm, который использовался для поддержки FRP, но с тех пор заменил его другим шаблоном
  • reflex - это эффективная реализация push / pull FRP в Haskell с хостами для браузера / DOM , SDL и Gloss.
  • reactive-banana - это реализация FRP, не зависящая от цели, в Haskell.
  • netwire и переменные отмечены стрелками, вытягивайте реализации FRP в Haskell.
  • Flapjax - это реализация FRP поведения / события в JavaScript .
  • React - это модуль OCaml для функционального реактивного программирования.
  • Sodium - это реализация push FRP, независимая от конкретной инфраструктуры пользовательского интерфейса для нескольких языков программирования, таких как Java, TypeScript и C #.
  • ReactiveX , популярный благодаря реализации rxjs в JavaScript , представляет собой комплексную кроссплатформенную парадигму для реализации функционального реактивного программирования, обрабатывая данные как потоки наблюдаемых.
  • Dunai - это быстрая реализация на Haskell с использованием монадических потоковых функций, которая поддерживает классический FRP и FRP со стрелками.
  • ObservableComputations , кроссплатформенная реализация .NET.
  • Stella - это язык реактивного программирования, основанный на акторах, который демонстрирует модель «акторов» и «реакторов», цель которой - избежать проблем, связанных с объединением императивного кода с реактивным кодом (путем разделения их на акторов и реакторов). Акторы подходят для использования в распределенных реактивных системах.

Смотрите также

Рекомендации

Внешние ссылки