• Keine Ergebnisse gefunden

Aktionen als abstrakter Datentyp

N/A
N/A
Protected

Academic year: 2022

Aktie "Aktionen als abstrakter Datentyp"

Copied!
4
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Praktische Informatik 3: Funktionale Programmierung Vorlesung 10 vom 20.12.2016: Aktionen und Zustände

Christoph Lüth Universität Bremen Wintersemester 2016/17

16:02:32 2017-01-17 1 [26]

Fahrplan

I Teil I: Funktionale Programmierung im Kleinen I Teil II: Funktionale Programmierung im Großen I Teil III: Funktionale Programmierung im richtigen Leben

I Aktionen und Zustände

IMonaden als Berechnungsmuster

IDomänenspezifische Sprachen (DSLs)

IScala — Eine praktische Einführung

IRückblich & Ausblick

PI3 WS 16/17 2 [26]

Inhalt

I Ein/Ausgabe in funktionale Sprachen

I Wo ist dasProblem?

I Aktionenund der DatentypIO.

I VordefinierteAktionen

I Beispiel: Wortratespiel

I AktionenalsWerte

PI3 WS 16/17 3 [26]

Ein- und Ausgabe in funktionalen Sprachen

Umwelt Haskell

Aktionen

Umwelt Reine

Funktionen

Haskell

Problem:

IFunktionen mit Seiteneffekten nicht referentiell transparent.

I readString :: . . .→String??

Lösung:

ISeiteneffekte am Typ erkennbar IAktionen

IKönnennurmitAktionen komponiert werden

I„einmal Aktion, immer Aktion“

PI3 WS 16/17 4 [26]

Aktionen als abstrakter Datentyp

I ADT mit OperationenKompositionundLifting

I Signatur:

typeIOα

(=) :: IOα→ (α→IOβ) →IOβ return :: α→ IOα

I DazuelementareAktionen (lesen, schreiben etc)

PI3 WS 16/17 5 [26]

Elementare Aktionen

I Zeile von Standardeingabe (stdin)lesen:

getLine :: IO String

I Zeichenkette auf Standardausgabe (stdout)ausgeben:

putStr :: String→ IO ()

I Zeichenkette mit Zeilenvorschubausgeben:

putStrLn :: String→ IO ()

PI3 WS 16/17 6 [26]

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

PI3 WS 16/17 7 [26]

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

PI3 WS 16/17 8 [26]

(2)

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.

PI3 WS 16/17 9 [26]

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

PI3 WS 16/17 10 [26]

Module in der Standardbücherei

I Ein/Ausgabe, Fehlerbehandlung (ModulSystem . IO, Control . Exception)

I Zufallszahlen (ModulSystem .Random)

I Kommandozeile, Umgebungsvariablen (ModulSystem . Environment) I Zugriff auf das Dateisystem (ModulSystem . Directory)

I Zeit (ModulSystem .Time)

PI3 WS 16/17 11 [26]

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 ModulSystem . IOder Standardbücherei

IBuffered/Unbuffered, Seeking, &c.

IOperationen aufHandle

I Noch mehr Operationen inSystem . Posix

IFiledeskriptoren, Permissions, special devices, etc.

PI3 WS 16/17 12 [26]

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 I Erstaunlich (hinreichend) effizient

PI3 WS 16/17 13 [26]

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

PI3 WS 16/17 14 [26]

Kontrollstrukturen

I VordefinierteKontrollstrukturen (Control .Monad):

when :: Bool→IO ()→IO () I Sequenzierung:

sequence :: [ IOα]→IO [α]

I Sonderfall:[ ( ) ]als() sequence_ :: [ IO ( ) ]→IO () I Map und Filter für Aktionen:

mapM :: (α→ IOβ)→ [α]→IO [β]

mapM_ :: (α→ IO ())→ [α]→IO () filterM :: (α→ IO Bool) → [α] → IO [α]

PI3 WS 16/17 15 [26]

Fehlerbehandlung

I Fehlerwerden durchExceptionrepräsentiert (Modul Control . Exception)

I ExceptionistTypklasse— kann durch eigene Instanzen erweitert werden

IVordefinierte Instanzen: u.a.IOError

I FehlerbehandlungdurchAusnahmen(ähnlich Java) catch :: Exceptionγ⇒ IOα→ (γ→ IOα) →IOα try :: Exceptionγ⇒ IOα→IO ( Either γ α)

I Faustregel:catchfür unerwartete Ausnahmen,tryfür erwartete I Fehlerbehandlungnur in Aktionen

PI3 WS 16/17 16 [26]

(3)

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 :: IOError ))

I IOErrorkann analysiert werden (sieheSystem . IO . Error) I readmit Ausnahme bei Fehler (statt Programmabbruch):

readIO :: Readα⇒ String→IOα

PI3 WS 16/17 17 [26]

Ausführbare Programme

I Eigenständiges Programm istAktion I Hauptaktion:main :: IO ()in ModulMain

I. . . oder mit der Option-main-isM.fsetzen Iwcals eigenständiges Programm:

moduleMainwhere

importSystem . Environment ( getArgs ) importControl . Exception

. . .

main :: IO () main =do

args ← getArgs mapM_ wc2 args

PI3 WS 16/17 18 [26]

Beispiel: Traversion eines Verzeichnisbaums

I Verzeichnisbaum traversieren, und für jede Datei eineAktion ausführen:

travFS :: ( FilePath→ IO ())→ FilePath→IO () I Nutzt Funktionalität ausSystem . Directory,System . FilePath

travFS action p =do

res ← try ( getDirectoryContents p) case res of

Left e → putStrLn $ "ERROR: ␣"++ show (e :: IOError ) Right cs→do let cp = map (p</>) ( cs \\ [ " . " , " . . " ] )

d i r s ← filterM doesDirectoryExist cp f i l e s ← filterM doesFileExist cp mapM_ action f i l e s

mapM_ ( travFS action ) d i r s

PI3 WS 16/17 19 [26]

So ein Zufall!

I Zufallswerte:

randomRIO :: (α, α)→IOα

IWarum istrandomIOAktion?

I Beispiele:

IAktion zufällig oft ausführen:

atmost :: Int→IOα→IO [α]

atmost most a =

do l←randomRIO (1 , most) sequence ( r e p l i c a t e l a)

IZufälliges Element aus einer nicht-leeren Liste auswählen:

pickRandom :: [α]→IOα

pickRandom [ ] = er ro r "pickRandom : ␣empty␣ l i s t "

pickRandom xs =do

i ←randomRIO (0 , length xs−1) return $ xs ! ! i

PI3 WS 16/17 20 [26]

Fallbeispiel: Wörter raten

I Unterhaltungsprogramm: der Benutzer rät Wörter

I Benutzer kann einzelne Buchstaben eingeben oder das ganze Wort

I Wort wird maskiert ausgegeben, nur geratene Buchstaben angezeigt

PI3 WS 16/17 21 [26]

Wörter raten: Programmstruktur

I Trennung zwischen Spiel-Logik und Nutzerschnittstelle I Spiel-Logik (GuessGame):

IProgrammzustand:

data State = St { word :: String−−Zu ratendes Wort , h i t s :: String−−Schon geratene Buchstaben , miss :: String−−Falsch geratene Buchstaben }

IInitialen Zustand (Wort auswählen):

i n i t i a l S t a t e :: [ String ]→IO State

INächsten Zustand berechnen (Charist Eingabe des Benutzers):

data Result = Miss | Hit | Repetition | GuessedIt | TooManyTries processGuess :: Char→State→( Result , State )

PI3 WS 16/17 22 [26]

Wörter raten: Nutzerschnittstelle

IHauptschleife (play)

I Zustand anzeigen

I Benutzereingabe abwarten

I Neuen Zustand berechnen

I Rekursiver Aufruf mit neuem Zustand

I Programmanfang (main)

I Lexikon lesen

I Initialen Zustand berechnen

I Hauptschleife aufrufen play :: State→IO ()

play st =do putStrLn ( render st ) c← getGuess st

case ( processGuess c st ) of ( Hit , st ) → play st

(Miss , st )→doputStrLn "Sorry , ␣no . " ; play st

( Repetition , st )→doputStrLn "You␣already␣ t r i e d ␣that . " ; play st ( GuessedIt , st )→ putStrLn "Congratulations , ␣you␣guessed␣ i t . "

(TooManyTries , st )→

putStrLn $ "The␣word␣was␣"++ word st ++ "␣−−␣you␣lose . "

PI3 WS 16/17 23 [26]

Kontrollumkehr

I Trennung von Logik (State,processGuess) und Nutzerinteraktion nützlich und sinnvoll

I Wird durch Haskell Tysystem unterstützt (keine UI ohneIO) I Nützlich für andere UI mitKontrollumkehr

I Beispiel: ein GUI für das Wörterratespiel (mitGtk2hs)

IGUI ruft Handler-Funktionen des Nutzerprogramms auf

ISpielzustand in Referenz (IORef) speichern I Vgl. MVC-Pattern (Model-View-Controller)

PI3 WS 16/17 24 [26]

(4)

Zusammenfassung

I Ein/Ausgabe in Haskell durchAktionen

I Aktionen(TypIOα) sind seiteneffektbehaftete Funktionen I Kompositionvon Aktionen durch

(=) :: IOα→ (α→ IOβ)→IOβ return :: α→ IOα

I do-Notation

I Fehlerbehandlung durch Ausnahmen (IOError,catch,try).

I Verschiedene Funktionen der Standardbücherei:

I Prelude:getLine,putStr,putStrLn,readFile,writeFile

I Module:System.IO,System.Random

I Aktionen sindimplementiertalsZustandstransformationen

PI3 WS 16/17 25 [26]

Frohe Weihnachten und einen Guten Rutsch!

PI3 WS 16/17 26 [26]

Referenzen

ÄHNLICHE DOKUMENTE

Praktische Informatik 3: Funktionale Programmierung Vorlesung 3 vom 28.10.2014: Rekursive Datentypen.. Christoph Lüth Universität Bremen

Praktische Informatik 3: Funktionale Programmierung Vorlesung 9 vom 09.12.2012: Signaturen und Eigenschaften.. Christoph Lüth Universität Bremen

Praktische Informatik 3: Funktionale Programmierung Vorlesung 10 vom 18.12.2012: Spezifikation und Beweis..

Praktische Informatik 3: Funktionale Programmierung Vorlesung 11 vom 06.01.2015: Aktionen und Zustände..

Praktische Informatik 3: Funktionale Programmierung Vorlesung 11 vom 06.01.2015: Aktionen und Zustände.. Christoph Lüth Universität Bremen

I Verzögerte Auswertung effizient, weil nur bei Bedarf ausgewertet wird.. I Aber

Praktische Informatik 3: Funktionale Programmierung Vorlesung 13 vom 20.01.15: Scala — Eine praktische Einführung.. Christoph Lüth Universität Bremen

Praktische Informatik 3: Funktionale Programmierung Vorlesung 3 vom 30.10.2012: Rekursive Datentypen.. Christoph Lüth Universität Bremen