• Keine Ergebnisse gefunden

Definition von Funktionen

N/A
N/A
Protected

Academic year: 2022

Aktie "Definition von Funktionen"

Copied!
5
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Praktische Informatik 3: Funktionale Programmierung Vorlesung 2 vom 23.10.2016: Funktionen

Christoph Lüth

Universität Bremen Wintersemester 2018/19

16:03:01 2018-12-18 1 [34]

Fahrplan

I Teil I: Funktionale Programmierung im Kleinen

IEinführung

I Funktionen

IAlgebraische Datentypen

ITypvariablen und Polymorphie

IZyklische Datenstrukturen

IFunktionen höherer Ordnung I

IFunktionen höherer Ordnung II

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

PI3 WS 18/19 2 [34]

Inhalt

I Organisatorisches I Definition vonFunktionen

I SyntaktischeFeinheiten

I Bedeutung von Haskell-Programmen

I Striktheit

I Leben ohne Variablen

I Funktionen statt Schleifen

I Zahllose Beispiele

PI3 WS 18/19 3 [34]

Organisatorisches

I Verteilung der Tutorien (laut stud.ip):

Abweichung Mi 08–10 MZH 1470 Thomas Barkowsky 16 -18

10–12 MZH 1090 Tobias Haslop 50 16 12–14 MZH 1470 Matz Habermann 49 15 16–18 MZH 1090 Andreas Kästner 18 -16 Do 12–14 MZH 1090 Gerrit Marquardt 50 15

16–18 MZH 1110 Gerrit Marquardt 23 -11

IWenn möglich, frühe/späte Tutorien belegen.

I Bewertung der Übungsblätter:

IDokumentation: kurz und knapp für jede Funktion

ICode: auf guten Stil achten

ITests und Testfälle

PI3 WS 18/19 4 [34]

Definition von Funktionen

PI3 WS 18/19 5 [34]

Definition von Funktionen

I Zwei wesentlicheKonstrukte:

IFallunterscheidung

IRekursion

I Reicht das?

Satz

Fallunterscheidung und Rekursion auf natürlichen Zahlen sind Turing-mächtig.

I Funktionen müssenpartiellsein können.

IInsbesondere nicht-terminierende Rekursion

PI3 WS 18/19 6 [34]

Haskell-Syntax: Charakteristika

I Leichtgewichtig

I Wichtigstes Zeichen:

I Funktionsapplikation:f a

I Klammern sindoptional

I HöchstePriorität (engste Bindung)

I Abseitsregel: Gültigkeitsbereich durch Einrückung

I KeineKlammern({. . .})

I Auch in anderenSprachen(Python, Ruby)

Haskell-Syntax: Funktionsdefinition

Generelle Form:

I Signatur:

max :: Int→ Int→ Int

I Definition:

max x y = i f x<y theny else x

IKopf, mit Parametern

IRumpf(evtl. länger, mehrere Zeilen)

ITypischesMuster: Fallunterscheidung, dann rekursiver Aufruf

IWas gehört zum Rumpf (Geltungsberereich)?

(2)

Haskell-Syntax I: Die Abseitsregel

Funktionsdefinition:

f x1 x2 x3 . . . xn = e

I Gültigkeitsbereichder Definition vonf: alles, was gegenüberfeingerücktist.

I Beispiel:

f x = h i e r faengts an und h i e r gehts weiter

immer weiter

g y z = und h i e r faengt was neues an I Gilt auchverschachtelt.

I Kommentare sindpassiv(heben das Abseits nicht auf).

PI3 WS 18/19 9 [34]

Haskell-Syntax II: Kommentare

I Pro Zeile: Ab−−bis Ende der Zeile

f x y = irgendwas −−und hier der Kommentar!

I Über mehrere Zeilen: Anfang{−, Ende−}

{−

Hier faengt der Kommentar an e r s tr e c k t sich ueber mehrere Zeilen

b i s h i e r −}

f x y = irgendwas

IKann geschachtelt werden.

PI3 WS 18/19 10 [34]

Haskell-Syntax III: Bedingte Definitionen

I Statt verschachtelter Fallunterscheidungen . . . f x y =i f B1thenP else

i f B2thenQelse. . . . . .bedingte Gleichungen:

f x y

| B1 =. . .

| B2 =. . .

I Auswertung der Bedingungen von oben nach unten I Wenn keine Bedingung wahr ist:Laufzeitfehler! Deshalb:

| otherwise =. . .

PI3 WS 18/19 11 [34]

Haskell-Syntax IV: Lokale Definitionen

I Lokale Definitionen mitwhereoderlet:

f x y

| g = P y

| otherwise = f x where y = M

f x = N x

f x y = let y = M

f x = N x in i f g thenP y

else f x I f,y, . . . werdengleichzeitigdefiniert (Rekursion!) I Namenf,yund Parameter (x)überlagernandere I Es gilt dieAbseitsregel

IDeshalb:Aufgleiche Einrückungder lokalen Definition achten!

PI3 WS 18/19 12 [34]

Bedeutung von Programmen

PI3 WS 18/19 13 [34]

Auswertung von Funktionen

I Auswertung durchAnwendungvon Gleichungen

I Auswertungsrelationst:

IAnwendung einer Funktionsdefinition

IAnwendung von elementaren Operationen (arithmetisch, Zeichenketten)

PI3 WS 18/19 14 [34]

Auswertung von Ausdrücken

inc :: Int → Int inc x = x+ 1

dbl :: Int → Int dbl x = 2∗x I Reduktion voninc ( dbl ( inc 3))

I Vonaußennachinnen(outermost-first):

inc ( dbl ( inc 3)) →dbl (inc 3)+ 1

→2*(inc 3)+ 1

→2*(3+ 1)+ 1

→2*4+1→9 I Voninnennachaußen(innermost-first):

inc (dbl (inc 3)) →inc (dbl (3+1))

→inc (2*(3+ 1))

→(2*(3+ 1))+ 1

→2*4+1→9

PI3 WS 18/19 15 [34]

Auswertung von Ausdrücken

inc :: Int → Int inc x = x+ 1

dbl :: Int → Int dbl x = 2∗x I Reduktion voninc ( dbl ( inc 3))

inc (dbl (inc 3) inc (2* (inc 3)

dbl (inc 3)+1 inc (dbl (3+1))

2*(inc 3)+1 dbl (3+1)+1 inc (2*(3+1) inc (dbl 4)

2*(3+1)+1 dbl 4 +1 inc (2* 4)

2*4+1 inc 8

8+1 9

PI3 WS 18/19 16 [34]

(3)

Konfluenz

I Es kommt immer das gleiche heraus?

I Sei→ die Reduktion in null oder mehr Schritten.

Definition (Konfluenz)

istkonfluentgdw:

Für aller,s,tmits r tgibt esuso dasss u t.

PI3 WS 18/19 17 [34]

Konfluenz

I Wenn wir von Laufzeitfehlern abstrahieren, gilt:

Theorem (Konfluenz)

Die Auswertungsrelation für funktionale Programme istkonfluent.

I Beweisskizze:

Seif x = Eunds t:

f s

-f t

E

"

s x

#

?

∗ -E

"

t x

#

?

PI3 WS 18/19 18 [34]

Auswirkung der Auswertungsstrategie

I Auswertungsstrategie ist also egal?

I Beispiel:

repeat :: Int→ String→ String repeat n s =i f n == 0then ""

else s ++ repeat (n−1) s

undef :: String undef = undef

I Auswertung vonrepeat 0 undef:

repeat 0 undef repeat 0 undef

repeat 0 undef repeat 0 undef repeat 0 undef

""

...

I outermost-firstterminiert I inntermost-first terminiertnicht

PI3 WS 18/19 19 [34]

Termination und Normalform

Definition (Termination)

→istterminierendgdw. eskeine unendlichenKetten gibt:

t1t2t3. . .tn. . .

Theorem (Normalform)

Sei konfluent und terminierend, dann wertet jeder Term zu genau einerNormalformaus, die nicht weiter ausgewertet werden kann.

I Daraus folgt:terminierendefunktionale Programme werten unter jeder Auswertungsstragie jeden Ausdruck zum gleichen Wert aus (der Normalform).

PI3 WS 18/19 20 [34]

Auswirkung der Auswertungsstrategie

I Auswertungsstrategie nur fürnicht-terminierendeProgramme relevant.

I Leider ist nicht-Terminationnötig(Turing-Mächtigkeit)

I Auswertungsstrategie und Parameterübergabe:

I Outermost-first entsprichtcall-by-need,verzögerteAuswertung.

I Innermost-first entsprichtcall-by-value,strikteAuswertung

I Gibt es einesemantischeCharakterisierung?

PI3 WS 18/19 21 [34]

Bedeutung (Semantik) von Programmen

I OperationaleSemantik:

IDurch denAusführungsbegriff

IEin Programm ist, was es tut.

IIn diesem Fall:→ I DenotationelleSemantik:

IProgramme werden aufmathematische Objekteabgebildet (Denotat).

IFür funktionale Programme:rekursivdefinierte Funktionen

Äquivalenz von operationaler und denotationaler Semantik

SeiPein funktionales Programm,→ die dadurch definierte Reduktion, und [[P]] das Denotat. Dann gilt für alle Ausdrücketund Wertev

t v ⇐⇒ [[P]](t) =v

PI3 WS 18/19 22 [34]

Striktheit

Definition (Striktheit)

Funktionf iststrikt ⇐⇒ Ergebnis ist undefiniert

sobald ein Argument undefiniert ist.

I DenotationelleEigenschaft (nicht operational) I Haskell istnicht-strikt(nach Sprachdefinition)

I repeat0 undefmuss""ergeben.

I MeistenImplementationennutzenverzögerte Auswertung I Andere Programmiersprachen:

I Java, C, etc. sindcall-by-value(nach Sprachdefinition) und damitstrikt

I Fallunterscheidung istimmernicht-strikt, Konjunktion und Disjunktion meist auch.

Leben ohne Variablen

(4)

Rekursion statt Schleifen

Fakultät imperativ:

r= 1;

while (n>0) { r= n∗ r ; n= n−1;

}

Fakultät rekursiv:

fac ’ n r = i f n≤0 then r else fac ’ (n−1) (n∗r ) fac n = fac ’ n 1 I Veränderliche Variablen werden zu Funktionsparametern

I Iteration (while-Schleifen) werden zu Rekursion

I Endrekursion verbraucht keinen Speicherplatz

PI3 WS 18/19 25 [34]

Rekursive Funktionen auf Zeichenketten

I Test auf die leere Zeichenkette:

n u l l :: String→ Bool n u l l xs = xs == ""

I Kopf und Rest einer nicht-leeren Zeichenkette (vordefiniert):

head :: String→ Char t a i l :: String→ String

PI3 WS 18/19 26 [34]

Suche in einer Zeichenkette

I Suche nach einem Zeichen in einer Zeichenkette:

count1 :: Char→ String→ Int

I In einem leeren String: kein Zeichen kommt vor

I Ansonsten: Kopf vergleichen, zum Vorkommen im Rest addieren count1 c s =

i f n u l l s then0

else i f head s== c then 1+ count1 c ( t a i l s ) else count1 c ( t a i l s )

PI3 WS 18/19 27 [34]

Suche in einer Zeichenkette

I Etwas lesbarer mit Guards:

count2 c s

| n u l l s = 0

| head s == c = 1+ count2 c ( t a i l s )

| otherwise = count2 c ( t a i l s ) I Endrekursiv:

count3 c s = count3 ’ c s 0 count3 ’ c s r =

i f n u l l s then r

else count3 ’ c ( t a i l s ) (i f head s == c then1+r else r ) I Endrekursiv mit lokaler Definition

count4 c s = count4 ’ s 0where count4 ’ s r =

i f n u l l s then r

else count4 ’ ( t a i l s ) (i f head s == c then1+r else r )

PI3 WS 18/19 28 [34]

Strings konstruieren

I :hängt Zeichen vorne an Zeichenkette an (vordefiniert) ( : ) :: Char→ String→ String

I Es gilt: Wenn not ( n u l l s ), dannhead s : t a i l s == s I Mit( : )wird(++)definiert:

(++) :: String→ String→ String xs ++ ys

| n u l l xs = ys

| otherwise = head xs : ( t a i l xs ++ ys ) I quadratkonstruiert ein Quadrat aus Zeichen:

quadrat :: Int→Char→ String

quadrat n c = repeat n ( repeat n (c : "" ) ++ "\n")

PI3 WS 18/19 29 [34]

Strings analysieren

I Warum immer nur Kopf/Rest?

I Letztes Zeichen (dual zuhead):

l a s t 1 :: String→Char

l a s t 1 s =i f n u l l s then l a s t 1 s

else i f n u l l ( t a i l s ) thenhead s else l a s t 1 ( t a i l s )

I Besser: mit Fehlermeldung l a s t :: String→ Char l a s t s

| n u l l s = er ro r " l a s t : ␣empty␣ s t r i n g "

| n u l l ( t a i l s ) = head s

| otherwise = l a s t ( t a i l s )

PI3 WS 18/19 30 [34]

Strings analysieren

I Anfang der Zeichenkette (dual zu t a i l):

i n i t :: String→ String i n i t s

| n u l l s = er ro r " i n i t : ␣empty␣ s t r i n g " −−nicht s

| n u l l ( t a i l s ) = ""

| otherwise = head s : i n i t ( t a i l s )

I Damit: Wenn not ( n u l l s ), danni n i t s ++ ( l a s t s : "" ) == s

PI3 WS 18/19 31 [34]

Strings analysieren: das Palindrom

I Palindrom: vorwärts und rückwärts gelesen gleich.

I Rekursiv:

IAlle Wörter der Länge 1 oder kleiner sind Palindrome

IFür längere Wörter: wenn erstes und letztes Zeichen gleich sind und der Rest ein Palindrom.

I Erster Versuch:

palin1 :: String→ Bool palin1 s

| length s≤1 = True

| head s == l a s t s = palin1 ( i n i t ( t a i l s ))

| otherwise = False

PI3 WS 18/19 32 [34]

(5)

Strings analysieren: das Palindrom

I Zweiter Versuch:

palin2 :: String→Bool palin2 s =

length s≤1 | | head s == l a s t s && palin2 ( i n i t ( t a i l s ))

I Terminiert wegen Nicht-Striktheit von| | I Erweiterte Version:

palin3 s = palin2 ( clean s )

I Nicht-alphanumerische Zeichen entfernen, alles Kleinschrift:

clean :: String→ String clean s

| n u l l s = ""

| isAlphaNum (head s ) = toLower (head s ) : clean ( t a i l s )

| otherwise = clean ( t a i l s )

PI3 WS 18/19 33 [34]

Zusammenfassung

I Bedeutungvon Haskell-Programmen:

IAuswertungsrelation→

IAuswertungsstrategien: innermost-first, outermost-firsta

IAuswertungsstrategie für terminierende Programme irrelevant I Striktheit

IHaskell istspezifiziertals nicht-strikt

IMeist implementiert durch verzögerte Auswertung I Lebenohne Variablen:

IRekursion statt Schleifen

IFunktionsparameter statt Variablen I Nächste Vorlesung: Datentypen

PI3 WS 18/19 34 [34]

Referenzen

ÄHNLICHE DOKUMENTE

Niemand darf kör-perlich oder mit Worten verletzt werden.Bei den genannten Telefonnummern finden Mädchen und Frauen Hilfe in ver-schiedensten

Entwässerungsrinne, 1 Läuferzeile Betonsteinpflaster 16/24/14 cm, ohne Fase, Farbe grau,auf einem Betonbett C 30/37 gepl. Grünfläche mit Begrünung durch Rasensaat

[r]

Druckerei Dorrong Kämtnerstr. 96, Graz. Auflage: 3500 Stück

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

sright = sort right in merge sleft sright wird parallelisiert durch Annotationen:.. sleft =

Bin e -&gt; List e Def: der Typ einer polymorphen Funktion beginnt mit All-Quantoren f¨ur Typvariablen4. Bsp: Datenkonstruktoren

Die Methode laenge() soll die Länge des aktuellen Intervalls liefern. Markieren Sie die Fehler im Pro- grammtext. Achtung: Für Programmstellen, die nicht zu einem Fehler führen,