ALP I Einführung in Haskell

Werbung
Funktionale Programmierung
ALP I
Einführung in Haskell
SS 2011
Prof. Dr. Margarita Esponda
Prof. Dr. Margarita Esponda
1
Funktionale Programmierung
Was ist Haskell?
Eine rein funktionale Programmiersprache
- Eine Funktion liefert immer bei gleicher Eingabe
das gleiche Ergebnis.
- keine Seiteneffekte!
- Referenzielle Transparenz. Der Wert eines
Ausdrucks ist von der Zeit seine Ausführung
unabhängig.
Prof. Dr. Margarita Esponda
2
Funktionale Programmierung
Funktionen
Eingabewerte
e1
e2
.
.
en
F
a
nur ein
Ausgabewert
Das Ergebnis einer Funktion hängt nur von den Eingabewerten ab.
Beispiel:
Arithmetische Operationen können auch als Funktionen betrachtet werden
1
2
+
3
Prof. Dr. Margarita Esponda
3
Funktionale Programmierung
Funktionen in Haskell
Funktionsdefinition in Haskell:
f x = x*x
Beispiel:
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
4
Funktionale Programmierung
Funktionsapplikation
Die Anwendung einer Funktion mit konkreten Argumenten wird als
Funktionsapplikation bezeichnet.
Funktionsdefinition:
f x y z = x*y + x*z
Funktionsapplikation:
f 1 0 2 ⇒ 1*0 + 1*2
⇒0+2
⇒2
Funktionsreduktion
Die Variablen auf der rechten
Seite der Funktionsdefinition
werden durch die
entsprechenden konkreten
Argumente ersetzt.
Prof. Dr. Margarita Esponda
5
Funktionale Programmierung
Normalform
Kann ein Ausdruck nicht mehr weiter reduziert werden, dann
befindet er sich in seiner Normalform und die Berechnung ist
beendet.
Beispiele:
Zeichenkette
3
1.0
Zahlen
"text"
f
Funktion ohne Argumente
Prof. Dr. Margarita Esponda
6
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
7
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
8
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
9
Funktionale Programmierung
Auswertungsstrategien
Funktionsbeispiele:
z
= 2*5
f x = x+x
Auszuwertender Ausdruck:
f z
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 z ⇒ f 10
⇒ 10 + 10
⇒ 20
Es wird garantiert, dass die Argumente
zuerst ausgewertet werden und dann
an die Funktion weitergegeben
werden.
f z
⇒
⇒
⇒
⇒
⇒
f (2*5)
(2*5) + (2*5)
10 + (2*5)
10 + 10
20
Ohne die Argumente auszuwerten,
werden zuerst die äusseren
Funktionen angewendet.
Prof. Dr. Margarita Esponda
10
Funktionale Programmierung
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:
f z
⇒
z * z where z = 2*5
⇒
z * z where z = 10
⇒ 10 * 10
call-by-need ist eine Art
⇒ 100
call-by-name-Auswertungsstrategie
mit Gedächtnis
Prof. Dr. Margarita Esponda
11
Funktionale Programmierung
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
12
Funktionale Programmierung
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⊥
⇒ ⊥
weil die Auswertung
von x nicht terminiert
Prof. Dr. Margarita Esponda
13
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)
(rectArea 4 5) + (rectArea 2 1)
:load Name.hs
wird diese vom HaskellInterpreter gelesen.
✴
Dann können Ausdrücke damit
ausgewertet werden.
Prof. Dr. Margarita Esponda
14
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
15
Funktionale Programmierung
Datentypen
✴
Ein Datentyp entspricht dem Wertebereich, 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 Typinferenz festgestellt.
Prof. Dr. Margarita Esponda
16
Funktionale Programmierung
Datentypen
Explizite Deklaration des Datentyps einer Funktion
Syntax:
Funktionsname :: Funktionstyp
Beispiele:
Typ-Signatur
sum :: Int -> Int ->
sum
a
b =
Int
a + b
doppel :: Int ->
Int
doppel
2*a
a
=
pi ::
double
pi
3.141598
=
Konstante Funktion
Prof. Dr. Margarita Esponda
17
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
18
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
False
'1'
'+'
Funktionen
Prof. Dr. Margarita Esponda
19
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
0
10
Gleitpunktzahlen
3.45
Zeichen
'A'
Zeichenketten
"Zeichenkette"
Integer
0.0
'a'
'1'
Double
'+'
'\n'
Char
[Char]
Prof. Dr. Margarita Esponda
20
Funktionale Programmierung
Arithmetische Operationen
Symbol
Operator
Priorität
+
Addition
4
-
Subtraktion
4
*
Multiplikation
3
/
Division
3
`div`
Ganzzahlige Division
3
`mod`
Rest
3
^
Potenz
2
die niedrigeren
Zahlen
entsprechen
einer höheren
Priorität
Arithmetische Operatoren mit der gleichen Priorität sind linksassoziativ
Prof. Dr. Margarita Esponda
21
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
0/0
⇒
NaN
Double
sqrt(-5)
⇒
NaN
Double
3/0
⇒
Infinity
Double
(3/0)/(2/0)
⇒
NaN
Double
keine Zahl
Prof. Dr. Margarita Esponda
22
Funktionale Programmierung
Kommentare
Blockkommentare
{- …….Blockkommentare ……
…………………………….…. -}
Zeilenkommentare
-- Zeilenkommentare
Prof. Dr. Margarita Esponda
23
Funktionale Programmierung
Vergleichsoperatoren
Priorität
Kleiner
<
5
Größer
>
5
Kleiner oder gleich
<=
5
Größer oder gleich
>=
5
Gleichheit
==
6
Ungleichheit
/=
6
Prof. Dr. Margarita Esponda
24
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
25
Funktionale Programmierung
Case-Verteiler
Beispiele:
char2Int :: Char -> Integer
char2Int x = case x of
'1' -> 1
'2' -> 2
'3' -> 3
'4' -> 4
'5' -> 5
digit :: String -> Integer
digit text = case text of
"eins" -> 1
"zwei" -> 2
"drei" -> 3
"vier" -> 4
"fünf" -> 5
Prof. Dr. Margarita Esponda
26
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
27
Funktionale Programmierung
Logische Operatoren
Beispiele:
Die Funktion fromEnum gibt den
ASCII-Code des Zeichens zurück.
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
28
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
Prof. Dr. Margarita Esponda
29
Funktionale Programmierung
Guards
Allgemeine Syntax:
<Funktionsname> a1 a2 … an
| <guard1> = <expression1>
| <guard2> = <expression2>
...
| <guardm> = <expressionm>
otherwise :: bool
otherwise = True
Prof. Dr. Margarita Esponda
30
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
31
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
32
Funktionale Programmierung
Rekursion
Rekursion ist ein fundamentales Konzept in der Mathematik
- eine Denkform für Problembeschreibung
- enge Beziehung zur mathematischen Induktion
Rekursion ist ein fundamentales Konzept in der Informatik
- eine Methode zur Problemlösung
Rekursive Funktionsdefinitionen sind die wichtigste
Programmiertechnik in funktionalen Programmiersprachen.
Prof. Dr. Margarita Esponda
33
33
Funktionale Programmierung
Rekursive Funktionen
Typisches Beispiel:
Die Fakultätsfunktion
Wie viele Permutationen
kann eine Reihe von
Objekten maximal
haben?
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n-1)
bigFactorial :: Integer -> Integer
bigFactorial 0 = 1
bigFactorial n = n * bigFactorial (n-1)
Prof. Dr. Margarita Esponda
34
Funktionale Programmierung
Rekursive Funktionen
noch ein Klassiker:
Größter gemeinsamer Teiler von zwei natürlichen Zahlen a, b
Euklid (originaler Algorithmus)
ggt p q | p>q
= ggt (p-q) q
| p==q = p
| p<q
Probleme?
Moderne Lösung:
= ggt p (q-p)
ggt a b
| b == 0
=a
| otherwise
= ggt b (a `mod` b)
Prof. Dr. Margarita Esponda
35
Funktionale Programmierung
Pizzaproblem (Jakob Steiner, 1826)
Wie viele Pizza-Teile entstehen
maximal, wenn eine Pizza mit
n geraden Schnitten aufgeteilt
wird?
maxSurfaces :: Int -> Int
maxSurfaces 0 = 1
maxSurfaces n = maxSurfaces (n - 1) + n
Prof. Dr. Margarita Esponda
36
Funktionale Programmierung
Rekursive Funktionen
Berechnung des goldenen Schnitts
Zwei positive reelle Zahlen stehen im Verhältnis der goldenen Zahl, wenn
a a+b
=
b
a
gilt,
Goldener Schnitt =
mit a > b > 0.
Φ = 1+
1
Φ
goldenRatio :: Int -> Double
goldenRatio n
| n == 0 = 1
| n > 0 = 1 + 1 / goldenRatio (n-1)
| otherwise = error "not defined for negative numbers"
Prof. Dr. Margarita Esponda
37
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
38
Funktionale Programmierung
Programmausführung
Compiler
Programm in
Maschinensprache
Programm in einer
höheren
Programmiersprache
0000011101101011
Übersetzer
0101010111110101
0000101010111111
1111110101010110
0010101010111110
....
Beispiele:
C, C++,
Das Programm kann
direkt von der Hardware
ausgeführt werden
Prof. Dr. Margarita Esponda
39
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
40
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
41
Funktionale Programmierung
Programmausführung in Haskell
Compiler
Interpreter
GHCI
Haskell (GHC)
Haskell (WinHugs)
Glasgow Haskell Compiler
hello.hs
main = putStrLn "Welcome to FU!"
HUGS
Haskell User's Gofer System
$ ghc --make -o hello hello.hs
$ ./hello
Welcome to FU!
Prof. Dr. Margarita Esponda
42
Herunterladen