Programmtransformationen und Induktion in funktionalen Programmen

Größe: px
Ab Seite anzeigen:

Download "Programmtransformationen und Induktion in funktionalen Programmen"

Transkript

1 Programmtransformationen und Induktion in funktionalen Programmen Prof. Dr. Manfred Schmidt-Schauß Künstliche Intelligenz und Softwaretechnologie 13. Januar 2009

2 Einschub: Monadisches IO verzögern Implementierung von ReadFile: explizit mit Handles (= erweiterte Dateizeiger) -- openfile :: FilePath -> IOMode -> IO Handle -- hgetchar :: Handle -> IO Char readfile :: FilePath -> IO String readfile path = handle <- openfile path ReadMode inhalt <- lesehandleaus handle return inhalt CEFP; Folien Concurrent Haskell - 1 -

3 Handle auslesen: Erster Versuch lesehandleaus handle = ende <- hiseof handle if ende then hclose handle >> return [] else c <- hgetchar handle cs <- lesehandleaus handle return (c:cs) Ineffizient: Komplette Datei wird gelesen, bevor etwas zurück gegeben wird. *Main> writefile "LargeFile" (concat [show i i <- [ ]]) *Main> readfile "LargeFile" >>= print. head 1 (7.09 secs, bytes) CEFP; Folien Concurrent Haskell - 2 -

4 unsafeinterleaveio -- System.IO.Unsafe unsafeinterleaveio :: IO a -> IO a unsafeinterleaveio a = return (unsafeperformio a) bricht strenge Sequentialisierung auf gibt sofort etwas zurück ohne die Aktion auszuführen Aktion wird by-need ausgeführt: erst wenn die Ausgabe vom Typ a in IO a benötigt wird. nicht vereinbar mit Welt -Modell! CEFP; Folien Concurrent Haskell - 3 -

5 Handle auslesen: verzögert lesehandleaus handle = ende <- hiseof handle if ende then hclose handle >> return [] else c <- hgetchar handle cs <- unsafeinterleaveio (lesehandleaus handle) return (c:cs) Test: *Main> writefile "LargeFile" (concat [show i i <- [ ]]) *Main> readfile1 "LargeFile" >>= print. head 1 (0.00 secs, 0 bytes) CEFP; Folien Concurrent Haskell - 4 -

6 Nebenläufige Programmierung Concurrent Haskell Concurrent Haskell = Erweiterung von Haskell Vorgeschlagen: 1996 (Peyton Jones, Gorn, Finne) Neue Konstrukte (in Bibliothek: Control.Concurrent) zum Erzeugen nebenläufiger Threads eine neue primitive Operation zur Kommunikation / Synchronisation von Threads ein neuer Datentyp mit drei primitiven Operationen CEFP; Folien Concurrent Haskell - 5 -

7 Erzeugen eines nebenläufigen Threads forkio :: IO () -> IO ThreadId forkio t wertet t in nebenläufigen Thread aus Im Haupthread: sofortiges Ergebnis = eindeutige ID Hauptthread läuft weiter Ende des Hauptthreads beendet alle nebenläufigen. GHC: killthread :: ThreadId -> IO () CEFP; Folien Concurrent Haskell - 6 -

8 Beispiel: Zweimal Echo echo i = putstr $ "Eingabe fuer Thread" ++ show i ++ ":" line <- getline putstrln $ "Letzte Eingabe fuer Thread" ++ show i ++ echo i ":" ++ line zweiechos = forkio (echo 1) forkio (echo 2) block -- Hauptthread blockieren block = block CEFP; Folien Concurrent Haskell - 7 -

9 Der Datentyp MVar MVar (mutable variable) = Speicherplätze mit Synchronisationsfunktion Basisoperationen: newemptymvar :: IO (MVar a) erzeugt leere MVar takemvar :: MVar a -> IO a liest Wert aus MVar, danach ist die MVar leer falls MVar vorher leer: Thread wartet Bei mehreren Threads: FIFO-Warteschlange MVar leer gefüllt takemvar warten lesen putmvar :: MVar a -> a -> IO () speichert Wert in der MVar, wenn diese leer ist Falls belegt: Thread wartet Bei mehreren Threads: FIFO-Warteschlange MVar leer gefüllt putmvar schreiben warten CEFP; Folien Concurrent Haskell - 8 -

10 Der Datentyp MVar Eine MVar implementiert gerade eine Semaphore! Weitere Operationen: newmvar:: a -> MVar a erzeugt MVar mit Wert readmvar :: MVar a -> IO a liest den Wert swapmvar :: MVar a -> a -> IO a tauscht Wert aus isemptymvar :: MVar a -> IO Bool testet, ob MVar leer ist... CEFP; Folien Concurrent Haskell - 9 -

11 Schützen kritischer Abschnitte Beim Echo-Beispiel, keine Synchronisation, daher Durcheinander Beispiel mit Schutz: atomar mvar aktionen = putmvar mvar () -- MVar belegen result <- aktionen -- gesch"utzte Aktionen takemvar mvar -- MVar entleeren return result CEFP; Folien Concurrent Haskell

12 Schützen kritischer Abschnitte echos sem i = result <- atomar sem ( putstr $ "Eingabe fuer Thread" ++ show i ++ ":" line <- getline return line ) atomar sem (putstrln $ "Letzte Eingabe fuer Thread" ++ show i ++ ":" ++ result) echos sem i zweiechoss = sem <- newemptymvar forkio (echos sem 1) forkio (echos sem 2) block CEFP; Folien Concurrent Haskell

13 Daten austauschen: Puffervariable Erzeuger berechnet Werte und gibt sie an den Verbraucher Synchronität: Erzeuger gibt erst den nächsten Wert, wenn Verbraucher den alten erhalten hat. Puffer durch MVar: Lässt sich direkt implementieren type Puffer a = MVar a neuer Puffer: newpuffer = newemptymvar schreiben (Erzeuger): writetopuffer = putmvar lesen (Verbraucher): readfrompuffer = takemvar CEFP; Folien Concurrent Haskell

14 Daten austauschen: Puffervariable Erzeuger berechnet Werte und gibt sie an den Verbraucher Synchronität: Erzeuger gibt erst den nächsten Wert, wenn Verbraucher den alten erhalten hat. Puffer durch MVar: Lässt sich direkt implementieren type Puffer a = MVar a neuer Puffer: newpuffer = newemptymvar puf <- newpuffer readfrompuffer puf writetopuffer puf 1 writetopuffer puf 2 schreiben (Erzeuger): writetopuffer = putmvar lesen (Verbraucher): readfrompuffer = takemvar CEFP; Folien Concurrent Haskell

15 Daten austauschen: Puffervariable Erzeuger berechnet Werte und gibt sie an den Verbraucher Synchronität: Erzeuger gibt erst den nächsten Wert, wenn Verbraucher den alten erhalten hat. Puffer durch MVar: Lässt sich direkt implementieren type Puffer a = MVar a neuer Puffer: newpuffer = newemptymvar puf <- newpuffer readfrompuffer puf writetopuffer puf 1 writetopuffer puf 2 schreiben (Erzeuger): writetopuffer = putmvar lesen (Verbraucher): readfrompuffer = takemvar CEFP; Folien Concurrent Haskell

16 Daten austauschen: Puffervariable Erzeuger berechnet Werte und gibt sie an den Verbraucher Synchronität: Erzeuger gibt erst den nächsten Wert, wenn Verbraucher den alten erhalten hat. Puffer durch MVar: Lässt sich direkt implementieren type Puffer a = MVar a neuer Puffer: newpuffer = newemptymvar puf <- newpuffer readfrompuffer puf writetopuffer puf 1 writetopuffer puf 2 schreiben (Erzeuger): writetopuffer = putmvar lesen (Verbraucher): readfrompuffer = takemvar CEFP; Folien Concurrent Haskell

17 Daten austauschen: Puffervariable Erzeuger berechnet Werte und gibt sie an den Verbraucher Synchronität: Erzeuger gibt erst den nächsten Wert, wenn Verbraucher den alten erhalten hat. Puffer durch MVar: Lässt sich direkt implementieren type Puffer a = MVar a neuer Puffer: newpuffer = newemptymvar puf <- newpuffer readfrompuffer puf writetopuffer puf 1 writetopuffer puf 2 schreiben (Erzeuger): writetopuffer = putmvar lesen (Verbraucher): readfrompuffer = takemvar CEFP; Folien Concurrent Haskell

18 Daten austauschen: Puffervariable Erzeuger berechnet Werte und gibt sie an den Verbraucher Synchronität: Erzeuger gibt erst den nächsten Wert, wenn Verbraucher den alten erhalten hat. Puffer durch MVar: Lässt sich direkt implementieren type Puffer a = MVar a neuer Puffer: newpuffer = newemptymvar puf <- newpuffer readfrompuffer puf writetopuffer puf 1 writetopuffer puf 2 schreiben (Erzeuger): writetopuffer = putmvar lesen (Verbraucher): readfrompuffer = takemvar CEFP; Folien Concurrent Haskell

19 Daten austauschen: Puffervariable Erzeuger berechnet Werte und gibt sie an den Verbraucher Synchronität: Erzeuger gibt erst den nächsten Wert, wenn Verbraucher den alten erhalten hat. Puffer durch MVar: Lässt sich direkt implementieren type Puffer a = MVar a neuer Puffer: newpuffer = newemptymvar puf <- newpuffer readfrompuffer puf writetopuffer puf 1 writetopuffer puf 2 schreiben (Erzeuger): writetopuffer = putmvar lesen (Verbraucher): readfrompuffer = takemvar CEFP; Folien Concurrent Haskell

20 Speisende Philosophen n Philosopen n Gabeln Philosoph isst oder denkt zum Essen: linke und rechte Gabel Implementierung: Eine Gabel durch eine MVar () Ein Philosoph durch einen Thread CEFP; Folien Concurrent Haskell

21 Speisende Philosophen i-ter Philopsoph: philosoph i gabeln = let n = length gabeln -- Anzahl Gabeln takemvar $ gabeln!!i -- nehme linke Gabel putstrln $ "Philosoph " ++ show i ++ " hat linke Gabel..." takemvar $ gabeln!!(mod (i+1) n) -- nehme rechte Gabel putstrln $ "Philosoph " ++ show i ++ " isst..." putmvar (gabeln!!i) () -- lege linke Gabel ab putmvar (gabeln!!(mod (i+1) n)) () -- lege rechte Gabel ab putstrln $ "Philosoph " ++ show i ++ " denkt..." philosoph i gabeln CEFP; Folien Concurrent Haskell

22 Speisende Philosophen Erzeugen der Philosophen philosophen n = -- erzeuge Gabeln (n MVars): gabeln <- sequence $ replicate n (newmvar ()) -- erzeuge Philosophen: sequence_ [forkio (philosoph i gabeln) i <- [0..n-1]] block Beachte: Deadlock möglich! CEFP; Folien Concurrent Haskell

23 Kanäle beliebiger Länge Puffer reicht nicht aus: z.b. Erzeuger schneller als Verbaucher mehrere Erzeuger und/oder Verbraucher Deshalb: FIFO-Kanal, an einem Ende schreiben, am anderen Ende lesen Gewünschte Schnittstelle type Kanal a neuerkanal :: IO (Kanal a) schreibe :: Kanal a -> a -> IO () lese :: Kanal a -> IO a Außerdem: Keine Fehler, wenn mehrere Threads schreiben / lesen. CEFP; Folien Concurrent Haskell

24 Veränderbarer Strom ähnlich zu Listen, aber: jeder Tail eine MVar (dadurch veränderbar) leerer Strom = leere MVar type Strom a = MVar (SCons a) data SCons a = SCons a (Strom a) Strom der 1,2 und 3 enthält: ende <- newemptymvar drei <- newmvar (SCons 3 ende) zwei <- newmvar (SCons 2 drei) eins <- newmvar (SCons 1 zwei) return eins CEFP; Folien Concurrent Haskell

25 Strom ausdrucken type Strom a = MVar (SCons a) data SCons a = SCons a (Strom a) printstrom strom = test <- isemptymvar strom if test then putstrln "[]\n" else SCons el tl <- readmvar strom putstr (show el ++ ":") printstrom tl CEFP; Folien Concurrent Haskell

26 Strom ausdrucken type Strom a = MVar (SCons a) data SCons a = SCons a (Strom a) printstrom strom = test <- isemptymvar strom if test then putstrln "[]\n" else SCons el tl <- readmvar strom putstr (show el ++ ":") printstrom tl CEFP; Folien Concurrent Haskell

27 Strom ausdrucken type Strom a = MVar (SCons a) data SCons a = SCons a (Strom a) printstrom strom = test <- isemptymvar strom if test then putstrln "[]\n" else SCons el tl <- readmvar strom putstr (show el ++ ":") printstrom tl CEFP; Folien Concurrent Haskell

28 Ströme aneinanderhängen appendstroeme strom1 strom2 = test <- isemptymvar strom2 if test then return strom1 else kopf2 <- readmvar strom2 ende <- findeende strom1 putmvar ende kopf2 return strom1 findeende strom = test <- isemptymvar strom if test then return strom else SCons hd tl <- readmvar strom findeende tl CEFP; Folien Concurrent Haskell

29 Ströme aneinanderhängen appendstroeme strom1 strom2 = test <- isemptymvar strom2 if test then return strom1 else kopf2 <- readmvar strom2 ende <- findeende strom1 putmvar ende kopf2 return strom1 findeende strom = test <- isemptymvar strom if test then return strom else SCons hd tl <- readmvar strom findeende tl CEFP; Folien Concurrent Haskell

30 Ströme aneinanderhängen appendstroeme strom1 strom2 = test <- isemptymvar strom2 if test then return strom1 else kopf2 <- readmvar strom2 ende <- findeende strom1 putmvar ende kopf2 return strom1 findeende strom = test <- isemptymvar strom if test then return strom else SCons hd tl <- readmvar strom findeende tl CEFP; Folien Concurrent Haskell

31 Ströme aneinanderhängen appendstroeme strom1 strom2 = test <- isemptymvar strom2 if test then return strom1 else kopf2 <- readmvar strom2 ende <- findeende strom1 putmvar ende kopf2 return strom1 findeende strom = test <- isemptymvar strom if test then return strom else SCons hd tl <- readmvar strom findeende tl CEFP; Folien Concurrent Haskell

32 Ströme aneinanderhängen appendstroeme strom1 strom2 = test <- isemptymvar strom2 if test then return strom1 else kopf2 <- readmvar strom2 ende <- findeende strom1 putmvar ende kopf2 return strom1 findeende strom = test <- isemptymvar strom if test then return strom else SCons hd tl <- readmvar strom findeende tl CEFP; Folien Concurrent Haskell

33 Ströme aneinanderhängen appendstroeme strom1 strom2 = test <- isemptymvar strom2 if test then return strom1 else kopf2 <- readmvar strom2 ende <- findeende strom1 putmvar ende kopf2 return strom1 findeende strom = test <- isemptymvar strom if test then return strom else SCons hd tl <- readmvar strom findeende tl CEFP; Folien Concurrent Haskell

34 Ströme aneinanderhängen appendstroeme strom1 strom2 = test <- isemptymvar strom2 if test then return strom1 else kopf2 <- readmvar strom2 ende <- findeende strom1 putmvar ende kopf2 return strom1 findeende strom = test <- isemptymvar strom if test then return strom else SCons hd tl <- readmvar strom findeende tl CEFP; Folien Concurrent Haskell

35 Ströme aneinanderhängen appendstroeme strom1 strom2 = test <- isemptymvar strom2 if test then return strom1 else kopf2 <- readmvar strom2 ende <- findeende strom1 putmvar ende kopf2 return strom1 findeende strom = test <- isemptymvar strom if test then return strom else SCons hd tl <- readmvar strom findeende tl CEFP; Folien Concurrent Haskell

36 Ströme aneinanderhängen appendstroeme strom1 strom2 = test <- isemptymvar strom2 if test then return strom1 else kopf2 <- readmvar strom2 ende <- findeende strom1 putmvar ende kopf2 return strom1 findeende strom = test <- isemptymvar strom if test then return strom else SCons hd tl <- readmvar strom findeende tl CEFP; Folien Concurrent Haskell

37 Kanal Zwei MVars die auf Lese- und Schreibe-Ende des Stroms zeigen (Die beiden MVars synchronisieren den Zugriff) type Kanal a = (MVar (Strom a), -- Lese-Ende MVar (Strom a)) -- Schreibe-Ende CEFP; Folien Concurrent Haskell

38 Leeren Kanal erzeugen neuerkanal :: IO (Kanal a) neuerkanal = hole <- newemptymvar read <- newmvar hole write <- newmvar hole return (read, write) CEFP; Folien Concurrent Haskell

39 Schreiben schreibe :: Kanal a -> a -> IO () schreibe (read,write) val = new_hole <- newemptymvar old_hole <- takemvar write putmvar write new_hole putmvar old_hole (SCons val new_hole) CEFP; Folien Concurrent Haskell

40 Schreiben schreibe :: Kanal a -> a -> IO () schreibe (read,write) val = new_hole <- newemptymvar old_hole <- takemvar write putmvar write new_hole putmvar old_hole (SCons val new_hole) CEFP; Folien Concurrent Haskell

41 Schreiben schreibe :: Kanal a -> a -> IO () schreibe (read,write) val = new_hole <- newemptymvar old_hole <- takemvar write putmvar write new_hole putmvar old_hole (SCons val new_hole) CEFP; Folien Concurrent Haskell

42 Schreiben schreibe :: Kanal a -> a -> IO () schreibe (read,write) val = new_hole <- newemptymvar old_hole <- takemvar write putmvar write new_hole putmvar old_hole (SCons val new_hole) CEFP; Folien Concurrent Haskell

43 Schreiben schreibe :: Kanal a -> a -> IO () schreibe (read,write) val = new_hole <- newemptymvar old_hole <- takemvar write putmvar write new_hole putmvar old_hole (SCons val new_hole) CEFP; Folien Concurrent Haskell

44 Lesen lese :: Kanal a -> IO a lese (read,write) = kopf <- takemvar read (SCons val stream) <- takemvar kopf putmvar read stream return val CEFP; Folien Concurrent Haskell

45 Lesen lese :: Kanal a -> IO a lese (read,write) = kopf <- takemvar read (SCons val stream) <- takemvar kopf putmvar read stream return val CEFP; Folien Concurrent Haskell

46 Lesen lese :: Kanal a -> IO a lese (read,write) = kopf <- takemvar read (SCons val stream) <- takemvar kopf putmvar read stream return val CEFP; Folien Concurrent Haskell

47 Lesen lese :: Kanal a -> IO a lese (read,write) = kopf <- takemvar read (SCons val stream) <- takemvar kopf putmvar read stream return val CEFP; Folien Concurrent Haskell

48 Nichtdeterministisches Mischen Gegeben: Zwei Listen xs und ys Mische beide Listen zu einer Liste zusammen, so dass die relative Sortierung von xs und ys erhalten bleibt. Eine Liste ist partiell (ein Tail ist ) = Elemente der anderen Liste erscheinen Sowohl ndmerge (1:2:bot) [3..] als auch ndmerge [3..] (1:2:bot) liefern eine unendlich lange Liste Sequentiell: Nicht möglich! (Auswertung bleibt stecken beim bot) CEFP; Folien Concurrent Haskell

49 Nichtdeterministisches Mischen Mischen mit Kanal: Schreibe beide nebenläufig auf den Kanal Hauptthread liest den Kanal aus in eine Liste ndmerge xs ys = chan <- neuerkanal id_s <- forkio (schreibelisteaufkanal chan xs) id_t <- forkio (schreibelisteaufkanal chan ys) lesekanal chan False CEFP; Folien Concurrent Haskell

50 Nichtdeterministisches Mischen schreibelisteaufkanal chan [] = schreibe chan (True,undefined) schreibelisteaufkanal chan (x:xs) = schreibe chan (False,x) schreibelisteaufkanal chan xs lesekanal chan flag = (flag1,el) <- lese chan if flag1 && flag then return [] else rest <- unsafeinterleaveio (lesekanal chan (flag flag1)) if flag1 then return rest else return (el:rest) CEFP; Folien Concurrent Haskell

51 Paralleles Oder Sequentielles Oder: a b = if a then True else b a b a b False s s True s True s s {, False, True} Gewünscht: por True s = True = por s True Sequentiell: nicht möglich! CEFP; Folien Concurrent Haskell

52 Paralleles Oder por :: Bool -> Bool -> IO Bool por s t = ergebnismvar <- newemptymvar id_s <- forkio (if s then (putmvar ergebnismvar True) else t) id_t <- forkio (if t then (putmvar ergebnismvar True) else s) ergebnis <- takemvar ergebnismvar killthread id_s killthread id_t return ergebnis CEFP; Folien Concurrent Haskell

53 McCarthys amb ambigious choice binärer Operator, der beide Argumente parallel auswertet Falls eine der beiden Auswertungen ein Ergebnis liefert, wird dies als Gesamtresultat übernommen. CEFP; Folien Concurrent Haskell

54 McCarthys amb amb :: a -> a -> IO a amb s t = ergebnismvar <- newemptymvar id_s <- forkio (let x = s in seq x (putmvar ergebnismvar x)) id_t <- forkio (let x = t in seq x (putmvar ergebnismvar x)) ergebnis <- takemvar ergebnismvar killthread id_s killthread id_t return ergebnis CEFP; Folien Concurrent Haskell

55 McCarthys amb Semantisch amb s t = t, wenn s nicht terminiert s, wenn t nicht terminiert s oder t, wenn s und t terminieren CEFP; Folien Concurrent Haskell

56 Kodierung anderer Operatoren mit amb Paralleles Oder: por2 :: Bool -> Bool -> IO Bool por2 s t = amb (if s then True else t) (if t then True else s) Nichtdeterministische Auswahl: choice :: a -> a -> IO a choice s t = res <- (amb (\x -> s) (\x -> t)) return (res ()) CEFP; Folien Concurrent Haskell

57 Erweiterung auf n Argumente Statt zwei Argumente, eine Liste von Argumenten amblist [x] = return x amblist (x:xs) = l <- unsafeinterleaveio (amblist xs) amb x l CEFP; Folien Concurrent Haskell

58 Beispiel: Parallele Suche Gegeben: Labyrinth Gesucht: Weg vom Eingang (oben) zum Ausgang (unten) data Suchbaum a = Ziel a Knoten a [Suchbaum a] labyrinth = let kn51 = Knoten (5,1) [kn52] kn52 = Knoten (5,2) [kn42,kn53,kn62]... kn78 = Ziel (7,8) in kn51 CEFP; Folien Concurrent Haskell

59 Beispiel: Parallele Suche suche = result <- ndbfsearch [] labyrinth print result ndbfsearch res (Ziel a) = return (reverse $ a:res) ndbfsearch res (Knoten a []) = yield ndbfsearch res (Knoten a []) ndbfsearch res (Knoten a nf) = nf <- mapm (unsafeinterleaveio. ndbfsearch (a:res)) nf amblist nf CEFP; Folien Concurrent Haskell

60 Beispiel: Arztpraxis Eine Gemeinschaftspraxis bestehe aus n Ärzten, die in FIFO- Reihenfolge auf Patienten warten. Ankommende Patienten reihen sich ebenfalls in FIFO-Ordnung in eine Warteschlange ein. Die Arzthelferin am Empfang verteilt je einen Patienten am Anfang der Patientenschlange auf einen Arzt am Anfang der Ärzteschlange. Wenn ein Arzt mit seiner Behandlung fertig ist, reiht er sich hinten in die Ärzteschlange ein. CEFP; Folien Concurrent Haskell

61 Beispiel: Arztpraxis Hauptthread > arztpraxis n m = > > outputsem <- newemptymvar > patienten_kanal <- neuerkanal > forkio (mapm_(schreibe patienten_kanal) [1..m]) > aerzte_kanal <- neuerkanal > forkio (mapm_(schreibe aerzte_kanal) [1..n]) > ordne patienten_kanal aerzte_kanal outputsem CEFP; Folien Concurrent Haskell

62 Beispiel: Arztpraxis Arzthelferin (ordne) > ordne patienten aerzte outputsem = > > patient <- lese patienten > arzt <- lese aerzte > forkio (behandle arzt patient aerzte outputsem) > ordne patienten aerzte outputsem CEFP; Folien Concurrent Haskell

63 Beispiel: Arztpraxis Behandlung > behandle arzt patient aerzte outputsem = > > j <- ranmio > let i = (abs j mod ) div > atomar outputsem ( > putstrln > ("Arzt " ++ show arzt ++ " behandelt Patient " > ++ show patient ++ " in " ++ show i ++ " Sekunden") > ) > threaddelay (i* ) > schreibe aerzte arzt CEFP; Folien Concurrent Haskell

Übersicht. Nebenläufige Programmierung: Praxis und Semantik. Nebenläufige Programmierung in Haskell (1) Funktionale Programmiersprachen (2)

Übersicht. Nebenläufige Programmierung: Praxis und Semantik. Nebenläufige Programmierung in Haskell (1) Funktionale Programmiersprachen (2) Übersicht Aktuelle Themen zu Informatik der Systeme: Nebenläufige Programmierung: Praxis und Semantik Nebenläufige Programmierung in Haskell (1) PD Dr. David Sabel WS 2013/14 Stand der Folien: 21. Januar

Mehr

Adressen. Praktikum Funktionale Programmierung Organisation und Überblick. Termine. Studienleistung

Adressen. Praktikum Funktionale Programmierung Organisation und Überblick. Termine. Studienleistung Adressen Adressen, Termine Studienleistung Praktikum Funktionale Programmierung Organisation und Überblick Dr. David Sabel Büro und Email Raum 216, Robert-Mayer-Str. 11-15 [email protected]

Mehr

Ströme als unendliche Listen in Haskell

Ströme als unendliche Listen in Haskell Ströme als unendliche Listen in Haskell Strom := Folge oder Liste von Daten, unbegrenzt viele Daten-Elemente. Ströme sind in Haskell als als (potentiell) unendliche Listen darstellbar und programmierbar

Mehr

Grundlagen der Programmierung 2. Unendliche Listen und Ströme(B)

Grundlagen der Programmierung 2. Unendliche Listen und Ströme(B) Grundlagen der Programmierung 2 Unendliche Listen und Ströme(B) Prof. Dr. Manfred Schmidt-Schauÿ Künstliche Intelligenz und Softwaretechnologie 17. Mai 2006 Beispiel: scanl, scanr scanl berechnet das foldl

Mehr

Einführung in die funktionale Programmierung

Einführung in die funktionale Programmierung Einführung in die funktionale Programmierung Prof. Dr. Manfred Schmidt-Schauÿ Künstliche Intelligenz und Softwaretechnologie 26. Oktober 2006 Haskell - Einführung Syntax Typen Auswertung Programmierung

Mehr

Paradigmen der Programmierung

Paradigmen der Programmierung SS 11 Prüfungsklausur 25.07.2011 Aufgabe 5 (6+9 = 15 Punkte) a) Bestimmen Sie jeweils den Typ der folgenden Haskell-Ausdrücke: ( 1, 2 :"3", 4 < 5) :: (Char, String, Bool) [(last, tail), (head, take 5)]

Mehr

Grundlegende Datentypen

Grundlegende Datentypen Funktionale Programmierung Grundlegende Datentypen Fakultät für Informatik und Mathematik Hochschule München Letzte Änderung: 14.11.2017 15:37 Inhaltsverzeichnis Typen........................................

Mehr

Funktionale Programmierung Grundlegende Datentypen

Funktionale Programmierung Grundlegende Datentypen Grundlegende Datentypen Prof. Dr. Oliver Braun Fakultät für Informatik und Mathematik Hochschule München Letzte Änderung: 06.11.2017 16:45 Inhaltsverzeichnis Typen........................................

Mehr

Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 15 (Linearer Speicher, Listen, Bäume)

Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 15 (Linearer Speicher, Listen, Bäume) Fachrichtung 6.2 Informatik Universität des Saarlandes Tutorenteam der Vorlesung Programmierung 1 Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 15 (Linearer Speicher, Listen,

Mehr

Einführung in die Informatik 2

Einführung in die Informatik 2 Technische Universität München Fakultät für Informatik Prof. Tobias Nipkow, Ph.D. Lars Noschinski, Dr. Jasmin Blanchette, Dmitriy Traytel Wintersemester 2012/13 Lösungsblatt Endklausur 9. Februar 2013

Mehr

1 - FortProg ist: [ ] objekt-orientiert; [ ] funktional; [ ] logisch; [ ] manchmal nicht auszuhalten

1 - FortProg ist: [ ] objekt-orientiert; [ ] funktional; [ ] logisch; [ ] manchmal nicht auszuhalten 1 - FortProg ist: [ ] objekt-orientiert; [ ] funktional; [ ] logisch; [ ] manchmal nicht auszuhalten Java-1. a), e) Java-2. --- gestrichen --- Java-3. keine Antwort ist richtig Java-4. a) Java-5. a), b)

Mehr

Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zu Übung 4 -

Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zu Übung 4 - Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zu Übung 4 - Dozent: Prof. Dr. G. Rote Tutoren: J. Fleischer, T. Haimberger, N. Lehmann, C. Pockrandt, A. Steen 11.11.011 Ziele

Mehr

Einführung in die Funktionale Programmierung mit Haskell

Einführung in die Funktionale Programmierung mit Haskell Funktoren I/O Monadische Funktionen Einführung in die Funktionale Programmierung mit Haskell Input/Output LFE Theoretische Informatik, Institut für Informatik, Ludwig-Maximilians Universität, München 20.

Mehr

Basiskonstrukte von Haskell

Basiskonstrukte von Haskell Basiskonstrukte von Haskell PD Dr. David Sabel Goethe-Universität Frankfurt am Main 29. September 2015 Basistypen und Operationen Ganzzahlen: Int = Ganzzahlen beschränkter Länge Integer = Ganzzahlen beliebiger

Mehr

Einführung in die funktionale Programmierung

Einführung in die funktionale Programmierung Einführung in die funktionale Programmierung Prof. Dr. Manfred Schmidt-Schauÿ Künstliche Intelligenz und Softwaretechnologie 20. November 2006 Monaden und I/O Monade ist ein Datentyp für (sequentielle)

Mehr

Informatik-Seminar Thema: Monaden (Kapitel 10)

Informatik-Seminar Thema: Monaden (Kapitel 10) Informatik-Seminar 2003 - Thema: Monaden (Kapitel 10) Stefan Neumann 2. Dezember 2003 Inhalt Einleitung Einleitung Die IO()-Notation Operationen Einleitung Gegeben seien folgende Funktionen: inputint ::

Mehr

Ströme als unendliche Listen in Haskell

Ströme als unendliche Listen in Haskell Kapitel 3 Ströme als unendliche Listen in Haskell Ein Strom ist eine Folge oder Liste von Daten, die man in Haskell als Liste bzw. auch als potentiell unendliche Liste darstellen kann. Die Modellvorstellung

Mehr

Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zur Übungsklausur -

Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zur Übungsklausur - Algorithmen und Programmieren 1 Funktionale Programmierung - Musterlösung zur Übungsklausur - Punkte: A1: 30, A2: 20, A3: 20, A4: 20, A5: 10, A6: 20 Punkte: /120 12.02.2012 Hinweis: Geben Sie bei allen

Mehr

Prüfung Funktionale Programmierung

Prüfung Funktionale Programmierung Hochschule für angewandte Wissenschaften München Fakultät für Informatik und Mathematik Studiengruppe IF, IB, IC Sommersemester 2015 Prüfung Funktionale Programmierung Datum : 23.07.2015, 10:30 Uhr Bearbeitungszeit

Mehr

Grundlagen der Programmierung 2. Operationale Semantik

Grundlagen der Programmierung 2. Operationale Semantik Grundlagen der Programmierung 2 Operationale Semantik Prof. Dr. Manfred Schmidt-Schauÿ Künstliche Intelligenz und Softwaretechnologie 29. April 2009 Semantik von Programmiersprachen Semantik = Bedeutung

Mehr

Programmierparadigmen

Programmierparadigmen Programmierparadigmen D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg Sommer 2009, 22. Juni 2009, c 2009 D.Rösner D. Rösner PGP 2009...

Mehr

Einführung in Haskell

Einführung in Haskell Einführung in Haskell Axel Stronzik 21. April 2008 1 / 43 Inhaltsverzeichnis 1 Allgemeines 2 / 43 Inhaltsverzeichnis 1 Allgemeines 2 Funktions- und Typdefinitionen 2 / 43 Inhaltsverzeichnis 1 Allgemeines

Mehr

Verarbeitung unendlicher Datenstrukturen Jetzt können wir z.b. die unendliche Liste aller geraden Zahlen oder aller Quadratzahlen berechnen:

Verarbeitung unendlicher Datenstrukturen Jetzt können wir z.b. die unendliche Liste aller geraden Zahlen oder aller Quadratzahlen berechnen: Verarbeitung unendlicher Datenstrukturen Jetzt können wir z.b. die unendliche Liste aller geraden Zahlen oder aller Quadratzahlen berechnen: take 1 0 ( f i l t e r ( fn x => x mod 2=0) nat ) ; val it =

Mehr

Typdeklarationen. Es gibt in Haskell bereits primitive Typen:

Typdeklarationen. Es gibt in Haskell bereits primitive Typen: Typdeklarationen Es gibt in bereits primitive Typen: Integer: ganze Zahlen, z.b. 1289736781236 Int: ganze Zahlen mit Computerarithmetik, z.b. 123 Double: Fließkommazahlen, z.b. 3.14159 String: Zeichenketten,

Mehr

Einführung in die Informatik 2

Einführung in die Informatik 2 Technische Universität München Fakultät für Informatik Prof. Tobias Nipkow, Ph.D. Lars Hupel, Lars Noschinski, Dr. Jasmin Blanchette Wintersemester 2013/14 Abschlussklausur 21. Februar 2014 Einführung

Mehr

Hilfsblatt für C++ Prüfungen im 5. Semester

Hilfsblatt für C++ Prüfungen im 5. Semester Hilfsblatt für C++ Prüfungen im 5. Semester Hilfsblatt für C++ Prüfungen im 5. Semester 1 Klassen 2 Win-32 Programmierung 3 Handles 3 Dateien, Files 3 Threads 3 Events 4 Funktionen 5 Einfache Funktionen

Mehr

Funktionale Programmierung mit Haskell

Funktionale Programmierung mit Haskell Funktionale Programmierung mit Haskell Dr. Michael Savorić Hohenstaufen-Gymnasium (HSG) Kaiserslautern Version 20120622 Überblick Wichtige Eigenschaften Einführungsbeispiele Listenerzeugung und Beispiel

Mehr

Programmieren in Haskell

Programmieren in Haskell Programmieren in Haskell Wir steigen ein... Programmieren in Haskell 1 Was wir heute machen Umfrage: Wer hat den Hugs ausprobiert? Ausdrücke und Werte Datentypen Funktionen Aufgabe für diese Woche Programmieren

Mehr

Bash-Skripting Linux-Kurs der Unix-AG

Bash-Skripting Linux-Kurs der Unix-AG Bash-Skripting Linux-Kurs der Unix-AG Sebastian Weber 07.01.2013 Was ist ein Bash-Skript? Skript muss mit chmod +x ausführbar gemacht sein Aneinanderreihung von Befehlen normale Befehle nutzbar Sebastian

Mehr

Ein-Ausgabe. 9.1 Zustände und Seiteneffekte

Ein-Ausgabe. 9.1 Zustände und Seiteneffekte 9 Ein-Ausgabe Alle Funktionen in Haskell sind referentiell transparent: Die Anwendung einer Funktion F auf ein Argument A liefert stets dasselbe Ergebnis, ist also unabhängig vom Zustand des Systems. Klassische

Mehr

Haskell für Mathematiker

Haskell für Mathematiker Haskell für Mathematiker Joachim Breitner AG Seminar Topology 12. Mai 2016, Karlsruhe LEHRSTUHL PROGRAMMIERPARADIGMEN 1 KIT 19.2.2016 University of the Joachim State ofbreitner Baden-Wuerttemberg - Haskell

Mehr

Praktikum Funktionale Programmierung Teil 1: Lexen und Parsen

Praktikum Funktionale Programmierung Teil 1: Lexen und Parsen Stand der Folien: SoSe 2011 Praktikum Funktionale Programmierung Teil 1: Lexen und Parsen Dr. David Sabel Sommersemester 2011 Übersicht FP-PR Teil 1: Lexen & Parsen Sommersemester 2011 D. Sabel 2/20 Übersicht

Mehr

Programmieren in Haskell

Programmieren in Haskell Programmieren in Haskell Syntax und Semantik von Haskell Programmieren in Haskell 1 Was wir heute (und nächstes mal) machen Datentypdefinitionen Wertdefinitionen, Variablenbindungen Musterbindungen Funktionsbindungen

Mehr

Funktionale Programmierung mit Haskell

Funktionale Programmierung mit Haskell Funktionale Programmierung mit Haskell Prof. Dr. Hans J. Schneider Lehrstuhl für Programmiersprachen und Programmiermethodik Friedrich-Alexander-Universität Erlangen-Nürnberg Sommersemester 2011 I. Die

Mehr

Programmieren in Haskell Einstieg in Haskell

Programmieren in Haskell Einstieg in Haskell Programmieren in Haskell Einstieg in Haskell Peter Steffen Universität Bielefeld Technische Fakultät 24.10.2008 1 Programmieren in Haskell Was wir heute machen Umfrage: Wer hat den Hugs ausprobiert? Ausdrücke

Mehr

Gliederung. Algorithmen und Datenstrukturen I. Listen in Haskell: Listen in Haskell: Listen in Haskell. Datentyp Liste Strings Listenkomprehension

Gliederung. Algorithmen und Datenstrukturen I. Listen in Haskell: Listen in Haskell: Listen in Haskell. Datentyp Liste Strings Listenkomprehension Gliederung Algorithmen und Datenstrukturen I D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg 1 Winter 2009/10, 16. Oktober 2009, c

Mehr

Motivation Von Funktoren, Komposition, Applikation Zu Monoiden Die Monade Zusammenfassung. Monaden für alle. Franz Pletz

Motivation Von Funktoren, Komposition, Applikation Zu Monoiden Die Monade Zusammenfassung. Monaden für alle. Franz Pletz Monaden für alle Franz Pletz Chaos Computer Club München 13. Juni 2010, GPN10 Wieso, weshalb, warum? einige von euch haben sich sicher schon mal Haskell angeschaut und sind an Monaden

Mehr

HASKELL KAPITEL 2.1. Notationen: Currying und das Lambda-Kalkül

HASKELL KAPITEL 2.1. Notationen: Currying und das Lambda-Kalkül HASKELL KAPITEL 2.1 Notationen: Currying und das Lambda-Kalkül Bisheriges (Ende VL-Teil 1) weite :: (Float,Float) ->Float weite (v0, phi) = (square(v0)/9.81) * sin(2 * phi) (10, 30 ) smaller ::(Integer,

Mehr

Programmierung 1 (Wintersemester 2012/13) Lösungsblatt 4 (Kapitel 4)

Programmierung 1 (Wintersemester 2012/13) Lösungsblatt 4 (Kapitel 4) Fachrichtung 6.2 Informatik Universität des Saarlandes Tutorenteam der Vorlesung Programmierung 1 Programmierung 1 (Wintersemester 2012/13) Lösungsblatt 4 (Kapitel 4) Hinweis: Dieses Übungsblatt enthält

Mehr

Praktische Informatik 3: Funktionale Programmierung Vorlesung 4 vom : Typvariablen und Polymorphie

Praktische Informatik 3: Funktionale Programmierung Vorlesung 4 vom : Typvariablen und Polymorphie Rev. 2749 1 [28] Praktische Informatik 3: Funktionale Programmierung Vorlesung 4 vom 04.11.2014: Typvariablen und Polymorphie Christoph Lüth Universität Bremen Wintersemester 2014/15 2 [28] Fahrplan Teil

Mehr

Kapitel 3: Eine einfache Programmiersprache. Programmieren in Haskell 1

Kapitel 3: Eine einfache Programmiersprache. Programmieren in Haskell 1 Kapitel 3: Eine einfache Programmiersprache Programmieren in Haskell 1 Datentypen, Datentypdefinitionen data Instrument = Oboe HonkyTonkPiano Cello VoiceAahs data Musik = Note Ton Dauer Pause Dauer Musik

Mehr

Lösungen zum Übungsblatt 3: Softwareentwicklung I (WS 2006/07)

Lösungen zum Übungsblatt 3: Softwareentwicklung I (WS 2006/07) Prof. Dr. A. Poetzsch-Heffter Dipl.-Inform. J.O. Blech Dipl.-Inform. M.J. Gawkowski Dipl.-Inform. N. Rauch Technische Universität Kaiserslautern Fachbereich Informatik AG Softwaretechnik Lösungen zum Übungsblatt

Mehr

Stackmaschine; Speicheradressierung

Stackmaschine; Speicheradressierung Stackmaschine; Speicheradressierung Erweiterung um globalen Speicher (Heap, Halde) pro Speicherplatz eine Zahl. Notation ist als Array SP [0..]. Zugriff mittels Adresse (Index): eine Zahl i.a.: Zahlen

Mehr

Crashkurs: Haskell. Mentoring FU Berlin Felix Droop

Crashkurs: Haskell. Mentoring FU Berlin Felix Droop Crashkurs: Haskell Mentoring FU Berlin 7.11.2018 Felix Droop Crashkurs Haskell 1. GHCi Umgebung

Mehr

Bash-Skripting Linux-Kurs der Unix-AG

Bash-Skripting Linux-Kurs der Unix-AG Bash-Skripting Linux-Kurs der Unix-AG Sebastian Weber 13.06.2012 Was ist ein Bash-Skript? Skript muss mit chmod +x ausführbar gemacht sein Aneinanderreihung von Befehlen normale Befehle nutzbar Sebastian

Mehr

Funktionale Programmierung. Das Funktionale Quiz. Das Funktionale Quiz. Das Funktionale Quiz

Funktionale Programmierung. Das Funktionale Quiz. Das Funktionale Quiz. Das Funktionale Quiz Funktionale Programmierung Das Funktionale Quiz 31.5.2005 Nenne eine Gemeinsamkeit zwischen Typklassen und OO-Klassen Das Funktionale Quiz Das Funktionale Quiz Nenne einen Unterschied zwischen Typklassen

Mehr

Was bisher geschah Funktionale Programmierung in Haskell: Algebraische Datentypen Pattern Matching Polymorphie Typklassen Rekursive Datentypen:

Was bisher geschah Funktionale Programmierung in Haskell: Algebraische Datentypen Pattern Matching Polymorphie Typklassen Rekursive Datentypen: Was bisher geschah Funktionale Programmierung in Haskell: Algebraische Datentypen Pattern Matching Polymorphie Typklassen Rekursive Datentypen: Peano-Zahlen, Listen, Bäume Rekursive Funktionen strukturelle

Mehr

Listen und Listenfunktionen. Grundlagen der Programmierung 2 A (Listen) Listen und Listenfunktionen. Listen? Haskell: Listen

Listen und Listenfunktionen. Grundlagen der Programmierung 2 A (Listen) Listen und Listenfunktionen. Listen? Haskell: Listen Listen und Listenfunktionen Grundlagen der Programmierung 2 A (Listen) Haskell: Listen Prof. Dr. Manfred Schmidt-Schauß Listen modellieren Folgen von gleichartigen, gleichgetypten Objekten. Ausdruck im

Mehr

zu große Programme (Bildschirmseite!) zerlegen in (weitgehend) unabhängige Einheiten: Unterprogramme

zu große Programme (Bildschirmseite!) zerlegen in (weitgehend) unabhängige Einheiten: Unterprogramme Bisher Datentypen: einfach Zahlen, Wahrheitswerte, Zeichenketten zusammengesetzt Arrays (Felder) zur Verwaltung mehrerer zusammengehörender Daten desselben Datentypes eindimensional, mehrdimensional, Array-Grenzen

Mehr

Praktische Informatik 3: Funktionale Programmierung Vorlesung 11 vom : Monaden als Berechnungsmuster

Praktische Informatik 3: Funktionale Programmierung Vorlesung 11 vom : Monaden als Berechnungsmuster 16:02:16 2017-01-17 1 [30] Praktische Informatik 3: Funktionale Programmierung Vorlesung 11 vom 10.01.2017: Monaden als Berechnungsmuster Christoph Lüth Universität Bremen Wintersemester 2016/17 Frohes

Mehr

zu große Programme (Bildschirmseite!) zerlegen in (weitgehend) unabhängige Einheiten: Unterprogramme

zu große Programme (Bildschirmseite!) zerlegen in (weitgehend) unabhängige Einheiten: Unterprogramme Bisher Datentypen: einfach Zahlen, Wahrheitswerte, Zeichenketten zusammengesetzt Arrays (Felder) zur Verwaltung mehrerer zusammengehörender Daten desselben Datentypes eindimensional, mehrdimensional, Array-Grenzen

Mehr

ALP I. Funktionale Programmierung

ALP I. Funktionale Programmierung ALP I Funktionale Programmierung Zusammengesetzte Datentypen in Haskell WS 2012/2013 Zusammengesetzte Datentypen Tupel List String Zusammengesetzte Datentypen Tupel-Datentyp Ein Tupel ist eine Ansammlung

Mehr

Was bisher geschah. deklarative Programmierung. funktionale Programmierung (Haskell):

Was bisher geschah. deklarative Programmierung. funktionale Programmierung (Haskell): Was bisher geschah deklarative Programmierung funktional: Programm: Menge von Termgleichungen, Term Auswertung: Pattern matsching, Termumformungen logisch: Programm: Menge von Regeln (Horn-Formeln), Formel

Mehr

Funktionale Programmierung

Funktionale Programmierung Funktionale Programmierung Jörg Kreiker Uni Kassel und SMA Solar Technology AG Wintersemester 2011/2012 2 Teil II Typen mit Werten und Ausdruck, sogar listenweise 3 Haskell Programme Programm Module ein

Mehr

Monoide. Funktionale Programmierung. Prof. Dr. Oliver Braun Letzte Änderung: :54. Monoide 1/16

Monoide. Funktionale Programmierung. Prof. Dr. Oliver Braun Letzte Änderung: :54. Monoide 1/16 Monoide Funktionale Programmierung Prof. Dr. Oliver Braun Letzte Änderung: 09.10.2018 06:54 Monoide 1/16 Abstraktion gleichartige Strukturen sollten abstrahiert werden Beispiel: Collections in Haskell

Mehr

Grundprinzipien der funktionalen Programmierung

Grundprinzipien der funktionalen Programmierung Grundprinzipien der funktionalen Programmierung Funktionen haben keine Seiteneffekte Eine Funktion berechnet einen Ausgabewert der nur von den Eingabewerten abhängt: 12 inputs + output 46 34 2 Nicht nur

Mehr

Lösungvorschlag zum Übungsblatt 6: Software-Entwicklung I (WS 2007/08)

Lösungvorschlag zum Übungsblatt 6: Software-Entwicklung I (WS 2007/08) Prof. Dr. A. Poetzsch-Heffter Dipl.-Inform. J. O. Blech Dipl.-Inform. M. J. Gawkowski Dipl.-Inform. N. Rauch TU Kaiserslautern Fachbereich Informatik AG Softwaretechnik Lösungvorschlag zum Übungsblatt

Mehr