Algebraische Datentypen und Abstrakte Datentypen

Werbung
Funktionale Programmierung
ALP I
Algebraische Datentypen
und
Abstrakte Datentypen
SS 2013
Prof. Dr. Margarita Esponda
Prof. Dr. Margarita Esponda
Abstrakt Datentypen
Algebraischen Datentypen für Bäume
Beispiel:
data SBTree = L | N SBTree SBTree
N
N
N
L
L
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
L
N
L
L
Abstrakt Datentypen
Einfache binäre Bäume
data SBTree = L | N SBTree SBTree deriving Show
Ein balancierter Baum
type Depth = Integer
mit der eingegebenen
genSBTree :: Depth -> SBTree
Tiefe wird erstellt.
genSBTree 0 = L
genSBTree (n+1) = N (genSBTree n) (genSBTree n)
N
N
N
genSBTree 3
⇒
N
L
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
L
N
L
N
N
L
L
L
L
L
Abstrakt Datentypen
Berechnung aller Knoten des Baumes
nodes :: SBTree -> Integer
nodes L = 1
nodes (N leftT rightT) = 1 + nodes leftT + nodes rightT
nodes (genSBTree 3)
N
⇒ 15
N
N
N
L
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
L
N
L
N
N
L
L
L
L
L
Abstrakt Datentypen
Tiefe des Baumes
depth :: SBTree -> Integer
depth L = 0
depth (N lt rt) = (max (depth lt) (depth rt)) + 1
N
depth N (N (N L L) L) (N L L) ⇒ 3
N
L
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
N
N
L
L
L
L
Abstrakt Datentypen
joinTrees :: SBTree -> SBTree -> SBTree
joinTrees leftTree rightTree = N leftTree rightTree
joinTrees leftT
rightT
⇒
N leftT rightT
N
leftT
L
rightT
N
N
L
L
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
N
N
N
L
L
rightT
leftT
L
N
L
L
L
L
Abstrakt Datentypen
balanced :: SBTree -> Bool
balanced L = True
balanced (N lt rt) = (balanced lt) && (balanced rt) && depth lt == depth rt
balanciert
N
L
L
N
L
N
N
N
N
nicht balanciert
balanciert
L
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
N
N
L
L
L
N
L
L
L
L
L
Abstrakt Datentypen
Algebraischer Datentyp für Binäre Suchbäume
Beispiel:
data Tree = Leaf Int | Node Int Tree Tree | Nil
53
ist sortiert.
69
27
13
Die gespeicherte Information
34
63
46
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
95
Algebraische Datentypen für Binäre Suchbäume
Operationen für Binäre Suchbäume
data BSTree a = Nil | Node a (BSTree a) (BSTree a)
deriving ( Show, Eq )
-- findet das kleinste Element
smallest:: (Ord a) => BSTree a -> a
smallest (Node x Nil _) = x
smallest (Node x leftTree _) = smallest leftTree
53
69
27
13
34
63
46
Prof. Dr. Margarita Esponda
95
Algebraische Datentypen für Binäre Suchbäume
Algebraischer Datentyp für Binäre Suchbäume
data BSTree a = Nil | Node a (BSTree a) (BSTree a)
deriving ( Show, Eq )
-- findet das größte Element
biggest:: (Ord a) => BSTree a -> a
biggest(Node x _ Nil) = x
biggest(Node x _ rightTree) = biggest rightTree
-- spiegelt einen Baum
mirror:: (Ord a) => BSTree a -> BSTree a
mirror Nil = Nil
mirror (Node x xl xr) = Node x (mirror xr) (mirror xl)
Prof. Dr. Margarita Esponda
Algebraische Datentypen für Binäre Suchbäume
Traversierung binärer Bäume
Baumtraversierung bedeutet, alle Knoten des Baumes in einer
bestimmten Reihenfolge zu besuchen.
Preorder:
Wurzel – linker Unterbaum – rechter Unterbaum
Inorder:
linker Unterbaum - Wurzel – rechter Unterbaum
Postorder:
linker Unterbaum – rechter Unterbaum - Wurzel
Levelorder:
von oben nach unten in jeder Ebene von links
nach rechts
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
23
Traversierung binärer Bäume
Inorder
Linker Unterbaum - Wurzel - Rechter Unterbaum
F
D
B
A
I
E
C
A B C D E F G H I J
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
J
G
H
Algebraische Datentypen für Binäre Suchbäume
Traversierung von Binärbäumen
-- verwandelt einen sortierten Baum in eine sortierte Liste
inOrder :: (Ord a) => BSTree a -> [a]
inOrder Nil = []
inOrder (Node x ltree rtree) = inOrder ltree ++ x : inOrder rtree
Prof. Dr. Margarita Esponda
Algebraische Datentypen
-- verwandelt einen Baum in eine Liste
preOrder :: (Ord a) => BSTree a -> [a]
preOrder Nil = []
preOrder (Node x ltree rtree) = x : preOrder ltree ++ preOrder rtree
F
D
B
A
I
E
C
F D B A C E I G H J
Prof. Dr. Margarita Esponda
J
G
H
Binärbäume
Binärbäume
einfachste
Beispiele:
AVL-Bäume
Baumstrukturen
Red-Black-Bäume
ausgeglichene Bäume
B-Bäume
usw.
Die wichtigste Voraussetzung für die effiziente Verwaltung von
Datenmengen mit Hilfe von Bäumen ist, dass die Bäume balanciert
sind.
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
Algebraische Datentypen
Suchen
3
11
19
7
3
1
Nil
11
9
3
3
16
5
Nil Nil
Nil
15
Nil
Nil
19
7
1
Nil
Nil
9
16
5
Nil Nil
Nil
15
Nil
Nil
Nil
search :: (Ord a) => a -> BSTree a -> Bool
search _ Nil = False
search k (Node x ltree rtree) | k==x = True
| k<x = search k ltree
| otherwise = search k rtree
Prof. Dr. Margarita Esponda
Algebraische Datentypen
6
11
19
7
3
1
Nil
Nil
Einfügen
9
5
Nil
Nil Nil
15
Nil
11
23
16
Nil
Nil
19
7
Nil
3
Nil
1
Nil
Nil
9
5
Nil
Nil
15
Nil
6
Nil Nil
Prof. Dr. Margarita Esponda
23
16
Nil
Nil
Nil
Nil
Algebraische Datentypen
Einfügen
insert :: (Ord a) => a -> BSTree a -> BSTree a
insert a Nil = Node a Nil Nil
insert a (Node x ltree rtree)
| a<x = Node x (insert a ltree) rtree
| otherwise = Node x ltree (insert a rtree)
Prof. Dr. Margarita Esponda
Algebraische Datentypen
Minimum und Maximum
53
Minimum
27
13
Maximum
69
34
63
95
Der erste
Knoten, der
keine linken
Kinder mehr
hat, beinhaltet
das kleinste
Element.
-- findet das kleinste Element
17
46
smallest (Node x Nil _) = x
smallest (Node x leftTree _) = smallest leftTree
-- findet das größte Element
biggest(Node x _ Nil) = x
biggest(Node x _ rightTree) = biggest rightTree
Prof. Dr. Margarita Esponda
Algebraische Datentypen
Löschen
mit "Brute force"
list2Tree [] = Nil
list2Tree (x:xs) = insert x (list2Tree xs)
remove _ [] = []
remove y (x:xs) | y==x = xs
| otherwise = x:(remove y xs)
delete a Nil = Nil
delete a tree = list2Tree(remove a (preOrder tree))
Prof. Dr. Margarita Esponda
Algebraische Datentypen
Nachfolger
1. Fall
53
Es gibt einen
rechten Unterbaum.
Minimum
13
8
69
30
34
63
17
46
39
Prof. Dr. Margarita Esponda
95
Algebraische Datentypen
Nachfolger
2. Fall
53
Es gibt keinen
rechten Unterbaum.
13
8
69
30
34
63
17
46
95
Maximum
39
Wie können wir nach oben laufen?
Prof. Dr. Margarita Esponda
Algebraische Datentypen
Delete-Operation ( Löschen )
1. Fall
2. Fall
Löschen eines Knotens
ohne Kinder
Löschen eines Knotens
mit nur einem Kind
53
53
27
13
69
34
17
Prof. Dr. Margarita Esponda
63
46
27
Nil
95
13
69
34
63
46
95
Algebraische Datentypen
Löschen
Löschen eines Knotens mit zwei Kindern
3. Fall
Der Knoten, den man löschen möchte, wird durch
seinen Nachfolger ersetzt.
53
53
27
13
8
17
69
34
30
63
46
69
30
13
95
8
17
34
32
63
95
46
32
Der Nachfolger von 27 ist das Minimum des rechten Unterbaumes.
Das Minimum ist entweder ein Blatt oder hat maximal ein rechtes Kind.
Prof. Dr. Margarita Esponda
Algebraische Datentypen
Löschen
Löschen eines Knotens mit zwei Kindern
Wir brauchen eine join-Funktion, die aus zwei KinderBäumen einen baut.
53
53
27
69
join
34
13
63
95
34
13
8
17
30
69
46
8
17
30
46
32
32
Prof. Dr. Margarita Esponda
63
95
Algebraische Datentypen
Löschen
etwas besser
delete :: (Ord a) => a-> BSTree a-> BSTree a
delete x Nil = Nil
delete x (Node y ltree rtree)
| x < y = Node y (delete x ltree) rtree
| x == y = join ltree rtree
| x > y = Node y ltree (delete x rtree)
……
Prof. Dr. Margarita Esponda
Algebraische Datentypen
Join-Funktion
join :: (Ord a) => BSTree a-> BSTree a-> BSTree a
join xtree Nil = xtree
join xtree ytree = Node e xtree ntree
where
(e, ntree) = splitMin ytree
-- splitMin :: BSTree a -> (a, BSTree a)
splitMin (Node x Nil tree) = (x, tree)
splitMin (Node x ltree rtree) = (f, Node x ntree rtree)
where
(f, ntree) = splitMin ltree
Prof. Dr. Margarita Esponda
Algebraische Datentypen
Probleme mit einfachen binären Suchbäumen
balancierter Binärbaum
nicht
balancierter Binärbaum
53
53
27
13
69
34
17
30
63
46
83
30
95
95
59
139
71
65
60
62
Prof. Dr. Margarita Esponda
77
Algebraische Datentypen
Algebraische Datentypen
-- für arithmetische Ausdrücke
data Expr = Lit Int | Add Expr Expr | Sub Expr Expr | Mult Expr Expr
eval :: Expr -> Int
eval (Lit n) = n
eval (Add x y) = eval x + eval y
eval (Sub x y) = eval x - eval y
eval (Mult x y) = eval x * eval y
eval (Mult (Add (Lit 3) (Lit 4)) (Lit 3))
Prof. Dr. Margarita Esponda
=> 21
Funktionale Programmierung
Haskell Typsystem
Monomorphe Funktionen
Der Datentyp wird genau durch die Signatur bestimmt
Beispiel:
asciiCode :: Char -> Int
Polymorphe Funktionen
Typvariablen in der Signatur lassen beliebige Datentypen zu
Beispiel:
length :: [a] -> [a]
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Einschränkung von Typen
Mit Hilfe von vordefinierten Typ-Klassen können polymorphe
Funktionen mit Einschränkung definiert werden
Verwendung eines Kontextes
Beispiel:
equalList :: Eq a => [a]->[a]->Bool
nur für Datentypen mit Gleichheitsoperator
add2List:: Num a => [a] -> a -> [a]
add2List xs y = map (+y) xs
nur numerische Typen mit definierten
arithmetischen Operationen
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Einige vordefinierte Typ-Klassen
Klassenname
Show, Read
Eigenschaften
anzeigbar oder lesbar
(a → String), (String → a)
Funktionen
show, read
Eq
vergleichbar
(==), (/=)
Ord
sortierbar
compare, (<), (>), (<=),
(>=), min, max, ..
Enum
aufzählbar
succ, pred, [..]
Num
allgemeine Zahlen
(+), (-), (*), negate, abs
Integral
ganzzahlig
mod, div, quot, rem
Fractional
Kehrwert-Funktion
(/), recip,...
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Typ-Anpassung
In Haskell ist Typ-Anpassung für numerische Werte wie in
anderen Programmiersprachen nicht erlaubt.
Beispiel:
mod 3 2 + 1.5
Fehler:
<interactive>:1:10:
Ambiguous type variable `t' in the constraints:
`Fractional t'
arising from the literal `1.5' at <interactive>:1:10-12
`Integral t' arising from a use of `mod' at <interactive>:1:0-6
Probable fix: add a type signature that fixes these type variable(s)
Explizites Type-Casting muss stattfinden
fromIntegral (mod 3 2) + 1.5
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Typ-Klassen
Typen werden durch die Operationen, die auf ihren Werten definiert
werden sollen, beschrieben.
Class Num a where
(+) :: a -> a -> a
(*) :: a -> a -> a
Typklassen sind abstrakte
(-) :: a -> a -> a
Schnittstellen, weil keine
...
Implementierung vorgegeben
wird.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Instanzen von Typ-Klassen
Mit einer Instanz-Deklaration definieren wir, welche Typen zu
welchen Typ-Klassen gehören.
Vordefinierte primitive Funktionen
instance Num Int
where
x+y
= primAdd x y
neg x = primNegateInt x
...
instance Eq Char where
x == y = ord x == ord y
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Instanzen von Typ-Klassen
Der Instanz-Typ einer Klasse muss die vorgeschriebenen
Operationen einer Typ-Klasse implementieren.
Implementierung:
instance (Eq a) => Eq [a] where
(==) [] [] = True
(==) [] (x:xs) = False
(==) (x:ys) [] = False
(==) (x:xs) (y:ys) = x == y && xs == ys
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Instanzen von Typ-Klassen
data Menge a = Menge [a]
instance (Eq a) => Eq (Menge a) where
Menge xs == Menge ys = subset xs ys && subset ys xs
subset :: Eq a => a -> a -> Bool
subset xs ys = all (’elem’ ys) xs
instance (Ord a) => Ord (Menge a) where
Menge xs <= Menge ys = subset xs ys
...
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Subklassen
Klassen dürfen andere Klassen umfassen
class (Eq a, Show a) => Num a where
(+), (-), (*) :: a -> a -> a
negate :: a -> a
abs, signum :: a -> a
fromInteger :: Integer -> a
-- Minimal complete definition:
-- All, except negate or (-)
x - y = x + negate y -- Default-Definitionen
negate x = 0 - x
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Mehrere Oberklassen
class Enum a where
class Num a where
fromEnum :: a -> Int
(+) :: a -> a -> a
toEnum
neg :: a -> a
:: Int -> a
...
...
class (Enum a, Num a) => Integral a where
quot, rem, div, mod :: a -> a -> a
quotRem, divMod
even, odd
:: a -> a -> (a, a)
:: a -> Bool
toInteger
:: a -> Integer
toInt
:: a -> Int
Prof. Dr. Margarita Esponda
Integral erbt die Operationen
von Enum und Num und fügt
noch weitere Operationen
hinzu. Ausprägungen von
Integral müssen folglich auch
Ausprägungen von Enum und
Num sein.
Funktionale Programmierung
Klassenhierarchie
Eq
Show
Num
Ord
Enum
Real
Integral
Prof. Dr. Margarita Esponda
Fractional
Floating
Algebraische Datentypen
Standard
Klassenhierarchie
Prelude
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
53
Funktionale Programmierung
Abstrakte Datentypen
Konkrete Datentypen
• konkrete Darstellung der Information
innerhalb einer Sprache
• Listen, Bäume usw.
Datentypen
Abstrakte Datentypen
• definiert durch die Operationen
unabhängig von einer konkreten
Darstellung des Datentyps.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Abstrakte Datentypen
- sind Datentypen, die durch die auf ihren Werten
erlaubten Operationen definiert sind und dessen
Implementierung den Nutzern des Typs
verborgen (Datenkapselung) ist
- in Haskell werden abstrakte Datentypen mit
Hilfe des Modul-Konzepts implementiert
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Module in Haskell
Ein Haskell-Modul ist eine Datei mit folgender Struktur:
module <Name> (<Exportliste>) where
• Nur die Datentypen und Funktionen, die in
<Exportliste> angegeben werden, sind nach außen
sichtbar.
• Wenn <Exportliste> weggelassen wird, sind alle
Definitionen automatisch nach außen sichtbar.
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Module in Haskell
module Stapel
(Stapel, push, pop, top, createStack, isEmpty, show)
where
createStack :: Stapel a
isEmpty :: Stapel a -> Bool
push :: a-> Stapel a -> Stapel a
pop :: Stapel a -> Stapel a
top :: Stapel a -> a
data Stapel a = Empty | S a (Stapel a)
...
Prof. Dr. Margarita Esponda
Funktionale Programmierung
Module in Haskell
module Stapel . . .
...
createStack = Empty
isEmpty Empty = True
isEmpty _
= False
push x s = S x s
pop Empty = error "pop from an empty stack ..."
pop (S _ s) = s
top Empty = error "top from an empty stack ..."
top (S x _) = x
Prof. Dr. Margarita Esponda
Algebraische Datentypen
Abstrakte Datentyp für Mengen
module Menge (Menge, emptySet, isEmpty, inSet, insertSet, list2Set,
subSet, (\\), (|||), (&&&), powerSet )
where
data Menge a = Menge [a]
instance Eq a => Eq (Menge a) where
(==) s1 s2 = subSet set1 set2 && subSet s2 s1
instance (Show a) => Show (Menge a) where
...
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
59
Algebraische Datentypen
Abstrakte Datentyp für Mengen
module Menge . . . .
emptySet :: (Menge [Int])
isEmpty :: Eq a => Menge a -> Bool
inSet :: Eq a => a -> Menge a -> Bool
(|||) :: Eq a => Menge a -> Menge a -> Menge a
(\\) :: Eq a => Menge a -> Menge a -> Menge a
(&&&) :: Eq a => Menge a -> Menge a -> Menge a
subSet :: Eq a => Menge a -> Menge a -> Bool
powerSet :: Eq a => Menge a -> Menge (Menge a)
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
60
Algebraische Datentypen
Abstrakte Datentyp für Mengen
module Menge . . . .
emptySet = Menge []
isEmpty (Menge []) = True
isEmpty _ = False
inSet x (Menge ys) = elem x ys
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
61
Algebraische Datentypen
Abstrakte Datentyp für Mengen
module Menge . . . .
-- Vereinigung von zwei Mengen
(|||) (Menge (x:xs)) m = insertSet x ((Menge xs) ||| m)
(|||) (Menge []) m = m
-- Differenzmenge
(\\) (Menge xs) m = Menge [x|x<-xs, not(inSet x m)]
-- Schnittmenge
(&&&) (Menge xs) m = Menge [x|x<-xs, (inSet x m)]
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
62
Algebraische Datentypen
Abstrakte Datentyp für Mengen
module Menge . . . .
subSet (Menge []) _ = True
subSet _ (Menge []) = False
subSet (Menge (x:xs)) m = (inSet x m) && (subSet (Menge xs) m)
powerSet (Menge xs) = Menge powerMenge
where
powerMenge = map Menge (powerList xs)
powerList :: [a] -> [[a]]
powerList [] = [[]]
powerList (x:xs) = (powerList xs) ++ (map (x:) (powerList xs))
ALP I: Margarita Esponda, 12. Vorlesung, 26.11.2012
63
Herunterladen