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

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

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

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

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

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

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

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

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

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

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

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

3 ответа

Решение

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

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

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

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

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

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

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

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

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

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

  1. реактивный не подходит для серьезных проектов из-за проблем с утечкой времени. (см. № 3). Нынешняя библиотека с наиболее похожим дизайном - "реактивный-банан", который был разработан с использованием реактивного в качестве источника вдохновения и обсуждался с Коналом Эллиоттом.

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

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

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

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

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

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

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

Вяз - ссылка

Его описание в соответствии с его сайтом:

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

У него есть свой вариант FRP. От игры с его примерами это кажется довольно зрелым.

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

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

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

Reactive Extensions происходит от MSFT и реализует множество превосходных операторов, которые упрощают обработку событий. Это было с открытым исходным кодом всего пару дней назад. Это очень зрелый и используется в производстве; по моему мнению, это был бы более хороший API для API Windows 8, чем обеспечивает библиотека 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 полезным в качестве инструмента для быстрого выражения идей или визуализаций. API и конструкции Bling оптимизированы для быстрого программирования одноразового кода, а не для тщательного программирования рабочего кода.

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

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

ReactiveUI - ссылка

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

Комментарии

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

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

Другие вопросы по тегам