• Keine Ergebnisse gefunden

Reaktive Programmierung Vorlesung 12 vom 07.06.17: Funktional-Reaktive Programmierung

N/A
N/A
Protected

Academic year: 2022

Aktie "Reaktive Programmierung Vorlesung 12 vom 07.06.17: Funktional-Reaktive Programmierung"

Copied!
16
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Reaktive Programmierung

Vorlesung 12 vom 07.06.17: Funktional-Reaktive Programmierung

Christoph Lüth, Martin Ring

Universität Bremen

Sommersemester 2017

(2)

Fahrplan

I

Einführung

I

Monaden als Berechnungsmuster

I

Nebenläufigkeit: Futures and Promises

I

Aktoren I: Grundlagen

I

Aktoren II: Implementation

I

Bidirektionale Programmierung

I

Meta-Programmierung

I

Reaktive Ströme I

I

Reaktive Ströme II

I

Functional Reactive Programming

I

Software Transactional Memory

I

Eventual Consistency

I

Robustheit und Entwurfsmuster

I

Theorie der Nebenläufigkeit, Abschluss

(3)

Das Tagemenü

I

Funktional-Reaktive Programmierung (FRP) ist rein funktionale, reaktive Programmierung.

I

Sehr abstraktes Konzept — im Gegensatz zu Observables und Aktoren.

I

Literatur: Paul Hudak, The Haskell School of Expression, Cambridge University Press 2000, Kapitel 13, 15, 17.

I Andere (effizientere) Implementierung existieren.

(4)

FRP in a Nutshell

Zwei Basiskonzepte:

I

Kontinuierliches, über der Zeit veränderliches Verhalten:

type

Time = Float

type

Behaviour a = Time

a

Time a

I

Beispiel: Position eines Objektes

I

Diskrete Ereignisse zu einem bestimmten Zeitpunkt:

type

Event a = [ (Time, a) ]

Time a

I

Beispiel: Benutzereingabe

Obige Typdefinitionen sind Spezifikation, nicht Implementation

(5)

Verhalten: erste einfache Beispiele

I

Ein kreisender und ein pulsierender Ball:

ci rc , pulse :: Behavior Region

c i r c = t r a n s l a t e ( cos time , s i n time) ( e l l 0.2 0.2) pulse = e l l ( cos time ∗ 0.5) ( cos time ∗ 0.5)

I

Was passiert hier?

I Basisverhalten:time :: Behaviour Time,constB :: a →Behavior a

I Grafikbücherei: DatentypRegion, Funktion Ellipse

I Liftings (∗, 0.5, sin, . . . )

(6)

Lifting

I

Um einfach mit Behaviour umgehen zu können, werden Funktionen zu Behaviour geliftet:

($∗) :: Behavior (a→b)

Behavior a

Behavior b l i f t 1 :: (a

b)

( Behavior a

Behavior b)

I Gleiches mit lift2, lift3,. . .

I

Damit komplexere Liftings (für viele andere Typklassen):

instance

Num a =

>

Num ( Behavior a)

where

(+) = l i f t 2 (+)

instance

Floating a =

>

Floating ( Behavior a)

where

s i n = l i f t 1 s i n

(7)

Reaktive Animationen: Verhaltensänderung

I

Beispiel: auf Knopfdruck Farbe ändern:

color1 :: Behavior Color

color1 = red ‘ untilB ‘ lbp

blue

I

Was passiert hier?

I untilB kombiniert Verhalten:

untilB :: Behavior a → Event ( Behavior a) → Behavior a

I =>> istmapfür Ereignisse:

(=>>) :: Event a → (a→b) → Event b

(−) :: Event a→ b→ Event b

I Kombination von Ereignissen:

( .|. ) :: Event a → Event a → Event a

(8)

Reaktive Animationen: Verhaltensänderung

I

Beispiel: auf Knopfdruck Farbe ändern:

color2 = red ‘ untilB ‘ ( lbp

blue .

|

. key

yellow )

I

Was passiert hier?

I untilB kombiniert Verhalten:

untilB :: Behavior a → Event ( Behavior a) → Behavior a

I =>> istmapfür Ereignisse:

(=>>) :: Event a → (a→b) → Event b

(−) :: Event a→ b→ Event b

I Kombination von Ereignissen:

( .|. ) :: Event a → Event a → Event a

(9)

Der Springende Ball

ball2 = paint red ( t r a n s l a t e (x , y) ( e l l 0.2 0.2) ) where g = −4

x = −3 + i n t e g r a l 0.5 y = 1.5 + i n t e g r a l vy vy = i n t e g r a l g ‘ switch ‘

( hity ‘ snapshot_ ‘ vy =>> λv ’→ l i f t 0 (−v ’ ) + i n t e g r a l g) hity = when (y <∗ −1.5)

I Nützliche Funktionen:

i n t e g r a l :: Behavior Float→ Behavior Float snapshot :: Event a → Behavior b → Event (a , b) Event fe ‘ snapshot ‘ Behavior fb

I Erweiterung: Ball ändert Richtung, wenn er gegen die Wand prallt.

(10)

Der Springende Ball

ball2x = paint red ( t r a n s l a t e (x , y) ( e l l 0.2 0.2) ) where g = −4

x = −3 + i n t e g r a l vx

vx = 0.5 ‘ switch ‘ ( hitx−−vx) hitx = when (x <∗ −3 | | ∗ x >∗ 3) y = 1.5 + i n t e g r a l vy

vy = i n t e g r a l g ‘ switch ‘

( hity ‘ snapshot_ ‘ vy =>> λv ’→ l i f t 0 (−v ’ ) + i n t e g r a l g) hity = when (y <∗ −1.5)

I Nützliche Funktionen:

i n t e g r a l :: Behavior Float→ Behavior Float snapshot :: Event a → Behavior b → Event (a , b) Event fe ‘ snapshot ‘ Behavior fb

I Erweiterung: Ball ändert Richtung, wenn er gegen die Wand prallt.

(11)

Implementation

I

Verhalten, erste Annäherung:

data

Beh1 a = Beh1 ( [ ( UserAction , Time) ]

Time→ a)

I

Problem: Speicherleck und Ineffizienz

I

Analogie: suche in sortierten Listen i n L i s t :: [ Int ]

Int

Bool i n L i s t xs y = elem y xs

manyInList ’ :: [ Int ]

[ Int ]

[ Bool ] manyInList ’ xs ys = map ( i n L i s t xs ) ys

I

Besser Sortiertheit direkt nutzen

(12)

Implementation

I

Verhalten werden inkrementell abgetastet:

data

Beh2 a

= Beh2 ( [ ( UserAction ,Time) ]

[Time]

[ a ] )

I

Verbesserungen:

I Zeit doppelt, nureinmal

I Abtastung auchohne Benutzeraktion

I Currying

data

Behavior a

= Behavior ( ( [Maybe UserAction ] , [ Time] )

[ a ] )

I

Ereignisse sind im Prinzip optionales Verhalten:

data

Event a = Event ( Behaviour (Maybe a) )

(13)

Längeres Beispiel: Pong!

I

Pong besteht aus Paddel, Mauern und einem Ball.

I

Das Paddel:

paddle = paint red ( t r a n s l a t e ( f s t mouse, −1.7) ( rec 0.5 0.05) )

I

Die Mauern:

walls :: Behavior Picture

I

. . . und alles zusammen:

paddleball v e l =

walls ‘ over ‘

paddle ‘ over ‘

pball v e l

(14)

Pong: der Ball

I

Der Ball:

pball v e l =

let xvel = v e l ‘stepAccum ‘ xbounce−negate xpos = i n t e g r a l xvel

xbounce = when (xpos >∗ 2 | | ∗ xpos <∗ −2) yvel = v e l ‘stepAccum ‘ ybounce−negate ypos = i n t e g r a l yvel

ybounce = when (ypos >∗ 1.5

| | ∗ ypos ‘between ‘ (−2.0,−1.5) &&∗

f s t mouse ‘between ‘ (xpos−0.25,xpos+0.25) ) in paint yellow ( t r a n s l a t e (xpos , ypos) ( e l l 0.2 0.2) )

I Ball völlig unabhängig von Paddel und Wänden

I

Nützliche Funktionen:

while , when :: Behavior Bool→ Event () step :: a → Event a → Behavior a

stepAccum :: a → Event (a→a) → Behavior a

(15)

Warum nicht in Scala?

I

Lifting und Typklassen für syntaktischen Zucker

I

Aber: zentrales Konzept sind unendliche Listen (Ströme) mit nicht-strikte Auswertung

I Implementation mit Scala-Listen nicht möglich

I Benötigt:Strömeals unendliche Listen mit effizienter, nicht-strikter Auswertung

I Möglich, aber aufwändig

(16)

Zusammenfassung

I

Funktional-Reaktive Programmierung am Beispiel FAL (Functional Animation Library)

I

Zwei Kernkonzepte: kontinuierliches Verhalten und diskrete Ereignisse

I

Implementiert in Haskell, Systemverhalten als unendlicher Strom von Zuständen

I

Stärke: Erlaubt abstrakte Progammierung von reaktiven Animationen

I

Schwächen:

I Fundamentalnicht-kompositional— ist gibteineHauptfunktion

I Debugging, Fehlerbehandlung, Nebenläufigkeit?

I

Nächste Vorlesung: Software Transactional Memory (STM)

Referenzen

ÄHNLICHE DOKUMENTE

I Systeme sind eingebettet, nebenläufig, reagieren auf ihre Umwelt.... Warum

I Cold Observables fangen erst an Werte zu produzieren, wenn man ihnen zuhört.. Für jeden Observer

[r]

I Promises sind das Gegenstück zu Futures trait Promise {. def complete(result: Try[T]) def

I Werte vom Typ IO (Aktionen) können kombiniert werden wie alle anderen. I

I Aber: zentrales Konzept sind unendliche Listen (Ströme) mit nicht-strikte Auswertung. I Implementation mit Scala-Listen

[r]

I Mengen und Maps sind gleich wenn sie die selben Elemente enthalten:. TreeSet(3,2,1) == HashSet(2,1,3)