• Keine Ergebnisse gefunden

I. Definition von Funktionen

N/A
N/A
Protected

Academic year: 2022

Aktie "I. Definition von Funktionen"

Copied!
5
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

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

Christoph Lüth

Wintersemester 2020/21

11:51:10 2021-02-22 1 [38]

Fahrplan

ITeil I: Funktionale Programmierung im Kleinen IEinführung

IFunktionen

IAlgebraische Datentypen ITypvariablen und Polymorphie IFunktionen höherer Ordnung I IRekursive und zyklische Datenstrukturen IFunktionen höherer Ordnung II

ITeil II: Funktionale Programmierung im Großen ITeil III: Funktionale Programmierung im richtigen Leben

PI3 WS 20/21 2 [38]

Inhalt und Lernziele

IDefinition vonFunktionen ISyntaktischeFeinheiten IBedeutung von Haskell-Programmen

IStriktheit

ILeben ohne Variablen IFunktionen statt Schleifen IZahllose Beispiele Lernziele

Wir wollen einfache Haskell-Programme schreiben können, eine Idee von ihrer Bedeutung bekommen, und ein Leben ohne veränderliche Variablen führen.

PI3 WS 20/21 3 [38]

I. Definition von Funktionen

PI3 WS 20/21 4 [38]

Definition von Funktionen

IZwei wesentlicheKonstrukte:

IFallunterscheidung IRekursion Satz

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

IFunktionen müssenpartiellsein können.

IInsbesondere nicht-terminierende Rekursion

IFragen: wie schreiben Funktionen in Haskell auf (Syntax), und was bedeutet das (Semantik)?

PI3 WS 20/21 5 [38]

Haskell-Syntax: Charakteristika

ILeichtgewichtig IWichtigstes Zeichen:

IFunktionsapplikation:f a IKlammern sindoptional IHöchstePriorität (engste Bindung)

IAbseitsregel: Gültigkeitsbereich durch Einrückung IKeineKlammern({. . .}) (optional)

IAuch in anderenSprachen(Python, Ruby)

PI3 WS 20/21 6 [38]

Haskell-Syntax: Funktionsdefinition

Generelle Form:

ISignatur:

max :: Int→Int→Int IDefinition:

max x y=ifx<y thenyelse x IKopf, mit Parametern

IRumpf(evtl. länger, mehrere Zeilen)

ITypischesMuster: Fallunterscheidung, dann rekursiver Aufruf IWas gehört zum Rumpf (Geltungsberereich)?

PI3 WS 20/21 7 [38]

Haskell-Syntax I: Die Abseitsregel

Funktionsdefinition:

f x1 x2 x3...xn=e

IGültigkeitsbereichder Definition vonf:

alles, was gegenüberfeingerücktist.

IBeispiel:

f x=hier faengts an und hier gehts weiter

immer weiter

g y z=und hier faengt was neues an IGilt auchverschachtelt.

IKommentare sindpassiv(heben das Abseits nicht auf).

PI3 WS 20/21 8 [38]

(2)

Haskell-Syntax II: Kommentare

IPro 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 erstreckt sich ueber mehrere Zeilen

bis hier −}

f x y=irgendwas IKann geschachtelt werden.

PI3 WS 20/21 9 [38]

Haskell-Syntax III: Bedingte Definitionen

IStatt verschachtelter Fallunterscheidungen . . . f x y=ifB1then Pelse

ifB2then Qelse R . . .bedingte Gleichungen: f x y

| B1=P

| B2=Q

IAuswertung der Bedingungen von oben nach unten IWenn keine Bedingung wahr ist:Laufzeitfehler! Deshalb:

| otherwise=R

PI3 WS 20/21 10 [38]

Haskell-Syntax IV: Lokale Definitionen

ILokale Definitionen mitwhereoderlet: f x y

| g=P y

| otherwise=f x where y=M

f x=N x

f x y= lety=M

f x=N x in ifgthen P y

else f x If,y, . . . werdengleichzeitigdefiniert (Rekursion!)

INamenf,yund Parameter (x)überlagernandere IEs gilt dieAbseitsregel

IDeshalb:Aufgleiche Einrückungder lokalen Definition achten!

PI3 WS 20/21 11 [38]

Jetzt seit ihr dran!

Übung 2.1: Syntax

In dem Beispielprogramm auf der vorherigen Folie, welche der Variablenf,xundyauf den rechten Seiten wird wo gebunden?

Lösung:

PI3 WS 20/21 12 [38]

II. Auswertung von Funktionen

PI3 WS 20/21 13 [38]

Auswertung von Funktionen

IAuswertung durchAnwendungvon Gleichungen IAuswertungsrelationst:

IAnwendung einer Funktionsdefinition

IAnwendung von elementaren Operationen (arithmetisch, Zeichenketten) IFrage: spielt dieReihenfolgeeine Rolle?

PI3 WS 20/21 14 [38]

Auswertung von Ausdrücken

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

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

IVonaußennachinnen(outermost-first):

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

→2∗(inc 3)+ 1

→2∗(3+ 1)+ 1→2∗4+1→8+1→9 IVoninnennachaußen(innermost-first):

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

→inc (2∗4)→inc 8

→8+1→9

PI3 WS 20/21 15 [38]

Auswertung von Ausdrücken

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

dbl :: Int →Int dbl x=2∗x IVolle 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 20/21 16 [38]

(3)

Konfluenz

IEs kommt immer das gleiche heraus?

ISei→ die Reduktion in null oder mehr Schritten.

Definition (Konfluenz)

istkonfluentgdw:

Für aller,s,tmitsr tgibt esuso dasss ut.

PI3 WS 20/21 17 [38]

Konfluenz

IWenn wir von Laufzeitfehlern abstrahieren, gilt:

Theorem (Konfluenz)

Die Auswertungsrelation für funktionale Programme istkonfluent.

IBeweisskizze:

Seif x=Eundst:

f s

-f t

E

"

s x

#

?

∗ -E

"

t x

#

?

PI3 WS 20/21 18 [38]

Auswirkung der Auswertungsstrategie

IAuswertungsstrategie ist also egal?

IBeispiel:

repeat :: Int→String→String repeat n s=ifn==0then""

elses++repeat (n-1) s

undef :: String undef=undef

IAuswertung vonrepeat 0 undef: repeat 0 undef repeat 0 undef repeat 0 undef

""

repeat 0 undef repeat 0 undef

"" repeat 0 undef repeat 0 undef repeat 0 undef

"" repeat 0 undef repeat 0 undef repeat 0 undef repeat 0 undef

"" repeat 0 undef repeat 0 undef repeat 0 undef ...

Ioutermost-firstterminiert Iinntermost-first terminiertnicht

PI3 WS 20/21 19 [38]

Termination und Normalform

Definition (Termination)

→istterminierendgdw. eskeine unendlichenKetten gibt:

t1t2t3. . .tn. . .

Theorem (Normalform)

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

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

PI3 WS 20/21 20 [38]

Auswirkung der Auswertungsstrategie

IAuswertungsstrategie nur fürnicht-terminierendeProgramme relevant.

ILeider ist nicht-Terminationnötig(Turing-Mächtigkeit) IGibt es einesemantischeCharakterisierung?

IAuswertungsstrategie und Parameterübergabe:

IOutermost-first entsprichtcall-by-need,verzögerteAuswertung.

IInnermost-first entsprichtcall-by-value,strikteAuswertung

PI3 WS 20/21 21 [38]

Zum Mitdenken. . .

Übung 2.2:

Warumentspricht outermost-first call-ny-need und innermost-first call-by-value?

Lösung:Der Aufruf einer Funktionf x=Eentspricht hier der Ersetzung der linken Seitef durch die rechte SeiteE, mit den Parameternxentsprechend ersetzt.

Wenn wir beispielsweise Auswertung des Ausdrucksdbl (dbl (dbl (7+3)))betrachten, dann wird innermost-first zuerst7+3reduziert, danndbl 10etc, d.h. jeweils dieArgumente der Funktion — Funktionen bekommen nur Werte übergeben.

Bei outermost-first wird zuerst das äußerstedblreduziert, was dem Aufruf der Funktiondbl mit dem nicht ausgewerteten Argumentdbl (dbl (7+3))entspricht (verzögerte Auswertung).

PI3 WS 20/21 22 [38]

III. Semantik und Striktheit

PI3 WS 20/21 23 [38]

Bedeutung (Semantik) von Programmen

IOperationaleSemantik:

IDurch denAusführungsbegriff IEin Programmist, was estut.

IIn diesem Fall:→ IDenotationelleSemantik:

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 20/21 24 [38]

(4)

Striktheit

Definition (Striktheit)

Funktionfiststrikt ⇐⇒ Ergebnis ist undefiniert, sobald ein Argument undefiniert ist.

IDenotationelleEigenschaft (nicht operational) IHaskell ist nachSprachdefinition nicht-strikt

Irepeat 0 undefmuss""ergeben.

IMeistenImplementationennutzenverzögerte Auswertung

IAndere Programmiersprachen:

IJava, C, etc. sindcall-by-value(nach Sprachdefinition) und damitstrikt IFallunterscheidung istimmernicht-strikt, Konjunktion und Disjunktion meist auch.

PI3 WS 20/21 25 [38]

Jetzt seit ihr dran!

Übung 2.3: Strikte Fallunterscheidung

Warum ist Fallunterscheidung immer nicht-strikt, auch in Java?

Lösung:Betrachte

y=x==0 ? -1 : 100/x; if (x==0) { y=-1;

} else{ y=100/x;

}

Wäre die Fallunterscheidung strikt, würden erstbeideFälle ausgewertet; es wäre nicht mehr möglich, die Auswertung undefinierter Ausdrücke abzufangen. Das gleich gilt für das Programm rechts.

PI3 WS 20/21 26 [38]

IV. Leben ohne Variablen

PI3 WS 20/21 27 [38]

Rekursion statt Schleifen

Fakultät imperativ:

r=1;

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

n=n- 1;

}

Fakultät rekursiv:

fac’ n r= ifn≤0then r else fac’ (n-1) (n∗r) fac n=fac’ n 1 IVeränderliche Variablen werden zu Funktionsparametern IIteration (while-Schleifen) werden zu Rekursion IEndrekursion verbraucht keinen Speicherplatz

PI3 WS 20/21 28 [38]

Rekursive Funktionen auf Zeichenketten

ITest auf die leere Zeichenkette:

null :: String→Bool null xs= xs==""

IKopf und Rest einer nicht-leeren Zeichenkette (vordefiniert):

head :: String→Char tail :: String→String

DEMO

PI3 WS 20/21 29 [38]

Suche in einer Zeichenkette

ISuche nach einem Zeichen in einer Zeichenkette:

count1 :: Char→String→Int IIn einem leeren String: kein Zeichen kommt vor

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

ifnull sthen 0

else ifhead s==cthen 1+ count1 c (tail s) else count1 c (tail s)

IÜbung: wie formuliere ichcountmit Guards? (Lösung in den Quellen)

PI3 WS 20/21 30 [38]

Suche in einer Zeichenkette

IEndrekursiv:

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

ifnull sthenr

elsecount3’ c (tail s) (if head s==cthen1+r elser) IEndrekursiv mit lokaler Definition

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

ifnull sthenr

elsecount4’ (tail s) (if head s==cthen1+r elser)

DEMO

PI3 WS 20/21 31 [38]

Strings konstruieren

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

IEs gilt: Wenn not (null s), dannhead s : tail s==s IMit(:)wird(++)definiert:

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

| null xs =ys

| otherwise=head xs : (tail xs++ys) Iquadratkonstruiert ein Quadrat aus Zeichen:

quadrat :: Int→Char→String

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

DEMO

PI3 WS 20/21 32 [38]

(5)

Strings analysieren

IWarum immer nur Kopf/Rest?

ILetztes Zeichen (dual zuhead):

last1 :: String→Char

last1 s=if null sthenlast1 s

else ifnull (tail s) thenhead s elselast1 (tail s)

IBesser: mit Fehlermeldung last :: String→Char last s

| null s=error "last:␣empty␣string"

| null (tail s)=head s

| otherwise =last (tail s)

PI3 WS 20/21 33 [38]

Strings analysieren

IAnfang der Zeichenkette (dual zutail):

init :: String→String init s

| null s=error "init:␣empty␣string" −− nicht s

| null (tail s)=""

| otherwise =head s : init (tail s)

IDamit: Wennnot (null s), danninit s++ (last s: "")==s

PI3 WS 20/21 34 [38]

Strings analysieren: das Palindrom

IPalindrom: vorwärts und rückwärts gelesen gleich.

IRekursiv:

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.

IErste Variante:

palin1 :: String→Bool palin1 s

| length s≤1 =True

| head s==last s=palin1 (init (tail s))

| otherwise =False

DEMO

PI3 WS 20/21 35 [38]

Strings analysieren: das Palindrom

IProblem: Groß/Kleinschreibung, Leerzeichen, Satzzeichen irrelevant.

IDaher: nicht-alphanumerische Zeichen entfernen, alles Kleinschrift:

clean :: String→String clean s

| null s=""

| isAlphaNum (head s)=toLower (head s) : clean (tail s)

| otherwise=clean (tail s) IErweiterte Version:

palin2 s=palin1 (clean s)

DEMO

PI3 WS 20/21 36 [38]

Fortgeschritten: Vereinfachung von palin1

IDas hier ist nicht so schön:

palin1 s

| length s≤1 =True

| head s==last s=palin1 (init (tail s))

| otherwise =False IWas steht da eigentlich:

palin1’ s=iflength s≤1then True

else ifhead s==last sthen palin1’ (init (tail s)) else False

IDamit:

palin3 s=length s≤1 | | head s==last s && palin3 (init (tail s)) ITerminiert nur wegen Nicht-Striktheit von| |

PI3 WS 20/21 37 [38]

Zusammenfassung

IBedeutungvon Haskell-Programmen:

IAuswertungsrelation→

IAuswertungsstrategien: innermost-first, outermost-first IAuswertungsstrategie für terminierende Programme irrelevant IStriktheit

IHaskell istspezifiziertals nicht-strikt IMeist implementiert durch verzögerte Auswertung ILebenohne Variablen:

IRekursion statt Schleifen IFunktionsparameter statt Variablen INächste Vorlesung: Datentypen

PI3 WS 20/21 38 [38]

Referenzen

ÄHNLICHE DOKUMENTE

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

I Für funktionale Programme: rekursiv definierte Funktionen Äquivalenz von operationaler und denotationaler Semantik. Sei P ein funktionales Programm, → P die dadurch

I Für funktionale Programme: rekursiv definierte Funktionen Äquivalenz von operationaler und denotationaler Semantik. Sei P ein funktionales Programm, → P die dadurch

Der dbl setzt sich zum Ziel, dass Logopädinnen und Logopäden als Berufsgruppe Mitbestim- mungsrechte erhalten, indem sie an den Entscheidungen zur Ausgestaltung

Es wird grundsätzlich empfohlen ausschließlich von Deutronic freigegebenes Equipment einzusetzen, da nur so eine entsprechende technische Eignung sowie eine ausreichende

Das Berufsbild des Logopäden hat sich gewandelt, aber es wird immer noch zu sehr mit der Sprachent- wicklung von Kindern oder mit der Stimmtherapie, etwa bei Heiserkeit,

Boolean bln blnGefunden Byte byt bytRasterDaten Collection col colMitglieder Date (Time) dtm dtmStart Double dbl dblToleranz Error err errBestellNr Integer int intAnzahl Long

Dieses Vorhaben wurde bereits in unserer Schall- technischen Untersuchung „Schalltechnische Untersuchung zum Baulärm für die F ernwärmeverbin- dungsleitung zwischen der Blockstation