ALP I Einführung in Haskell

Werbung
Funktionale Programmierung
ALP I
Einführung in Haskell
WS 2012/2013
Prof. Dr. Margarita Esponda
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Was ist Haskell?
Haskell ist eine rein Funktionale
Programmiersprache mit einer nach Bedarf
Auswertung-Strategie oder "Lazy Evaluation".
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Was bedeutet rein funktional?
-
Programme werden als mathematische Funktionen dargestellt
-
Haskell Funktionen haben keine Seiteneffekte.
keine Seiteneffekte ⇒ Referenzielle Transparenz
-
Eine Funktion liefert immer bei gleicher Eingabe das gleiche
Ergebnis.
-
Der Wert eines Ausdrucks hängt nur von den Werten der
aktuellen Parameter ab.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Funktionen
Eingabewerte
e1
e2
.
.
en
F
a
nur ein
Ausgabewert
Das Ergebnis einer Funktion hängt nur von den Eingabewerten ab.
Beispiel:
f(1,2)
1 2
f ( x , y ) = x 2+ y
Prof. Dr. Margarita Esponda
3
Funktionale Programmierung
Funktionen
Arithmetische Operationen können auch als Funktionen betrachtet werden
1
2
+
3
1 2
(+)(x,y) = x + y
Prof. Dr. Margarita Esponda
3
Funktionale Programmierung
Funktionen in Haskell
Einfache Funktionsdefinitionen in Haskell:
f x = x*x
quadrat x = x*x
Allgemeine Syntax:
Ausdruck, dessen Wert dem
Ergebnis der Funktion
entspricht
Funktionsname
f e1 e2
...
en
= Funktionskörper
Eingabeargumente ohne Klammern und Kommas
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Funktionsapplikation
Die Anwendung einer Funktion mit konkreten Argumenten wird als
Funktionsapplikation bezeichnet.
Funktionsdefinition:
f x y z = x*y + x*z
Funktionsapplikation:
f102
⇒ 1*0 + 1*2
⇒0+2
⇒2
Prof. Dr. Margarita Esponda
Funktionsreduktion
Die Variablen auf der rechten
Seite der Funktionsdefinition
werden durch die
entsprechenden konkreten
Argumente ersetzt.
Funktionale Programmierung
Normalform
Kann ein Ausdruck nicht mehr weiter reduziert werden, dann befindet
er sich in seiner Normalform und die Berechnung ist beendet.
Beispiele:
Ausdruck
3+7
sin 0
10
"text"
"text"
"1 + 2"
"1 + 2"
'2'
'2'
Prof. Dr. Margarita Esponda
Normalform des Ausdruck
0.0
Zahlen
Zeichenkette
Zeichen
Funktionale Programmierung
Auswertungsstrategie
✴
Innerhalb eines Ausdrucks kann es mehrere
Funktionsapplikationen geben.
✴
Die Reihenfolge, in der unabhängige Teilausdrücke ausgewertet
werden, verändert nicht den Wert des gesamtes Ausdrucks.
✴
Aber verschiedene Reihenfolgen können die Anzahl der
notwendigen Berechnungen stark beeinflussen.
✴
Eine Auswertungsstrategie kann sogar entscheiden, ob eine
Berechnung beendet werden kann oder nicht.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Bottom (⊥)
✴
✴
Wenn die Auswertung eines Ausdrucks zu einer
unendlichen Folge von Reduktionen führt, wird entweder
•
das Programm nicht beendet oder
•
es stürzt ab, weil der Speicher voll wird.
In der Theorie wird das Symbol Bottom ⊥ verwendet, um
den Wert von Ausdrücken darzustellen, die nicht vollständig
ausgewertet werden können (die divergent sind).
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Bottom (⊥)
Bottom kann in Haskell wie folgt ausgedrückt
werden:
bottom = bottom
In dem Prelude-Module ist eine Funktion dafür
definiert:
undefined = error "Prelude; undefined"
Prof. Dr. Margarita Esponda
Auswertungsstrategien
Auswertungsstrategien
Funktionsbeispiele:
g x = 2*x
f x = x+x
Auszuwertender Ausdruck:
f (g 5)
Call-by-value
Call-by-name
Ausdrücke werden von innen nach
außen und von links nach rechts
ausgewertet.
Ausdrücke werden von außen nach
innen ausgewertet.
f (g 5)
⇒
⇒
⇒
⇒
f (2 * 5)
f 10
10 + 10
20
Es wird garantiert, dass die Argumente
zuerst ausgewertet werden und dann
an die Funktion weitergegeben werden.
Prof. Dr. Margarita Esponda
f (g 5)
⇒ (g 5) + (g 5)
⇒ (2*5) + (g 5)
⇒ 10 + (g 5)
⇒ 10 + (2*5)
⇒ 10 + 10
⇒ 20
Ohne die Argumente auszuwerten,
werden zuerst die äusseren
Funktionen angewendet.
Auswertungsstrategien
Auswertungsstrategie in Haskell
Call-by-need oder Lazy-evaluation
Auswertung nach Bedarf
Lazy-evaluation ist eine optimierte Auswertungsvariante von
call-by-name und wird in Haskell und anderen funktionalen
Sprachen verwendet.
Beispiel:
g x = 2*x
f x = x*x
f (g 5)
⇒
(g 5) * (g 5) where g 5 = 2*5
⇒
(g 5) * (g 5) where g 5 = 10
⇒ 10 * 10
⇒ 100
Prof. Dr. Margarita Esponda
call-by-need ist eine Art
call-by-name-Auswertungsstrategie mit Gedächtnis
Auswertungsstrategien
Auswertungsstrategie in Haskell
f 6 (double 3)
⇒ (2 + 6) +
*
Definitionen:
f y x = (2 + y) + x * x
double x = 2 * x
(double 3)
⇒ 8 +
*
(double 3)
Anwendung:
f 6 (double 3)
⇒ 8 +
*
(2*3)
Call-by-need oder Lazy-evaluation
⇒ 8 +
Auswertung nach Bedarf
6
⇒ 8 + 36
⇒ 44
Prof. Dr. Margarita Esponda
*
Auswertungsstrategien
Strikte Funktionen
Informell kann man sagen, dass eine Funktion f strikt nach
einem ihrer Argumente a ist, wenn für die Auswertung der
Funktion, die Auswertung von a notwendig ist.
Formale Definition:
f ist strikt
Beispiel:
⇔
f
⊥
⊥
Die + Funktion ist strikt nach beiden Argumenten
(2*4) + (5*6)
oder
(+) (2*4) (5*6) ⇒ (2*4) + (5*6)
⇒ 8 + 30
⇒ 38
Prof. Dr. Margarita Esponda
=
Auswertungsstrategien
Haskell - Auswertungsstrategie
ist nicht strikt
✴
✴
Ausdrücke werden nur bei Bedarf ausgewertet
im Gegensatz zu imperative Sprachen, in denen eager-evaluation
verwendet wird.
Beispiel:
x = x+1
g 5
⇒ 5
g a = a
g x
⇒ g⊥
⇒ ⊥
f a b = b
x ⇒
⇒
⇒
⇒
x+1
(x + 1) + 1
((x + 1) + 1) + 1
...
f 2 3 ⇒ 3
g ist strikt nach a
f x 3 ⇒ 3
f ist strikt nach b, aber
nicht nach a
f 2 x ⇒ f 2⊥
⇒ ⊥
Prof. Dr. Margarita Esponda
weil die Auswertung
von x nicht terminiert
Funktionale Programmierung
Haskell-Programm
Ein Haskell-Programm besteht aus einer Reihe von Funktionen und einem
Ausdruck, der ausgewertet werden soll.
Name.hs
rectArea a b = a*b
✴
Eine Reihe von
Funktionsdefinitionen werden in
eine Skript-Datei geschrieben
✴
mit der Kommandozeile
rectPerimeter a b = 2*(a+b)
:load Name.hs
wird diese vom HaskellInterpreter gelesen.
(rectArea 4 5) + (rectArea 2 1)
✴
Prof. Dr. Margarita Esponda
Dann können Ausdrücke damit
ausgewertet werden.
Funktionale Programmierung
Berechnungsmodel
• Funktionsdefinitionen werden als Ersetzungsregeln
interpretiert
• Ausdrücke werden damit zu einem Wert (Normalform)
reduziert
• Hat ein Ausdruck keine reduzierbaren Teilausdrücke, so ist
er in Normalform
• In Haskell werden Ausdrücke nur nach Bedarf ausgewertet.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Pseudo-Funktionen mit Seiteneffekte
Eingabe der Zeit abhängig ist
e1
e2
.
.
en
F
a
Der Zustand einer globalen Variable wird verändert
Eine Funktion, die während Ihrer Berechnung globale Daten in irgend ein
Speichermedium manipuliert, verändert damit der Zustand der AusführungUmgebung und produziert damit Seiteneffekte.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
keine Seiteneffekte ⇒ Referentielle Transparenz
Vorteile der referentiellen Transparenz
-
Die Korrektheit der Programme oder einfache Eigenschaften können
mit klassischen mathematischen Verfahren geprüft werden.
-
Die Wartung ist einfacher, weil die Auswertung von Teilausdrücken
Kontext und Zeit unabhängig sind.
-
Wichtige Optimierungen durch den Compiler sind möglich
-
Parallele Auswertung von Teilausdrücke
-
gleiche Ausdrücke werden nur ein mal ausgewertet
-
usw.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Datentypen
✴
Ein Datentyp entspricht dem Wertbereich, den die Argumente
oder das Ergebnis einer Funktion haben können.
✴
Jeder Ausdruck in Haskell hat einen wohldefinierten Datentyp.
✴
Funktionen werden oft nur für bestimmte Datentypen
definiert.
✴
Der Datentyp von Variablen oder Ausdrücken wird durch
explizite Deklaration oder durch Typ-Inferenz festgestellt.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Datentypen
Explizite Deklaration des Datentyps einer Funktion
Syntax:
Funktionsname :: Funktionstyp
Beispiele:
Typ-Signatur
sum :: Int -> Int ->
sum
Prof. Dr. Margarita Esponda
a
b =
Int
a + b
doppel :: Int ->
Int
doppel
2*a
a
=
pi ::
double
pi
3.141598
=
Konstante Funktion
Funktionale Programmierung
Datentypen
Haskell hat ein statisches Typsystem
Der Datentyp der Funktionen wird statisch während der
Übersetzungszeit des Programms abgeleitet.
Vorteile:
•
Datentyp-Fehler werden früher erkannt
•
durch die Reduzierung der Typ-Überprüfung reduziert
sich die Ausführungszeit
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Grundlegende Datentypen
Int
ganzzahlige Werte
(-231 … 231-1)
Integer
ganzzahlige Werte
(unbeschränkt)
Bool
Wahrheitswerte
True
Char
Zeichen
'a'
Float
Gleitkommazahlen
(32 Bits)
Double
Gleitkommazahlen
(64 Bits)
Typ1 -> Typ2
Prof. Dr. Margarita Esponda
Funktionen
False
'1'
'+'
Funktionale Programmierung
Konstanten (Literale)
Konstante Werte, die im Programm direkt geschrieben
werden, besitzen einen Typ, der sich aus der Schreibweise
ergibt.
Typ
Beispiele:
Ganze Zahlen:
345
Gleitpunktzahlen
3.45
Zeichen
'A'
Zeichenketten
"Zeichenkette"
Prof. Dr. Margarita Esponda
0
10
Integer
0.0
'a'
'1'
Double
'+'
'\n'
Char
[Char]
Funktionale Programmierung
Arithmetische Operationen
Symbol
Operator
Priorität
+
*
/
`div`
`mod`
**
^
Addition
4
Subtraktion
4
Multiplikation
3
Division
3
Ganzzahlige Division
3
Rest
3
Ganzzahlige Potenz
2
Potenz
2
die niedrigeren
Zahlen
entsprechen
einer höheren
Priorität
Arithmetische Operatoren mit der gleichen Priorität sind linksassoziativ
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Jeder Ausdruck hat einen Wert und einen Datentyp
Typ
Wert
1 `div` 2
⇒
0
Integer
1/2
⇒
0.5
Double
1 `mod` 2
⇒
1
Integer
-6 `mod` 4 ⇒
-2
Integer
0.0 ^ 0
⇒
1.0
Double
3/0
⇒
Infinity
Double
sqrt(-5)
⇒
NaN
Double
0/0
⇒
NaN
Double
(3/0)/(2/0)
⇒
NaN
Double
Prof. Dr. Margarita Esponda
keine Zahl
Funktionale Programmierung
Kommentare
Blockkommentare
{- …….Blockkommentare ……
…………………………….…. -}
Zeilenkommentare
-- Zeilenkommentare
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Vergleichsoperatoren
Priorität
Prof. Dr. Margarita Esponda
Kleiner
<
5
Größer
>
5
Kleiner oder gleich
<=
5
Größer oder gleich
>=
5
Gleichheit
==
6
Ungleichheit
/=
6
Funktionale Programmierung
Fallunterscheidung
Allgemeine Form:
if <bool-Ausdruck> then <Ausdruck> else <Ausdruck>
Beispiel:
sign :: Int -> Int
sign x = if x > 0
then 1
else if x < 0
then -1
else 0
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Case-Verteiler
Beispiele: Übersetzung der Tonnamen von Deutsch zu Italienisch
german2italian :: Char -> String
german2italian x = case x of
'c' → "do"
'd' → "re"
'e' → "mi"
'f' → "fa"
'g' → "sol"
'a' → "la"
'h' → "si"
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Logische Operatoren
Priorität
Logische Negation
not
1
UND
ODER
&&
||
7
8
Beispiele:
True || False
⇒
True
True && False
⇒
False
not ( True || undefined )
⇒
False
not ( True && undefined )
⇒
*** Exception: Prelude.undefined
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Logische Operatoren
Die Funktion fromEnum gibt den
ASCII-Code des Zeichens zurück.
Beispiele:
char2Digit :: Char -> Int
char2Digit x = if (fromEnum x) >= (fromEnum '0') &&
(fromEnum x) <= (fromEnum '9')
then (fromEnum x) - (fromEnum '0')
else error "wrong argument value ..."
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Gibt es Funktionsnamen, die nicht erlaubt sind?
Schlüsselwörter sind reserviert und können nicht als
Funktionsnamen bzw. Namen für Funktionsargumente
verwendet werden.
Beispiel:
Prof. Dr. Margarita Esponda
if
where
then
error
else
not
case
undefined
of
NaN
let
infinity
usw.
Funktionale Programmierung
Lokale Funktionsdefinitionen
f :: Float -> Float -> Float
f x y = (a+1)*(b+2)
where
a = (x+y)/2
b = (x+y)/3
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Guards
sign :: Int -> Int
sign x
|x<0
| x == 0
|x>0
= -1
= 0
= 1
sign :: Int -> Int
sign x
|x>0
= 1
| x == 0
= 0
| otherwise = -1
otherwise :: bool
otherwise = True
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Guards
Allgemeine Syntax:
<Funktionsname> a1 a2 … an
| <guard1> = <expression1>
| <guard2> = <expression2>
...
| <guardm> = <expressionm>
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Struktur eines Haskell-Programms
Ein Haskell-Programm besteht aus einem oder
mehreren Modulen.
Ein Modul besteht aus Funktionsdefinitionen
und Typ-Deklarationen.
Beispiel:
haelfte:: Int -> Int
-- Typ-Deklaration
haelfte x = x `div` 2
-- Funktionsdefinition
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Programmausführung
Compiler
Die Programme werden direkt in die
Maschinensprache des jeweiligen Rechners übersetzt.
Das übersetzte Programm wird dann direkt von der
Hardware interpretiert.
Interpreter
Drei Wege bis zur
Programmausführung
Die Programme werden nicht übersetzt, sondern
direkt von einem Interpreter-Programm ausgeführt.
Compiler + Interpreter (virtuelle Maschine)
Die Programme werden in eine Zwischensprache
übersetzt und von einer so genannten virtuellen
Maschine (vereinfachter Interpreter) ausgeführt.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Programmausführung
Compiler
Programm in
Maschinensprache
Programm in einer
höheren
Programmiersprache
0000011101101011
Übersetzer
0101010111110101
0000101010111111
1111110101010110
0010101010111110
....
Beispiele:
Prof. Dr. Margarita Esponda
C, C++,
Das Programm kann
direkt von der Hardware
ausgeführt werden
Funktionale Programmierung
Programmausführung
Interpreter
Programm in einer
höheren
Programmiersprache
Quellprogramm
read (a);
read (b);
if (a<b) then
a = a*a;
else
a = a+b;
print a;
Der Interpreter
Interpreter
wird direkt von
der Hardware
ausgeführt
Das Programm wird
hier interpretiert
Beispiel: Skriptsprachen: JavaScript, JScript, Python, Tcl/Tk, VBA usw.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Programmausführung
Programm in einer
höheren
Programmiersprache
read (a);
read (b);
if (a<b) then
a = a*a;
else
a = a+b;
print a;
Compiler + Interpreter
Programm in einer
Zwischensprache
Übersetzer
LOAD
LOAD
MULT
#1 C
#2 B
#1 #2 #3
LOAD
ADD
STORE
LOAD
ADD
#4
#3
#1
#4
#3
A
#4 #1
C
A
#4 #1
Der
Zwischencode
Beispiele: Java
wird hier
interpretiert
Interpreter
Virtuelle Maschine
Der Interpreter
wird direkt von der
Hardware
ausgeführt.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Programmausführung in Haskell
Compiler
Interpreter
GHCI
Haskell (GHC)
Haskell (WinHugs)
Glasgow Haskell Compiler
hello.hs
main = putStrLn "Welcome to FU!"
$ ghc --make -o hello hello.hs
$ ./hello
Welcome to FU!
Prof. Dr. Margarita Esponda
HUGS
Haskell User's Gofer System
Herunterladen