Ist eine funktionale GUI-Programmierung möglich? [geschlossen]

404

Ich habe kürzlich den FP-Fehler entdeckt (beim Versuch, Haskell zu lernen) und war wirklich beeindruckt von dem, was ich bisher gesehen habe (erstklassige Funktionen, verzögerte Bewertung und all die anderen Extras). Ich bin noch kein Experte, aber ich habe bereits begonnen, es einfacher zu finden, "funktional" zu argumentieren als zwingend für grundlegende Algorithmen (und ich habe Probleme, dorthin zurückzukehren, wo ich muss).

Der einzige Bereich, in dem die aktuelle FP flach zu fallen scheint, ist die GUI-Programmierung. Der Haskell-Ansatz scheint darin zu bestehen, nur imperative GUI-Toolkits (wie GTK + oder wxWidgets) zu verpacken und "do" -Blöcke zu verwenden, um einen imperativen Stil zu simulieren. Ich habe F # nicht verwendet, aber ich verstehe, dass es mit OOP mit .NET-Klassen etwas Ähnliches macht. Offensichtlich gibt es dafür einen guten Grund: Bei der aktuellen GUI-Programmierung dreht sich alles um E / A und Nebenwirkungen, sodass mit den meisten aktuellen Frameworks keine rein funktionale Programmierung möglich ist.

Meine Frage ist, ist es möglich, einen funktionalen Ansatz für die GUI-Programmierung zu haben? Ich kann mir nur schwer vorstellen, wie das in der Praxis aussehen würde. Kennt jemand irgendwelche experimentellen oder sonstigen Frameworks, die solche Dinge ausprobieren (oder sogar Frameworks, die von Grund auf für eine funktionale Sprache entwickelt wurden)? Oder ist die Lösung, nur einen hybriden Ansatz zu verwenden, mit OOP für die GUI-Teile und FP für die Logik? (Ich frage nur aus Neugier - ich würde gerne denken, dass FP "die Zukunft" ist, aber die GUI-Programmierung scheint ein ziemlich großes Loch zu sein, das es zu füllen gilt.)

shosti
quelle
7
Nachdem ich mir die GUIs in Common Lisp und OCaml angesehen habe, würde ich sagen, dass es wahrscheinlicher ist, dass die Faulheit von Haskell das Problem verursacht.
new123456
5
@ new123456 Common Lisp ist jedoch keine funktionale Sprache, es funktioniert mit veränderlichen Daten und umfasst Nebenwirkungen
Electric Coffee
3
@ElectricCoffee Lisp ist eine äußerst flexible Sprache, die in vielen verschiedenen Stilen verwendet werden kann, und viele Menschen entscheiden sich dafür, Lisp in einem funktionalen Stil zu verwenden.
chrismamo1
7
Aus meiner Erfahrung (obwohl ich immer noch versuche, daran zu glauben und mehr zu lernen) stößt FRP mit der GUI-Programmierung wirklich an seine Grenzen. Es ist für 80% der Anwendungsfälle schön und elegant, aber umfangreiche Widgets erfordern eine sehr genaue Kontrolle ihres internen Status (z. B. Suchkombinationsfelder usw.), und FRP steht nur im Weg. Imperativ ist nicht immer böse; Der Versuch, die Menge an zwingendem Code zu minimieren, ist gut, aber 100% davon zu entfernen? Habe noch nicht gesehen, dass es für die nicht triviale UI-Entwicklung funktioniert.
AlexG
8
@ElectricCoffee "Common Lisp ist jedoch keine funktionale Sprache". Lisp ist die Mutter aller funktionalen Sprachen. Du meinst, Lisp ist nicht rein.
Jon Harrop

Antworten:

183

Der Haskell-Ansatz scheint darin zu bestehen, nur imperative GUI-Toolkits (wie GTK + oder wxWidgets) zu verpacken und "do" -Blöcke zu verwenden, um einen imperativen Stil zu simulieren

Das ist nicht wirklich der "Haskell-Ansatz" - so binden Sie sich am direktesten an imperative GUI-Toolkits - über eine imperative Schnittstelle. Haskell hat zufällig ziemlich markante Bindungen.

Es gibt mehrere mäßig ausgereifte oder experimentellere rein funktionale / deklarative Ansätze für GUIs, hauptsächlich in Haskell, und hauptsächlich unter Verwendung funktionaler reaktiver Programmierung.

Einige Beispiele sind:

Für diejenigen unter Ihnen, die mit Haskell, Flapjax, nicht vertraut sind, ist http://www.flapjax-lang.org/ eine Implementierung der funktionalen reaktiven Programmierung auf JavaScript.

Don Stewart
quelle
32
In Conal Elliotts Artikel über Obst finden Sie eine ausführliche Beschreibung der Technik und der Entscheidungen: conal.net/papers/genuuly-functional-guis.pdf Ich mache seit einigen Monaten eine rein funktionale GUI-Programmierung in diesem Stil . Ich liebe es, es ist eine so angenehme Erleichterung von der Spaghetti-Hölle der imperativen UI-Programmierung, die in dieser Hinsicht schlechter zu sein scheint als die meisten imperativen Programmierungen.
Luqui
44
Ich stimme dem zu 100% zu. Um es kristallklar zu machen: Der Grund, warum vorhandene GUI-Toolkits häufig verwendet werden, liegt darin, dass sie vorhanden sind. Der Grund, warum Schnittstellen zu ihnen in der Regel zwingend und unrein sind, liegt darin, dass die Toolkits in der Regel zwingend und unrein sind. Der Grund, warum die Toolkits in der Regel zwingend und unrein sind, liegt darin, dass die Betriebssysteme, von denen sie abhängen, in der Regel zwingend und unrein sind. Grundsätzlich muss nichts davon unrein sein: Es gibt funktionale Bindungen für diese Toolkits, funktionale Toolkits und sogar funktionale Betriebssysteme.
Jörg W Mittag
16
Es ist alles nur eine Frage der Faulheit. (Schlechtes Wortspiel beabsichtigt.)
Jörg W Mittag
10
Eines Tages wird das gesamte GUI-Design über WYSIWYG implementiert, wobei die Logik funktional implementiert wird. Das ist meine Vorhersage.
BlueRaja - Danny Pflughoeft
23
Das Papier, das Luqui erwähnt, scheint tot zu sein. Es gibt jedoch einen funktionierenden Link auf Conal Elliotts Website: conal.net/papers/genuuly-functional-guis.pdf
aganders3
74

Meine Frage ist, ist es möglich, einen funktionalen Ansatz für die GUI-Programmierung zu haben?

Die Schlüsselwörter, nach denen Sie suchen, sind "Functional Reactive Programming" (FRP).

Conal Elliott und einige andere haben es sich zur Aufgabe gemacht, die richtige Abstraktion für FRP zu finden. In Haskell gibt es mehrere Implementierungen von FRP-Konzepten.

Sie könnten in Betracht ziehen, mit Conals jüngstem Artikel "Push-Pull Functional Reactive Programming" zu beginnen , aber es gibt mehrere andere (ältere) Implementierungen, von denen einige über die Website haskell.org verlinkt sind . Conal hat ein Händchen für die Abdeckung der gesamten Domäne, und sein Artikel kann ohne Bezugnahme auf das Vorherige gelesen werden.

Um ein Gefühl dafür zu bekommen, wie dieser Ansatz für die GUI-Entwicklung verwendet werden kann, sollten Sie sich Fudgets ansehen , das, obwohl es heutzutage etwas langwierig wird und Mitte der 90er Jahre entwickelt wurde, einen soliden FRP-Ansatz darstellt zum GUI-Design.

Edward Kmett
quelle
Ich möchte die zunehmende Verwendung von "Reactive Extensions" (FRP-Bibliotheken; jedoch nicht FP) hinzufügen, die ursprünglich für C # geschrieben und dann auf Java (RxJava) und JavaScript (RxJS) und verschiedene Sprachen portiert wurden. Schauen Sie sich reactivex.io an. An diesem Punkt nutzt Angular 2 RxJS in großem Umfang.
srph
63

Windows Presentation Foundation ist ein Beweis dafür, dass der funktionale Ansatz für die GUI-Programmierung sehr gut funktioniert. Es hat viele funktionale Aspekte und "guter" WPF-Code (Suche nach MVVM-Muster) betont den funktionalen Ansatz gegenüber dem Imperativ. Ich könnte mutig behaupten, dass WPF das erfolgreichste funktionale GUI-Toolkit der realen Welt ist :-)

WPF beschreibt die Benutzeroberfläche in XAML (obwohl Sie sie auch in C # oder F # umschreiben können), um eine Benutzeroberfläche zu erstellen, die Sie schreiben würden:

<!-- Declarative user interface in WPF and XAML --> 
<Canvas Background="Black">
   <Ellipse x:Name="greenEllipse" Width="75" Height="75" 
      Canvas.Left="0" Canvas.Top="0" Fill="LightGreen" />
</Canvas>

Darüber hinaus können Sie mit WPF Animationen und Reaktionen auf Ereignisse mithilfe eines anderen Satzes deklarativer Tags deklarativ beschreiben (dasselbe kann auch als C # / F # -Code geschrieben werden):

<DoubleAnimation
   Storyboard.TargetName="greenEllipse" 
   Storyboard.TargetProperty="(Canvas.Left)"
   From="0.0" To="100.0" Duration="0:0:5" />

Tatsächlich denke ich, dass WPF viele Gemeinsamkeiten mit Haskells FRP hat (obwohl ich glaube, dass WPF-Designer nichts über FRP wussten und es ein bisschen unglücklich ist - WPF fühlt sich manchmal etwas seltsam und unklar an, wenn Sie die Funktion verwenden Perspektive).

Tomas Petricek
quelle
12
Während XAML sehr deklarativ ist, fördert MVVM wirklich einen funktionalen Programmierstil? Die ganze Vorstellung eines Ansichtsmodells, dessen Aufgabe es ist, den Status der Ansicht zu verfolgen (und eine Schnittstelle zu implementieren, die ausgerechnet aufgerufen wird INotifyPropertyChanged), scheint FP im Widerspruch zu stehen. Ich bin definitiv kein Experte für FP, und vielleicht konzentriere ich mich zu sehr auf den Unveränderlichkeitsaspekt im Gegensatz zum deklarativen Aspekt, aber ich habe Probleme zu erkennen, wie das MVVM-Muster (wie es normalerweise verwendet wird) ein Beispiel für FP ist.
Devuxer
1
@ Devuxer Ich würde argumentieren, dass es tut. Ich glaube nicht, dass irgendjemand FP realistisch für streng unveränderlichen Code verwenden würde. Stattdessen entscheiden Sie, wo sich Ihre Veränderbarkeitsgrenzen befinden, und arbeiten auf allen anderen Ebenen unveränderlich. In diesem Fall kann jeder davon ausgehen, dass der Zustand unveränderlich ist, mit Ausnahme des einzelnen winzigen Teils, der den Zustand tatsächlich mutiert. Es funktioniert ähnlich wie HTML - ja, Sie haben das unveränderliche DOM, aber wenn Sie navigieren, müssen Sie immer noch ein neues erstellen. INotifyPropertyChangedist nur eine Update-Funktion, die Sie überall dort übergeben, wo Sie die GUI-Updates durchführen müssen - es handelt sich um eine Latenz-Korrektur.
Luaan
3
Steven Pemberton hat 2 großartige Beiträge zu F # und WPF geschrieben. Seine Gedanken zur WPF-Entwicklung mit F # gegen Ende des zweiten Beitrags ergänzen diese Diskussion. 2 weitere Beispiele, die mich ebenfalls faszinierten, waren die Verwendung eines funktionalen Controllers in ereignisgesteuerter MVVM und die Verwendung diskriminierter Gewerkschaften und Rekursionen zum Erstellen einer einfachen Schnittstelle in der WPF-Steuerungsdemo von Flying Frog Consultancy.
Funk
29

Ich würde tatsächlich sagen, dass die funktionale Programmierung (F #) ein viel besseres Werkzeug für die Programmierung der Benutzeroberfläche ist als zum Beispiel C #. Sie müssen nur ein wenig anders über das Problem nachdenken.

Ich diskutiere dieses Thema in meinem funktionalen Programmierbuch in Kapitel 16, aber es gibt einen kostenlosen Auszug , der (IMHO) das interessanteste Muster zeigt, das Sie in F # verwenden können. Angenommen, Sie möchten das Zeichnen von Rechtecken implementieren (Benutzer drückt die Taste, bewegt die Maus und lässt die Taste los). In F # können Sie so etwas schreiben:

let rec drawingLoop(clr, from) = async { 
   // Wait for the first MouseMove occurrence 
   let! move = Async.AwaitObservable(form.MouseMove) 
   if (move.Button &&& MouseButtons.Left) = MouseButtons.Left then 
      // Refresh the window & continue looping 
      drawRectangle(clr, from, (move.X, move.Y)) 
      return! drawingLoop(clr, from) 
   else
      // Return the end position of rectangle 
      return (move.X, move.Y) } 

let waitingLoop() = async { 
   while true do
      // Wait until the user starts drawing next rectangle
      let! down = Async.AwaitObservable(form.MouseDown) 
      let downPos = (down.X, down.Y) 
      if (down.Button &&& MouseButtons.Left) = MouseButtons.Left then 
         // Wait for the end point of the rectangle
         let! upPos = drawingLoop(Color.IndianRed, downPos) 
         do printfn "Drawn rectangle (%A, %A)" downPos upPos }

Dies ist ein sehr zwingender Ansatz (im üblichen pragmatischen F # -Stil), der jedoch die Verwendung eines veränderlichen Zustands zum Speichern des aktuellen Zeichnungszustands und zum Speichern der Anfangsposition vermeidet. Es kann jedoch noch funktionaler gestaltet werden. Ich habe eine Bibliothek geschrieben, die dies im Rahmen meiner Masterarbeit tut und in den nächsten Tagen auf meinem Blog verfügbar sein sollte .

Funktionale reaktive Programmierung ist ein funktionalerer Ansatz, aber ich finde es etwas schwieriger, ihn zu verwenden, da er auf ziemlich fortgeschrittenen Haskell-Funktionen (wie Pfeilen) beruht. Es ist jedoch in vielen Fällen sehr elegant. Die Einschränkung besteht darin, dass Sie eine Zustandsmaschine nicht einfach codieren können (was ein nützliches mentales Modell für reaktive Programme ist). Dies ist mit der obigen F # -Technik sehr einfach.

Tomas Petricek
quelle
7
+1 Dies spiegelt unsere Erfahrung wider, mehrere Produktions-GUIs in F # unter Verwendung von Kombinatorbibliotheken und geschrieben zu haben IObservable.
Jon Harrop
Hat sich der Kommentar zu FRP seit der Einführung reaktiver Erweiterungen in der .NET-Bibliothek geändert?
Fsharp Pete
1
Hier einige Untersuchungen zu Arrowized FRP und wie Effekte und Mutationen in Arrowized FRP eingebettet werden können, ohne gegen die Gesetze zu verstoßen: haskell.cs.yale.edu/wp-content/uploads/2015/10/… (Übrigens verwenden die meisten FRP-Bibliotheken Monaden oder sogar Bewerber, daher ist es nicht korrekt, dass Pfeile erforderlich sind.
Erik Kaplun
17

Egal, ob Sie in einer hybriden funktionalen / OO-Sprache wie F # oder OCaml oder in einer rein funktionalen Sprache wie Haskell arbeiten, in der Nebenwirkungen auf die E / A-Monade verwiesen werden, es ist meistens so , dass eine Menge Arbeit für die Verwaltung einer GUI erforderlich ist ist viel mehr wie ein "Nebeneffekt" als wie ein rein funktionaler Algorithmus.

Trotzdem wurden einige wirklich solide Untersuchungen zu funktionalen GUIs durchgeführt . Es gibt sogar einige (meistens) funktionale Toolkits wie Fudgets oder FranTk .

sblom
quelle
6
Link "funktionale GUIs" defekt :( zwischengespeichert: webcache.googleusercontent.com/search?q=cache:http://…
Dan Burton
12

Eine der aufschlussreichen Ideen hinter Functional Reactive Programming ist eine Ereignisbehandlungsfunktion, die sowohl eine Reaktion auf Ereignisse als auch die nächste Ereignisbehandlungsfunktion erzeugt. Somit wird ein sich entwickelndes System als eine Folge von Ereignisbehandlungsfunktionen dargestellt.

Für mich wurde das Erlernen von Yampa zu einem entscheidenden Punkt, um diese funktionsproduzierenden Funktionen richtig zu machen. Es gibt einige nette Papiere über Yampa. Ich empfehle The Yampa Arcade:

http://www.cs.nott.ac.uk/~nhn/Talks/HW2003-YampaArcade.pdf (Folien, PDF) http://www.cs.nott.ac.uk/~nhn/Publications/hw2003. pdf (vollständiger Artikel, PDF)

Es gibt eine Wiki-Seite auf Yampa bei Haskell.org

http://www.haskell.org/haskellwiki/Yampa

Original Yampa Homepage:

http://www.haskell.org/yampa (ist momentan leider kaputt)

Boris Berkgaut
quelle
1
Diese Verbindung ist seit langem unterbrochen. Versuchen Sie diese Yampa
CoR
7

Seit diese Frage zum ersten Mal gestellt wurde, hat Elm die funktionale reaktive Programmierung etwas mehr zum Mainstream gemacht.

Ich schlage vor, es unter http://elm-lang.org zu lesen , wo es auch einige wirklich hervorragende interaktive Tutorials gibt, wie man eine voll funktionsfähige GUI im Browser erstellt.

Sie können damit voll funktionsfähige GUIs erstellen, bei denen der Code, den Sie selbst bereitstellen müssen, nur aus reinen Funktionen besteht. Ich persönlich fand es viel einfacher, in die verschiedenen Haskell-GUI-Frameworks einzusteigen.

saolof
quelle
Hier ist die ursprüngliche FRP-These hinter Elm . Aber auch seit Mai 2016 ist Elm keine FRP-Sprache mehr .
icc97
6

Elliots Vortrag über FRP finden Sie hier .

Außerdem nicht wirklich eine Antwort, sondern eine Bemerkung und ein paar Gedanken : Irgendwie scheint der Begriff "funktionale GUI" ein bisschen wie ein Oxymoron zu sein (Reinheit und E / A im selben Begriff).

Mein vages Verständnis ist jedoch, dass es bei der funktionalen GUI-Programmierung darum geht, eine zeitabhängige Funktion deklarativ zu definieren, die die (Echtzeit-) abhängige Benutzereingabe verwendet und eine zeitabhängige GUI-Ausgabe erzeugt.

Mit anderen Worten, diese Funktion wird deklarativ wie eine Differentialgleichung definiert, anstatt durch einen Algorithmus, der zwingend einen veränderlichen Zustand verwendet.

In herkömmlichen FP werden zeitunabhängige Funktionen verwendet, während in FRP zeitabhängige Funktionen als Bausteine ​​zur Beschreibung eines Programms verwendet werden.

Denken wir darüber nach, einen Ball auf einer Feder zu simulieren, mit dem der Benutzer interagieren kann. Die Position des Balls ist die grafische Ausgabe (auf dem Bildschirm). Der Benutzer, der den Ball drückt, ist ein Tastendruck (Eingabe).

Die Beschreibung dieses Simulationsprogramms in FRP (nach meinem Verständnis) erfolgt durch eine einzige Differentialgleichung (deklarativ): Beschleunigung * Masse = - Federdehnung * Federkonstante + vom Benutzer ausgeübte Kraft.

Hier ist ein Video zu ELM , das diesen Standpunkt veranschaulicht.

jhegedus
quelle
5

Ab 2016 gibt es für Haskell mehrere relativ ausgereifte FRP-Frameworks wie Natrium und Reflex (aber auch Netwire).

Das Manning-Buch über funktionale reaktive Programmierung zeigt anhand von Arbeitsbeispielen die Java-Version von Sodium und zeigt, wie sich eine FRP-GUI-Codebasis im Vergleich zu imperativen und aktorbasierten Ansätzen verhält und skaliert.

Es gibt auch ein kürzlich veröffentlichtes Papier über Arrowized FRP und die Aussicht, Nebenwirkungen, IO und Mutation in eine gesetzestreue, reine FRP-Einstellung einzubeziehen: http://haskell.cs.yale.edu/wp-content/uploads/2015/10/ dwc-yale-formatierte-dissertation.pdf .

Erwähnenswert ist auch, dass JavaScript-Frameworks wie ReactJS und Angular und viele andere entweder bereits einen FRP oder einen anderen funktionalen Ansatz zur Erzielung skalierbarer und zusammensetzbarer GUI-Komponenten verwenden oder verwenden.

Erik Kaplun
quelle
Natrium wurde zugunsten von reaktiver Banane gemäß der Github-Readme-
Datei
4

Mit Markup-Sprachen wie XUL können Sie eine GUI deklarativ erstellen.

StackedCrooked
quelle
3

Um dies zu beheben, habe ich einige meiner Gedanken zur Verwendung von F # gepostet.

http://fadsworld.wordpress.com/2011/04/13/f-in-the-enterprise-i/ http://fadsworld.wordpress.com/2011/04/17/fin-the-enterprise-ii- 2 /

Ich plane auch ein Video-Tutorial, um die Serie zu beenden und zu zeigen, wie F # zur UX-Programmierung beitragen kann.

Ich spreche hier nur im Zusammenhang mit F #.

-Fahad

Fahad
quelle
2

Alle diese anderen Antworten basieren auf funktionaler Programmierung, treffen jedoch viele eigene Entwurfsentscheidungen. Eine Bibliothek, die im Wesentlichen vollständig aus Funktionen und einfachen abstrakten Datentypen besteht, ist gloss. Hier ist der Typ für seine playFunktion aus der Quelle

-- | Play a game in a window. Like `simulate`, but you manage your own input events.
play    :: Display              -- ^ Display mode.
        -> Color                -- ^ Background color.
        -> Int                  -- ^ Number of simulation steps to take for each second of real time.
        -> world                -- ^ The initial world.
        -> (world -> Picture)   -- ^ A function to convert the world a picture.
        -> (Event -> world -> world)    
                -- ^ A function to handle input events.
        -> (Float -> world -> world)
                -- ^ A function to step the world one iteration.
                --   It is passed the period of time (in seconds) needing to be advanced.
        -> IO ()

Wie Sie sehen können, funktioniert es vollständig, indem reine Funktionen mit einfachen abstrakten Typen bereitgestellt werden, bei denen andere Bibliotheken Ihnen helfen.

PyRulez
quelle
1

Die offensichtlichste Neuerung, die Menschen in Haskell bemerken, ist die Trennung zwischen der unreinen Welt, die sich mit der Kommunikation mit der Außenwelt befasst, und der reinen Welt der Berechnungen und Algorithmen. Eine häufige Anfängerfrage lautet: "Wie kann ich loswerden IO, dh konvertieren IO ain a?" Der Weg dorthin besteht darin, Monaden (oder andere Abstraktionen) zu verwenden, um Code zu schreiben, der E / A- und Ketteneffekte ausführt. Dieser Code sammelt Daten aus der Außenwelt, erstellt ein Modell davon, führt einige Berechnungen durch, möglicherweise unter Verwendung von reinem Code, und gibt das Ergebnis aus.

Was das obige Modell betrifft, sehe ich nichts Schreckliches daran, GUIs in der IOMonade zu manipulieren . Das größte Problem, das sich aus diesem Stil ergibt, ist, dass Module nicht mehr zusammensetzbar sind, dh ich verliere den größten Teil meines Wissens über die globale Ausführungsreihenfolge von Anweisungen in meinem Programm. Um es wiederherzustellen, muss ich ähnliche Überlegungen anstellen wie im gleichzeitigen, zwingenden GUI-Code. Für unreinen Nicht-GUI-Code ist die Ausführungsreihenfolge aufgrund der Definition des IOMonadenoperators offensichtlich >==(mindestens solange nur ein Thread vorhanden ist). Für reinen Code spielt es keine Rolle, außer in Eckfällen, um die Leistung zu steigern oder Auswertungen zu vermeiden, die dazu führen .

Der größte philosophische Unterschied zwischen Konsole und grafischer E / A besteht darin, dass Programme, die erstere implementieren, normalerweise synchron geschrieben werden. Dies ist möglich, weil es (abgesehen von Signalen und anderen offenen Dateideskriptoren) nur eine Ereignisquelle gibt: den allgemein aufgerufenen Bytestream stdin. GUIs sind jedoch von Natur aus asynchron und müssen auf Tastaturereignisse und Mausklicks reagieren.

Eine beliebte Philosophie, asynchrone E / A auf funktionale Weise auszuführen, heißt Functional Reactive Programming (FRP). Dank Bibliotheken wie ReactiveX und Frameworks wie Elm hat es in letzter Zeit in unreinen, nicht funktionierenden Sprachen viel Anklang gefunden. Kurz gesagt, es ist so, als würde man GUI-Elemente und andere Dinge (wie Dateien, Uhren, Alarme, Tastatur, Maus) als Ereignisquellen, sogenannte "Observables", anzeigen, die Ereignisströme ausgeben. Diese Ereignisse werden mit dem bekannten Operatoren wie map, foldl, zip, filter, concat, join, etc., um neue Streams zu erzeugen. Dies ist nützlich, da der Programmstatus selbst ab scanl . map reactToEvents $ zipN <eventStreams>dem Programm gesehen werden kann, wobei dies Nder Anzahl der Observablen entspricht, die jemals vom Programm berücksichtigt wurden.

Durch die Arbeit mit FRP-Observablen kann die Kompositionsfähigkeit wiederhergestellt werden, da Ereignisse in einem Stream rechtzeitig geordnet werden. Der Grund dafür ist, dass die Ereignisstromabstraktion es ermöglicht, alle Observablen als Black Boxes anzuzeigen. Letztendlich gibt das Kombinieren von Ereignisströmen mit Operatoren bei der Ausführung eine lokale Reihenfolge zurück. Dies zwingt mich, viel ehrlicher darüber zu sein, auf welche Invarianten sich mein Programm tatsächlich stützt, ähnlich wie alle Funktionen in Haskell referenziell transparent sein müssen: Wenn ich Daten aus einem anderen Teil meines Programms abrufen möchte, muss ich explizit sein Anzeige deklarieren Sie einen geeigneten Typ für meine Funktionen. (Die E / A-Monade, eine domänenspezifische Sprache zum Schreiben von unreinem Code, umgeht dies effektiv.)

MauganRa
quelle
-22

Die funktionale Programmierung mag sich seit meinem Studium weiterentwickelt haben, aber wie ich mich erinnere, bestand der Hauptpunkt eines funktionalen Programmiersystems darin, den Programmierer daran zu hindern, „Nebenwirkungen“ zu verursachen. Benutzer kaufen jedoch Software aufgrund der Nebenwirkungen, die entstehen, z. B. beim Aktualisieren einer Benutzeroberfläche.

Ian Ringrose
quelle
25
Ich denke, Sie haben den Punkt falsch verstanden: Es ist nicht so, dass funktionale Programmierung keine äußeren Auswirkungen auf die Welt hat - das würde alle Programme völlig unbrauchbar machen! Mit der funktionalen Programmierung können Sie das E / A unter Quarantäne stellen, damit Sie wissen, welche Bits es verwenden und welche nicht.
Tikhon Jelvis
Whoooooooosh x20