Vier Folien pro Seite

Werbung
Ganzzahlen beschränkter Länge
Überladung
Beobachtungen:
Der Typ Int umfasst Ganzzahlen beschränkter Länge
• Alle Zahlenoperatoren und Funktionen arbeiten auf Int und
Integer.
Operatoren: +,*,^,• == und /= arbeiten auf Bool, Int und Integer (und vielen mehr)
Funktionen: div, mod, abs, negate
Vergleichsoperatoren: >,>=,==,/=,<=,<
Überladung: Der gleiche Name wird für verschiedene Operationen
verwendet.
Auf den Folien jetzt immer Int.
Auch die Zahlenkonstanten sind überladen
Später: Überladung selbst definieren
Guards
Syntax und Auswertung von Guards
Syntax: name pat+ | guard-expr = expr
Mathematik:
abs(x) =
x, falls x >= 0
-x, falls x < 0
In Haskell:
abs x | x >= 0 = x
abs x | x < 0 = -x
Guard gibt an, ob eine Gleichung ausgewählt werden soll
• guard-expr muss den Typ Bool haben.
• Auswahl der Gleichung erfolgt noch immer von oben nach unten.
• Passen die Argumente auf die Muster pat+ so ersetze die
Parameter in guard-expr und in expr durch die Argumente.
• Wenn guard-expr gleich True ist, so passt die Gleichung, wenn
guard-expr gleich False ist, so passt die Gleichung nicht.
1-4
Zeichen
Fließkommazahlen
• Typ: Float
• Typ: Char
• Literale: 0.235, 231.61e7, -2.33
• Literale: Zeichen zwischen Hochkommata, z.B. 'a', '3'
• Eingebaute Funktionen: Arithmetik, Trigonometrie, ...
• Spezailfälle: '\t', '\n','\\','\'','\"'
• Funktionen, Operatoren und Konstanten sind überladen.
1.0 + 2.2 = 3.2
abs -2.2 = 2.2
round 1 = 1
• Modul Char stellt einige Funktionen für Zeichen bereit
Typkonversion für Zahlen
Layout-Syntax
• Das Layout (die Einrückung) eines Haskell-Programms bestimmt
die Syntax.
• Bei Definitionen:
Automatische Typkonversion findet nicht statt!
Erster Buchstabe beginnt Definition
• 1 + 2.2 = 3.2,denn 1 ist überladen
• round 1 + 2.2 ⇒ Typfehler, denn round liefert Int
• Typen der Argumente müssen gleich sein, denn sie legen
Ergebnistyp fest
Buchstabe mit gleicher Einrückung beendet Definition
foo x = x
+ x
- 3
g y = y
5-8
Layout-Syntax
Konstruktion von Funktionen
• Explizites Ende mit ; möglich
Zuerst:
• Bei Guards bestimmen | und = die Syntax:
threeMax x y z
| x >= y
&& x >= z =
x | y >= z
= y
| otherwise
1. Kurze Beschreibung als Kommentar
2. Typsignatur angeben
3. Beispiele angeben
In Zukunft immer bei den Abgaben!
= z
Konstruktion rekursiver Funktionen über Zahlen
Schablone für primitiv-rekurisive Funktionen
• Induktive Definition von Zahlen:
0 ist eine natürliche Zahl
Der Nachfolger einer natürlichen Zahl ist eine nat. Zahl
Eine Funktion heißt primitiv-rekurisiv wenn sie definiert ist durch
Angabe des Wertes bei Null und durch eine Vorschrift, die besagt,
wie der Wert für n aus dem Wert für n - 1 berechnet wird.
f n
| n == 0 = ...
| n > 0 = ... f (n - 1) ...
D.h. annehmen, dass f (n - 1) bereits die Spezifikation erfüllt.
9-12
Konstruktion allgemein rekursiver Funktionen über Zahlen
Fehlermeldung ausgeben
Schablone:
f n
| n == 0 = ...
| n > 0 = ... f k ...
Dabei annehmen, dass f k bereits die Spezifikation erfüllt.
fac
fac
|
|
|
:: Int -> Int
n
n == 0
= 1
n > 0
= n * fac (n - 1) * n
otherwise
= error "fac mit negativem Argument"
Achtung: Terminierung ist hier nicht garantiert!
Beispiele als Testfälle
Tupel und Listen
• Black-Box-Tests: später und mit Tool
• White-Box-Tests: Testfälle formulieren anhand der Definition
Bei rekursiven Funktionen Basisfall und rekursiven Fall/Fälle
• Bis jetzt: Nur Basistypen
Bei Guards alle Fälle abdecken
• Jetzt: Zusammengesetzte Typen
Beispiele sind ebenfalls Testfälle, am besten als White-Box-Tests
formulieren
three x = 3
testThree =
Tupel: Feste Anzahl von Werten unterschiedlichen Typs
Listen: Beliebige Anzahl von Werten gleichen Typs
three 23 == 3
&& three 34 == 3
13-16
Tupel
Beispiele
• Mathe: (1,2) ∈ Int X Int
• Zusammengesetzte Typen fester Länge
Der Typ (t1,t2,...,tN) umfasst Tupel (v1,v2,...,vN) mit
v1::t1,v2::t2,...,vN::tN
(1,True) :: (Int,Bool)
origin :: (Int,Int)
origin = (0,0)
makePoint :: Int -> Int -> (Int,Int)
makePoint x y = (x,y)
(1.2,'a',) :: (Float,Char,Int)
• Die Syntax für Typen und Werte ist also gleich
Muster für Tupel
Nochmal Currying
Tupel können als Muster in Funktionsdefinitionen verwendet werden.
pointAddX :: (Int,Int) -> Int -> (Int,Int)
pointAddX (x,y) deltaX = (x + deltaX,y)
point3dAddY :: (Int,Int,Int) -> Int -> (Int,Int,Int)
point3dAddY (x,y,z) deltaY = (x,y+deltaY,z)
• Mathe: g(x,y) = 2 * x + y
• Haskell: g (x,y) = 2 * x + y
• Haskell, mit Currying: gc x y = 2 * x + y
curry :: ((Int,Int) -> Int) -> Int -> Int -> Int
curry f x y = f(x,y)
gc = curry g
P.S. Currying heißt auch Schönfinkeln
17-20
Einschub: Aussagen über Programmen beweisen
Listen
• Beliebige Anzahl von Werten gleichen Typs
• Funktionen sind als Gleichungen formuliert
• Für jeden Typ t gibt es einen Typ [t] von Listen über t
• Diese Gleichungen können auch in Beweisen verwendet werden
• Freie Variabeln der Aussagen sind ∀-quantifiziert
• Kanonische Repräsentation: [x,y,...]
• Die leere Liste: []
Z.Z: square x ≡ x
square x
2
• Beispiele:
Def. Potenzieren
Def.*
Def.square
2
=
x
=
x * x = x⋅x
[1,2] :: [Int]
['a','b','c'] :: [Char]
Einschub: Typsynonyme
Notation für Listen
• Auch für Typen können Namen definiert werden
• Syntax: type name = Typ
• Definiert name als Typsynonym für Typ
[n .. m]
[n,n+1,...,m']
• Beispiele:
[2 .. 7]
[2,3,4,5,6,7]
type IntPair = (Int,Int)
curry :: (IntPair -> Int) -> Int -> Int -> Int
[n,p .. m] [n,n+(n-p),...,m']
[7,5 .. 2] [7,5,3]
type MaybeFloat = (Bool, Float)
• Vordefiniert: type String = [Char] kanonische Rep.: "..."
21-24
List-Comprehensions
List-Comprehensions
Operationen:
• Generieren
• Mathe: M = { f (x,y) | x ∈ A, y ∈ B}
• Filtern
Idee: Aus bestehender Liste neue Liste erzeugen
Syntax: [ expr | qual1 , ... , qualN ]
Beispiel:
Qualifiers:
[3 * n | n <- [2,4,7,8,19], isEven n]
=> [6,12,24]
• pattern <- expr Generator
• expr Guard
Variablen aus pattern sind in allen Ausdrücken "rechts" des
Generators gebunden
25-26
Herunterladen