Workshop Einführung in die Sprache Haskell

Werbung
Workshop
Einführung in die Sprache Haskell
Nils Rexin und Marcellus Siegburg
[email protected]
[email protected]
itemis AG
Niederlassung Leipzig
Hochschule für Technik,
Wirtschaft und Kultur Leipzig
20. Juni 2014
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
1 / 27
Übersicht
Übersicht
1
Haskell
2
Programmieren mit Haskell
3
Rekursionsmuster
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
2 / 27
Haskell
Eigenschaften
Allgemeines zu Haskell
referentielle Transparenz (keine Nebenwirkung)
Bedarfsauswertung (Lazy Evaluation)
Funktionen höherer Ordnung
Entwurfsmusterunterstützung
kurzer Weg zwischen Spezifikation und Implementation
...
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
3 / 27
Programmieren mit Haskell
Datentypen
Datentyp
eigener Datentyp Boolean
data B o o l e a n = Wahr | F a l s c h
d e r i v i n g Show
Boolean ist der Typ
Wahr, Falsch sind Konstruktoren
| ist das Trennzeichen zwischen Konstruktoren
deriving Show ≈ Vererbung .toString() in Java
Einrückung beachten (Leerzeichen, Tabulatur)
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
4 / 27
Programmieren mit Haskell
Datentypen
Pattern Matching
eigener Datentyp Boolean
data B o o l e a n = Wahr | F a l s c h
d e r i v i n g Show
UND - Funktion
und x y =
case x of
Falsch → Falsch
Wahr → c a s e y o f
Wahr → Wahr
Falsch → Falsch
N. Rexin, M. Siegburg
ODER - Funktion
oder x y = undefined
Haskell-Einführung
20. Juni 2014
5 / 27
Programmieren mit Haskell
Datentypen
Pattern Matching
verschiedene Möglichkeiten
UND - Funktion
und x y =
case x of
Falsch → Falsch
Wahr → c a s e y o f
Wahr → Wahr
Falsch → Falsch
. . . mit if-then-else
und x y =
i f x == F a l s c h
then F a l s c h
e l s e i f y == Wahr
then Wahr
else Falsch
. . . ohne spezielle Einrückung
und x y =
c a s e x o f { F a l s c h → F a l s c h ; Wahr → u n d e f i n e d }
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
6 / 27
Programmieren mit Haskell
Datentypen
Pattern Matching
verschiedene Möglichkeiten
UND - Funktion
und x y =
case x of
Falsch → Falsch
Wahr → c a s e y o f
Wahr → Wahr
Falsch → Falsch
. . . mit if-then-else
und x y =
i f x == F a l s c h
then F a l s c h
e l s e i f y == Wahr
then Wahr
else Falsch
. . . ohne spezielle Einrückung
und x y =
c a s e x o f { F a l s c h → F a l s c h ; Wahr → u n d e f i n e d }
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
6 / 27
Programmieren mit Haskell
Datentypen
Pattern Matching
verschiedene Möglichkeiten
UND - Funktion
und x y =
case x of
Falsch → Falsch
Wahr → c a s e y o f
Wahr → Wahr
Falsch → Falsch
. . . mit if-then-else
und x y =
i f x == F a l s c h
then F a l s c h
e l s e i f y == Wahr
then Wahr
else Falsch
. . . ohne spezielle Einrückung
und x y =
c a s e x o f { F a l s c h → F a l s c h ; Wahr → u n d e f i n e d }
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
6 / 27
Programmieren mit Haskell
Datentypen
Pattern Matching
mit un-/konkreten Konstruktoren
UND - Funktion
und Wahr Wahr = Wahr
und
= Falsch
ODER - Funktion
oder Falsch Falsch = Falsch
oder
= Wahr
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
7 / 27
Programmieren mit Haskell
Datentypen
Pattern Matching
mit konkreten Konstruktoren
Datentyp mit zwei ploymorphen Elementen;
positionelle Notation
data Paar a = Paar a a
swap ( Paar x y ) = Paar y x
Datentyp mit zwei ploymorphen Elementen;
benannte Notation
data Paar a = Paar { x : : a , y : : a }
swap p = Paar ( y p ) ( x p )
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
8 / 27
Programmieren mit Haskell
Datentypen
Pattern Matching
mit konkreten Konstruktoren
Datentyp mit zwei ploymorphen Elementen;
positionelle Notation
data Paar a = Paar a a
swap ( Paar x y ) = Paar y x
Datentyp mit zwei ploymorphen Elementen;
benannte Notation
data Paar a = Paar { x : : a , y : : a }
swap p = Paar ( y p ) ( x p )
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
8 / 27
Programmieren mit Haskell
Datentypen
Pattern Matching
mit konkreten Konstruktoren und case-of-Ausdruck
case-of-Ausdruck mit beliebigen Datentyp
data D = Foo { a : : I n t , b : : I n t }
| Bar { c : : I n t }
d e r i v i n g Show
f x = case x of
Foo { a = x , b = y } → x + y
Bar {} → c x
Allgemein ist zubehalten
Zu jedem Konstruktor eines Datentyps gibt es einen Zweig
im case-of-Ausdruck.
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
9 / 27
Programmieren mit Haskell
Datentypen
Rekursiver Datentyp
Datentyp für polymorphe Listen definieren
data L i s t e a = N i l | Cons a ( L i s t e a )
d e r i v i n g Show
Funktionen auf Liste a
k e y ( Cons x x s ) = x
next ( Cons x x s ) = x s
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
10 / 27
Programmieren mit Haskell
Datentypen
Rekursiver Datentyp
Datentyp Liste mit benannten Komponenten
data L i s t e a = N i l | Cons { k e y : : a , next : :
d e r i v i n g Show
L i s t e a}
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
11 / 27
Programmieren mit Haskell
Datentypen
Anwendung
Aufgabe
Datenstruktur die eine Linie, ein Rechteck und ein
Kreis zusammenfasst
Jedes Element soll eine Position enthalten (ganzzahlig)
(Paar Int)
Funktion, die den Flächeninhalt der oben genannten
Objekte berechnet
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
12 / 27
Programmieren mit Haskell
Datentypen
Typen
Typdefinitionen bei Funktionen explizit möglich
Typdefinition
n i c h t : : Boolean → Boolean
n i c h t a = case a of
Wahr → F a l s c h
F a l s c h → Wahr
Haskell kann den Typ inferieren (ableiten)
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
13 / 27
Programmieren mit Haskell
Datentypen
Rekursive Funktionen
Aufgaben
Können bei rekursiven Datenstrukturen verwendet werden
Auswertung einer Boolean-Liste
undListe
undListe
Nil →
Cons a
: : L i s t e Boolean → Boolean
l i s t e = case l i s t e of
Wahr
a s → und a ( u n d L i s t e a s )
Listenverknüpfung
verbinden : : Liste a → Liste a → Liste a
v e r b i n d e n a b = case a of
Nil → b
Cons a ’ a s → Cons a ’ ( v e r b i n d e n a s b )
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
14 / 27
Programmieren mit Haskell
Datentypen
Rekursive Funktionen
Funktion, die eine Liste umkehrt
Typ der Umpkehrfunktion
umkehren : :
Liste a → Liste a
Ein Paar von zwei Listen gleicher Länge, gleichen Typs in einer
Paar-Liste zusammenführen
Aus einer Paar Liste ein Paar mit zwei neuen Listen erzeugen
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
15 / 27
Programmieren mit Haskell
Datentypen
Map
Anonyme Funktionen
Funktion wird nicht benannt
Verwendung eines Lambda-Ausdrucks
Beispiel
addAnonym : : B o o l e a n → B o o l e a n → B o o l e a n
addAnonym = ( λ a b → c a s e a o f
Wahr → b
Falsch → Falsch )
addAnonym2 = ( λ a → ( λ b → c a s e a o f
Wahr → b
Falsch → Falsch ) )
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
16 / 27
Programmieren mit Haskell
Datentypen
Map
Funktionen höherer Ordnung
Funktion als Rückgabewert
Funktion als Parameter
Beispiel
o p e r a t i o n P a a r : : ( a → a → b ) → Paar a → b
o p e r a t i o n P a a r f ( Paar a b ) = f a b
undPaar : : Paar B o o l e a n → B o o l e a n
undPaar p = o p e r a t i o n P a a r ( λ a b → und a b ) p
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
17 / 27
Programmieren mit Haskell
Datentypen
Map
Definition
Idee: Auf alle Elemente einer rekursiven Struktur die selbe Funktion
anwenden
Definition von Map:
Map für Listen
mapListe
mapListe
Nil →
Cons a
N. Rexin, M. Siegburg
: : (a → b) → Liste a → Liste b
f l = case l of
Nil
a s → Cons ( f a ) ( m a p L i s t e f a s )
Haskell-Einführung
20. Juni 2014
18 / 27
Programmieren mit Haskell
Datentypen
Map
Aufgaben
und auf alle Boolean-Paare in einer Liste anwenden
Aus einer Liste mit geometrischen Objekten alle Quadrate durch Wahr
in einer neu erzeugten Boolean-Liste hervorheben
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
19 / 27
Rekursionsmuster
Motivation
Rekursive Funktionen auf Listen
summe l i s t e = c a s e l i s t e o f
Nil
→ 0
Cons x x s → x + summe x s
l a e n g e l i s t e = case l i s t e of
Nil
→ 0
Cons
xs → 1 + laenge xs
u n d L i s t e l i s t e = case l i s t e of
Nil
→ Wahr
Cons x x s → und x ( u n d L i s t e x s )
→ gemeinsames Muster?
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
20 / 27
Rekursionsmuster
Fold auf Listen (1)
Muster (Pseudocode)
f l i s t e = case l i s t e of
Nil
→ ? exp1 ?
Cons x x s → ? exp2 ? x ( f x s )
Abstraktion des gemeinsamen Musters
foldListe : : b → (a → b → b) → Liste a → b
f o l d L i s t e exp1 exp2 l i s t e = c a s e l i s t e o f
Nil
→ exp1
Cons x x s → exp2 x ( f o l d L i s t e exp1 exp2 x s )
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
21 / 27
Rekursionsmuster
Fold auf Listen (2)
Rekursive Funktionen auf Listen
summe l i s t e = c a s e l i s t e o f
Nil
→ 0
Cons x x s → x + summe x s
laenge l i s t e = case l i s t e of
Nil
→ 0
Cons
xs → 1 + laenge xs
undListe l i s t e = case l i s t e of
Nil
→ Wahr
Cons x x s → und x ( u n d L i s t e x s )
Definition mit Fold
summe ’
laenge ’
l i s t e = f o l d L i s t e 0 ( λx r e s u l t → 1 + r e s u l t ) l i s t e
undListe ’
l i s t e = f o l d L i s t e 0 ( λx r e s u l t → x + r e s u l t ) l i s t e
l i s t e = f o l d L i s t e Wahr ( λx r e s u l t → und x r e s u l t ) l i s t e
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
22 / 27
Rekursionsmuster
Fold auf Listen (3)
Übung: Ersetze undefined
verbinden : : Liste a → Liste a → Liste a
verbinden a b = f o l d L i s t e undefined undefined a
umkehren : : L i s t e a → L i s t e a → L i s t e a
umkehren l i s t e = f o l d L i s t e u n d e f i n e d u n d e f i n e d l i s t e
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
23 / 27
Rekursionsmuster
Fold im Allgemeinen
für jeden Konstruktor K eines Types bekommt fold ein Parameter p
p hat die gleiche Stelligkeit wie K
Parametertypen von K entsprechen den Parametertypen von p
(fast, s. Rekursion)
Vergleiche Liste a mit foldListe
data L i s t e a = N i l | Cons a ( L i s t e a )
foldListe
N. Rexin, M. Siegburg
: : b → (a → b → b) → Liste a → b
Haskell-Einführung
20. Juni 2014
24 / 27
Rekursionsmuster
Fold auf Bäumen
Übung: Ersetze ? und undefined
data Baum a = B l a t t | Zweig (Baum a ) a (Baum a )
foldBaum : : ? → ? → Baum a → b
foldBaum b l a t t z w e i g baum = u n d e f i n e d
s u m m e S c h l u e s s e l : : Baum I n t e g e r → I n t e g e r
s u m m e S c h l u e s s e l baum = foldBaum u n d e f i n e d u n d e f i n e d baum
hoehe : : Baum a → I n t e g e r
hoehe baum = foldBaum u n d e f i n e d u n d e f i n e d baum
i n o r d e r S c h l u e s s e l : : Baum a → L i s t e a
i n o r d e r S c h l u e s s e l baum = foldBaum u n d e f i n e d u n d e f i n e d baum
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
25 / 27
Zusammenfassung
Zusammenfassung
Aufgabe
Datentypen mit Pattern Matching (case-of)
rekursive Datentypen (Liste, Baum)
Polymorphie
Typ-Definition
Funktionen höherer Ordnung (mapListe)
Lambda-Ausdruck
Besuchermuster (fold) auf Listen, Bäumen
Quelltext
Link: http://www.imn.htwk-leipzig.de/~nrexin/hal9
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
26 / 27
Vielen Dank für
Ihre Aufmerksamkeit
N. Rexin, M. Siegburg
Haskell-Einführung
20. Juni 2014
27 / 27
Herunterladen