Funktionale Programmierung ALP I Funktionale Programmierung Typ-Klassen und Algebraische Datentypen SS 2011 Prof. Dr. Margarita Esponda Prof. Dr. Margarita Esponda Funktionale Programmierung Überladung von Datentypen Funktionen sollen oft auf verschiedene Datentypen anwendbar sein, aber nicht auf beliebige Datentypen. Beispiel: Die (+) Funktion oder die anderen arithmetischen Operationen sollen auf die Datentypen Int und Double anwendbar sein, aber nicht auf andere Datentypen. 1+2 2.5 + 3.4 Das wird gelöst, indem Typ-Klassen definiert werden. Prof. Dr. Margarita Esponda Funktionale Programmierung Typ-Klassen Mit Typ-Klassen lassen sich in Haskell Typen zusammenfassen, die ähnliche Operationen unterstützen. Beispiel: Variabler Datentyp (+) :: Num a => a -> a -> a Klassenname Die Typ-Variable a kann alle Instanzen der Num-Typklasse annehmen. Die Funktion wird dann für alle Datentypen, die eine Instanz der NumKlasse sind, definiert. Prof. Dr. Margarita Esponda Funktionale Programmierung Definition von Typ-Klassen Vordefinierte Typklassen: Beispiel: class Eq a where (==) :: a - > a -> Bool instance Eq Int where (==) = intEq -- intEq ist die primitive Funktion, die zwei -- ganze Zahlen auf Gleichheit testet. Prof. Dr. Margarita Esponda Funktionale Programmierung Definition von eigenen Typ-Klassen Eine Typ-Klasse deklariert eine Familie von Funktionen, die für verschiedene Typen unterschiedlich definiert sein können. Allgemeine Syntax: class C a where f1 :: t1 f2 :: t2 … fn :: tn Prof. Dr. Margarita Esponda Typvariable Die Typen ti müssen die Typvariable a enthalten Funktionale Programmierung Typ-Klassen in Haskell Eine Typ-Klasse ist eine Sammlung von Typen, auf denen eine in der Typ-Klasse festgelegte Menge von Funktionen definiert ist. Die Typ-Klasse Num stellt z. B. die Sammlung der numerischen Datentypen Int, Integer, Float, Double usw. dar, auf denen die Funktionen (+), (*), usw. definiert sind. Prof. Dr. Margarita Esponda Funktionale Programmierung Typklassen in Haskell Die vordefinierte Num-Typ-Klasse sieht vereinfacht so aus: class Num a where (+) :: a -> a -> a (-) :: a -> a -> a (*) :: a -> a -> a negate :: a -> a abs :: a -> a signum :: a -> a ... Typ-Klassen schreiben eine Schnittstelle vor. Prof. Dr. Margarita Esponda Funktionale Programmierung Typ-Klassen in Haskell Alle Typen, die Instanzen von Ord sein sollen, müssen die vorgeschriebenen Vergleichsoperationen implementieren. class Ord a where (<) :: a -> a -> Bool (<=) :: a -> a -> (>) :: a -> a -> Bool (>=) :: a -> a -> Bool max :: a -> a -> a min :: a -> a -> a … Prof. Dr. Margarita Esponda Bool Funktionale Programmierung Eigene Datentypen definieren Typ-Synonyme Ein vorhandener Datentyp wird umbenannt Algebraische Datentypen Neue Datentypen werden definiert mit Hilfe von sogenannten Typ-Konstruktoren. data Prof. Dr. Margarita Esponda Typ-Name = K1 | K2 | … | Kn Funktionale Programmierung Algebraische Datentypen Allgemeine Form: data T a1 …ak = K1 t11 … t1m 1 | K2 t21 … t2m 2 |… | Kn tn1 … tnm n Die Ki sind Konstruktoren und die ai sind die TypParameter des neuen Datentyps T. Prof. Dr. Margarita Esponda Funktionale Programmierung Algebraische Datentypen Beispiele: einfache Aufzählungen data Bool = True | False data Move = Left | Right | Up | Down type Position = (Int, Int) Funktionsbeispiel: move move move move move Prof. Dr. Margarita Esponda :: Move -> Position -> Position Left (x,y) = (x-1,y) Right (x,y) = (x+1,y) Up (x,y) = (x,y+1) Down (x,y) = (x,y-1) Funktionale Programmierung Algebraische Datentypen Beispiel: data Weekday = Mo | Tu | We | Th | Fr | Sa | Su isWeekend :: Weekday -> Bool isWeekend Sa = True isWeekend Su = True isWeekend _ = False Prof. Dr. Margarita Esponda Funktionale Programmierung Beispiel: Algebraische Datentypen data Weekday = Mo | Tu | We | Th | Fr | Sa | Su Mo == Mo => No instance for (Eq Weekday) arising from a use of `==' at <interactive>:1:0-5 Possible fix: add an instance declaration for (Eq Weekday) Wir brauchen eine eigene Gleichheits-Operation 1. Lösung equal :: Weekday -> Weekday -> Bool equal Mo Mo = True equal Tu Tu = True ... equal _ _ = False instance Eq Weekday where x == y = equal x y Prof. Dr. Margarita Esponda Funktionale Programmierung Beispiel: Algebraische Datentypen data Weekday = Mo | Tu | We | Th | Fr | Sa | Su deriving (Eq, Ord, Show) Instanzen dieser Klassen werden automatisch aus der Typdefinition abgeleitet. Eq Gleichheit und Ungleichheit lässt sich durch Mustervergleich ableiten Ord verwendet die Reihenfolge der Konstruktoren in der Typdefinition Mo < Tu < .. < Su Show Die Namen der Konstruktoren werden in Zeichenketten verwandelt Prof. Dr. Margarita Esponda Funktionale Programmierung Beispiel: Algebraische Datentypen data Weekday = Mo | Tu | We | Th | Fr | Sa | Su deriving (Eq, Ord, Show, Enum) Damit haben wir automatisch alle Vergleichsoperationen, eine show-Funktion für die Ausgabe von Ausdrücken und AufzählungsFunktionen wie succ, pred, fromEnum usw. Wir können sogar Listengeneratoren verwenden! isWorkday :: Weekday -> Bool isWorkday day = elem day [Mo .. Fr] Prof. Dr. Margarita Esponda Funktionale Programmierung Algebraische Datentypen Typ-Konstruktoren mit Typen als Argumente Beispiel: data Temperatur = Celsius Double | Fahrenheit Double | Kelvin Double deriving Show Die Show-Funktion wird abgeleitet celsius2Kelvin :: Temperatur -> Temperatur celsius2Kelvin (Celsius cel) = Kelvin (cel + 273.16) fahrenheit2Celsius :: Temperatur -> Temperatur fahrenheit2Celsius (Fahrenheit fah) = Celsius ((fah-32)*5/9) Prof. Dr. Margarita Esponda Funktionale Programmierung Algebraische Datentypen type Point = (Double, Double) data Shape = Circ Point Double | Rect Point Point | CPoly [Point] deriving (Eq, Show) area :: Shape-> Double area (Circ _ d) = pi*d area (Rect (x1, y1) (x2, y2)) = abs ((x2-x1) * (y2-y1)) area (CPoly ps) | length ps < 3 = 0 area (CPoly (p1:p2:p3:ps)) = triangleArea p1 p2 p3 + area (CPoly (p1:p3:ps)) triangleArea :: Point -> Point -> Point triangleArea (x1,y1) (x2,y2) (x3,y3) = abs ((x2-x1)*(y3-y1) - (x3-x1)*(y2-y1)) / 2 Prof. Dr. Margarita Esponda Funktionale Programmierung Algebraische Datentypen Rekursive Definitionen Beispiel: data Tree = Leaf Int | Node Int Tree Tree | Nil 53 27 13 69 34 63 46 Prof. Dr. Margarita Esponda 95