Praktische Informatik 3: Funktionale Programmierung Vorlesung 9 vom 11.12.2018: Signaturen und Eigenschaften
Christoph Lüth Universität Bremen Wintersemester 2018/19
16:03:13 2018-12-18 1 [29]
Organisatorisches
I Anmeldung zurProbeklausur:
IAb sofort auf der stud.ip-Seite.
IBisDo 12:00
I Termin: Montag, 17.12.2018 10:00 (pünktlich) und 10:30
I Ort: Testzentrum des ZMML, neben der Uni-Bücherei auf dem Boulevard
I Dauer: 30 Minuten
I Inhalt: zwei kleine Funktionen implementieren, vier M/C-Fragen
PI3 WS 18/19 2 [29]
Fahrplan
I Teil I: Funktionale Programmierung im Kleinen
I Teil II: Funktionale Programmierung im Großen
I Abstrakte Datentypen
I Signaturen und Eigenschaften
I Teil III: Funktionale Programmierung im richtigen Leben
PI3 WS 18/19 3 [29]
Abstrakte Datentypen und Signaturen
I Letzte Vorlesung:Abstrakte Datentypen
ITypplusOperationen
I Heute:SignaturenundEigenschaften
Definition (Signatur)
DieSignatureines abstrakten Datentyps besteht aus den Typen, und der Signatur der darüber definierten Funktionen.
I Keine direkte Repräsentation in Haskell I Signatur:Typeines Moduls
PI3 WS 18/19 4 [29]
Endliche Abbildung: Signatur
I AdressenundWertesindParameter
I TypMapα β, Operationen:
dataMapα β empty :: Mapα β
lookup :: Ordα⇒α→Mapα β→Maybeβ i n s e r t :: Ordα⇒α→β→Mapα β→Mapα β delete :: Ordα⇒α→Mapα β→Mapα β
PI3 WS 18/19 5 [29]
Signatur und Eigenschaften
I Signatur genug, um ADTtypkorrektzu benutzen
IInsbesondereAnwendbarkeitundReihenfolge
I Signatur beschreibt nicht dieBedeutung(Semantik):
IWaswirdgelesen?
IWieverhältsich die Abbildung?
I Signatur istSprache(Syntax) umEigenschaftenzu beschreiben
PI3 WS 18/19 6 [29]
Eigenschaften Endlicher Abbildungen
1 Aus derleerenAbbildung kannnichtsgelesen werden.
2 Wenn etwasgeschriebenwird, und an dergleichenStelle wieder gelesen, erhalte ich den geschriebenen Wert.
3 Wenn etwasgeschriebenwird, und anandererStelle etwasgelesen wird, kann das Schreiben vernachlässigt werden.
4 An dergleichenStellezweimal geschriebenüberschreibt der zweite den ersten Wert.
5 An unterschiedlichen Stellengeschriebenkommutiert.
PI3 WS 18/19 7 [29]
Formalisierung von Eigenschaften
Definition (Axiome)
AxiomesindPrädikateüber denOperationender Signatur
I ElementarePrädikateP:
IGleichheits == t
IOrdnungs<t
ISelbstdefinierte Prädikate I ZusammengesetztePrädikate
INegationnot p
IKonjunktionp && q
IDisjunktionp | | q
IImplikationp =⇒q
PI3 WS 18/19 8 [29]
Axiome als Interface
I Axiome müssengelten
I füralleWerte der freien Variablen zuTrueauswerten I Axiomespezifizieren:
I nach außen dasVerhalten
I nach innen dieImplementation I Signatur+Axiome=Spezifikation
Spezifikation
Implementation Nutzer
rich thin interface
PI3 WS 18/19 9 [29]
Axiome für Map
I Lesenaus leerer Abbildung undefiniert:
lookup a (empty :: Map Int String ) == Nothing
I Lesenan vorher geschriebener Stelle liefert geschriebenen Wert:
lookup a ( i n s e r t a v ( s :: Map Int String )) == Just v lookup a ( delete a ( s :: Map Int String )) == Nothing I Lesenan anderer Stelle liefert alten Wert:
a6= b =⇒lookup a ( delete b s ) == lookup a ( s :: Map Int String ) I Schreibenan dieselbe Stelle überschreibt alten Wert:
i n s e r t a w ( i n s e r t a v s ) == i n s e r t a w ( s :: Map Int String ) I Schreibenüber verschiedene Stellen kommutiert:
a6= b =⇒ i n s e r t a v ( delete b s ) ==
delete b ( i n s e r t a v s :: Map Int String ) I SehrvieleAxiome (insgesamt 13)!
PI3 WS 18/19 10 [29]
Thin vs. Rich Interfaces
I Benutzersicht:reichesInterface
I Viele Operationen und Eigenschaften I Implementationssicht:schlankesInterface
I Wenig Operation und Eigenschaften I BeispielMap:
I Rich interface:
i n s e r t :: Ordα⇒α→β→Mapα β→Mapα β delete :: Ordα⇒α→Mapα β→Mapα β
I Thin interface:
put :: Ordα⇒α→Maybeβ→Mapα β→Mapα β
I Thin-to-rich:
i n s e r t a v = put a ( Just v) delete a = put a Nothing
PI3 WS 18/19 11 [29]
Axiome für Map (thin interface)
I Lesenaus leerer Abbildung undefiniert:
lookup a (empty :: Map Int String ) == Nothing I Lesenan vorher geschriebener Stelle liefert geschriebenen Wert:
lookup a (put a v ( s :: Map Int String )) == v I Lesenan anderer Stelle liefert alten Wert:
a6= b =⇒lookup a (put b v s ) ==
lookup a ( s :: Map Int String ) I Schreibenan dieselbe Stelle überschreibt alten Wert:
put a w (put a v s ) == put a w ( s :: Map Int String ) I Schreibenüber verschiedene Stellen kommutiert:
a6= b =⇒put a v (put b w s ) ==
put b w (put a v s :: Map Int String )Thin: 5 Axiome Rich: 13 Axiome
PI3 WS 18/19 12 [29]
Axiome als Eigenschaften
I Axiome könnengetestetoderbewiesenwerden I Tests findenFehler, Beweis zeigtKorrektheit
E. W. Dijkstra, 1972
Program testing can be used to show the presence of bugs, but never to show their absence.
I Artenvon Tests:
I Unit tests(JUnit, HUnit)
I Black Boxvs.White Box
I Coverage-based(z.B. path coverage, MC/DC)
I ZufallsbasiertesTesten
I Funktionale Programme eignen sichsehr gutzum Testen
PI3 WS 18/19 13 [29]
Zufallsbasiertes Testen in Haskell
I Werkzeug:QuickCheck
I Zufällige Werteeinsetzen, Auswertung aufTrueprüfen I Polymorphe Variablen nichttestbar
IDeshalb Typvariableninstantiieren
ITyp muss genug Element haben (hierMap Int String)
IDurch SignaturTypinstanzerzwingen
I Freie Variablender Eigenschaft werdenParameterder Testfunktion
PI3 WS 18/19 14 [29]
Axiome mit QuickCheck testen
I Für das Lesen:
prop1 :: TestTree
prop1 = QC. testProperty "read_empty" $λa→
lookup a (empty :: Map Int String ) == Nothing prop2 :: TestTree
prop2 = QC. testProperty "lookup_put␣eq" $ λa v s→
lookup a (put a v ( s :: Map Int String )) == v I Hier: Eigenschaften alsHaskell-Prädikate
I QuickCheck-Axiome mitQC. testPropertyinTastyeingebettet I Es werdenNZufallswerte generiert und getestet (DefaultN= 100)
PI3 WS 18/19 15 [29]
Axiome mit QuickCheck testen
I BedingteEigenschaften:
IA =⇒BmitA,BEigenschaften
ITyp istProperty
IEs werden solange Zufallswerte generiert, bisNdie Vorbedingung erfüllende gefunden und getestet wurden, andere werden ignoriert.
prop3 :: TestTree
prop3 = QC. testProperty "lookup_put␣other " $λa b v s→
a6= b =⇒lookup a (put b v s ) ==
lookup a ( s :: Map Int String )
PI3 WS 18/19 16 [29]
Axiome mit QuickCheck testen
I Schreiben:
prop4 :: TestTree
prop4 = QC. testProperty "put_put␣eq" $λa v w s→
put a w (put a v s ) == put a w ( s :: Map Int String )
I Schreibenan anderer Stelle:
prop5 :: TestTree
prop5 = QC. testProperty "put_put␣other " $ λa v b w s→
a6= b =⇒put a v (put b w s ) ==
put b w (put a v s :: Map Int String ) I Test benötigtGleichheitundZufallswerte fürMap a b
PI3 WS 18/19 17 [29]
Zufallswerte selbst erzeugen
I Problem:ZufälligeWerte vonselbstdefiniertenDatentypen
IGleichverteiltheitnicht immer erwünscht (z.B.[α])
IKonstruktionnicht immer offensichtlich (z.B.Map) I InQuickCheck:
ITypklasseclass ArbitraryαfürZufallswerte
IEigeneInstanziierungkann Verteilung und Konstruktion berücksichtigen instance (Ord a , QC. Arbitrary a , QC. Arbitrary b)⇒
QC. Arbitrary (Map a b)where
IBspw.KonstruktioneinerMap:
IZufällige Länge, dann aus sovielen zufälligen WertenMapkonstruieren
IZufallswerte in Haskell?
PI3 WS 18/19 18 [29]
Beobachtbare und Abstrakte Typen
I BeobachtbareTypen: interne Struktur bekannt
I Vordefinierte Typen (Zahlen,Zeichen), algebraische Datentypen (Listen)
I Viele Eigenschaften und Prädikate bekannt I AbstrakteTypen: interne Struktur unbekannt
I Wenige Eigenschaften bekannt, Gleichheit nur wenn definiert
I BeispielMap:
I beobachtbar: Adressen und Werte
I abstrakt: Speicher
PI3 WS 18/19 19 [29]
Beobachtbare Gleichheit
I Auf abstrakten Typen: nurbeobachtbareGleichheit
IZwei Elemente sindgleich, wenn alle Operationen die gleichen Werte liefern
I BeiImplementation: Instanz fürEq(Ordetc.) entsprechend definieren
IDie Gleichheit==muss diebeobachtbareGleichheit sein.
I AbgeleiteteGleichheit (derivingEq) wirdimmerexportiert!
PI3 WS 18/19 20 [29]
Signatur und Semantik
Stacks Typ:St α Initialwert:
empty :: Stα Wert ein/auslesen:
push :: α→ Stα→St α top :: Stα→α pop :: Stα→ Stα Last in first out (LIFO).
Queues Typ:Quα Initialwert:
empty :: Quα Wert ein/auslesen:
enq :: α→Quα→Quα f i r s t :: Quα→α deq :: Quα→Quα First in first out (FIFO)
GleicheSignatur, unterscheidlicheSemantik.
PI3 WS 18/19 21 [29]
Eigenschaften von Stack
I Last in first out (LIFO):
top(push a1(push a2 . . .(push anempty))) =a1
top (push a s ) == a pop (push a s ) == s push a s6= empty
PI3 WS 18/19 22 [29]
Eigenschaften von Queue
I First in first out (FIFO):
f i r s t(enq a1(enq a2 . . . (enq anempty))) =an
f i r s t (enq a empty) == a
q6= empty =⇒ f i r s t (enq a q) == f i r s t q deq (enq a empty) == empty
q6= empty =⇒deq (enq a q) = enq a (deq q) enq a q6= empty
PI3 WS 18/19 23 [29]
Implementation von Stack: Liste
Sehr einfach: ein Stack ist eine Liste dataSt α= St [α] deriving (Show, Eq) empty = St [ ]
push a (St s ) = St (a : s )
top (St [ ] ) = er ro r "St : ␣top␣on␣empty␣stack "
top (St s ) = head s
pop (St [ ] ) = er ro r "St : ␣pop␣on␣empty␣stack "
pop (St s ) = St ( t a i l s )
PI3 WS 18/19 24 [29]
Implementation von Queue
I Mit einerListe?
I Problem: am Ende anfügen oder abnehmen ist teuer.
I DeshalbzweiListen:
I Erste Liste: zuentnehmendeElemente
I Zweite Liste:hinzugefügteElementerückwärts
I Invariante: erste Liste leer gdw. Queue leer
PI3 WS 18/19 25 [29]
Repräsentation von Queue
Operation Resultat Interne Repräsentation
empty h i ([], [])
enq 9 h9i ([9], [])
enq 4 h4→9i ([9], [4])
enq 7 h7→4→9i ([9], [7, 4])
f i r s t 9
deq h7→4i ([4, 7], [])
enq 5 h5→7→4i ([4, 7], [5]) enq 3 h3→5→7→4i ([4, 7], [3, 5])
f i r s t 4
deq h3→5→7i ([7], [3, 5])
f i r s t 7
deq h3→5i ([5, 3], [])
f i r s t 5
deq h3i ([3], [])
f i r s t 3
deq h i ([], [])
f i r s t er ro r
deq er ro r
PI3 WS 18/19 26 [29]
Implementation
I Datentyp:
dataQuα= Qu [α] [α]
I Leere Schlange: alles leer empty = Qu [ ] [ ]
I Erstes Element steht vorne in erster Liste f i r s t :: Quα→α
f i r s t (Qu [ ] _) = er ro r "Queue: ␣ f i r s t ␣of␣empty␣Q"
f i r s t (Qu (x : xs ) _) = x I Gleichheit:
v a l i d :: Quα→ Bool v a l i d (Qu [ ] ys ) = n u l l ys v a l i d (Qu (_:_) _) = True
PI3 WS 18/19 27 [29]
Implementation
I BeienqunddeqInvariante prüfen enq x (Qu xs ys ) = check xs (x : ys )
deq (Qu [ ] _ ) = er ro r "Queue: ␣deq␣of␣empty␣Q"
deq (Qu (_: xs ) ys ) = check xs ys
IPrüfung der Invariantenachdem Einfügen und Entnehmen
I checkgarantiertInvariante check :: [α]→ [α]→Quα check [ ] ys = Qu ( reverse ys ) [ ] check xs ys = Qu xs ys
PI3 WS 18/19 28 [29]
Zusammenfassung
I Signatur: Typ und Operationen eines ADT I Axiome: über Typen formulierteEigenschaften I Spezifikation= Signatur + Axiome
I Interfacezwischen Implementierung und Nutzung
I Testenzur Erhöhung der Konfidenz und zum Fehlerfinden
I Beweisender Korrektheit
I QuickCheck:
I Freie Variablen der Eigenschaften werdenParameterder Testfunktion
I=⇒fürbedingteEigenschaften
PI3 WS 18/19 29 [29]