Wie ist der Status der aktuellen Implementierungen der funktionalen reaktiven Programmierung?

90

Ich versuche, einige einfache automatische physikalische Systeme (wie Pendel, Roboterarme usw.) In Haskell zu visualisieren. Oft können diese Systeme durch Gleichungen wie beschrieben werden

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

wo u(t)repräsentiert eine Art "intelligente Steuerung". Diese Systeme scheinen sehr gut in das Paradigma der funktionalen reaktiven Programmierung zu passen.

Also habe ich das Buch „The Haskell School of Expression“ von Paul Hudak packte und festgestellt , dass die domänenspezifische Sprache „FAL“ (für Functional - Animation Language) präsentierte dort recht tatsächlich funktioniert pleasently für meine einfachen Spielzeug - Systeme (auch wenn einige Funktionen, vor allem integrate, schien ein bisschen zu faul für eine effiziente Nutzung zu sein, aber leicht zu reparieren).

Meine Frage ist, was ist die ausgereiftere, aktuellere, gepflegte, leistungsoptimierte Alternative für fortgeschrittenere oder sogar praktische Anwendungen heute?

Diese Wiki-Seite listet verschiedene Optionen für Haskell auf, aber mir sind die folgenden Punkte nicht klar:

  1. Der Status von "reaktiv", dem Projekt von Conal Eliott, der (wie ich es verstehe) einer der Erfinder dieses Programmierparadigmas ist, sieht etwas abgestanden aus. Ich liebe seinen Code, aber vielleicht sollte ich andere aktuellere Alternativen ausprobieren? Was ist der Hauptunterschied zwischen ihnen in Bezug auf Syntax / Leistung / Laufzeitstabilität?

  2. Um aus einer Umfrage im Jahr 2011 zu zitieren , Abschnitt 6: " ... FRP-Implementierungen sind immer noch nicht effizient genug oder vorhersehbar genug, um in Domänen, in denen Latenzgarantien erforderlich sind, effektiv eingesetzt zu werden ... ". Obwohl die Umfrage einige interessante mögliche Optimierungen vorschlägt, da FRP seit mehr als 15 Jahren besteht, habe ich den Eindruck, dass dieses Leistungsproblem zumindest innerhalb weniger Jahre sehr oder sogar von Natur aus schwierig zu lösen sein könnte . Ist das wahr?

  3. Der gleiche Autor der Umfrage spricht in seinem Blog über "Zeitlecks" . Ist das Problem nur bei FRP oder etwas, das wir normalerweise haben, wenn wir in einer reinen, nicht strengen Sprache programmieren? Haben Sie es jemals zu schwierig gefunden, ein FRP-basiertes System im Laufe der Zeit zu stabilisieren, wenn nicht leistungsfähig genug?

  4. Ist das noch ein Forschungsprojekt? Verwenden die Leute wie Anlageningenieure, Robotikingenieure, Finanzingenieure usw. sie tatsächlich (in welcher Sprache auch immer, die ihren Bedürfnissen entspricht)?

Obwohl ich persönlich eine Haskell-Implementierung bevorzuge, bin ich offen für andere Vorschläge. Zum Beispiel würde es besonders Spaß machen, eine Erlang-Implementierung zu haben - es wäre dann sehr einfach, einen intelligenten, adaptiven, selbstlernenden Serverprozess zu haben!

mnish
quelle

Antworten:

82

Derzeit gibt es hauptsächlich zwei praktische Haskell-Bibliotheken für die funktionale reaktive Programmierung. Beide werden von Einzelpersonen verwaltet, erhalten jedoch auch Codebeiträge von anderen Haskell-Programmierern:

  • Netwire konzentriert sich auf Effizienz, Flexibilität und Vorhersehbarkeit. Es hat ein eigenes Ereignisparadigma und kann in Bereichen verwendet werden, in denen herkömmliches FRP nicht funktioniert, einschließlich Netzwerkdiensten und komplexen Simulationen. Stil: anwendbar und / oder pfeilförmig. Erstautor und Betreuer: Ertugrul Söylemez (das bin ich).

  • Reactive-Banana baut auf dem traditionellen FRP-Paradigma auf. Die Verwendung ist zwar praktisch, dient aber auch als Grundlage für die klassische FRP-Forschung. Das Hauptaugenmerk liegt auf Benutzeroberflächen und es gibt eine vorgefertigte Schnittstelle zu wx. Stil: anwendbar. Erstautor und Betreuer: Heinrich Apfelmus.

Sie sollten beide ausprobieren, aber je nach Ihrer Anwendung werden Sie wahrscheinlich feststellen, dass die eine oder andere besser zu Ihnen passt.

Für Spiele, Netzwerke, Robotersteuerung und Simulationen ist Netwire hilfreich. Es wird mit vorgefertigten Kabeln für diese Anwendungen geliefert , einschließlich verschiedener nützlicher Differentiale, Integrale und vieler Funktionen für eine transparente Ereignisbehandlung. Ein Tutorial finden Sie in der Dokumentation des Control.WireModuls auf der von mir verlinkten Seite.

Für grafische Benutzeroberflächen ist Reactive-Banana derzeit die beste Wahl. Es hat bereits eine wx-Schnittstelle (als separate Bibliothek reactive-banana-wx) und Heinrich bloggt in diesem Zusammenhang viel über FRP, einschließlich Codebeispiele.

Um Ihre anderen Fragen zu beantworten: FRP eignet sich nicht für Szenarien, in denen Sie Vorhersagbarkeit in Echtzeit benötigen. Dies ist größtenteils auf Haskell zurückzuführen, aber leider ist FRP in niedrigeren Sprachen schwer zu realisieren. Sobald Haskell selbst in Echtzeit bereit ist, wird auch FRP dort ankommen. Konzeptionell ist Netwire für Echtzeitanwendungen bereit.

Zeitlecks sind kein Problem mehr, da sie weitgehend mit dem monadischen Rahmen zusammenhängen. Praktische FRP-Implementierungen bieten einfach keine monadische Schnittstelle. Yampa hat damit begonnen und Netwire und Reactive-Banana bauen beide darauf auf.

Ich kenne derzeit keine kommerziellen oder anderweitig großen Projekte mit FRP. Die Bibliotheken sind fertig, aber ich denke, die Leute sind es noch nicht.

ertes
quelle
Tolle Antwort, danke. Es wird eine lustige Übung sein, einige Verstärkungslernalgorithmen über Ihrer Bibliothek zu implementieren.
mnish
3
Insbesondere ein kürzlich in Haskell geschriebenes Indie-Spiel ( Nikki and the Robots ) traf die Entscheidung , FRP nicht zu verwenden.
Alex R
23

Obwohl es bereits einige gute Antworten gibt, werde ich versuchen, Ihre spezifischen Fragen zu beantworten.

  1. reaktiv ist aufgrund von Zeitleckproblemen nicht für ernsthafte Projekte verwendbar. (siehe # 3). Die aktuelle Bibliothek mit dem ähnlichsten Design ist Reactive-Banana, die mit Reactive als Inspiration und im Gespräch mit Conal Elliott entwickelt wurde.

  2. Obwohl Haskell selbst für harte Echtzeitanwendungen ungeeignet ist, ist es in einigen Fällen möglich, Haskell für weiche Echtzeitanwendungen zu verwenden. Ich bin mit der aktuellen Forschung nicht vertraut, aber ich glaube nicht, dass dies ein unüberwindbares Problem ist. Ich vermute, dass entweder Systeme wie Yampa oder Codegenerierungssysteme wie Atom möglicherweise der beste Ansatz sind, um dies zu lösen.

  3. Ein "Zeitleck" ist ein spezifisches Problem bei schaltbarem FRP. Das Leck tritt auf, wenn ein System alte Objekte nicht freigeben kann, weil es sie möglicherweise benötigt, wenn irgendwann in der Zukunft ein Wechsel stattfinden sollte. Zusätzlich zu einem Speicherverlust (der sehr schwerwiegend sein kann) besteht eine weitere Konsequenz darin, dass das System beim Umschalten eine Pause einlegen muss, während die Kette alter Objekte durchlaufen wird, um den aktuellen Status zu generieren.

Nicht umschaltbare frp-Bibliotheken wie Yampa und ältere Versionen von reaktiven Bananen leiden nicht unter Zeitlecks. Umschaltbare frp-Bibliotheken verwenden im Allgemeinen eines von zwei Schemata: Entweder haben sie eine spezielle "Erstellungsmonade", in der FRP-Werte erstellt werden, oder sie verwenden einen Parameter vom Typ "Alterung", um die Kontexte zu begrenzen, in denen Umschaltungen auftreten können. elerea (und möglicherweise netwire?) verwenden das erstere, während neuere reaktive Bananen und Grapefruits das letztere verwenden.

Mit "schaltbar frp" meine ich eine, die Conals Funktion switcher :: Behavior a -> Event (Behavior a) -> Behavior aoder identische Semantik implementiert . Dies bedeutet, dass sich die Form des Netzwerks während des Betriebs dynamisch ändern kann.

Dies widerspricht nicht wirklich der Aussage von @ ertes über monadische Schnittstellen: Es stellt sich heraus, dass die Bereitstellung einer MonadInstanz für eine EventZeitlecks ermöglicht, und mit einem der oben genannten Ansätze ist es nicht mehr möglich, die entsprechenden Monad-Instanzen zu definieren.

Obwohl noch viel Arbeit mit FRP zu erledigen ist, denke ich, dass einige der neueren Plattformen (Reactive-Banana, Elerea, Netwire) stabil und ausgereift genug sind, um daraus zuverlässigen Code zu erstellen. Möglicherweise müssen Sie jedoch viel Zeit damit verbringen, die Vor- und Nachteile zu erlernen, um zu verstehen, wie Sie eine gute Leistung erzielen.

John L.
quelle
2
Auch die pfeilbasierten Bibliotheken (Yampa, Netwire) sind umschaltbar. Der Grund dafür ist, dass in Pfeilen eine Alterung eingebaut ist, die man eigentlich nicht loswerden kann. (Als Stromtransformatoren sind Pfeile
unabhängig
3
Vergessen Sie nicht die Bananennemesis der reaktiven Banane : Natrium .
Dan Burton
1
@HeinrichApfelmus: das ist ein interessanter Punkt. Ich halte pfeilbasierte Bibliotheken im Allgemeinen nicht für umschaltbar wie elerea / grapefruit / current-reactive-banana. Ich denke, ihr Wechsel ist viel näher an dem, was in früheren Versionen von reaktiven Bananen erforderlich war. Dies ist nur ein Bauchgefühl, ich habe nicht genug darüber nachgedacht, um überhaupt zu beschreiben, was ich meine.
John L
2
@ DanBurton danke, ich habe erfolglos versucht, mich an diesen Namen zu erinnern. Ich stimme zu, dass Natrium als moderne FRP-Bibliothek betrachtet werden sollte, obwohl es nicht so beliebt ist wie reaktive Bananen.
John L
Obwohl die Diskussion etwas schwierig zu verfolgen ist, scheint dies darauf hinzudeuten, dass ein Soft-Realtime-System tatsächlich möglich ist, vorausgesetzt, die GC-Zeit kann auf irgendeine Weise begrenzt werden. Trotzdem danke für deine tolle Antwort.
mnish
20

Ich werde ein paar Elemente im Mono- und .Net-Bereich und eines aus dem Haskell-Bereich auflisten, die ich vor nicht allzu langer Zeit gefunden habe. Ich werde mit Haskell beginnen.

Ulme - Link

Seine Beschreibung gemäß seiner Website:

Elm möchte die Front-End-Webentwicklung angenehmer gestalten. Es wird ein neuer Ansatz für die GUI-Programmierung eingeführt, mit dem die systemischen Probleme von HTML, CSS und JavaScript behoben werden. Mit Elm können Sie schnell und einfach mit visuellen Layouts arbeiten, die Leinwand verwenden, komplizierte Benutzereingaben verwalten und der Hölle der Rückrufe entkommen.

Es hat eine eigene Variante von FRP . Wenn man mit seinen Beispielen spielt, scheint es ziemlich ausgereift zu sein.

Reaktive Erweiterungen - Link

Beschreibung von seiner Titelseite:

Die Reactive Extensions (Rx) sind eine Bibliothek zum Erstellen asynchroner und ereignisbasierter Programme unter Verwendung beobachtbarer Sequenzen und Abfrageoperatoren im LINQ-Stil. Mit Rx stellen Entwickler asynchrone Datenströme mit Observables dar, fragen asynchrone Datenströme mit LINQ-Operatoren ab und parametrisieren die Parallelität in den asynchronen Datenströmen mit Schedulern. Einfach ausgedrückt, Rx = Observables + LINQ + Scheduler.

Reactive Extensions stammt von MSFT und implementiert viele hervorragende Operatoren, die die Behandlung von Ereignissen vereinfachen. Es war erst vor ein paar Tagen Open Source . Es ist sehr ausgereift und wird in der Produktion verwendet. Meiner Meinung nach wäre es eine schönere API für die Windows 8-APIs gewesen, als die TPL-Bibliothek bietet. weil Observables sowohl heiß als auch kalt sein und erneut versucht / zusammengeführt werden können usw., während Aufgaben immer heiße oder durchgeführte Berechnungen darstellen, die entweder ausgeführt, fehlerhaft oder abgeschlossen sind.

Ich habe serverseitigen Code mit Rx für Asynchronität geschrieben, aber ich muss zugeben, dass das funktionale Schreiben in C # etwas ärgerlich sein kann. F # hat ein paar Wrapper, aber es war schwierig, die API-Entwicklung zu verfolgen, da die Gruppe relativ geschlossen ist und nicht wie andere Projekte von MSFT beworben wird.

Das Open Sourcing wurde mit dem Open Sourcing des IL-to-JS-Compilers geliefert, sodass es wahrscheinlich gut mit JavaScript oder Elm funktionieren könnte.

Sie könnten F # / C # / JS / Haskell wahrscheinlich sehr gut mit einem Nachrichtenbroker wie RabbitMQ und SocksJS zusammenbinden.

Bling UI Toolkit - Link

Beschreibung von seiner Titelseite:

Bling ist eine C # -basierte Bibliothek zum einfachen Programmieren von Bildern, Animationen, Interaktionen und Visualisierungen in Microsoft WPF / .NET. Bling richtet sich an Designtechnologen, dh an Designer, die manchmal programmieren, um das Rapid Prototyping umfangreicher UI-Designideen zu unterstützen. Studenten, Künstler, Forscher und Bastler finden Bling auch nützlich, um schnell Ideen oder Visualisierungen auszudrücken. Die APIs und Konstrukte von Bling sind für die schnelle Programmierung von Wegwerfcode optimiert, im Gegensatz zur sorgfältigen Programmierung von Produktionscode.

Ein kostenloser LTU-Artikel .

Ich habe dies getestet, aber nicht für ein Kundenprojekt damit gearbeitet. Es sieht fantastisch aus und hat eine nette Überladung des C # -Operators, die die Bindungen zwischen den Werten bildet. Es verwendet Abhängigkeitseigenschaften in WPF / SL / (WinRT) als Ereignisquellen. Die 3D-Animationen funktionieren gut mit vernünftiger Hardware. Ich würde dies verwenden, wenn ich in einem Projekt landen würde, das Visualisierungen benötigt. wahrscheinlich auf Windows 8 portieren.

ReactiveUI - Link

Paul Betts, zuvor bei MSFT, jetzt bei Github, hat diesen Rahmen geschrieben. Ich habe ziemlich ausgiebig damit gearbeitet und mag das Modell. Es ist entkoppelter als Blink (von Natur aus von der Verwendung von Rx und seinen Abstraktionen), was es einfacher macht, Code mit ihm zu testen. Darin ist der Github Git Client für Windows geschrieben.

Bemerkungen

Das reaktive Modell ist für die meisten leistungsintensiven Anwendungen leistungsfähig genug. Wenn Sie an harte Echtzeit denken, würde ich wetten, dass die meisten GC-Sprachen Probleme haben. Rx, ReactiveUI erstellen eine gewisse Menge kleiner Objekte, die GCed werden müssen, da auf diese Weise Abonnements erstellt / entsorgt werden und Zwischenwerte in der reaktiven "Monade" von Rückrufen weiterentwickelt werden. Im Allgemeinen bevorzuge ich in .Net die reaktive Programmierung gegenüber der aufgabenbasierten Programmierung, da Rückrufe statisch sind (zur Kompilierungszeit bekannt, keine Zuordnung), während Aufgaben dynamisch zugewiesen werden (nicht bekannt, alle Aufrufe benötigen eine Instanz, Müll erstellt) - und Lambdas kompilieren vom Compiler generierte Klassen.

Offensichtlich werden C # und F # streng ausgewertet, so dass Zeitlecks hier kein Problem darstellen. Gleiches gilt für JS. Es kann jedoch ein Problem mit wiedergabefähigen oder zwischengespeicherten Observablen sein.

Henrik
quelle
Danke für die tolle Antwort. Eines der Dinge, die ich für Haskell FRP-Implementierungen mochte, ist, dass sie es mir anscheinend ermöglichen, die Berechnungen für die Steuerung u(t)und die Simulationen für sauber zu entkoppeln f(t). Ist das bei F # -Implementierungen der Fall?
mnish
Ich denke, man kann sagen, dass diese beiden Funktionen zeitlich entkoppelt sind, ja. Sie sind jedoch wahrscheinlich nicht logisch entkoppelt. ;)
Henrik
Soweit ich weiß, verwenden Reactive Extensions und die anderen ausgefeilteren UI-fokussierten Pakete (und tatsächlich alles außerhalb von Haskell) nur ereignisgesteuerte Semanik - das heißt, sie haben eine Vorstellung von Ereignissen, die Sie einschalten können. aber keine Vorstellung von kontinuierlichen Zeitsignalen, die gleichwertig interagieren können. Für den Bau von Guis ist das in Ordnung, denke ich. Für Gebäudesimulationen und -modelle kann dies jedoch unglücklich sein.
sclv
Bedeuten Sie, dass alle Implementierungen der funktionalen reaktiven Programmierbibliothek die Zeit kontinuierlich und nicht diskret modellieren müssen? Ich habe einen Artikel mit dem Titel "Prozessalgebra mit Timing: Echtzeit und diskrete Zeit" gefunden. Ist dies ein guter Ausgangspunkt, um zu verstehen, wovon Sie sprechen?
Henrik
Ich sage nicht, dass alle es müssen - manche tun es, manche nicht. Aber diejenigen, die dies tun, sind für bestimmte Aufgaben besser geeignet, und diejenigen, die nicht besser für andere geeignet sind ...
sclv