Programmieren in Haskell

Werbung
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Programmieren in Haskell
WS 2011/2012
Administratives
Musik
Guards
Arrays
RobertGiegerich
Universität Bielefeld
AG Praktische Informatik
November 14, 2012
Algebraic
Datatypes
Listen
Ranges
List Comprehensions
Sortieren
Primzahlen
Musik
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Administratives
Der Nachfolger von Haskore ist Euterpea:
http://haskell.cs.yale.edu/?page_id=103
Paul Hudak. The Haskell School of Music. 2.0 edition,
2011.
http:
//www.cs.yale.edu/homes/hudak/Papers/HSoM.pdf
Musik
Guards
Arrays
Algebraic
Datatypes
Listen
Ranges
List Comprehensions
Sortieren
Primzahlen
Fallunterscheidungen ...
Universität Bielefeld
Programmieren
in Haskell
... in Ausdrücken:
if condition then ausdruck else ausdruck
1
2
3
4
5
case expr of
pat1 | guard1 -> expr1
pat2 | guard2 -> expr2
pat3 | guard3 -> expr3
...
... in Definitionen auf der linken Seite
Giegerich
Administratives
Musik
Guards
Arrays
Algebraic
Datatypes
Listen
Ranges
Pattern matching:
f [] (y:ys) = Ausdruck mit y und ys
List Comprehensions
Bewachte Gleichungen: ersetzen geschachtelte
if-Anweisungen auf der rechten Seite
Primzahlen
Sortieren
Wächter (Guards) in Funktionsdefinitionen
Universität Bielefeld
Programmieren
in Haskell
1
2
3
4
> fn pat1 pat2 ...
>
| guard1 = expr1
>
| guard2 = expr2
>
...
Giegerich
Administratives
Musik
Guards
syntaktische Zucker für Funktionsdefinitionen
Arrays
guards (Wächter) sind Ausdrücke (vom Typ Bool)
Algebraic
Datatypes
Listen
Example
1
2
3
4
howManyEqual n m p
| ( n == m ) && ( m == p )
= 3
| ( n == m ) || ( m == p ) || ( n == p ) = 2
| otherwise
= 0
Ranges
List Comprehensions
Sortieren
Primzahlen
Datenstrukturen mit konstantem Zugriff
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Administratives
“Konstanter Zugriff” heisst: Zugriff mit Aufwand unabhängig
von der Größe der Datenstruktur.
Beispiel Musik:
Finden der n-ten Note erfordert Durchlauf der Datenstruktur in
n oder mehr Schritten.
Beispiel Listen: Element-Operator (!!) wird kaum verwendet
Musik
Guards
Arrays
Algebraic
Datatypes
Listen
Ranges
List Comprehensions
Sortieren
Primzahlen
Zugriff auf Listenelemente
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Listen beherbergen viele Elemente gleichen Typs.
1
2
1
2
Sequentielle Abarbeitung ist einfach und effizient, z.B.
map f [] = []
map f ( x : xs ) = f x : map f xs
Random Zugriff auf einzelne Elemente durch operator !!
hängt von der Listenlänge ab:
( x : xs ) !! 0 = x
( x : xs ) !! n = xs !!( n -1)
Abhilfe schafft der Datentyp Array a b
Administratives
Musik
Guards
Arrays
Algebraic
Datatypes
Listen
Ranges
List Comprehensions
Sortieren
Primzahlen
Datentyp Array a b
Universität Bielefeld
Programmieren
in Haskell
Arrays – auf Deutsch “Felder”
Modul Array stellt Datwntyp Array a b und Funktionen
darauf bereit
a ist der Datentyp des Index, b der Elementtyp
Operator ! für element-Zugriff bietet effizienten
Random-Access
Indextyp erlaubt mehrere Dimensionen
Giegerich
Administratives
Musik
Guards
Arrays
Algebraic
Datatypes
Listen
Ranges
Funktion array liefert ein Array zurück
1
array
: : ( I x a ) => ( a , a ) −> [ ( a , b ) ] −> Array a b
List Comprehensions
Sortieren
2
3
t = a r r a y ( low , h i g h ) l i s t _ o f _ e n t r i e s = . . .
1
(!)
:: ( Ix a ) = > Array a b -> a -> b
Primzahlen
Beispiel: 2D Array
1
2
3
> module A r r
> where
> import Array
4
5
6
7
8
9
10
11
12
13
14
15
16
19
Programmieren
in Haskell
Giegerich
Administratives
> t a b l e : : Array ( Char , I n t ) I n t
> t a b l e = array ( ( ’ a ’ , 0) , ( ’ c ’ , 2) )
>
[ ( ( ’ a ’ , 0) , 0 ) ,
>
( ( ’ a ’ , 1) , 1 ) ,
>
( ( ’ a ’ , 2) , 2 ) ,
>
( ( ’b ’ , 0) , 3 ) ,
>
( ( ’b ’ , 1) , 4 ) ,
>
( ( ’ c ’ , 0) , 6 ) ,
>
( ( ’ c ’ , 1) , 7 ) ,
>
( ( ’b ’ , 2) , 5 ) ,
>
( ( ’ c ’ , 2) , 8 )
>
]
17
18
Universität Bielefeld
> access a b = table ! (a , b)
> access2
= ( table !)
Musik
Guards
Arrays
Algebraic
Datatypes
Listen
Ranges
List Comprehensions
Sortieren
Primzahlen
Alternative
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern Matching als Alternative für read-only Felder
Administratives
vs. Feldgröße
Musik
Guards
Arrays
Example
1
2
3
4
5
access
access
access
access
...
’a ’
’a ’
’a ’
’b ’
0
1
2
1
=
=
=
=
0
1
2
3
Algebraic
Datatypes
Listen
Ranges
List Comprehensions
Sortieren
Primzahlen
Beispiel: Umwandlung String in Char Array
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Administratives
Musik
Guards
1
2
3
Arrays
> s 2 a : : S t r i n g −> Array I n t Char
> s2a xs = l i s t A r r a y (0 , length xs − 1) xs
Algebraic
Datatypes
Listen
Ranges
List Comprehensions
Sortieren
Primzahlen
Beispiel: Tabellierung einer Funktion
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Verwandung einer Funktion in eine Tabelle
2
3
4
5
> tabulate
> tabulate
>
t
>
domain
: : ( I n t , I n t ) −> ( I n t −> a ) −> ( I n t −> a )
( l o , up ) f = ( t ! ) where
= a r r a y ( l o , up ) ( z i p domain (map f domain ) )
= [ l o . . up ]
6
Arrays
Algebraic
Datatypes
Ranges
8
10
Guards
Listen
7
9
Administratives
Musik
1
> sq1 x
= x ∗ x+1
> f a s t s q 1 = t a b u l a t e ( 1 , 1 0 ) sq1
List Comprehensions
Sortieren
Primzahlen
Algebraische Datentypen – Fortsetzung
Universität Bielefeld
Programmieren
in Haskell
Allgemeine Form der Deklaration:
data T a1 . . . am = C1 t11 . . . t1n1
...
|
|
Cr tr 1 . . . trnr
Giegerich
Administratives
Musik
Guards
Arrays
T Typkonstruktor
Algebraic
Datatypes
Ci (Daten-)Konstruktoren
Listen
ai Typvariablen
tij Typen oder Typvariablen
Ranges
List Comprehensions
Sortieren
Warum heißen Algebraische Datentypen „algebraisch“?
deriving
Typ-Kontexte
Primzahlen
Beispiel: Listen
Universität Bielefeld
Programmieren
in Haskell
Example
Giegerich
[1..5] = [1,2,3,4,5] = 1:2:3:4:5:[]
Administratives
:
Cons
Musik
Guards
1
1
Cons
Arrays
:
Algebraic
Datatypes
2
2
Cons
:
Listen
Ranges
3
Cons
3
List Comprehensions
:
Sortieren
4 Cons
5 Nil
4
:
5 []
Primzahlen
Listendefinition
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Administratives
1
2
Wenn man sie nicht schon hätte:
data List a = Cons a ( List a ) |
Nil
Pseudo-Code für vordefinierte Listen
1
2
data [ a ] = a : [ a ] |
[]
Musik
Guards
Arrays
Algebraic
Datatypes
Listen
Ranges
List Comprehensions
Sortieren
Primzahlen
Elementare Funktionen auf Listen
Universität Bielefeld
Programmieren
in Haskell
Die meisten kennen wir bereits:
Giegerich
head, tail
Administratives
length
Musik
sum, product
Guards
Arrays
enumFromTo
append
reverse
take, drop
Algebraic
Datatypes
siehe Tafel
Listen
Ranges
List Comprehensions
map
Sortieren
filter
Primzahlen
concat, concatMap
Arithmetic Sequences
Universität Bielefeld
Syntaktischer Zucker für Listen
[expr1..]
[expr1..expr2]
[expr1,expr2..]
[expr1,expr2..expr3]
Programmieren
in Haskell
Example
Arrays
Giegerich
Administratives
Musik
Guards
Algebraic
Datatypes
Hugs> [1..5]
[1,2,3,4,5]
Hugs> [1,3..10]
[1,3,5,7,9]
Hugs> [2,4..10]
[2,4,6,8,10]
Hugs> [1..]
[1,2,3,...
Listen
Ranges
List Comprehensions
Sortieren
Primzahlen
Arithmetic Sequences
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Übersetzung:
Administratives
[expr1..] = enumFrom expr1
Musik
[expr1..expr2] = enumFromTo expr1 expr2
Guards
[expr1,expr2..] = enumFromThen expr1 expr2
Arrays
Algebraic
Datatypes
[expr1,expr2..expr3] = enumFromThenTo expr1 expr2 Listen
expr3
Ranges
Voraussetzung:
expri haben den Gleichen Typ T
Typ T gehört der Typklasse Enum an
List Comprehensions
Sortieren
Primzahlen
List Comprehensions
(Übersetzt auch: Listenbeschreibung)
List Comprehension
1
[ expr | qual1 , ... , qualn ]
(wobei n >= 1)
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Administratives
Musik
Guards
Qualifier ist:
Generator: pat <- expr
Guard (oder Filter): boolexpr
lokale Deklaration: let decls
Example
Arrays
Algebraic
Datatypes
Listen
Ranges
List Comprehensions
Sortieren
1
[ x * x | x <- [1..20] , odd x ]
[1,9,25,49,81,121,169,225,289,361]
Primzahlen
Auflösung von List Comprehensions
Universität Bielefeld
Programmieren
in Haskell
Übersetzungsschema:
[ expr | True ] = [ expr ]
Giegerich
Administratives
[ expr | qual, True ] = [ expr | qual ]
Musik
[ expr | guard, qual1, ..., qualn ] =
if guard then [ e | qual1 , ... , qualn ]
else []
Guards
[ expr | pat <- list, qual1, ..., qualn] =
let f pat = [ expr | qual1 , ... , qualn ]
f _
= []
in concatMap f list
Listen
[ expr | let decls, qual1, ..., qualn ] =
let decls in [ expr | qual1 , ... , qualn ]
Primzahlen
Arrays
Algebraic
Datatypes
Ranges
List Comprehensions
Sortieren
Sortieren
Universität Bielefeld
Programmieren
in Haskell
Spezifikation des Sortierproblems:
genauer: Sortieren per Vergleich
Eingabe: Liste l
Giegerich
Administratives
Musik
Guards
Elemente vom Typ T
Arrays
T ist eine Instanz der Typklasse Ord
Algebraic
Datatypes
Ausgabe: sortierte Liste r
Listen
length l = length r
für alle x ∈ l: length [ a | a <- l, a == x]
= length [ b | b <- r, b == x]
Ranges
List Comprehensions
Sortieren
Insertion Sort
is_ordered l
Quicksort
Primzahlen
Insertion Sort
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Administratives
1
2
3
> isort :: Ord a = > [ a ] -> [ a ]
> isort [] = []
> isort ( x : xs ) = insert x ( isort xs ) where
4
5
6
7
8
>
>
>
>
insert x
insert x
| x <=
| x >
[] = [ x ]
( y : ys )
y = x : y : ys
y = y :( insert x ys )
Musik
Guards
Arrays
Algebraic
Datatypes
Listen
Ranges
List Comprehensions
Sortieren
Insertion Sort
Quicksort
Primzahlen
Quicksort
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Quicksort – noch bekannt aus der ersten Vorlesung ...?
Administratives
Musik
Guards
Arrays
1
2
3
4
5
> qsort :: Ord a = > [ a ] -> [ a ]
Algebraic
Datatypes
> qsort []
= []
Listen
> qsort ( a : xs ) = qsort [ b | b <- xs , b < a ] ++
Ranges
>
[ a ] ++
List Compre>
qsort [ b | b <- xs , b >= a ] hensions
Sortieren
Insertion Sort
Quicksort
Primzahlen
Primzahlen
Universität Bielefeld
Programmieren
in Haskell
Primzahl
natürliche Zahl > 1
nur teilbar durch 1 und sich selbst
Giegerich
Administratives
Musik
Guards
Arrays
Erster Versuch: Hier ist direkt die Definition progammiert:
Algebraic
Datatypes
Listen
Ranges
1
2
3
4
5
> primesSlow :: Integral a = > [ a ]
List Compre> primesSlow = [ n | n <- [2..] , divisors n ==hensions
[1 , n ]
Sortieren
>
where
Primzahlen
>
divisors :: Integral a = > a -> [ a ]
>
divisors n = [ d | d <- [1.. n ] , n ‘mod ‘ d == 0]
Sieb des
Eratosthenes
Sieb des Eratosthenes
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Aus der Liste aller Zahlen werden sukzessive die Vielfachen der
bereits gefundenen Primzahlen herausgesiebt ...
Administratives
Musik
Guards
Arrays
1
2
> primes :: Integral a = > [ a ]
> primes = sieve [2..] where
5
Listen
Ranges
3
4
Algebraic
Datatypes
>
>
List Compresieve :: Integral a = > [ a ] -> [ a ]
hensions
sieve ( a : xs ) = a : sieve [ n |n < - xs , n ‘ mod ‘ a /=Sortieren
0]
Primzahlen
Sieb des
Eratosthenes
Herunterladen