Каков статус текущих реализаций функционального реактивного программирования?

90

Я пытаюсь визуализировать некоторые простые автоматические физические системы (такие как маятник, манипуляторы и т. Д.) В Haskell. Часто эти системы можно описать уравнениями типа

df/dt = c*f(t) + u(t)

где u(t)представляет собой своего рода «интеллектуальное управление». Эти системы очень хорошо вписываются в парадигму функционального реактивного программирования.

Итак, я взял книгу Пола Худака «Школа выражения Haskell» и обнаружил, что представленный там предметно-ориентированный язык «FAL» (для языка функциональной анимации) действительно неплохо работает для моих простых игрушечных систем (хотя некоторые функции, в частности integrate, показалось ленивым для эффективного использования, но легко поправимо).

У меня вопрос: какая сегодня более зрелая, современная, хорошо обслуживаемая и настроенная на производительность альтернатива для более продвинутых или даже практических приложений?

На этой вики-странице перечислены несколько вариантов Haskell, но я не совсем понимаю следующие моменты:

  1. Статус "реактивного" проекта Конала Элиотта, который (насколько я понимаю) одним из изобретателей этой парадигмы программирования, выглядит несколько устаревшим. Мне нравится его код, но, может быть, мне стоит попробовать другие, более современные альтернативы? В чем основное различие между ними с точки зрения синтаксиса / производительности / стабильности во время выполнения?

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

  3. Об «утечках времени» тот же автор опроса рассказывает в своем блоге . Является ли проблема уникальной для FRP или с чем мы обычно сталкиваемся при программировании на чистом, нестрогом языке? Вы когда-нибудь находили слишком сложным стабилизировать систему на основе FRP с течением времени, если она недостаточно эффективна?

  4. Это все еще проект исследовательского уровня? Действительно ли их используют такие люди, как заводские инженеры, инженеры-робототехники, финансовые инженеры и т.д.

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

mnish
источник

Ответы:

82

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

  • Netwire фокусируется на эффективности, гибкости и предсказуемости. Он имеет свою собственную парадигму событий и может использоваться в областях, где традиционный FRP не работает, включая сетевые службы и сложные симуляции. Стиль: аппликативный и / или со стрелками. Первоначальный автор и сопровождающий: Ertugrul Söylemez (это я).

  • reactive-banana основывается на традиционной парадигме FRP. Хотя его практично использовать, он также служит основой для классических исследований FRP. Его основное внимание уделяется пользовательским интерфейсам, а для wx есть готовый интерфейс. Стиль: аппликативный. Первоначальный автор и сопровождающий: Генрих Апфельмус.

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

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

Для графических пользовательских интерфейсов в настоящее время лучшим выбором является реактивный банан. У него уже есть интерфейс wx (как отдельная библиотека reactive-banana-wx), и Генрих много пишет о FRP в этом контексте, включая примеры кода.

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

Утечки времени больше не проблема, потому что они во многом связаны с монадической структурой. Практические реализации FRP просто не предлагают монадического интерфейса. Yampa начала это, и Netwire, и reactive-banana основываются на этом.

На данный момент мне неизвестны коммерческие или другие крупномасштабные проекты, использующие FRP. Библиотеки готовы, но я думаю, что людей нет - пока.

Ertes
источник
Отличный ответ, спасибо ... это будет забавное упражнение по реализации некоторых алгоритмов обучения с подкреплением поверх вашей библиотеки.
mnish
3
Примечательно, что в недавней инди-игре, написанной на Haskell ( Nikki and the Robots ), было принято решение не использовать FRP.
Alex R
23

Хотя уже есть несколько хороших ответов, я попытаюсь ответить на ваши конкретные вопросы.

  1. reactive не подходит для серьезных проектов из-за проблем с утечкой времени. (см. № 3). Текущая библиотека с наиболее похожим дизайном - это reactive-banana, которая была разработана с использованием reactive в качестве вдохновения и в ходе обсуждения с Коналом Эллиоттом.

  2. Хотя сам Haskell не подходит для приложений жесткого реального времени, в некоторых случаях можно использовать Haskell для приложений мягкого реального времени. Я не знаком с текущими исследованиями, но не считаю, что это непреодолимая проблема. Я подозреваю, что лучше всего подходят системы вроде Yampa или системы генерации кода, такие как Atom.

  3. «Утечка времени» - это проблема, специфичная для переключаемого FRP. Утечка происходит, когда система не может освободить старые объекты, потому что они могут понадобиться, если в какой-то момент в будущем произойдет переключение. Помимо утечки памяти (которая может быть довольно серьезной), еще одним последствием является то, что при переключении система должна приостановить работу, пока выполняется обход цепочки старых объектов для генерации текущего состояния.

Невыключаемые библиотеки frp, такие как Yampa и более старые версии reactive-banana, не страдают от утечек времени. Переключаемые библиотеки frp обычно используют одну из двух схем: либо у них есть специальная «монада создания», в которой создаются значения FRP, либо они используют параметр типа «устаревание» для ограничения контекстов, в которых могут происходить переключения. elerea (и, возможно, netwire?) используют первое, тогда как недавние реактивные банан и грейпфрут используют второе.

Под «переключаемым frp» я имею в виду тот, который реализует функцию Конала switcher :: Behavior a -> Event (Behavior a) -> Behavior aили идентичную семантику. Это означает, что форма сети может динамически изменяться во время работы.

На самом деле это не противоречит утверждению @ertes об монадических интерфейсах: оказывается, что предоставление Monadэкземпляра для an Eventделает возможными утечки времени, и с помощью любого из вышеперечисленных подходов больше невозможно определить эквивалентные экземпляры Monad.

Наконец, хотя с FRP еще предстоит проделать много работы, я думаю, что некоторые из новых платформ (reactive-banana, elerea, netwire) стабильны и достаточно зрелы, чтобы вы могли создавать из них надежный код. Но вам, возможно, придется потратить много времени на изучение тонкостей, чтобы понять, как добиться хорошей производительности.

Джон Л
источник
2
Что касается стрелочных библиотек (Yampa, netwire), то они тоже переключаемые. Причина в том, что стрелки имеют встроенное старение, от которого практически невозможно избавиться. (Будучи преобразователями потока, стрелки не зависят от времени начала их входного потока.)
Генрих Апфельмус
3
Не забывайте, реактивно-банан банановый-Немезида : натрия .
Дэн Бертон
1
@HeinrichApfelmus: это интересный момент. Я вообще не считаю библиотеки на основе стрелок переключаемыми так же, как elerea / grapefruit / current-reactive-banana. Я думаю, что их переключение намного ближе к тому, что требовалось в предыдущих версиях реактивного банана. Это всего лишь внутреннее ощущение, я не подумал достаточно, чтобы даже описать, что я имею в виду.
John L
2
@DanBurton, спасибо, я безуспешно пытался вспомнить это имя. Я согласен с тем, что натрий следует рассматривать как современную библиотеку FRP, хотя он не так популярен, как реактивный банан.
John L
Хотя за продолжающимся обсуждением немного сложно следить, похоже, это указывает на то, что система мягкого реального времени действительно возможна, при условии, что время сборки мусора может быть каким-то образом ограничено. В любом случае спасибо за отличный ответ.
mnish
20

Я собираюсь перечислить пару пунктов из пространства Mono и .Net и один из пространства Haskell, которое я нашел не так давно. Начну с Haskell.

Вяз - ссылка

Его описание согласно его сайту:

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

Имеет свой вариант FRP . Судя по его примерам, он кажется довольно зрелым.

Реактивные расширения - ссылка

Описание с его первой страницы:

Reactive Extensions (Rx) - это библиотека для создания асинхронных программ и программ на основе событий с использованием наблюдаемых последовательностей и операторов запросов в стиле LINQ. Используя Rx, разработчики представляют асинхронные потоки данных с помощью Observables, запрашивают асинхронные потоки данных с помощью операторов LINQ и параметризуют параллелизм в асинхронных потоках данных с помощью планировщиков. Проще говоря, Rx = Observables + LINQ + Schedulers.

Reactive Extensions происходит от MSFT и реализует множество отличных операторов, упрощающих обработку событий. Его исходный код был открыт всего пару дней назад. Он очень зрелый и используется в производстве; на мой взгляд, это был бы более приятный API для Windows 8 API, чем предоставляет библиотека TPL; потому что наблюдаемые могут быть как горячими, так и холодными, повторными / объединенными и т. д., в то время как задачи всегда представляют собой горячие или выполненные вычисления, которые либо выполняются, либо выполняются с ошибками, либо завершаются.

Я написал код на стороне сервера с использованием Rx для асинхронности, но должен признать, что функциональная запись на C # может немного раздражать. У F # есть несколько оболочек, но было сложно отслеживать разработку API, потому что группа относительно закрыта и не продвигается MSFT, как другие проекты.

Его открытый исходный код пришел с открытым исходным кодом его компилятора IL-to-JS, поэтому он, вероятно, мог хорошо работать с JavaScript или Elm.

Вероятно, вы могли бы очень хорошо связать F # / C # / JS / Haskell вместе с помощью брокера сообщений, такого как RabbitMQ и SocksJS.

Набор инструментов Bling UI - ссылка

Описание с его первой страницы:

Bling - это библиотека на основе C # для простого программирования изображений, анимации, взаимодействий и визуализаций в Microsoft WPF / .NET. Bling ориентирован на дизайнеров-технологов, то есть дизайнеров, которые иногда занимаются программированием, чтобы помочь в быстром прототипировании богатых дизайнерских идей пользовательского интерфейса. Студенты, художники, исследователи и любители также сочтут Bling полезным инструментом для быстрого выражения идей или визуализаций. API-интерфейсы и конструкции Bling оптимизированы для быстрого программирования ненужного кода в отличие от тщательного программирования производственного кода.

Бесплатная LtU-статья .

Я тестировал это, но не работал с ним для клиентского проекта. Он выглядит потрясающе, имеет хорошую перегрузку оператора C #, которая формирует привязки между значениями. В качестве источников событий он использует свойства зависимостей в WPF / SL / (WinRT). Его 3D-анимация хорошо работает на разумном оборудовании. Я бы использовал это, если в конечном итоге оказался в проекте, нуждающемся в визуализации; возможно портирование на Windows 8.

ReactiveUI - ссылка

Пол Беттс, ранее работавший в MSFT, а теперь в Github, написал эту структуру. Я работал с ней довольно много, и эта модель мне нравится. Он более изолирован, чем Blink (по своей природе от использования Rx и его абстракций), что упрощает использование кода модульного тестирования. В этом написан клиент github git для Windows.

Комментарии

Реактивная модель достаточно производительна для большинства требовательных к производительности приложений. Если вы думаете о жестком реальном времени, я готов поспорить, что у большинства GC-языков есть проблемы. Rx, ReactiveUI создает некоторое количество небольших объектов, которые необходимо собирать в сборку мусора, потому что именно так создаются / удаляются подписки и промежуточные значения передаются в реактивной «монаде» обратных вызовов. В целом в .Net я предпочитаю реактивное программирование, а не программирование на основе задач, потому что обратные вызовы статичны (известны во время компиляции, не выделяются), в то время как задачи распределяются динамически (неизвестно, все вызовы нуждаются в экземпляре, создается мусор) - и лямбды компилируются в классы, созданные компилятором.

Очевидно, что C # и F # строго оцениваются, поэтому утечка времени здесь не проблема. То же самое и с JS. Однако это может быть проблемой с воспроизводимыми или кешируемыми наблюдаемыми объектами.

Хенрик
источник
Спасибо за отличный ответ. Одна из вещей, которые мне нравились в реализациях Haskell FRP, - это то, что они, кажется, позволяют мне четко разделить вычисления для управления u(t)и моделирования для f(t). Так ли обстоит дело с реализациями F #?
mnish
Думаю, вы можете сказать, что эти две функции временно разделены, да. Однако они, вероятно, не разделены логически. ;)
Henrik
Насколько мне известно, Reactive Extensions и другие более совершенные пакеты, ориентированные на пользовательский интерфейс (и все, что находится за пределами Haskell, фактически) используют только событийную семанику, то есть они имеют представление о событиях, которые вы можете включить, но не понятие непрерывных сигналов времени, которые могут взаимодействовать по уравнениям. Думаю, для построения guis это нормально. Однако для построения симуляторов и моделей это может быть неудачным.
sclv
Вы подразумеваете, что все реализации библиотеки функционального реактивного программирования должны моделировать время непрерывно, а не дискретно? Я нашел статью под названием «Алгебра процессов с синхронизацией: реальное и дискретное время» - это хорошая отправная точка для понимания того, о чем вы говорите?
Henrik
Я не говорю, что всем нужно - некоторым нужно, а некоторым нет. Но те, которые подходят, больше подходят для определенных задач, а те, которые не подходят, больше подходят для других ...
sclv