Einführung in die Informatik II

Werbung
Einführung in die Informatik II
SS 2011
7 Funktionale Programmierung
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
1
7 Funktionale Programmierung ...
Lernziele
Verständnis funktionaler Porgrammierkonzepte
Funktionen als Werte, Funktionen höherer Ordnung,
Polymorphismus, ...
Auseinandersetzung mit einem nicht-imperativen
Programmierparadigma
neue Sicht- und Denkweise!
Vertieftes Verständnis der Rekursion
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
2
7 Funktionale Programmierung ...
Literatur
[Er99], Kap. 1, 2
[Kr02], Kap. 2, 3, 4
[Pa00], Kap. 1, 2, 4(.1), 7(.1), 8(.1)
S. Sabrowski, Schnelleinstieg in Standard ML of New Jersey, 1996.
http://www-pscb.informatik.tu-cottbus.de/~wwwpscb/studenten/sml.ps
http://www.bs.informatik.unisiegen.de/web/wismueller/vl/gen/ei2/sml.pdf
E. Januzaj, SML zum Mitnehmen – Eine Kurzreferrenz von
SML-Funktionen
www.dbs.informatik.uni-muenchen.de/Lehre/Info1/smlref/SMLKurzreferenz pdf 2.pdf
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
3
7 Funktionale Programmierung ...
Inhalt
Konzepte funktionaler Programmiersprachen
SML: Überblick
Werte und Ausdrücke
Tupel, Records und Listen
Variablen und Funktionen
Typen und Polymorphismus
Datentypen und Pattern Matching
Funktionen höherer Ordnung
Problemlösung mit Rekursion
Auswertung funktionaler Programme
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
4
7.1 Konzepte funktionaler Programmiersprachen
Besonderheiten funktionaler
Programmiersprachen:
Sie basieren auf dem Funktionsbegriff der Mathematik
ein Programm ist eine Funktion, die aus anderen
Funktionen zusammengesetzt ist
Es gibt keine Variablen, deren Wert verändert werden kann
der Variablenbegriff entspricht dem der Mathematik
es gibt keine Zuweisungen
eine Variable hat an allen Stellen innerhalb ihres Gültigkeitsbereichs immer
denselben Wert (referenzielle Transparenz)
Es gibt weder programmierten Kontrollfluß noch Seiteneffekte
keine Anweisungsfolgen, keine Schleifen, ...
eine Funktion liefert mit identischen Parametern immer dasselbe Ergebnis
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
5
7.1 Konzepte funktionaler Programmiersprachen )
(Mathematische) Funktionen
Eine Funktion f von A in B ordnet jedem Element aus der Menge A
genau ein Element aus der Menge B zu
A ist der Definitionsbereich, B der Wertebereich von f
f kann definiert werden durch:
eine Aufzählung von Wertepaaren aus A × B
eine Funktionsgleichung, z.B. f(x) = sin(x)/x
Eine Funktionsgleichung
führt auf der linken Seite Variablen ein, die für Werte aus dem
Definitionsbereich stehen
hat auf der rechten Seite einen Ausdruck aus Variablen, Konstanten und
Funktionen
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
6
7.1 Konzepte funktionaler Programmiersprachen )
Funktionen: Begriffe und Schreibweisen
A → B ist die Menge aller Funktionen von A in B
Ist f ∈ A → B, schreiben wir auch f : A → B
Für f : A → B liefert die Funktionsanwendung (Applikation) von f auf ein
Argument a ∈ A das vermöge f zugeordnete Element aus B
Schreibweisen für die Funktionsanwendung:
f(a) Funktionsschreibweise
fa Präfixschreibweise
a1fa2 Infixschreibweise,
falls A = A1 × A2, (a1, a2) ∈ A
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
7
7.1 Konzepte funktionaler Programmiersprachen )
Funktionen als Werte
Eine Funktion f : A → B ist ein Wert der Menge A → B
genauso, wie
5,2 ein Wert der Menge R ist
Damit können Funktionen
als Argumente an andere Funktionen übergeben werden
und als Funktionsergebnis auftreten
Dies führt zu Funktionen höherer Ordnung
Beispiel: Funktionskomposition ◦
Der Operator ◦ ist eine Funktion aus der Menge
(B → C) × (A → B) → (A → C)
Funktionsgleichung für ◦:
(f ◦ g)(x) = f(g(x))
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
8
7.1 Konzepte funktionaler Programmiersprachen )
Referentielle Transparenz
Jedes Vorkommen einer Variable (innerhalb ihres Gültigkeitsbereichs)
bezeichnet denselben Wert
Die Semantik hängt nicht wie bei imperativen Sprachen von einem
impliziten Zustand (= Speicherbelegung) ab
Mathematisch ist ein Ausdruck wie i = i + 1 sinnlos
Gleichung ohne Lösung (0 = 1)
Referentielle Transparenz erlaubt es immer, Variable durch ihre
Definition zu ersetzen, ohne die Semantik zu ändern
die Auswertung funktionaler Programme basiert genau auf diesem Prinzip
dadurch lassen sich Eigenschaften funktionaler Programme einfach(er)
beweisen (→Bedeutung der funkt. Prog.)
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
9
7.1 Konzepte funktionaler Programmiersprachen )
Kein programmierter Kontrollfluß
In funktionalen Programmen gibt es keine Anweisungen
keine Zuweisungen, Anweisungsfolgen, Schleifen, bedingte
Anweisungen, ...
Stattdessen: Rekursion und bedingte Ausdrücke
Beispiel: Berechnung der Fakultät von n (= 1 — 2 — ... — n)
die Funktionsgleichung schreibt die Art und Weise (z.B. die Reihenfolge) der
Berechnung nicht vor!
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
10
7.1 Konzepte funktionaler Programmiersprachen )
Strukturen funktionaler Programme
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
11
7.2 SML: Überblick
SML = Standard ML = Standard Meta Language
ML wurde 1973 als Teil eines Theorembeweisers entwickelt
seither viele Dialekte, 1984 ”standardisierte“ Version SML
Referenzimplementierung: ”SML of New Jersey“ (SML/NJ)
interaktiver Compiler für SML
frei erhältlich für Windows und Linux (http://www.smlnj.org/)
Eigenschaften von SML
streng getypte funktionale Sprache
polymorphes Typsystem
Syntax nahe an mathematischer Notation
enthält auch imperative Konstrukte (in der Vorlesung nicht behandelt)
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
12
7.2 SML: Überblick )
Interaktiver Compiler SML/NJ
Start mit Kommando sml
Ausgabe des Compilers (auf Folien rot und kursiv):
Standard ML of New Jersey v110.57 [built: Wed Feb ...] Das Promptzeichen - zeigt, daß der Compiler eine Eingabe erwartet
abgeschlossen mit ; und Enter-Taste
Beispiel:
- 5 + 10;
val it = 15 : int
it ist eine Variable (vom Typ int), die das Ergebnis der letzten
Berechnung (15) bezeichnet
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
13
7.2 SML: Überblick )
Interaktiver Compiler SML/NJ ...
Das Promptzeichen = zeigt unvollständige Eingabe an
Beispiel:
-5
= + 10;
val it = 15 : int
Eine Eingabe kann auch durch Drücken von Control-C abgebrochen
werden
Der Compiler wird durch Drücken von Control-D auf der obersten Ebene
(Prompt: - ) beendet
- ~5
= + 10;
val it = 5 : int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
14
7.2 SML: Überblick )
Eingaben können sein:
Vereinbarungen von Variablen für Werte (einschließlich Funktionen),
z.B. val x = 42 (-x; val it = 42 : int) ; oder fun f(x) = x+1; (val f = fn : int -> int)
(- f(10); val it = 11 : int)
Ausdrücke, z.B. x - 40; oder f x;
Sie werden jeweils durch Semikolon voneinander getrennt
Der Compiler prüft die Eingaben auf korrekte Syntax, übersetzt sie und
führt sie ggf. sofort aus
Die Ausgabe des Compilers ist immer eine Liste der vereinbarten
Variablen (mit Angabe von Wert und Typ)
- val x = 42; val y = 5;
val x = 42 : int
val y = 5 : int
spezielle Variable ist für Ergebnis des letzten Ausdrucks
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
15
7.2 SML: Überblick )
SML-Programme können auch in Dateien abgelegt werden
Einlesen in den Compiler:
- use "beispiel.sml";
←Datei enthält: val x = 42;
[opening beispiel.sml]
val x = 42 : int
←Ergebnis der Funktion use
val it = () : unit
- x + 2;
val it = 44 : int
Alternative: Aufruf des Compilers mit Dateiname
sml beispiel.sml
Syntax für Kommentare:
(* Das ist ein Kommentar *)
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
16
7.2 SML: Überblick )
Fehlermeldungen des Compilers
Beim Einlesen aus einer Datei:
- use "beispiel.sml"
[opening beispiel.sml]
beispiel.sml:1.6-1.11 Error: unbound variable or ...
↑ Ort des Fehlers: Zeile.Spalte - Zeile.Spalte
die Datei enthielt 1234-hallo;
Bei interaktiver Eingabe: Zeilennummern teilweise unsinnig
- 1234-hallo;
stdIn:1.6-5.4 Error: unbound variable or constructor
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
17
7.3 Werte und Ausdrücke
Werte sind Ausdrücke, die nicht weiter ausgewertet werden können
einfache Werte: z.B. Zahlen, Zeichenketten, ...
konstruierte Werte: z.B. Tupel, Listen, ...
Funktionen, mit der Besonderheit: sie können auf andere Werte
angewandt werden
Alle Werte haben in SML einen eindeutig bestimmten Typ
Werte, die keine Funktionen sind oder enthalten, heißen Konstante
Aus Werten (incl. Funktionen) können Ausdrücke geformt werden, die
bei der Auswertung auf Werte reduziert werden
d.h. Auswertung im Sinne mathematischer Vereinfachung
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
18
7.3 Werte und Ausdrücke )
Ganze Zahlen (int)
Übliche Darstellung, negative Zahlen aber mit vorangestellter Tilde (~),
z.B. 13, ~5
Vordefinierte Funktionen auf ganzen Zahlen:
binäre Operationen: +, -, *, div, mod
zweistellige Funktionen in Infixschreibweise
vom Typ int * int -> int (math.: Z × Z → Z)
unäre Operationen: ~, abs (Negation, Absolutbetrag)
einstellige Funktionen in Pr äfixschreibweise
vom Typ int -> int (math.: Z → Z)
* und -> sind Typkonstruktoren
zur Bildung neuer Typen (kartesisches Produkt bzw. Funktionstyp)
aus vorhandenen Typen
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
19
7.3 Werte und Ausdrücke )
Zur Funktionsapplikation
Die Applikation hat höchste syntaktische Priorität
d.h. abs 4-5 bedeutet (abs 4) - 5
die Klammern bei z.B. f(x+y) sind normale Klammern um den
Ausdruck x+y, auf dessen Wert f angewandt wird
Die Applikation ist linksassoziativ
d.h. f g x bedeutet (f g) x
Beispiel:
- ~ abs(4-5);
stdIn:1.1 Error: overloaded variable not defined at type
symbol: ~
type: int -> int
Versuch, die Funktion ~ auf die Funktion abs anzuwenden
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
20
7.3 Werte und Ausdrücke )
Reelle Zahlen (real)
Übliche Darstellung, aber mit ~ statt -, z.B. 3.0, ~5E2, 0.5E~3
Die Operationen +, -, *, ~ und abs sind auch auf rellen Zahlen definiert
(d.h. sie sind überladen)
Division: / (Typ: real * real -> real)
Umwandlung zwischen int und real:
real: int -> real
floor: real -> int größte ganze Zahl ≤ Argument (- floor 3.4; / val it = 3 : int)
Keine implizite Typumwandlung:
- 3.0 * 4;
stdIn:1.1-6.3 Error: operator and operand don’t agree
operator domain: real * real
operand: real * int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
21
7.3 Werte und Ausdrücke )
Zeichenketten (string) und Zeichen (char)
Übliche Darstellung für Strings, z.B. "Ein String" (val it = „Ein String“ : string)
Darstellung für Zeichen: #"a"
Funktionen für Strings:
^: string * string -> string Konkatenation
size: string -> int Länge
substring: string * int * int -> string
Teilstring, Argumente: Startposition (ab 0) und Länge
Beispiel:
- substring ("abcd" ^ "efgh", 2, 4);
val it = "cdef" : string
- substring("ab",2,1);
uncaught exception Subscript [subscript out of bounds]
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
22
7.3 Werte und Ausdrücke )
Wahrheitswerte (bool)
Konstanten: true, false
Operationen: not (Negation), andalso (Und), orelse (Oder)
das zweite Argument von andalso bzw. orelse wird nur
ausgewertet, falls notwendig
Vergleichsoperationen (mit Ergebnis vom Typ bool):
=, <> für int, char, string und bool
<, <=, >, >= für int, real, char und string
Fallunterscheidung (ternäre Funktion): if ... then ... else ...
- val n = 2;
val n = 2 : int
- (if n<>0 then 100 div n else 0) + 10;
val it = 60 : int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
23
7.4 Tupel, Records und Listen
Tupel, Records und Listen fassen mehrere Werte zu einer Einheit
zusammen
Tupel
feste Zahl von Werten, auch mit unterschiedlichen Typen
Zugriff auf Komponenten über Positionsindex
Record:
feste Zahl von Werten, auch mit unterschiedlichen Typen
Zugriff auf Komponenten über beliebige Identifikatoren oder ganze
Zahlen
d.h. Tupel sind spezielle Records
Liste
beliebige, variable Zahl von Werten desselben Typs
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
24
7.4 Tupel, Records und Listen )
7.4.1 Tupel
Schreibweise / Konstruktion von Tupeln:
( [ <Ausdruck> {, <Ausdruck>} ] )
Beispiele:
- (1-1, true, 5.0, 2<1);
val it = (0,true,5.0,false) : int * bool * real * bool
- (2);
val it = 2 : int
einstellige Tupel bilden keinen eigenständiger Typ
- ();
val it = () : unit
das nullstellige Tupel hat den Typ unit, der () als einzigen Wert
besitzt
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
25
7.4.1 Tupel ...
Selektion von Komponenten
Komponenten eines Tupels können über ihre Position selektiert werden
(Zählung ab 1)
Operator # <IntKonstante> <Ausdruck>
Beispiele:
- #1 (1-1, true, 5.0, 2<1);
val it = 0 : int
- #1 (#2 (1.1,(2,3.3)));
val it = 2 : int
Tupel können auch wieder Tupel enthalten
- #3 (1,2);
stdIn:15.1-15.9 Error: operator and operand don’t agree
Compiler prüft Zulässigkeit des Selektors
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
26
7.4 Tupel, Records und Listen ...
7.4.2 Records
Schreibweise / Konstruktion von Records:
{ [ <Name> = <Ausdruck> {, <Name> = <Ausdruck>} ] }
Beispiele:
- {Name="Joe",Age=35};
val it = {Age=35,Name="Joe"} : {Age:int, Name:string}
die Reihenfolge der Komponenten spielt keine Rolle, die
Komponentennamen gehören mit zum Typ
- {2=7, true=false};
val it = {2=7,true=false} : {2:int, true:bool}
Komponentennamen können beliebige Identifikatoren oder ganze
Zahlen sein
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
27
7.4.2 Records ...
Beispiele...:
- {2=9,1=35,3="hallo"} = (35,9,"hallo");
val it = true : bool
Records mit Komponentennamen 1...n werden als Tupel interpretiert
Selektion von Komponenten
Analog zu Tupeln über den Operator #
Beispiele:
- #Pos {Ort="Hagen", Pos=(1.0,2.3)};
val it = (1.0,2.3) : real * real
- #r (#2 (3,{x=1,r=4}));
val it = 4 : int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
28
7.4 Tupel, Records und Listen ...
7.4.3 Listen
Schreibweise / Konstruktion von Listen:
[ [ <Ausdruck> {, <Ausdruck>} ] ]
Beispiele:
- [1,2,3,4];
val it = [1,2,3,4] : int list
- [1,3.0];
stdIn:29.1-29.8 Error: operator and operand don’t agree
alle Listenelemente müssen denselben Typ haben
- [];
val it = [] : ’a list
leere Liste: der Typ enthält eine freie Typvariable (s. später)
alternativ auch nil statt [] / (- nil ;)
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
29
7.4.3 Listen ...
Operationen auf Listen
Erstes Element der Liste (hd / head) und Restliste (tl / tail):
- hd [1,2,3];
val it = 1 : int
- tl [1,1+1];
val it = [2] : int list
- tl [[1,2],[3],[]];
val it = [[3],[]] : int list list
←Ergebnis ist immer Liste!
←Liste von Listen
Anfügen am Anfang der Liste: ::
- 1 :: [2, hd[3]];
val it = [1,2,3] : int list
Konkatenation zweier Listen: @
- [1,2] @ [3,4];
val it = [1,2,3,4] : int list
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
30
7.4.3 Listen ...
Operationen auf Listen ...
Umkehren einer Liste: rev
- rev [1,2,3,4];
val it = [4,3,2,1] : int list
(reverse bei LISP)
- hd (rev [1,2,3,4]);
val it = 4 : int
←letztes Element der Liste
Umwandlung von string nach char list: explode
- explode "Bombe";
val it = [#"B",#"o",#"m",#"b",#"e"] : char list
Umwandlung von char list nach string: implode
- implode (rev (explode "Bombe"));
val it = "ebmoB" : string
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
31
7.5 Variablen und Funktionen
7.5.1 Variablen
Eine Variable ist ein Bezeichner für einen Wert
Die Zuordnung eines Werts zu einem Bezeichner heißt Bindung
Bindung ist Paar (Bezeicher, Wert)
Die Menge der aktuell existierenden Bindungen heißt Umgebung
Die (Werte-)Definition val <Variable> = <Ausdruck> erzeugt eine neue
Variablen-Bindung
der Wert des Ausdrucks wird an die Variable gebunden
Beispiel:
- val Name = "Mi"^"ln"^"er";
val Name = "Milner" : string
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
32
7.5.1 Variablen )
Mehrfache Bindung
Eine Variable kann nacheinander an verschiedene Werte (auch
verschiedenen Typs) gebunden werden:
- val bsp = 1234;
val bsp = 1234 : int
- bsp + 1;
val it = 1235 : int
- val bsp = ("Hallo", "Welt");
val bsp = ("Hallo","Welt") : string * string
- #1 bsp;
val it = "Hallo" : string
auch die Variable it wird hier mehrfach gebunden
Die Umgebung wird somit durch Definitionen verändert
Beachte: die Werte haben einen Typ, nicht die Variablen!
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
33
7.5.1 Variablen )
Pattern Matching
Eine Definition kann auch mehrere Variablen auf einmal binden
linke und rechte Seite dürfen komplexe Werte mit gleicher Struktur
sein
Tupel, Records, Listen und selbst definierte Datentypen
die Bindung der Variablen ergibt sich dann als Lösung der
(einfachen) mathematischen Gleichung
Beispiel:
- val (x,y) = (3,2.0);
val x = 3 : int
val y = 2.0 : real
- val {a=u,2=v} = {2="Hallo",a=43};
val v = "Hallo" : string
val u = 43 : int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
34
7.5 Variablen und Funktionen ...
7.5.2 Funktionen
Funktionen (als Werte) werden in SML wie folgt dargestellt:
fn <Variable> => <Ausdruck>
Beispiel: fn x => 2 * x ist die Funktion, die jeder Zahl x ihr Doppeltes
zuordnet
Ein solcher Funktions-Wert kann auf andere Werte angewandt werden:
- (fn x => 2 * x) 5;
val it = 10 : int
Er kann wie jeder andere Wert verwendet werden
Bindung an Namen
Speichern in Tupeln, Records oder Listen
Argument oder Ergebnis von Funktionen
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
35
7.5.2 Funktionen )
Binden von Funktionswerten an Namen (Funktionsdeklaration)
Syntax genau wie bei anderen Werten, z.B.:
- val dbl = fn x => 2 * x;
val dbl = fn : int -> int
Compiler gibt statt des Werts nur fn aus
Der Typ (hier: int -> int) wird automatisch aus der
Funktionsgleichung (x => 2 * x) ermittelt (Typinferenz)
Abkürzende Schreibweise:
fun <Variable1> <Variable2> = <Ausdruck>
<Variable1>: Funktions-Bezeichner, <Variable2>: Argument
im Beispiel:
- fun dbl x = 2 * x;
val dbl = fn : int -> int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
36
7.5.2 Funktionen )
Applikation von Funktionen
Über den Funktions-Bezeichner:
- dbl 5;
val it = 10 : int
- dbl (5+5);
val it = 20 : int
Direkte Anwendung eines Funktions-Werts auf einen
anderen
Wert:
- (fn x => 2 * x) ((fn x => x + 1) 5);
val it = 12 : int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
37
7.5.2 Funktionen )
Typrestriktion
Eine Funktion zum Quadrieren:
- fun square x = x * x;
val square = fn : int -> int
Warum hat diese Funktion den Typ int -> int und nicht real -> real?
der Operator * ist überladen für int und real
die Typinferenz kann damit den notwendigen Typ des Arguments
nicht eindeutig bestimmen
SML wählt dann den Default-Typ, hier int
SML erlaubt aber auch, den Typ eines Ausdrucks zu erzwingen
(Typrestriktion)
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
38
7.5.2 Funktionen )
Typrestriktion ...
Beispiele
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
39
7.5.2 Funktionen )
Funktionen mit mehreren Argumenten
Eine (mathematische) Funktion hat genau ein Argument und genau ein
Resultat
Eine Funktion mit mehreren Argumenten ist genau betrachtet eine
Funktion auf einem Tupel:
- fun minimum (x,y) = if x<y then x else y;
val minimum = fn : int * int -> int
Ebenso kann eine Funktion auch ein Tupel von Werten als Resultat
liefern:
- fun DivMod (a,b) = (a div b, a mod b);
val DivMod = fn : int * int -> int * int
- DivMod (9,4);
val it = (2,1) : int * int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
40
7.5.2 Funktionen )
Pattern Matching
Pattern Matching ist auch bei Funktionsargumenten möglich
Dabei können mehrere alternative Muster angegeben werden
Dies erlaubt z.B. die Funktionsdefinition durch Aufzählung:
- fun f 0 = 0
=|f1=2
= | f 2 = 3;
stdIn:27.5-29.10 Warning: match nonexhaustive
val f = fn : int -> int
Warnung, da Funktion nicht für alle int-Werte definiert wird
Auch möglich: Ausnahmefälle und allgemeiner Fall
- fun f 0 = 0
←wird zuerst geprüft
= | f n = n + 1;
←falls n 6= 0
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
41
7.5.2 Funktionen )
Pattern Matching: Weitere Beispiele
Eine Funktion muß jedoch einen wohldefinierten Typ haben:
- fun f (x,y) = x + y
= | f (x,y,z) = x + y + z;
stdIn:1.5-59.26 Error: parameter or result constraint of clauses don’t agree [tycon mismatch]
der Typ kann nicht gleichzeitig int * int -> int und int * int * int -> int
sein
Beispiel: Fakult ätsfunktion (rekursive Funktion)
- fun fak 0 = 1
= | fak n = n * fak(n-1);
val fak = fn : int -> int
- fak 10;
val it = 3628800 : int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
42
7.5.2 Funktionen )
Pattern Matching: Funktionen auf Listen
Länge einer Liste:
- fun len [] = 0
= | len (x::rest) = 1 + len rest;
val len = fn : ’a list -> int
←leere Liste
←Liste x :: rest
die Klammern um x::rest sind notwendig
die Funktion kann auf Listen beliebigen Typs (’a list) angewandt
werden (polymorphe Funktion):
- len [3,3,2,2];
val it = 4 : int
- len ["hallo", "welt"];
val it = 2 : int
- len [[],[1,2,3],[5,2]];
val it = 3 : int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
43
7.5.2 Funktionen ...
Pattern Matching: Funktionen auf Listen ...
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
44
7.5.2 Funktionen ...
Pattern Matching: Funktionen auf Listen ...
Ein Operator zum sortierten Einfügen in eine
Liste:
definiert einen neuen, rechtsassoziativen InfixOperator ++ mit Priorität 5
linksassoziative Operatoren werden mit infix
definiert
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
45
7.5.2 Funktionen ...
Pattern Matching: Funktionen auf Listen ...
Sortiertes Einfügen in eine Liste von
Gleitkommazahlen:
Gesamtl änge einer Liste von Listen:
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
46
7.5.2 Funktionen ...
Statisches Binden
Was passiert mit glen, wenn wir len neu definieren?
- fun len x = 0;
val len = fn : ’a -> int
- glen [[],[1,2,3],[5,2]];
val it = 5 : int
Die neue Bindung für len hat keinen Einfluß auf glen
Maßgeblich für die Semantik einer Funktion ist die Umgebung (d.h. die
Bindungen) zum Zeitpunkt ihrer Definition, nicht die zum Zeitpunkt ihrer
Auswertung (statisches Binden)
Eigenschaft fast aller funktionaler Sprachen
Eine einmal definierte Funktion verhält sich damit bei jedem Aufruf
gleich
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
47
7.5.2 Funktionen ...
Freie Variablen in Funktionsdefinitionen
Funktionsgleichungen können auch Variablen enthalten, die keine
Argumente sind (freie Variablen)
diese Variablen müssen aber an ein Wert gebunden sein
auch hier wird statisches Binden verwendet
Beispiel:
- val pi = 3.14159265;
val pi = 3.14159265 : real
- fun area r = pi * r * r;
←pi ist freie Variable
val area = fn : real -> real
- val pi = 0.0;
←neue Bindung für pi
val pi = 0.0 : real
- area 2.0;
←verwendet Bindung zum
val it = 12.5663706 : real
Zeitpunkt der Def. v. area
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
Einführung in die Informatik II
48
7.5.2 Funktionen ...
Lokale Definitionen
Manchmal sollen Definitionen nur lokal in einem Ausdruck gelten
z.B. Einführen einer Variable als Abkürzung für einen Term
SML bietet dazu let-Ausdrücke an:
let <Deklarationsfolge> in <Ausdruck> end
die lokalen Deklarationen ver ändern die Umgebung außerhalb des
let-Ausdrucks nicht!
Beispiel:
- val x = 1;
val x = 1 : int
↓ x aus der Umgebung (mit Wert 1)
- val res = let val x = x+1 in x * x end;
val res = 4 : int
↑ lokal definiertes x (= 2)
- x;
val it = 1 : int
Madjid Fathi
Wissensbasierte Systeme / Wissensmanagement
←dieses x blieb unberührt
Einführung in die Informatik II
49
7.5.3 Typen und Polymorphismus
In funktionalen Sprachen: Typsystem hat hohen Stellenwert
Strenge Typisierung: jeder Wert hat einen eindeutigen Typ
in imperativen Sprachen meist abgeschwächte Typsysteme, die
Uminterpretierung von Typen erlauben, z.B. durch:
Typkonversion
generische Typen wie void * in C oder Object in Java, um
generische Funktionen zu realisieren
In funktionalen Sprachen stattdessen flexible Typsysteme
Typen von Variablen (inkl. Funktionen) können oft automatisch
ermittelt werden: Typinferenz
Konzepte wie generische Funktionen sind sinnvoll in das Typsystem
integriert: Typpolymorphismus
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
50
7.5.3 Typen und Polymorphismus ...
Eigenschaften des SML Typsystems
Der Typ eines Ausdrucks kann allein aus der syntaktischen
Struktur ermittelt werden
statische Typprüfung zur Übersetzungszeit
keine Laufzeit-Typfehler möglich (vgl. Java!)
schnellerer und sichererer Code
Das Typsystem unterstützt polymorphe Typen
Typen können freie Variablen (z.B. ‘a) enthalten
Funktionen können für eine ganze Klasse von Typen definiert
werden
dies erhöht die Wiederverwendbarkeit der Software
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
51
7.5.3 Typen und Polymorphismus ...
Typausdrücke
Das Typsystem in SML bildet eine eigene Sprache mit
Ausdrüucken, die auch an Variable gebunden werden
können
Die Konstanten sind die einfachen Typen:
unit, bool, int, real, char, string
Operationen (Typkonstruktoren):
Tupel,
Records,
Listen,
Funktionstypen,
z.B. int * int
z.B. {a:int, b:string}
z.B. real list
z.B. string -> int
Binden an Variable: type <Variable> = <Typausdruck>
Beispiel: type point = real * real
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
52
7.5.3 Typen und Polymorphismus ...
Parametrischer Polymorphismus
Abstraktionsmechanismus für Typausdrücke:
durch Variablen in Typausdrücken kann man Typen mit gegebener
Struktur beschreiben
Beispiele:
int * string, bool * real etc. sind alles Paare
int list, real list, (int * bool) list etc. sind alles Listen
In einem Typausdruck steht eine Typvariable, z.B. ’a oder
’b für einen beliebigen Typ
vorgestellter Apostroph zur syntaktischen Unterscheidung
Typvariablen mit zwei Apostrophen (z.B. ’’a) stehen für
beliebige Typen, auf denen Gleichheit definiert ist
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
53
7.5.3 Typen und Polymorphismus ...
Parametrischer Polymorphismus )
Die Menge aller Paar-Typen ist damit: ’a * ’b
Menge aller Listen-Typen: ’a list
Menge aller Funktionstypen, die zu einer Liste einen Wert
ihres Elementtyps liefern: ’a list -> ’a
Definition eines polymorphen Typs: die Bindung der
Typvariablen erfolgt durch Auflisten vor dem zu
definierenden Typ:
type ’a idPair = ’a * ’a;
type (’a,’b) pairList = (’a * ’b) list;
Instanziierung eines Typs: Angabe von Werten f.
Typvariablen
(2,2) : int idPair;
[(1,"foo"),(2,"bar")] : (int,string) pairList;
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
54
7.5.3 Typen und Polymorphismus ...
Polymorphe Funktionen
Parametrischer Polymorphismus erlaubt die typsichere
Definition generischer Funktionen
Beispiel: erstes Element eines Tupels
- fun first (a,b) = a;
val first = fn : ’a * ’b -> ’a
Beispiel: Länge einer Liste
- fun length l = if l=[] then 0 else 1 + length(tl l);
val length = fn : ’’a list -> int
Argument vom Typ ’’a list, da der Vergleich zweier Listen auf
dem Vergleich der Elemente basiert
- fun length [] = 0
=
| length (hd::tl) = 1 + length(tl);
val length = fn : ’a list -> int
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
55
7.5.3 Typen und Polymorphismus ...
Typinferenz: Wie bestimmt man den Typ eines
Ausdrucks?
Beispiel: fun f (x,y) = x + 1 = y;
Starte mit dem allgemeinsten möglichen Typ für jedes
Element des Ausdrucks:
type(x) = ’a, type(y) = ’b, type(1) = int,
type(f) = ’c -> ’d
Füge Gleichungen hinzu, die sich aus der Struktur des
Ausdrucks ergeben und löse das Gleichungssystem:
aus x+1 folgt ’a = type(1) und type(x+1) = ’a
aus x+1=y folgt ’b = type(x+1) und type(x+1=y) = bool
aus (x,y) folgt type((x,y)) = ’a * ’b
aus fun f(x,y) = x+1=y folgt: ’c = type((x,y)) und
’d = type(x+1=y)
Lösung: type(f) = int * int -> bool
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
56
Klausurtermine EI2 im SS 2011
1. Termin: Mo., 08.08.2011, 10:15 - 12:15 Uhr
AR/E/1-8101 - Audimax
2. Termin: Fr., 23.09.2011, 10:15 - 12:15 Uhr
AR/E/2-9202/03 – Turnhalle
Anmeldezeitraum für Klausuren beim Prüfungsamt Informatik:
Mo., 04.07. – Fr., 15.07.2011 (2 Wochen)
alle anderen: bei Frau Wenderoth (Raum H-A 8111, 10-13 Uhr)
Durchführung ohne Hilfsmittel
Kurzreferenz zu Java-Klassen und SML als Anlage
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
57
Zur Klausur EI2 im SS 2011
1. Termin: Mo., 08.08.2011, 10:15 - 12:15 Uhr
AR/E/1-8101 - Audimax
2. Termin: Fr., 23.09.2011, 10:15 - 12:15 Uhr
AR/E/2-9202/03 – Turnhalle
Aufteilung des Stoffes:
ca. 20% UML
ca. 60% Java-Programmierung
u.a. Vererbung, Exceptions, Collections, GUIs, (Threads)
ca. 5-10% Entwurfsmuster
ca. 10-15% SML-Programmierung
u.a.Typen, Funktionen
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
58
Mögliche Fragetypen
Fragestellungen:
UML-Klassendiagramme (OOA / OOD) zeichnen
Umsetzung von UML nach Java oder umgekehrt
einfache Programmieraufgaben
i.a. als Lückentext (wenige Zeilen)
vorgegebene Programme verstehen
Was ist die Ausgabe?
Wo sind Fehler im Programm?
Bei SML: Typ/Wert von Ausdrücken/Funktionen
Wissensfragen zum Ankreuzen
Musterklausur: siehe Duesie
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
59
7.6 Datentypen und Pattern Matching
Typen, die mit type an Variablen gebunden werden, stellen
lediglich abkürzende Schreibweisen dar
innerer Aufbau der Datenstruktur ist offengelegt
Eine SML datatype Deklaration definiert einen Typ
zusammen mit seinen Konstruktoren
spezifiziert wird nur, wie Werte dieses Typs erzeugt werden, nicht
wie sie gespeichert oder dargestellt werden
tatsächlich wird in SML nie eine Implementierung für die
Konstruktoren angegeben!
SML-Funktionen arbeiten lediglich auf der syntaktischen Struktur des
Terms, der eine Datenstruktur erzeugt hat
Berechnung basiert auf der Termalgebra
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
60
7.6 Datentypen und Pattern Matching )
Variantentypen
Ein Datentyp besteht aus einer Menge typisierter
Konstruktoren, von denen jeder eine Variante des Typs
beschreibt
Syntax für die Defninition eines Datentyps:
datatype [ <Typvariablen> ] <Typname> =
<Konstruktor> [ of <Typ> ]
{ | <Konstruktor> [ of <Typ> ] }
<Typvariablen> definiert die auf der rechten Seite vorkommenden
Typvariablen bei polymorphen Typen
z.B. datatype ’a tree = ...
<Typ> gibt den Argumenttyp des jeweiligen Konstruktors an
das Ergebnis ist immer vom definierten Typ <Typname>
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
61
7.6 Datentypen und Pattern Matching )
Variantentypen )
Beispiel: Datentyp für geometrische Objekte
type point =
datatype geo
|
|
real * real;
= POINT of point
CIRCLE of point * real
RECT of {lowLeft:point, upRight:point};
(vgl. mit dem Ansatz der objektorientierten Programmierung!)
Erzeugung von Werten des Datentyps geo:
- val
val p
- val
val c
p
=
c
=
= POINT (1.0,2.0);
POINT (1.0,2.0) : geo
= CIRCLE ((2.0, 3.5), 1.0);
CIRCLE ((2.0,3.5),1.0) : geo
POINT (1.0,2.0) und CIRCLE ((2.0,3.5),1.0) sind Werte!
sie werden als Terme bezeichnet
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
62
7.6 Datentypen und Pattern Matching )
Pattern Matching
Auf die Varianten eines Datentyp-Werts kann wieder durch
Pattern Matching zugegriffen werden
ein Muster ist aus Konstruktoren und Variablen gebildet
es passt auf einen Term derselben Struktur
die Variablen im Muster werden dann an die Argumente der
entsprechenden Konstruktoren im Term gebunden
Beispiel:
- val CIRCLE (m,r) = c; ←c wie auf voriger Folie gebunden
stdIn:26.5-26.21 Warning: binding not exhaustive
CIRCLE (m,r) = ...
val m = (2.0,3.5) : real * real
val r = 1.0 : real
Warnung, da Muster nicht alle Varianten von geo abdeckt
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
63
7.6 Datentypen und Pattern Matching )
Pattern Matching: Beispiel
Berechnung des Flächeninhalts eines geometrischen
Objekts:
- fun area (POINT _) = 0.0
= | area (CIRCLE (_,r)) = 3.1415926 * r * r
= | area (RECT {lowLeft=(x1,y1),upRight=(x2,y2)}) =
= abs ((x1-x2)*(y1-y2));
val area = fn : geo -> real
- area (CIRCLE((0.0,0.0),1.0));
val it = 3.1415926 : real
In Mustern kann anstelle einer Variable ein Unterstrich ( _ )
als anonyme Variable (wildcard) auftreten
für diese ”Variable“ wird keine Bindung erzeugt
Funktionsdefinitionen verlaufen mit Hilfe von Mustern
”entlang“ der Definition der Datentypen
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
64
7.6 Datentypen und Pattern Matching )
Rekursive Datentypen
Bei der Definition der Varianten darf auch der gerade
definierte Datentyp selbst verwendet werden
dies führt zu rekursiven Typdefinitionen und damit zu rekursiven
Datenstrukturen
Beispiel: ein binärer Baum ganzer Zahlen
datatype tree = EMPTY
| NODE of int * tree * tree;
Der Term
NODE(3,NODE(8,EMPTY,EMPTY),
NODE(1,NODE(4,EMPTY,EMPTY),
EMPTY))
entspricht dann dem rechts stehenden
Baum
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
65
7.6 Datentypen und Pattern Matching )
Bäume als polymorphe Datentypen
Die Knoten eines Binärbaums können im Prinzip beliebige
Daten enthalten
Modellierung in SML durch einen polymorphen Datentyp:
- datatype ’a tree = EMPTY
=
| NODE of ’a * ’a tree * ’a tree;
datatype ’a tree = EMPTY | NODE of ’a * ’a tree * ’a tree
- val t1 = NODE(3,EMPTY,EMPTY);
val t1 = NODE (3,EMPTY,EMPTY) : int tree
- val t2 = NODE("Hallo",EMPTY,EMPTY);
val t2 = NODE ("Hallo",EMPTY,EMPTY) : string tree
Damit können auch generische, polymorphe Funktionen für
Bäume definiert werden
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
66
7.6 Datentypen und Pattern Matching )
Einige generische Funktionen auf Bäumen
Anzahl der Knoten eines Baums:
- fun nodes EMPTY = 0
=
| nodes (NODE(_,l,r)) = 1 + nodes l + nodes r;
val nodes = fn : ’a tree -> int
- nodes EMPTY;
val it = 0 : int
- (* Baum von Folie 65 *)
- val baum = NODE(3,NODE(8,EMPTY,EMPTY),
=
NODE(1,NODE(4,EMPTY,EMPTY),EMPTY));
val baum = NODE (3,NODE (8,EMPTY,EMPTY),NODE (1,NODE #,
EMPTY)) : int tree
- nodes baum;
val it = 4 : int
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
67
7.6 Datentypen und Pattern Matching )
Einige generische Funktionen auf Bäumen )
Beispiel zur Auswertung der Funktion nodes:
⇒
⇒
⇒
⇒
⇒
nodes (NODE(3,NODE(8,EMPTY,EMPTY),EMPTY))
1 + nodes (NODE(8,EMPTY,EMPTY)) + nodes EMPTY
1 + (1 + nodes EMPTY + nodes EMPTY) + 0
1 + (1 + 0 + 0) + 0
1 + (1 + 0) + 0 ⇒ 1 + 1 + 0 ⇒ 2 + 0
2
(Die jeweils ausgewerteten Funktionen sind blau
unterstichen)
Die Auswertung erfolgt durch Einsetzen der Werte für
Argumente, Variablen und Funktionen
eingebaute Funktionen (wie + ) werden direkt ausgewertet
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
68
7.6 Datentypen und Pattern Matching )
Einige generische Funktionen auf Bäumen )
Höhe eines Baums:
- fun height EMPTY = 0
=
| height (NODE(_,l,r)) =
=
let
=
val hl = height l;
=
val hr = height r;
=
in
=
1 + (if hl>hr then hl else hr)
=
end;
val height = fn : ’a tree -> int
der bedingte Ausdruck berechnet das Maximum der Höhen von
linkem und rechtem Unterbaum
der let-Ausdruck verhindert deren doppelte Berechnung
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
69
7.6 Datentypen und Pattern Matching )
Einige generische Funktionen auf Bäumen )
Umwandlung eines Baums in eine Liste:
- fun inorder EMPTY = []
=
| inorder (NODE(v,l,r)) =
=
@
=
@
val inorder = fn : ’a tree ->
inorder l
[v]
inorder r;
’a list
- inorder baum;
val it = [8,3,4,1] : int list
list [8,3,4,1]
es wird immer erst der linke Unterbaum bearbeitet, dann der
aktuelle Knoten, dann der rechte Unterbaum
Inorder-Durchlauf durch den Baum
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
70
7.7 Funktionen höherer Ordnung
Bisher haben wir Funktionen nur auf Datenwerte
angewendet
Funktionen höherer Ordnung sind Funktionen, die
andere Funktionen als Argument haben
oder Funktionen als Ergebnis liefern
Sie sind daran erkennbar, daß ihr Typ mindestens zweimal
den Typkonstruktor -> enthält
Viele Operationen lassen sich mit Funktionen höherer
Ordnung elegant und allgemein formulieren
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
71
7.7 Funktionen höherer Ordnung )
Beispiel: Filtern einer Liste
Programmiere eine Funktion, die aus einer Liste alle
Elemente ausfiltert, die eine bestimmte Bedingung erfüllen
die Bedingung wird der Funktion als Argument übergeben
- fun filter (p,[]) = []
=
| filter (p,x::l) = if p x
=
then x :: filter (p,l)
=
else filter (p,l);
val filter = fn : (’a -> bool) * ’a list -> ’a list
- val l = [1,2,3,4,5,6,7,8];
val l = [1,2,3,4,5,6,7,8] : int list
← gerade Elemente
- filter (fn x => x mod 2 = 0, l);
val it = [2,4,6,8] : int list
- filter (fn x => x > 4, l);
← Elemente > 4
val it = [5,6,7,8] : int list
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
72
7.7 Funktionen höherer Ordnung )
Currying
Funktionen mit mehreren Argumenten haben wir bisher
immer als Funktionen auf einem Tupel aufgefaßt:
- fun mult (a,b) = a * b;
val mult = fn : int * int -> int
- mult (2,3);
val it = 6 : int
Wir können eine solche Funktion aber auch anders
realisieren:
die Funktion hat nur ein Argument
sie liefert aber als Ergebnis eine Funktion, die auf das zweite Argument
angewendet werden kann
Der Aufruf sähe dann so aus:
- mult 2 3;
←Ergebnis von mult 2 ist eine Funktion!
val it = 6 : int
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
73
7.7 Funktionen höherer Ordnung )
Currying )
Die Umwandlung einer Funktion mehrerer Argumente in
mehrere Funktionen mit einem Argument heißt Currying
nach dem Logiker Haskell B. Curry
Mathematisch: Currying verwandelt eine Funktion des Typs
(A1 × A2 × ... × An) → B
in eine Funktion des Typs
A1 → A2 → ... → An → B
d.h. die Anwendung dieser Funktion auf ein a1 ∈ A1 liefert eine
Funktion aus A2 → ... → An → B
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
74
7.7 Funktionen höherer Ordnung )
Currying )
Wie kann eine solche Funktion in SML definiert werden?
Anwendung des bisher Gelernten:
die Funktion, die ihr Argument mit einem Wert x multipliziert, ist
fn y => x * y
das x ist dabei eine freie Variable, deren Wert durch die Umgebung
bestimmt wird
also können wir schreiben:
- fun mult x = fn y => x * y;
val mult = fn : int -> int -> int
- mult 2 3;
← = (mult 2) 3 = (fn y => 2 * y) 3
val it = 6 : int
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
75
7.7 Funktionen höherer Ordnung )
Kurzschreibweise für curried Funktionen
Statt
fun <Variable> <Muster1> = fn <Muster2> => ... =>
fn <Mustern> => <Ausdruck>
kann man auch kürzer schreiben:
fun <Variable> <Muster1> ... <Mustern> = <Ausdruck>
Eine Variable darf dabei immer nur in einem Muster
auftreten
Beispiele:
- fun mult x y = x * y;
val mult = fn : int -> int -> int
- fun und false _ = false
=
| und _ false = false;
=
| und true true = true;
val und = fn : bool -> bool -> bool
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
76
7.7 Funktionen höherer Ordnung )
Bedeutung des Currying
Currying ermöglicht die partielle Applikation von Funktionen
d.h. durch Fixierung eines Arguments erhält man eine neue
Funktion, die bereits teilweise ausgewertet ist
Beispiel: Summe von Funktionswerten f(1) + ... + f(n)
- fun sumf 1 f = f 1
=
| sumf n f = sumf (n-1) f + f n;
val sumf = fn : int -> (int -> int) -> int
← = 1 + 4 + 9 + 16 + 25
- sumf 5 (fn x => x * x);
val it = 55 : int
- val sum2f = sumf 2;
← = fn f => f(1) + f(2)
val sum2f = fn : (int -> int) -> int
- sum2f (fn x => x);
← = 1 + 2
val it = 3 : int
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
77
7.7 Funktionen höherer Ordnung )
Bedeutung des Currying )
Auswertung des Ausdrucks sumf 2:
ausführliche Definition der Funktion sumf ist:
fun sumf 1 = (fn f => f 1)
| sumf n = (fn f => sumf (n-1) f + f n);
damit wird sumf 2 wie folgt ausgewertet:
sumf 2
⇒
⇒fn
f => sumf (2-1) f + f 2
⇒
⇒fn
f => sumf 1 f + f 2
⇒fn f => (fn f => f 1) f + f 2
⇒fn f => f 1 + f 2
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
78
7.7 Funktionen höherer Ordnung )
Oft genutzte Funktionen höherer Ordnung
Filtern einer Liste (curried Version):
- fun filter p [] = []
=
| filter p (x::l) = if p x
=
then x :: filter p l
=
else filter p l;
val filter = fn : (’a -> bool) -> ’a list -> ’a list
Anwendung einer Funktion auf alle Elemente einer Liste:
- fun map f []
= []
=
| map f (x::l)
= f x :: map f l;
val map = fn : (’a -> ’b) -> ’a list -> ’b list
- map (fn x => x*x) [1,2,3,4]; ← quadriere die Elemente
val it = [1,4,9,16] : int list
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
79
7.7 Funktionen höherer Ordnung )
Oft genutzte Funktionen höherer Ordnung )
Reduzieren einer Liste mit einer binären Operation
z.B. Reduktion von [1,2,3] mit + liefert 1+2+3
- fun foldr f u [] = u
=
| foldr f u (x::l) = f (x, foldr f u l);
val foldr = fn : (’a * ’b -> ’b) -> ’b -> ’a list -> ’b
foldr reduziert die Liste von rechts, d.h. die Funktion f wird
rechtsassoziativ angewandt
der Aufruf foldr op+ 0 [1,2,3] berechnet daher exakt
op+(1, op+(2, op+(3, 0))) = 1 + ( 2 + ( 3 + 0))
Anmerkung: op erlaubt es einen Infix-Operator als Funktion
(in Präfix-Notation) zu verwenden, z.B. op+ (2,3)
op- ?
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
80
7.7 Funktionen höherer Ordnung )
Oft genutzte Funktionen höherer Ordnung )
Funktionskomposition o
- infix 3 o; ←Infixschreibweise, Priorität 3
infix 3 o
- fun (f o g) x = f(g(x));
val o = fn : (’a -> ’b) * (’c -> ’a) -> ’c -> ’b
Anmerkung:
die Funktionen map, foldr und o sind in SML/NJ standardmäßig
definiert
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
81
7.7 Funktionen höherer Ordnung )
Beispiele zur Anwendung der Funktionen
Berechne die Länge für jeden String in einer Liste:
- map size ["Dies","ist","ein","Satz"];
val it = [4,3,3,4] : int list
Berechne die Summe über eine Liste ganzer Zahlen:
- val sum = foldr op+ 0; ←rechte Seite ist Funktion!
val sum = fn : int list -> int
- sum [1,2,3,4];
val it = 10 : int
Gesamtlänge aller Strings in einer Liste:
- val gsum = sum o (map size);
val gsum = fn : string list -> int
- gsum ["Dies","ist","ein","Satz"];
val it = 14 : int
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
82
7.7 Funktionen höherer Ordnung )
Beispiele zur Anwendung der Funktionen )
Listenkonkatenation: fun l1 @ l2 = foldr op:: l2 l1
z.B.: [1,2]@[3] = foldr op:: [3] [1,2] = 1::(2::[3])
Listenlänge: fun length l = foldr (fn (x,y) => y+1) 0 l
wenn wir fn (x,y) => y+1 einmal abkürzend mit f bezeichnen, wird
z.B. length [6,7,8] wie folgt berechnet:
f(6,f(7,f(8,0))) = f(6,f(7,1)) = f(6,2) = 3
Letztes Listenelement: val last = hd o rev
d.h. last l = hd (rev l)
String-Umkehr: val revert = implode o rev o explode
d.h. revert s = implode(rev(explode s))
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
83
7.8 Problemlösung mit Rekursion
7.8.1 Die Türme von Hanoi
Gegeben ist ein Turm von Holzscheiben:
Der Turm ist vom linken auf den rechten Stab zu
verschieben, wobei
immer nur jeweils eine Scheibe bewegt werden und
nie eine größere auf einer kleineren Scheibe liegen darf
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
84
7.8.1 Die Türme von Hanoi )
Lösung des Problems:
Ausgangssituation:
0
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
1
2
Einführung in die Informatik II
85
7.8.1 Die Türme von Hanoi )
Lösung des Problems: )
Schiebe die oberen n-1 Scheiben von Pos. 0 auf Pos. 1:
0
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
1
2
Einführung in die Informatik II
86
7.8.1 Die Türme von Hanoi )
Lösung des Problems: )
Schiebe die unterste Scheibe von Pos. 0 auf Pos. 2:
0
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
1
2
Einführung in die Informatik II
87
7.8.1 Die Türme von Hanoi )
Lösung des Problems: )
Schiebe die oberen n-1 Scheiben von Pos. 1 auf Pos. 2:
0
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
1
2
Einführung in die Informatik II
88
7.8.1 Die Türme von Hanoi )
Und wie verschieben wir einen Turm der Höhe n-1?
Antwort: Genauso! (Prinzip der Rekursion!)
0
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
1
2
Einführung in die Informatik II
89
7.8.1 Die Türme von Hanoi )
Und wie verschieben wir einen Turm der Höhe n-1? )
Schiebe die obersten n-2 Scheiben von Pos. 1 auf Pos. 0
0
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
1
2
Einführung in die Informatik II
90
7.8.1 Die Türme von Hanoi )
Und wie verschieben wir einen Turm der Höhe n-1? )
Schiebe die unterste Scheibe von Pos. 1 auf Pos. 2
0
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
1
2
Einführung in die Informatik II
91
7.8.1 Die Türme von Hanoi )
Und wie verschieben wir einen Turm der Höhe n-1? )
Schiebe die obersten n-2 Scheiben von Pos. 0 auf Pos. 2
0
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
1
2
Einführung in die Informatik II
92
7.8.1 Die Türme von Hanoi )
SML-Programm für die allgemeine Lösung
- (* Die folgende Spezialanweisung sorgt dafür, daß der *)
- (* Compiler auch längere Listen vollständig ausgibt. *)
- Control.Print.printLength := 100;
val it = () : unit
- fun hanoi(1,A,B,C) = [(A,C)]
=
| hanoi(n,A,B,C) = hanoi(n-1,A,C,B)
=
@ [(A,C)]
=
@ hanoi(n-1,B,A,C);
val hanoi = fn : int * ’a * ’a * ’a -> (’a * ’a) list
- hanoi(4, 0, 1, 2);
val it =
[(0,1),(0,2),(1,2),(0,1),(2,0),(2,1),(0,1),(0,2),(1,2),
(1,0),(2,0),(1,2),(0,1),(0,2),(1,2)] : (int * int) list
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
93
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 1:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
94
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 2:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
95
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 3:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
96
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 4:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
97
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 5:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
98
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 6:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
99
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 7:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
100
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 8:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
101
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 9:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
102
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 10:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
103
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 11:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
104
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 12:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
105
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 13:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
106
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 14:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
107
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 15:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
108
7.8.1 Die Türme von Hanoi )
Visualisierung der Lösung für Turmhöhe 4
Schritt 16:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
109
7.8.1 Die Türme von Hanoi )
Wie lösen wir ein Problem durch Rekursion?
Wir gehen davon aus, daß alle kleineren Probleme bereits
gelöst sind
Dann konstruieren wir aus der Lösung der kleineren
Probleme eine Lösung des größeren Problems
oft: konstruiere aus der Lösung für die Problemgröße n eine Lösung
für die Problemgröße n + 1
Zu beachten ist jetzt noch der Terminierungsfall, d.h. wir
brauchen noch eine Lösung für die kleinsten Probleme
oft: Problemgröße 0 oder 1
Vgl. das Beweisprinzip der vollständigen Induktion!
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
110
7.8 Problemlösung mit Rekursion ...
7.8.2 Das Damenproblem
Gegeben ist ein Schachbrett mit n * n Feldern
Gesucht sind alle Stellungen für n Damen auf dem
Schachbrett, so daß sich keine
zwei Damen gegenseitig
bedrohen
d.h. keine zwei Damen in derselben
Reihe, Linie oder Diagonale
Beispiel für n = 8: s. rechts
Offensichtlich:
auf jeder Linie muß genau eine
Dame stehen
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
111
7.8.2 Das Damenproblem ...
Rekursiver Lösungsansatz
Verallgemeinerung: wir betrachten auch nicht-quadratische
Schachbretter
Angenommen, wir haben bereits die Lösung L für ein Brett
der Größe n * (m− 1)
d.h. alle möglichen Stellungen der (m− 1) Damen
Wir erhalten dann die Lösungen für ein n * m Brett wie
folgt:
bilde neue Stellungskandidaten:
kombiniere alle Stellungen aus L mit jeder möglichen Position der Dame
auf der neuen Linie
behalte davon die Stellungen, die ”sicher“ sind
Rekursionsende beim n * 0 Brett:
Lösungsmenge ist leer ...
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
112
7.8.2 Das Damenproblem ...
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
113
7.8.2 Das Damenproblem ...
Darstellung der Daten
Eine Position ist ein Paar ganzer Zahlen (Reihe, Linie)
Datentyp (int * int)
Eine Stellung ist eine Liste mit den Positionen aller Damen
Datentyp (int * int) list
Die Lösung ist eine Liste von Stellungen
Datentyp (int * int) list list
Ein Stellungskandidat ist ein Paar:
( Position der neuen Dame, Stellung für n * (m − 1) Brett )
Datentyp (int * int) * (int * int) list
nach dem Ausfiltern der sicheren Stellungen reihen wir das erste
Element dieses Paars in die Stellungs-Liste ein
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
114
7.8.2 Das Damenproblem ...
Erzeugung der Stellungskandidaten
Die Liste der Stellungskandidaten ist das kartesische
Produkt aus:
Liste der möglichen Positionen der m-ten Dame
Liste der Stellungen für das n * (m− 1) Brett
Kartesisches Produkt zweier Listen:
[a1, ..., an] × [b1, ..., bm] = [ (a1, b1), ... , (a1, bm),
(a2, b1), ... , (a2, bm),
...
...
(an, b1), ... , (an, bm)]
Hilfsfunktion dafür: Produkt eines Skalars mit einer Liste:
a · [b1, ..., bm] = [(a, b1), ... , (a, bm)]
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
115
7.8.2 Das Damenproblem ...
Erzeugung der Stellungskandidaten )
SML-Funktion für das Produkt eines Skalars mit einer Liste:
- fun prod x [] = []
=
| prod x (hd::tl) = (x, hd) :: (prod x tl);
val prod = fn : ’a -> ’b list -> (’a * ’b) list
- prod 8 [1,2,3,4];
val it = [(8,1),(8,2),(8,3),(8,4)] : (int * int) list
SML-Funktion für das kartesische Produkt zweier Listen:
- fun cartesian [] l = []
=
| cartesian (hd::tl) l = (prod hd l)
=
@ (cartesian tl l);
val cartesian = fn : ’a list -> ’b list -> (’a * ’b) list
- cartesian [1,2] [3,4];
val it = [(1,3),(1,4),(2,3),(2,4)] : (int * int) list
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
116
7.8.2 Das Damenproblem ...
Weitere Hilfsfunktionen für die Lösung
Eine Funktion, die die Liste [1,2,...,n] erzeugt
- fun enumerate 0 = []
=
| enumerate n = enumerate(n-1) @ [n];
val enumerate = fn : int -> int list
- enumerate 8;
val it = [1,2,3,4,5,6,7,8] : int list
Damit: Liste der möglichen Positionen für die neue Dame
- cartesian (enumerate 8) [5];
val it = [(1,5),(2,5),(3,5),(4,5),(5,5),(6,5),(7,5),
(8,5)] : (int * int) list
hier: 5-te Dame auf dem 8 * 8 Brett
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
117
7.8.2 Das Damenproblem ...
Wann ist eine Stellung sicher?
Hilfsfunktion: kann eine Dame auf Feld (i, j) die Dame
auf Feld (k, l) schlagen?
- fun capture (i,j) (k,l) = i = k orelse j = l
=
orelse (i-j) = (k-l)
=
orelse (i+j) = (k+l);
val capture = fn : int * int -> int * int -> bool
Prädikat: Dame auf Feld p ist zusammen mit gegebener
Stellung der anderen Damen sicher
- fun safe (p,[]) = true
=
| safe (p,hd::tl) = not (capture p hd)
=
andalso safe (p,tl);
val safe = fn : (int * int) * (int * int) list -> bool
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
118
7.8.2 Das Damenproblem ...
Herausfiltern der sicheren Stellungen
Anwendung der Funktion filter:
- filter safe [((1,3),[(1,2),(3,1)]),
= ((1,3),[(3,2),(5,1)])];
val it = [((1,3),[(3,2),(5,1)])]
: ((int * int) * (int * int) list) list
das Argument ist eine Liste von Stellungskandidaten
Umwandlung des Ergebnisses in eine Liste von Stellungen:
- map (fn (x,l) => x::l) [((1,3),[(3,2),(5,1)])];
val it = [[(1,3),(3,2),(5,1)]] : (int * int) list list
aus jedem Paar (x, [y1, ..., yn]) in der Liste wird eine Liste
[x, y1, ..., yn]
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
119
7.8.2 Das Damenproblem ...
Berechnung aller Lösungen
Erzeuge alle Lösungen für ein n * m Brett:
- fun allValidBoards n 0 = [[]]
=
| allValidBoards n m =
=
map (fn (x,l) => x::l) (
=
filter safe (
=
cartesian (cartesian (enumerate n) [m])
=
(allValidBoards n (m-1))
=
)
=
);
val allValidBoards = fn : int -> int -> (int * int)
list list
Erzeuge alle Lösungen für ein n * n Brett:
- fun queens n = allValidBoards n n;
val queens = fn : int -> (int * int) list list
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
120
7.8.2 Das Damenproblem ...
Berechnung aller Lösungen ...
Beispiel: 4 * 4 Brett
- queens 4;
val it = [[(2,4),(4,3),(1,2),(3,1)],[(3,4),(1,3),
(4,2),(2,1)]] : (int * int) list list
Anzahl der Lösungen für n = 1, ..., 10:
- map (fn n => length (queens n)) (enumerate 10);
val it = [1,0,0,2,10,4,40,92,352,724] : int list
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
121
7.8 Problemlösung mit Rekursion ...
7.8.3 Symbolisches Differenzieren
Funktionale Sprachen sind gut geeignet zur symbolischen
Manipulation von Termen
Einfaches Beispiel: Differenzieren von Funktionen
Mathematische Regeln:
Beispiel:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
122
7.8.3 Symbolisches Differenzieren ...
Eine Datenstruktur für Terme
Rekursive Datenstruktur mit Konstruktoren für:
Konstante und Variablen
Addition und Multiplikation
Keine Klammern in der Datenstruktur, da die Struktur des
Terms durch die Verschachtelung der Konstruktoren
gegeben ist
Definition des Datentyps in SML:
- datatype term = CONST of int | VAR of string
=
| ADD of term * term
=
| MUL of term * term;
Anmerkung: eigentlich sollte es CONST of real heißen
SML/NJ hat (wegen des fehlenden Gleichheitsoperators) aber
Probleme beim Pattern Matching mit real-Werten
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
123
7.8.3 Symbolisches Differenzieren ...
Eine Datenstruktur für Terme )
Beispiel: Term für x2 + y + 2
- val t = ADD(ADD(MUL(VAR "x", VAR "x"), VAR "y"),
=
CONST 2);
val t = ADD (ADD (MUL #,VAR #),CONST 2) : term
Ausgabe nur bis zu einer festen Tiefe (einstellbar)
Baumstruktur des Terms:
Anmerkung: statt ADD / MUL wären auch Infix-Operatoren
möglich
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
124
7.8.3 Symbolisches Differenzieren ...
Eine Funktion zum symbolischen Differenzieren
- fun deriv
=
| deriv
=
=
| deriv
=
| deriv
=
val deriv =
(CONST _) x = CONST 0
(VAR v) x = if x = v then CONST 1
else CONST 0
(ADD (t1,t2)) x = ADD (deriv t1 x, deriv t2 x)
(MUL (t1,t2)) x = ADD (MUL(deriv t1 x, t2),
MUL(t1, deriv t2 x));
fn : term -> string -> term
Rekursion über die Struktur des Terms
dabei Pattern Matching zur musterbasierten Transformation der
Baumstruktur
Typisch für Algorithmen auf rekursiven Strukturen
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
125
7.8.3 Symbolisches Differenzieren ...
Eine Funktion zum symbolischen Differenzieren )
Beispiele zur Anwendung der Funktion:
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
126
7.8.3 Symbolisches Differenzieren ...
Eine Funktion zum Vereinfachen
Die berechneten Terme sollten am Ende noch vereinfacht
werden
also z.B. 2 · x statt 1 · x + x · 1 + 0 + 0
Realisierbar durch rekursive Funktion mit Pattern Matching,
z.B.:
- fun simpl (ADD (t, CONST 0)) = simpl t
←t + 0 = t
=
| simpl (ADD (CONST 0, t)) = simpl t
←0 + t = t
=
| simpl (MUL (t, CONST 1)) = simpl t
←t · 1 = t
=
| simpl (MUL (CONST 1, t)) = simpl t
←1 · t = t
=
| simpl (MUL (_, CONST 0)) = CONST 0
←t · 0 = 0
=
| simpl (MUL (CONST 0, _)) = CONST 0
←0 · t = 0
=
| simpl (ADD (t1, t2)) =
←t+t = 2·t
=
if t1=t2 then MUL (CONST 2, simpl t1)
=
else ADD (simpl t1, simpl t2)
=
| simpl (MUL (t1, t2)) = MUL (simpl t1, simpl t2)
=
| simpl t = t;
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
127
7.8.3 Symbolisches Differenzieren ...
Eine Funktion zum Vereinfachen )
Beispiele:
- simpl tx;
val it = ADD (VAR "x",VAR "x") : term
- simpl it;
val it = MUL (CONST 2,VAR "x") : term
- simpl (simpl (simpl ty));
val it = CONST 1 : term
Die Funktion könnte noch so erweitert werden, daß sie
solange vereinfacht, bis sich der Term nicht mehr ändert ...
Anmerkung: mit CONST of real würde das Muster
fun simpl (ADD (t, CONST 0.0)) = ...
in SML/NJ zu einem Syntaxfehler führen
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
128
7.9 Auswertung funktionaler Programme
Eifrige Auswertung (Eager Evaluation)
Auswertung von Ausdrücken in SML ist Folge von
Ersetzungen
Variablen werden durch den Wert ersetzt, an den sie in der aktuellen
Umgebung gebunden sind
Argumente von Funktionen werden ausgewertet und die Werte in die
Funktionsdefinition eingesetzt
Beispiel:
betrachte fun sqr x = x * x;
Auswertung von sqr(sqr(sqr 2):
sqr(sqr(sqr 2) ⇒sqr(sqr(2 * 2))
⇒sqr(sqr 4) ⇒ sqr(4 * 4))
⇒sqr 16 ⇒ 16 * 16 ⇒ 256
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
129
7.9 Auswertung funktionaler Programme )
Eifrige Auswertung (Eager Evaluation)
Bei der eifrigen Auswertung werden die Argumente einer
Funktion immer vollständig ausgewertet, bevor der
definierende Funktionsausdruck ausgewertet wird
die Funktion erhält die Werte der Argumente (Call by value)
Folge: hat ein Argument einen undefinierten Wert, so hat die
Funktionsanwendung ebenfalls einen undefinierten Wert
Beispiele:
sqr (1 div 0);
sqr (fak ~1);
←1 div 0 ist undefiniert
und damit auch sqr (1 div 0)
←fak ~1 terminiert nicht
und damit auch sqr (fak ~1)
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
130
7.9 Auswertung funktionaler Programme )
Strikte Funktionen
Eine Funktion
Argument, wenn gilt:
heißt strikt im k-ten
hat nur dann einen definierten Wert, wenn auch ek
einen definierten Wert hat
Oder umgekehrt: ist
undefiniert, so auch
In SML sind (fast) alle Funktionen strikt in allen Argumenten
einzige Ausnahmen:
andalso: nicht strikt im 2. Argument
orelse: nicht strikt im 2. Argument
if then else: nicht strikt im 2. und 3. Argument
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
131
7.9 Auswertung funktionaler Programme )
Verzögerte Auswertung (Lazy Evaluation)
Argumente, in denen eine Funktion nicht strikt ist, dürfen
erst dann ausgewertet werden, wenn es wirklich notwendig
ist
verzögerte Auswertung
Beispiel: Zweierpotenz
fun even n = (n mod 2 = 0);
fun ZP n = n=1 orelse (even(n) andalso ZP(n div 2));
Auswertung von ZP(7):
ZP(7) ⇒7=1 orelse (even(7) andalso ZP(7 div 2))
⇒false orelse (even(7) andalso ZP(7 div 2))
⇒even(7) andalso ZP(7 div 2) ⇒ ...
⇒false andalso ZP(7 div 2)
⇒false
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
132
7.9 Auswertung funktionaler Programme )
Verzögerte Auswertung (Lazy Evaluation) )
Im Beispiel wurden orelse und andalso ausgewertet, bevor
ihr 2. Argument ausgewertet wurde
Der Funktion wird also statt des Werts des Arguments der
definierenden Ausdruck übergeben
diese Art der Parameterübergabe heißt Call by name
Beispiel: Auswertung von sqr(sqr(sqr 2)) mit Call by
name:
sqr(sqr(sqr 2)) ⇒ sqr(sqr 2) * sqr(sqr 2)
⇒(sqr 2 * sqr 2) * (sqr 2 * sqr 2)
⇒((2 * 2) * (2 * 2)) * ((2 * 2) * (2 * 2)) ⇒... ⇒ 256
Problem: mehrfache Auswertung desselben Ausdrucks
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
133
7.9 Auswertung funktionaler Programme )
Verzögerte Auswertung (Lazy Evaluation) )
Call by need ist wie Call by name, stellt aber sicher, daß
jeder Ausdruck höchstens einmal ausgewertet wird
Anwendung in vielen funktionalen Sprachen (nicht bei SML!)
Motivationen für verzögerte Auswertung:
Realisierung nicht strikter Funktionen, z.B.:
fun f (x,y) = if x=0 then y else x;
f (3, 1 div 0);
←der Wert sollte 3 sein ...
Einsparung überflüssiger Berechnungen, z.B.:
bestimme eine Lösung des 8-Damenproblems:
hd (queens 8);
ohne auch die anderen 91 Lösungen zu berechnen ...
Realisierung unendlicher Datenstrukturen
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
134
7.9 Auswertung funktionaler Programme )
Verzögerte Auswertung in SML
In SML kann verzögerte Auswertung realisiert werden, wenn
man Argumente nicht direkt übergibt, sondern in Funktionen
verpackt
Im Beispiel der vorigen Folie:
- fun f (x,y) = if x=0 then y() else x;
val f = fn : int * (unit -> int) -> int
- f(3, fn () => 1 div 0);
val it = 3 : int
an y wird hier kein int-Wert übergeben, sondern eine Funktion, die
beim Aufruf (d.h. erst bei Bedarf) den int-Wert liefert
die Funktion ist vom Typ unit -> int, hat also immer () als
Argument
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
135
7.9 Auswertung funktionaler Programme )
Unendliche Listen in SML
Mit verzögerter Auswertung lassen sich auch unendliche
Datenstrukturen erzeugen und bearbeiten
Beispiel: unendliche Liste (Stream, Sequenz)
type ’a lazy = unit -> ’a;
datatype ’a sequ = NIL | CONS of ’a * ’a sequ lazy;
der Rest der Sequenz ist durch eine Funktion beschrieben, die diese
Restsequenz erzeugt
Die Liste aller natürlichen Zahlen:
- fun from
val from =
- val nats
val nats =
n = CONS(n, fn () => from (n+1));
fn : int -> int sequ
= from 1;
CONS (1,fn) : int sequ
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
136
7.9 Auswertung funktionaler Programme )
Unendliche Listen in SML )
Funktionen für das erste Element und den Reststrom:
- fun head (CONS(x,_)) = x;
val head = fn : ’a sequ -> ’a
- fun tail NIL = NIL
=
| tail (CONS(_,r)) = r();
val tail = fn : ’a sequ -> ’a sequ
- head(tail(tail nats));
←drittes Element von nats
val it = 3 : int
Auch alle anderen Listenfunktionen lassen sich analog für
Sequenzen realisieren
neue, mächtige Datenstruktur ...
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
137
7.10 SML: Zusammenfassung
Die Ausdrucksfähigkeit von SML wird bewirkt durch:
Integrierte ”Collections“: Tupel, Records, Listen
Betrachtung von Funktionen als normale Werte
damit: Funktionen höherer Ordnung, Currying
Automatische Bestimmung der Typen (Typinferenz)
Polymorphes Typsystem (parametrisierte Typen)
damit: typsichere generische Funktionen
Konstruktorbasierte Datentypen
Pattern Matching von Funktionsargumenten
Rekursion (Funktionen und Datentypen)
Madjid Fathi
Wissensbassierte Systeme / Wissensmanagement
Einführung in die Informatik II
138
Herunterladen