Programmieren in Haskell

Programmieren in Haskell
Syntax und Semantik von Haskell
Programmieren in Haskell
1
Was wir heute (und nächstes mal) machen
• Datentypdefinitionen
• Wertdefinitionen, Variablenbindungen
• Musterbindungen
• Funktionsbindungen
• Bewachte Gleichungen
• Lokale Definitionen mit where und let
• Gültigkeitsbereiche
• Fallunterscheidungen
• Syntaktischer Zucker / Kernsprache
Programmieren in Haskell
2
Datentypen, Datentypdefinitionen
data Instrument =
|
|
|
Oboe
HonkyTonkPiano
Cello
VoiceAahs
data Musik
Note Ton Dauer
Pause Dauer
Musik :*: Musik
Musik :+: Musik
Instr Instrument Musik
Tempo GanzeZahl Musik
Programmieren in Haskell
=
|
|
|
|
|
3
Wahrheitswerte
data Bool = False | True
Programmieren in Haskell
-- vordefiniert
4
Ganze Zahlen
data Ganz = Zero |
Succ Ganz
Zero, Succ Zero, Succ (Succ Zero), . . .
Eingebaute Datentypen: Int und Integer
Programmieren in Haskell
5
Tupeltypen
data Pair a b
= Pair a b
data Triple a b c = Triple a b c
Eingebaute Datentypen: (a,b), (a,b,c)
Programmieren in Haskell
6
Listen
data List a = Empty | Front a (List a)
Eingebauter Datentyp: [a]
Programmieren in Haskell
7
Allgemeine Form
data T a1 . . . am
=
C1 t11 . . . t1n1
|
...
|
Cr tr1 . . . trnr
T : Typkonstruktor; Ci : (Daten-)Konstruktoren; ai : Typvariablen; tij : Typen oder
Typvariablen
Programmieren in Haskell
8
Selektorfunktionen auf Tupeln
fst :: (a,b) -> a
fst (a,b) = a
-- vordefiniert
snd :: (a,b) -> b
snd (a,b) = b
-- vordefiniert
Programmieren in Haskell
9
Selektorfunktionen auf Listen
head :: [a] -> a
head (x:xs) = x
-- vordefiniert
tail :: [a] -> [a]
tail (x:xs) = xs
-- vordefiniert
Programmieren in Haskell
10
Selektorfunktionen auf Musik
ton :: Musik -> Int
ton (Note ton dauer) = ton
dauer :: Musik -> Rational
dauer (Note ton dauer) = dauer
dauer (Pause
dauer) = dauer
Programmieren in Haskell
11
Typsynonyme
type GanzeZahl
type Bruch
= Int
= Rational
type Ton
type Dauer
= GanzeZahl
= Bruch
Programmieren in Haskell
12
Nutzen und Gefahren von Typsynonymen
type OrdList a = [a]
sort :: [a] -> OrdList a
sort xs = xs
Typ ok? Ja
Ergebnis geordnete Liste? Nein (jedenfalls nicht im allgemeinen)
Programmieren in Haskell
13
Wertdefinitionen, Variablenbindungen
theFinalAnswer :: Integer
theFinalAnswer = 42
aShortList :: [Integer]
aShortList = [1,2,3]
helloWorld :: String
helloWorld = "Hello World"
monotonie :: Musik
monotonie = c’ (1/1) :*: monotonie
Programmieren in Haskell
14
Funktionsbindungen
length :: [a] -> Int
length []
= 0
length (a:as) = 1 + length as
Programmieren in Haskell
-- vordefiniert
15
Allgemeiner Fall
f p11 . . . p1n
=
e1
...
=
...
f pk1 . . . pkn
=
ek
pij : Muster, ei : Ausdrücke
Programmieren in Haskell
16
Bewachte Gleichungen
member :: (Ord a) => a -> OrdList a -> Bool
member a []
= False
member a (b:bs) = a >= b && (a == b || member a bs)
member a [] = False
member a (b:bs) = if a < b then False else if a == b then True else member a bs
member a []
member a (b:bs)
| a < b
| a == b
| a > b
Programmieren in Haskell
= False
= False
= True
= member a bs
17
Lokale Definitionen mit where
sumSquares :: Int -> Int -> Int
sumSquares x y = sqX + sqY where
sqX = x * x
sqY = y * y
Programmieren in Haskell
18
Lokale Definitionen mit let
sumSquares :: Int -> Int -> Int
sumSquares x y = let sqX = x * x
sqY = y * y
in sqX + sqY
Programmieren in Haskell
19
Abseitsregel
• Das erste Zeichen der Definition unmittelbar nach dem where bestimmt die
Einrücktiefe des neu eröffneten Definitionsblocks.
• Zeilen, die weiter als bis zu dieser Position eingerückt sind, gelten als
Fortsetzungen einer begonnenen lokalen Definition.
• Zeilen auf gleicher Einrücktiefe beginnen eine neue Definition im lokalen Block.
• Die erste geringer eingerückte Zeile beendet den lokalen Block.
Programmieren in Haskell
20
Beispiel für Abseitsregel
calc x y = calc1 x +
calc2 y
where
calc1 x = squares x
where
squares x = x * x
calc2 x = x * x * x
Programmieren in Haskell
21
Fallunterscheidungen
length :: [a] -> Int
length []
= 0
length (a:as) = 1 + length as
-- vordefiniert
length’ :: [a] -> Int
length’ as = case as of
[]
-> 0
a:as’ -> 1 + length’ as’
last’ :: [a] -> a
last’ as = case reverse as of
a:as’ -> a
Programmieren in Haskell
22
Funktionsausdrücke
Ist n + 1 ein Wert oder eine Funktion?
Als Funktion:
f n = n + 1
\n -> n + 1
Allgemeine Form eines Funktionsausdrucks:
\p1 . . . pn -> e .
\p1 p2 -> e als Abkürzung für \p1 -> \p2 -> e
Programmieren in Haskell
23
Gestaffelte Funktionen
add :: Integer -> Integer -> Integer
add m n = m + n
add’ :: Integer -> (Integer -> Integer)
add’ = \m -> \n -> m + n
Programmieren in Haskell
24
note :: Int -> Int -> Dauer -> Musik
note oct h d = Note (12 * oct + h) d
note Eine Note in einer beliebigen Oktave und von beliebiger Höhe und Dauer.
note 2 Eine Note in der dritten Oktave und von beliebiger Höhe und Dauer.
note 2 ef Die Note f in der dritten Oktave und von beliebiger Dauer.
note 2 ef (1/4) ergibt Note 29 (1/4).
Programmieren in Haskell
25
Syntaktischer Zucker / Kernsprache
• Mustergleichungen / case-Ausdrücke
length []
= 0
length (x:xs) = 1 + length xs
length’ xs = case xs of
[]
-> 0
(x:xs) -> 1 + length’ xs
• Funktionsdefinitionen / Funktions-Ausdrücke
add m n = m + n
add’ = \m -> \n -> m + n
Programmieren in Haskell
26
• where-Klauseln / let-Ausdrücke
double n = add0 (dup n) where
dup a = (a,a)
double n = let dup a = (a,a) in add0 (dup n)
Programmieren in Haskell
27
Auswertung von Fallunterscheidungen
case C e1 ...ek of {...; C x1 ...xk -> e;...}
(case-Regel)
⇒ e[x1 /e1 , . . . , xn /en ]
Programmieren in Haskell
28
abs :: (Ord a, Num a) => a -> a
abs n = case n >= 0 of
True -> n
False -> -n
encode :: (Num a) => Maybe a -> a
encode x = case x of
Nothing -> -1
Just n -> abs n
encode (Just 5)
⇒
case Just 5 of {Nothing -> -1; Just n -> abs n}
(Def. encode)
⇒
abs 5
(case − Regel)
⇒
case 5 >= 0 of {True -> 5; False -> -5}
(Def. abs)
⇒
case True of {True -> 5; False -> -5}
(Def. >=)
⇒
5
Programmieren in Haskell
(case − Regel)
29
Auswertung von Funktionsanwendungen
(\x -> e) a ⇒ e[x/a]
Programmieren in Haskell
(β-Regel)
(1)
30
abs
=
encode =
\n -> case n >= 0 of {True -> n; False -> -n}
\x -> case x of {Nothing -> -1; Just n -> abs n}
encode (Just 5)
(Def. encode)
⇒
(\x-> case x of {Nothing-> -1; Just n-> abs n}) (Just 5)
⇒
case Just 5 of {Nothing -> -1; Just n -> abs n}
⇒
abs 5
⇒
(\n -> case n >= 0 of {True -> n; False -> -n}) 5
(Def. abs)
⇒
case 5 >= 0 of {True -> 5; False -> -5}
(β − Regel)
⇒
case True of {True -> 5; False -> -5}
(Def. (>=))
⇒
5
Programmieren in Haskell
(β − Regel)
(case − Regel)
(case − Regel)
31
Auswertung von lokalen Definitionen
let {x1 = e1 ;...;xn = en } in e
⇒ e[x1 /let {x1 = e1 ;...;xn = en } in e1 , . . . ,
(let-Regel)
xn /let {x1 = e1 ;...;xn = en } in en ]
Programmieren in Haskell
32
rep n a = let x = a:x in take n x
rep 2 8
Programmieren in Haskell
⇒
let x = 8:x in take 2 x
⇒
take 2 (let x = 8:x in 8:x)
(let − Regel)
⇒
take 2 (8:let x = 8:x in 8:x)
(let − Regel)
⇒
8:take 1 (let x = 8:x in 8:x)
(Def. take)
⇒
8:take 1 (8:let x = 8:x in 8:x)
(let − Regel)
⇒
8:8:take 0 (let x = 8:x in 8:x)
(Def. take)
⇒
8:8:[]
(Def. take)
(Def. rep)
33