Я пытаюсь визуализировать некоторые простые автоматические физические системы (такие как маятник, манипуляторы и т. Д.) В Haskell. Часто эти системы можно описать уравнениями типа
df/dt = c*f(t) + u(t)
где u(t)
представляет собой своего рода «интеллектуальное управление». Эти системы очень хорошо вписываются в парадигму функционального реактивного программирования.
Итак, я взял книгу Пола Худака «Школа выражения Haskell» и обнаружил, что представленный там предметно-ориентированный язык «FAL» (для языка функциональной анимации) действительно неплохо работает для моих простых игрушечных систем (хотя некоторые функции, в частности integrate
, показалось ленивым для эффективного использования, но легко поправимо).
У меня вопрос: какая сегодня более зрелая, современная, хорошо обслуживаемая и настроенная на производительность альтернатива для более продвинутых или даже практических приложений?
На этой вики-странице перечислены несколько вариантов Haskell, но я не совсем понимаю следующие моменты:
Статус "реактивного" проекта Конала Элиотта, который (насколько я понимаю) одним из изобретателей этой парадигмы программирования, выглядит несколько устаревшим. Мне нравится его код, но, может быть, мне стоит попробовать другие, более современные альтернативы? В чем основное различие между ними с точки зрения синтаксиса / производительности / стабильности во время выполнения?
Процитируем обзор 2011 года, раздел 6: « ... реализации FRP все еще недостаточно эффективны или достаточно предсказуемы по производительности для эффективного использования в доменах, требующих гарантии задержки ... ». Несмотря на то, что обзор предлагает некоторые интересные возможные оптимизации, учитывая тот факт, что FRP существует уже более 15 лет, у меня сложилось впечатление, что эта проблема производительности может оказаться чем-то очень или даже сложным для решения по крайней мере в течение нескольких лет. Это правда?
Об «утечках времени» тот же автор опроса рассказывает в своем блоге . Является ли проблема уникальной для FRP или с чем мы обычно сталкиваемся при программировании на чистом, нестрогом языке? Вы когда-нибудь находили слишком сложным стабилизировать систему на основе FRP с течением времени, если она недостаточно эффективна?
Это все еще проект исследовательского уровня? Действительно ли их используют такие люди, как заводские инженеры, инженеры-робототехники, финансовые инженеры и т.д.
Хотя лично я предпочитаю реализацию Haskell, я открыт для других предложений. Например, было бы особенно интересно иметь реализацию на Erlang - тогда было бы очень легко иметь интеллектуальный, адаптивный, самообучающийся серверный процесс!
Хотя уже есть несколько хороших ответов, я попытаюсь ответить на ваши конкретные вопросы.
reactive не подходит для серьезных проектов из-за проблем с утечкой времени. (см. № 3). Текущая библиотека с наиболее похожим дизайном - это reactive-banana, которая была разработана с использованием reactive в качестве вдохновения и в ходе обсуждения с Коналом Эллиоттом.
Хотя сам Haskell не подходит для приложений жесткого реального времени, в некоторых случаях можно использовать Haskell для приложений мягкого реального времени. Я не знаком с текущими исследованиями, но не считаю, что это непреодолимая проблема. Я подозреваю, что лучше всего подходят системы вроде Yampa или системы генерации кода, такие как Atom.
«Утечка времени» - это проблема, специфичная для переключаемого FRP. Утечка происходит, когда система не может освободить старые объекты, потому что они могут понадобиться, если в какой-то момент в будущем произойдет переключение. Помимо утечки памяти (которая может быть довольно серьезной), еще одним последствием является то, что при переключении система должна приостановить работу, пока выполняется обход цепочки старых объектов для генерации текущего состояния.
Невыключаемые библиотеки frp, такие как Yampa и более старые версии reactive-banana, не страдают от утечек времени. Переключаемые библиотеки frp обычно используют одну из двух схем: либо у них есть специальная «монада создания», в которой создаются значения FRP, либо они используют параметр типа «устаревание» для ограничения контекстов, в которых могут происходить переключения. elerea (и, возможно, netwire?) используют первое, тогда как недавние реактивные банан и грейпфрут используют второе.
Под «переключаемым frp» я имею в виду тот, который реализует функцию Конала
switcher :: Behavior a -> Event (Behavior a) -> Behavior a
или идентичную семантику. Это означает, что форма сети может динамически изменяться во время работы.На самом деле это не противоречит утверждению @ertes об монадических интерфейсах: оказывается, что предоставление
Monad
экземпляра для anEvent
делает возможными утечки времени, и с помощью любого из вышеперечисленных подходов больше невозможно определить эквивалентные экземпляры Monad.Наконец, хотя с FRP еще предстоит проделать много работы, я думаю, что некоторые из новых платформ (reactive-banana, elerea, netwire) стабильны и достаточно зрелы, чтобы вы могли создавать из них надежный код. Но вам, возможно, придется потратить много времени на изучение тонкостей, чтобы понять, как добиться хорошей производительности.
источник
Я собираюсь перечислить пару пунктов из пространства Mono и .Net и один из пространства Haskell, которое я нашел не так давно. Начну с Haskell.
Вяз - ссылка
Его описание согласно его сайту:
Имеет свой вариант FRP . Судя по его примерам, он кажется довольно зрелым.
Реактивные расширения - ссылка
Описание с его первой страницы:
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 - ссылка
Описание с его первой страницы:
Бесплатная LtU-статья .
Я тестировал это, но не работал с ним для клиентского проекта. Он выглядит потрясающе, имеет хорошую перегрузку оператора C #, которая формирует привязки между значениями. В качестве источников событий он использует свойства зависимостей в WPF / SL / (WinRT). Его 3D-анимация хорошо работает на разумном оборудовании. Я бы использовал это, если в конечном итоге оказался в проекте, нуждающемся в визуализации; возможно портирование на Windows 8.
ReactiveUI - ссылка
Пол Беттс, ранее работавший в MSFT, а теперь в Github, написал эту структуру. Я работал с ней довольно много, и эта модель мне нравится. Он более изолирован, чем Blink (по своей природе от использования Rx и его абстракций), что упрощает использование кода модульного тестирования. В этом написан клиент github git для Windows.
Комментарии
Реактивная модель достаточно производительна для большинства требовательных к производительности приложений. Если вы думаете о жестком реальном времени, я готов поспорить, что у большинства GC-языков есть проблемы. Rx, ReactiveUI создает некоторое количество небольших объектов, которые необходимо собирать в сборку мусора, потому что именно так создаются / удаляются подписки и промежуточные значения передаются в реактивной «монаде» обратных вызовов. В целом в .Net я предпочитаю реактивное программирование, а не программирование на основе задач, потому что обратные вызовы статичны (известны во время компиляции, не выделяются), в то время как задачи распределяются динамически (неизвестно, все вызовы нуждаются в экземпляре, создается мусор) - и лямбды компилируются в классы, созданные компилятором.
Очевидно, что C # и F # строго оцениваются, поэтому утечка времени здесь не проблема. То же самое и с JS. Однако это может быть проблемой с воспроизводимыми или кешируемыми наблюдаемыми объектами.
источник
u(t)
и моделирования дляf(t)
. Так ли обстоит дело с реализациями F #?