Каково состояние текущих реализаций функционально-реактивного программирования?
Я пытаюсь визуализировать некоторые простые автоматические физические системы (такие как маятник, руки робота и т. Д.) В Haskell. Часто эти системы могут быть описаны уравнениями, такими как
df/dt = c*f(t) + u(t)
где u(t)
представляет собой некое "интеллектуальное управление". Эти системы очень хорошо вписываются в парадигму функционально-реактивного программирования.
Поэтому я схватил книгу "Школа выражений на Хаскелле" Пола Худака и обнаружил, что предметно-ориентированный язык "FAL" (для языка функциональной анимации), представленный там, на самом деле работает довольно удобно для моих простых игрушечных систем (хотя некоторые функции, особенно integrate
, кажется, слишком ленив для эффективного использования, но легко исправимо).
Мой вопрос в том, что является более зрелой, современной, хорошо обслуживаемой, настроенной на производительность альтернативой для более продвинутых или даже практических приложений сегодня?
На этой вики-странице перечислено несколько опций для Haskell, но я не совсем понимаю следующие аспекты:
Статус "реактивного", проекта Конала Элиота, который (насколько я понимаю) является одним из изобретателей этой парадигмы программирования, выглядит несколько устаревшим. Мне нравится его код, но, возможно, я должен попробовать другие более современные альтернативы? В чем основное различие между ними с точки зрения синтаксиса / производительности / стабильности во время выполнения?
Цитируя результаты опроса, проведенного в 2011 году, раздел 6: "... реализации FRP по-прежнему недостаточно эффективны или предсказуемы по производительности, чтобы эффективно использоваться в областях, требующих гарантий задержки...". Несмотря на то, что опрос предлагает некоторые интересные возможные оптимизации, учитывая тот факт, что FRP существует более 15 лет, у меня складывается впечатление, что эта проблема с производительностью может быть чем-то очень или даже по своей природе трудным для решения, по крайней мере, в течение нескольких лет. Это правда?
Тот же автор опроса рассказывает о "утечках времени" в своем блоге. Является ли проблема уникальной для FRP или что-то, что мы обычно имеем при программировании на чистом, нестрогом языке? Вы когда-нибудь находили слишком сложным стабилизировать систему на основе FRP с течением времени, если она недостаточно эффективна?
Это все еще проект исследовательского уровня? Используют ли их люди, например, инженеры-технологи, инженеры-робототехники, финансовые инженеры и т. Д. (На любом языке, который соответствует их потребностям)?
Хотя я лично предпочитаю реализацию на 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 прямо сейчас. Библиотеки готовы, но я думаю, что люди еще не готовы.
Хотя уже есть несколько хороших ответов, я попытаюсь ответить на ваши конкретные вопросы.
реактивный не подходит для серьезных проектов из-за проблем с утечкой времени. (см. № 3). Нынешняя библиотека с наиболее похожим дизайном - "реактивный-банан", который был разработан с использованием реактивного в качестве источника вдохновения и обсуждался с Коналом Эллиоттом.
Хотя сам Haskell не подходит для жестких приложений реального времени, в некоторых случаях можно использовать Haskell для мягких приложений реального времени. Я не знаком с текущими исследованиями, но я не считаю, что это непреодолимая проблема. Я подозреваю, что либо системы, подобные Yampa, либо системы генерации кода, такие как Atom, возможно, являются лучшим подходом к решению этой проблемы.
"Утечка времени" - это проблема, характерная для переключаемого 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. Это может быть проблемой с воспроизводимыми или кэшируемыми наблюдаемыми.