Reaktive Programmierung
Vorlesung 1 vom 14.04.15: Was ist Reaktive Programmierung?
Christoph Lüth & Martin Ring
Universität Bremen Sommersemester 2014
16:09:52 2015-04-21 1 [36]
Organisatorisches
I Vorlesung: Donnerstags 8-10, MZH 1450
I Übung: Dienstags 16-18, MZH 1460 (nach Bedarf)
I Webseite:www.informatik.uni-bremen.de/~cxl/lehre/rp.ss15
I Scheinkriterien:
IVoraussichtlich 6 Übungsblätter
IAlle bearbeitet, insgesamt 40% (Notenspiegel PI3)
IÜbungsgruppen 2 – 4 Mitglieder
IFachgespräch am Ende
2 [36]
Warum Reaktive Programmierung?
Herkömmliche Programmiersprachen:
IC, C++
IJavaScript, Ruby, PHP, Python IJava
I(Haskell) Eigenschaften:
IImperativundprozedural ISequentiell
Zugrundeliegendes Paradigma:
. . . aber die Welt ändert sich:
I DasNetzverbindet Rechner I Selbst eingebettete Systeme sind
vernetzt (Auto: ca. 100 Proz.) I Mikroprozessoren sindmehrkernig I Systeme sindeingebettet,
nebenläufig,reagierenauf ihre Umwelt.
3 [36]
Probleme mit dem herkömmlichen Ansatz
Programm
Daten Eingabe
Ausgabe
Daten Programm
Eingabe Ausgabe
Daten Programm
Eingabe Ausgabe
Eingabe
Ausgabe Programm Daten
Eingabe Ausgabe
Eingabe Ausgabe
Eingabe
Ausgabe
Daten Programm
Eingabe Ausgabe
Eingabe Ausgabe
Eingabe
Ausgabe Eingabe Ausgabe
Daten Programm
Eingabe Ausgabe
Eingabe Ausgabe
Eingabe Ausgabe
Eingabe
Ausgabe Eingabe Ausgabe
IProblem:Nebenläufigkeit INebenläufigkeit verursacht
Synchronisationsprobleme IBehandlung:
I Callbacks (JavaScript)
I Events (Java)
I Global Locks (Python, Ruby)
I Programmiersprachenkonstrukte:
Locks, Semaphoren, Monitore
4 [36]
Amdahl’s Law
“The speedup of a program using multiple processors in parallel computing is limited by the sequential fraction of the program. For example, if 95% of the program can be parallelized, the theoretical maximum speedup using parallel computing would be 20×as shown in the diagram, no matter how many processors are used.”
20.00 18.00 16.00 14.00 12.00 10.00 8.00 6.00 4.00 2.00 0.00
Speedup 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536
NumberLofLProcessors Amdahl’sLLaw
ParallelLPortion 50%
75%
90%
95%
Quelle: Wikipedia
5 [36]
The Reactive Manifesto
I http://www.reactivemanifesto.org/
Responsive
Resilient
Message Driven Elastic
6 [36]
Was ist Reaktive Programmierung?
I ImperativeProgrammierung: Zustandsübergang
I ProzeduralundOO: Verkapselter Zustand
I FunktionaleProgrammierung: Abbildung (mathematische Funktion)
I ReaktiveProgrammierung:
1.Datenabhängigkeit
2.Reaktiv=funktional+nebenläufig
Datenflusssprachen (data flow languages)
I Frühe Sprachen: VAL, SISAL, ID, LUCID (1980/1990)
I Heutige Sprachen: Esterel, Lustre (Gérard Berry, Verimag)
IKeineZuweisungen, sondernDatenfluss
ISynchron:alle Aktionen ohne Zeitverzug
IVerwendung in der Luftfahrtindustrie (Airbus)
Fahrplan
I Teil I: Grundlegende Konzepte
I Was ist Reaktive Programmierung?
I Nebenläufigkeit und Monaden in Haskell
I Funktional-Reaktive Programmierung
I Einführung in Scala
I Die Scala Collections
I ScalaCheck
I Teil II: Nebenläufigkeit
I Teil III: Fortgeschrittene Konzepte
9 [36]
Fahrplan
I Teil I: Grundlegende Konzepte
I Teil II: Nebenläufigkeit
IFutures and Promises
IReaktive Datenströme I
IReaktive Datenströme II
IDas Aktorenmodell
IAktoren und Akka
I Teil III: Fortgeschrittene Konzepte
10 [36]
Fahrplan
I Teil I: Grundlegende Konzepte
I Teil II: Nebenläufigkeit
I Teil III: Fortgeschrittene Konzepte
I Bidirektionale Programmierung: Zippers and Lenses
I Robustheit, Entwurfsmuster
I Theorie der Nebenläufigkeit
11 [36]
Rückblick Haskell
I Definition von Funktionen:
Ilokale Definitionen mitletundwhere
IFallunterscheidung undguarded equations
IAbseitsregel
IFunktionen höherer Ordnung
I Typen:
IBasisdatentypen:Int,Integer,Rational,Double,Char,Bool
IStrukturierte Datentypen:[a],(a, b)
IAlgebraische Datentypen:data Maybe a = Just a | Nothing
12 [36]
Rückblick Haskell
I Abstrakte Datentypen
I Module
I Typklassen
I Verzögerte Auswertung und unendliche Datentypen
13 [36]
Ein- und Ausgabe in Haskell
Umwelt Haskell
Aktionen
Umwelt Reine
Funktionen
Haskell
Problem:
IFunktionen mit Seiteneffekten nicht referentiell transparent.
I readString :: . . .→String??
Lösung:
ISeiteneffekte am Typ erkennbar IAktionenkönnennurmit
Aktionenkomponiert werden I„einmal Aktion, immer Aktion“
14 [36]
Aktionen als abstrakter Datentyp
I ADT mit OperationenKompositionundLifting
I Signatur:
typeIOα
(=) :: IOα→ (α→IOβ) →IOβ return :: α→ IOα
I PluselementareOperationen (lesen, schreiben etc)
Elementare Aktionen
I Zeile vonstdinlesen:
getLine :: IO String
I Zeichenkette aufstdoutausgeben:
putStr :: String→ IO ()
I Zeichenkette mit Zeilenvorschubausgeben:
putStrLn :: String→ IO ()
Einfache Beispiele
I Echoeinfach echo1 :: IO ()
echo1 = getLine= putStrLn I Echomehrfach
echo :: IO ()
echo = getLine= putStrLn=λ_→ echo I Was passiert hier?
I Verknüpfenvon Aktionen mit=
I Jede Aktion gibtWertzurück
17 [36]
Noch ein Beispiel
I Umgekehrtes Echo:
ohce :: IO () ohce = getLine
=λs→ putStrLn ( reverse s ) ohce
I Was passiert hier?
IReineFunktionreversewird innerhalb vonAktionputStrLngenutzt
IFolgeaktionohcebenötigtWertder vorherigen Aktion nicht
IAbkürzung:
pq = p=λ_→ q
18 [36]
Die do-Notation
I Syntaktischer Zucker fürIO:
echo = getLine
=λs→ putStrLn s echo
⇐⇒
echo =
do s← getLine putStrLn s echo
I Rechts sind=,implizit.
I Es gilt dieAbseitsregel.
I Einrückungderersten Anweisungnachdobestimmt Abseits.
19 [36]
Drittes Beispiel
I Zählendes, endliches Echo echo3 :: Int→ IO () echo3 cnt =do
putStr (show cnt ++ " : ␣" ) s← getLine
i f s6= "" then do
putStrLn $ show cnt ++ " : ␣"++ s echo3 ( cnt+ 1)
else return () I Was passiert hier?
IKombinationausKontrollstrukturenundAktionen
IAktionenalsWerte
IGeschachteltedo-Notation
20 [36]
Module in der Standardbücherei
I Ein/Ausgabe, Fehlerbehandlung (ModulIO) I Zufallszahlen (ModulRandom)
I Kommandozeile, Umgebungsvariablen (ModulSystem) I Zugriff auf das Dateisystem (ModulDirectory) I Zeit (ModulTime)
21 [36]
Ein/Ausgabe mit Dateien
I ImPreludevordefiniert:
IDateien schreiben (überschreiben, anhängen):
type FilePath = String
w r i t e F i l e :: FilePath → String →IO () appendFile :: FilePath → String →IO () I Datei lesen (verzögert):
readFile :: FilePath →IO String I Mehr Operationenim ModulIOder Standardbücherei
IBuffered/Unbuffered, Seeking, &c.
IOperationen aufHandle
22 [36]
Beispiel: Zeichen, Wörter, Zeilen zählen (wc)
wc :: String→IO () wc f i l e =
docont ← readFile f i l e putStrLn $ f i l e ++ " : ␣"++
show ( length ( l i n e s cont ) , length (words cont ) , length cont ) I Datei wird gelesen
I Anzahl Zeichen, Worte, Zeilen gezählt
Aktionen als Werte
I AktionensindWertewie alle anderen.
I DadurchDefinitionvonKontrollstrukturenmöglich.
I Endlosschleife:
forever :: IO α→IOα forever a = aforever a I Iteration (feste Anzahl):
forN :: Int→IOα→ IO () forN n a | n == 0 = return ()
| otherwise = aforN (n−1) a I VordefinierteKontrollstrukturen (Control .Monad):
Iwhen,mapM,forM,sequence, . . .
Map und Filter für Aktionen
I Listen von Aktionen sequenzieren:
sequence :: [ IO a ]→ IO [ a ] sequence_ :: [ IO ( ) ]→IO () I Map für Aktionen:
mapM :: (a→IO b)→ [ a ]→IO [ b ] mapM_ :: (a→ IO ())→ [ a ]→IO () I Filter für Aktionen
I Importieren mitimport Monad (filterM).
filterM :: (a →IO Bool) → [ a ] →IO [ a ]
25 [36]
Fehlerbehandlung
I Fehlerwerden durchExceptionrepräsentiert
IExceptionistTypklasse— kann durch eigene Instanzen erweitert werden
IVordefinierte Instanzen: u.a.IOError
I FehlerbehandlungdurchAusnahmen(ähnlich Java) catch :: Exception e⇒ IOα→ (e→ IOα) →IOα try :: Exception e⇒ IOα→IO ( Either e a)
I Faustregel:catchfür unerwartete Ausnahmen,tryfür erwartete I Fehlerbehandlungnur in Aktionen
26 [36]
Fehler fangen und behandeln
I Fehlerbehandlung fürwc:
wc2 :: String→ IO () wc2 f i l e =
catch (wc f i l e )
(λe → putStrLn $ " Fehler : ␣"++ show (e :: IOException ))
I IOErrorkann analysiert werden (sieheSystem.IO.Error) I readmit Ausnahme bei Fehler (statt Programmabbruch):
readIO :: Read a⇒ String→IO a
27 [36]
Ausführbare Programme
I Eigenständiges Programm istAktion
I Hauptaktion:main :: IO ()in ModulMain I wcals eigenständiges Programm:
moduleMainwhere
importSystem . Environment ( getArgs ) importControl . Exception
. . .
main :: IO () main =do
args ← getArgs mapM_ wc2 args
28 [36]
So ein Zufall!
I Zufallswerte:
randomRIO :: (α,α)→ IOα
I Warum istrandomIOAktion?
I Beispiele:
I Aktion zufällig oft ausführen:
atmost :: Int→IOα→IO [α]
atmost most a =
dol←randomRIO (1 , most) sequence ( r e p l i c a t e l a)
I Zufälligen String erzeugen:
randomStr :: IO String
randomStr = atmost 40 (randomRIO ( ’ a ’ , ’ z ’ ) )
29 [36]
Funktionen mit Zustand
I Idee: Seiteneffektexplizitmachen
I Funktionf:A→Bmit Seiteneffekt inZustandS:
f :A×S→B×S
∼=
f :A→S→B×S
I Datentyp:S→B×S
I Komposition: Funktionskomposition unduncurry
30 [36]
In Haskell: Zustände explizit
I Datentyp: Berechnung mit Seiteneffekt in Typσ(polymorph überα) type State σ α=σ→ (α, σ)
I Komposition zweier solcher Berechnungen:
comp :: Stateσ α→ (α→ Stateσ β)→ State σ β comp f g = uncurry g◦f
I Lifting:
l i f t :: α→ State σ α l i f t = curry id
Beispiel: Ein Zähler
I Datentyp:
typeWithCounterα= State Int α I Zähler erhöhen:
t i c k :: WithCounter () t i c k i = ( ( ) , i+1) I Zähler auslesen:
read :: WithCounter Int read i = ( i , i ) I Zähler zurücksetzen:
reset :: WithCounter () reset i = ( ( ) , 0)
Implizite vs. explizite Zustände
I Nachteil: Zustand istexplizit
I Kanndupliziertwerden
I Daher: Zustandimplizitmachen
I Datentypverkapseln
I SignaturState , comp, lift, elementare Operationen I Beispiel für eineMonade
I Generische Datenstruktur, dieVerkettungvonBerechnungenerlaubt
33 [36]
Aktionen als Zustandstransformationen
I Idee: Aktionen sindTransformationenauf SystemzustandS
I Sbeinhaltet
ISpeicher als AbbildungA*V(AdressenA, WerteV)
IZustand des Dateisystems
IZustand des Zufallsgenerators
I In Haskell: TypRealWorld
typeIOα= State RealWorldα −−... oder so ähnlich
I“Virtueller” Typ, Zugriff nur über elementare Operationen
IEntscheidend nurReihenfolgeder Aktionen
34 [36]
War das jetzt reaktiv?
I Haskell istfunktional
I Für eine reaktive Sprache fehltNebenläufigkeit
I Nächste Vorlesung: Concurrent Haskell
I Damit könnten wir die Konzepte dieser VL modellieren
I Besser:Scala = Funktional + JVM
35 [36]
Zusammenfassung
I Reaktive Programmierung: Beschreibung derAbhängigkeitvon Daten
I Rückblick Haskell:
IAbhängigkeit von Aussenwelt in TypIOkenntlich
IBenutzung von IO: vordefinierte Funktionen in der Haskell98 Bücherei
IWerte vom TypIO(Aktionen) können kombiniert werden wie alle anderen I Nächstes Mal:
IMonaden und Nebenläufigkeit in Haskell
36 [36]