• Keine Ergebnisse gefunden

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

N/A
N/A
Protected

Academic year: 2022

Aktie "Praktische Informatik 3: Funktionale Programmierung Vorlesung 11 vom 08.01.2013: Aktionen und Zustände"

Copied!
29
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

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

Christoph Lüth

Universität Bremen

Wintersemester 2012/13

(2)

Fahrplan

I Teil I: Funktionale Programmierung im Kleinen

I Teil II: Funktionale Programmierung im Großen

I Abstrakte Datentypen

I Signaturen und Eigenschaften

I Spezifikation und Beweis

I Aktionen und Zustände

I Teil III: Funktionale Programmierung im richtigen Leben

(3)

Inhalt

I Ein/Ausgabe in funktionale Sprachen

I Wo ist dasProblem?

I Aktionenund der Datentyp IO.

I Aktionenals Werte

I Aktionenals Zustandstransformationen

(4)

Ein- und Ausgabe in funktionalen Sprachen

Umwelt Haskell

Aktionen

Umwelt Reine

Funktionen Haskell

Problem:

I Funktionen mit Seiteneffekten nicht referentiell transparent.

I readString :: . . .→String ??

Lösung:

I Seiteneffekte am Typ erkennbar

I Aktionenkönnen nurmit Aktionenkomponiert werden

I „einmal Aktion, immer Aktion“

(5)

Ein- und Ausgabe in funktionalen Sprachen

Umwelt Haskell

Aktionen

Umwelt Reine

Funktionen Haskell

Problem:

I Funktionen mit Seiteneffekten nicht referentiell transparent.

I readString :: . . .→String ??

Lösung:

I Seiteneffekte am Typ erkennbar

I Aktionenkönnen nurmit Aktionenkomponiert werden

I „einmal Aktion, immer Aktion“

(6)

Aktionen als abstrakter Datentyp

I ADT mit OperationenKomposition und Lifting

I Signatur:

type IO α

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

r e t u r n :: α→ IO α

I Pluselementare Operationen (lesen, schreiben etc)

(7)

Elementare Aktionen

I Zeile von stdin lesen:

g e t L i n e :: IO S t r i n g

I Zeichenkette auf stdout ausgeben:

p u t S t r :: S t r i n g→ IO ( )

I Zeichenkette mit Zeilenvorschubausgeben:

p u t S t r L n :: S t r i n g→ IO ( )

(8)

Einfache Beispiele

I Echoeinfach e c h o 1 :: IO ( )

e c h o 1 = g e t L i n e = p u t S t r L n

I Echomehrfach e c h o :: IO ( )

e c h o = g e t L i n e = p u t S t r L n = λ_ → e c h o

I Was passiert hier?

I Verknüpfenvon Aktionen mit=

I Jede Aktion gibtWertzurück

(9)

Noch ein Beispiel

I Umgekehrtes Echo:

o h c e :: IO ( ) o h c e = g e t L i n e

= λs→ p u t S t r L n ( r e v e r s e s ) o h c e

I Was passiert hier?

I ReineFunktion reverse wird innerhalb vonAktionputStrLngenutzt

I FolgeaktionohcebenötigtWertder vorherigen Aktion nicht

I Abkürzung:

p q = p =λ_ q

(10)

Die do-Notation

I Syntaktischer Zucker fürIO:

e c h o = g e t L i n e

= λs→ p u t S t r L n s e c h o

⇐⇒

e c h o =

do s← g e t L i n e p u t S t r L n s e c h o

I Rechts sind=,implizit.

I Es gilt dieAbseitsregel.

I Einrückungderersten Anweisungnachdobestimmt Abseits.

(11)

Drittes Beispiel

I Zählendes, endliches Echo e c h o 3 :: I n t→ IO ( ) e c h o 3 c n t = do

p u t S t r ( show c n t ++ " : ␣ " ) s← g e t L i n e

i f s 6= " " then do

p u t S t r L n $ show c n t ++ " : ␣ "++ s e c h o 3 ( c n t+ 1 )

e l s e r e t u r n ( )

I Was passiert hier?

I KombinationausKontrollstrukturenundAktionen

I AktionenalsWerte

I Geschachteltedo-Notation

(12)

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)

(13)

Ein/Ausgabe mit Dateien

I ImPreludevordefiniert:

I Dateien schreiben (überschreiben, anhängen):

type F i l e P a t h = S t r i n g

w r i t e F i l e :: F i l e P a t h → S t r i n g → IO ( ) a p p e n d F i l e :: F i l e P a t h → S t r i n g → IO ( )

I Datei lesen (verzögert):

r e a d F i l e :: F i l e P a t h → IO S t r i n g

I Mehr Operationenim Modul IOder Standardbücherei

I Buffered/Unbuffered, Seeking, &c.

I Operationen aufHandle

(14)

Beispiel: Zeichen, Wörter, Zeilen zählen (wc)

wc :: S t r i n g→ IO ( ) wc f i l e =

do c o n t ← r e a d F i l e f i l e p u t S t r L n $ f i l e++ " : ␣ "++

show ( l e n g t h ( l i n e s c o n t ) , l e n g t h ( w o r d s c o n t ) , l e n g t h c o n t )

I Nicht sehr effizient — Datei wirdim Speicher gehalten.

(15)

Beispiel: wc verbessert.

I Effizienter: Dateiinhalteinmal traversieren

c n t :: I n t→ I n t→ I n t→ B o o l→ S t r i n g

→ ( I n t , I n t , I n t ) c n t l w c _ [ ] = ( l , w , c ) c n t l w c s k i p ( x : x s )

| n o t ( i s S p a c e x ) && n o t s k i p = c n t l (w+1 ) ( c+1 ) True x s

| n o t ( i s S p a c e x ) && s k i p = c n t l w ( c+1 ) True x s

| o t h e r w i s e = c n t l ’ w ( c+1 ) F a l s e x s where l ’ = i f x == ’ \n ’ then l+1 e l s e l

I Hauptprogramm:

wc :: S t r i n g→ IO ( ) wc f i l e = do

c o n t ← r e a d F i l e f i l e

p u t S t r L n $ f i l e++ " : ␣ "++ show ( c n t 0 0 0 F a l s e c o n t )

I Datei wirdverzögert gelesen unddabei verbraucht.

(16)

Beispiel: wc verbessert.

I Effizienter: Dateiinhalteinmal traversieren

c n t :: I n t→ I n t→ I n t→ B o o l→ S t r i n g

→ ( I n t , I n t , I n t ) c n t l w c _ [ ] = ( l , w , c ) c n t l w c s k i p ( x : x s )

| n o t ( i s S p a c e x ) && n o t s k i p = c n t l (w+1 ) ( c+1 ) True x s

| n o t ( i s S p a c e x ) && s k i p = c n t l w ( c+1 ) True x s

| o t h e r w i s e = c n t l ’ w ( c+1 ) F a l s e x s where l ’ = i f x == ’ \n ’ then l+1 e l s e l

I Hauptprogramm:

wc :: S t r i n g→ IO ( ) wc f i l e = do

c o n t ← r e a d F i l e f i l e

p u t S t r L n $ f i l e++ " : ␣ "++ show ( c n t 0 0 0 F a l s e c o n t )

(17)

Aktionen als Werte

I Aktionensind Wertewie alle anderen.

I DadurchDefinitionvon Kontrollstrukturenmöglich.

I Endlosschleife:

f o r e v e r :: IO α→ IO α f o r e v e r a = a f o r e v e r a

I Iteration (feste Anzahl):

f o r N :: I n t→ IO α→ IO ( )

f o r N n a | n == 0 = r e t u r n ( )

| o t h e r w i s e = a f o r N ( n−1) a

I VordefinierteKontrollstrukturen (Control.Monad):

I when,mapM,forM,sequence, . . .

(18)

Fehlerbehandlung

I Fehlerwerden durch IOError repräsentiert

I FehlerbehandlungdurchAusnahmen (ähnlich Java) i o E r r o r :: I O E r r o r → IO α −−"throw"

c a t c h :: IO α→ ( I O E r r o r→ IO α) → IO α

I Fehlerbehandlungnur in Aktionen

(19)

Fehler fangen und behandeln

I Fehlerbehandlung fürwc:

wc2 :: S t r i n g→ IO ( ) wc2 f i l e =

c a t c h ( wc f i l e )

(λe→ p u t S t r L n $ " F e h l e r : ␣ "++ show e )

I IOErrorkann analysiert werden (siehe Modul IO)

I readmit Ausnahme bei Fehler (statt Programmabbruch):

r e a d I O :: Read a⇒ S t r i n g→ IO a

(20)

So ein Zufall!

I Zufallswerte:

randomRIO :: (α, α)→ IO α

I Warum istrandomIOAktion?

I Beispiel:Aktionen zufällig oft ausführen a t m o s t :: I n t→ IO α→ IO [α] a t m o s t most a =

do l← randomRIO ( 1 , most ) s e q u e n c e ( r e p l i c a t e l a )

I Zufälligen String erzeugen r a n d o m S t r :: IO S t r i n g

r a n d o m S t r = a t m o s t 40 ( randomRIO ( ’ a ’ , ’ z ’ ) )

(21)

So ein Zufall!

I Zufallswerte:

randomRIO :: (α, α)→ IO α

I Warum istrandomIOAktion?

I Beispiel:Aktionen zufällig oft ausführen a t m o s t :: I n t→ IO α→ IO [α] a t m o s t most a =

do l← randomRIO ( 1 , most ) s e q u e n c e ( r e p l i c a t e l a )

I Zufälligen String erzeugen r a n d o m S t r :: IO S t r i n g

r a n d o m S t r = a t m o s t 40 ( randomRIO ( ’ a ’ , ’ z ’ ) )

(22)

Ausführbare Programme

I Eigenständiges Programm istAktionen

I Hauptaktion:main in ModulMain

I wcals eigenständiges Programm:

module Main where

import System . E n v i r o n m e n t ( g e t A r g s ) import Data . Char ( i s S p a c e )

main = do

a r g s ← g e t A r g s mapM wc2 a r g s

(23)

Funktionen mit Zustand

Theorem (Currying)

Folgende Typen sindisomorph:

A×BC ∼=ABC

I In Haskell: folgende Funktionen sindinvers:

c u r r y :: ( (α, β) → γ)→ αβγ u n c u r r y :: (αβγ)→ (α, β) → γ

(24)

Funktionen mit Zustand

I Idee: Seiteneffektexplizit machen

I Funktionf :AB mit Seiteneffekt in ZustandS:

f :A×SB×S

∼=

f :ASB×S

I Datentyp:SB×S

I Komposition: Funktionskomposition unduncurry

(25)

In Haskell: Zustände explizit

I Datentyp: Berechnung mit Seiteneffekt in TypΣ:

type S t a t e Σ α = Σ→ (α, Σ)

I Komposition zweier solcher Berechnungen:

comp :: S t a t e Σ α→ (α→ S t a t e Σ β)→ S t a t e Σ β comp f g = u n c u r r y g ◦ f

I Lifting:

l i f t :: α→ S t a t e Σ α l i f t = c u r r y i d

(26)

Beispiel: Ein Zähler

I Datentyp:

type W i t h C o u n t e r α = S t a t e I n t α

I Zähler erhöhen:

t i c k :: W i t h C o u n t e r ( ) t i c k i = ( ( ) , i+1 )

I Zähler auslesen:

r e a d :: W i t h C o u n t e r I n t r e a d i = ( i , i )

I Zähler zurücksetzen:

r e s e t :: W i t h C o u n t e r ( ) r e s e t i = ( ( ) , 0 )

(27)

Implizite vs. explizite Zustände

I Nachteil: Zustand istexplizit

I Kanndupliziertwerden

I Daher: Zustandimplizit machen

I Datentypverkapseln

I Signatur State , comp, lift, elementare Operationen

(28)

Aktionen als Zustandstransformationen

I Idee: Aktionen sindTransformationen auf Systemzustand S

I S beinhaltet

I Speicher als AbbildungA*V (AdressenA, WerteV)

I Zustand des Dateisystems

I Zustand des Zufallsgenerators

I In Haskell: TypRealWorld

I “Virtueller” Typ, Zugriff nur über elementare Operationen

I Entscheidend nurReihenfolgeder Aktionen

(29)

Zusammenfassung

I Ein/Ausgabe in Haskell durchAktionen

I Aktionen(Typ IOα) sind seiteneffektbehaftete Funktionen

I Kompositionvon Aktionen durch

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

r e t u r n :: α→ IO α

I do-Notation

I Fehlerbehandlung durch Ausnahmen (IOError,catch).

I Verschiedene Funktionen der Standardbücherei:

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

I Module:IO,Random

I Aktionen sindimplementiertalsZustandstransformationen

Referenzen

ÄHNLICHE DOKUMENTE

konstanter Aufwand ←→ beliebige Genauigkeit, wachsender Aufwand Haskell bietet die Auswahl:. I Int - ganze Zahlen als Maschinenworte (≥

I Funktionen höherer Ordnung II und Effizenzaspekte I Teil II: Funktionale Programmierung im Großen I Teil III: Funktionale Programmierung im richtigen Leben.. PI3 WS 16/17

Ein Typsystem ist eine handhabbare syntaktische Methode, um die Abwesenheit bestimmter Programmverhalten zu beweisen, indem Ausdrücke nach der Art der Werte, die sie

Ein Typsystem ist eine handhabbare syntaktische Methode, um die Abwesenheit bestimmter Programmverhalten zu beweisen, indem Ausdrücke nach der Art der Werte, die sie

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 Tutorien: Mo 10-12 MZH 5210 Christian Maeder Mo 16-18 MZH 1380 Rene Wagner Di 8-10 MZH 1100 Diedrich Wolter Di 10-12 MZH 1380 Diedrich Wolter Di 10-12 MZH 1400 Bernd Gersdorf Di

werden gleichzeitig definiert (Rekursion!) I Namen f, y und Parameter (x) überlagern andere I Es gilt die Abseitsregel. I Deshalb: Auf gleiche Einrückung der lokalen