Typklassen
Übersicht: Typklassen
Begriff und Verwendung von Typklassen
Die im vorigen Abschnitt dargestellte Gleicheits- und Ungleichheitsfunktion wurde nur für
Werte vom Typ Bool
definiert. Es soll für den Benutzer jedoch auch möglich sein
Werte eines davon abweichenden Datentyps zu vergleichen. Mehrere Typdefinitionen für eine Funktion
sind allerdings nicht möglich.
Genau für diesen Zweck sind Typklassen vorgeshen. Sie definieren eine Klasse von Typen, zu der jeder
Typ gehört, der eine Instanz der Typklasse bildet. Hierbei kann ein Typ zu mehreren Typklassen gehören.
Deklaration einer Typklasse
Die Deklaration einer Typklasse beginnt mit dem Schlüsselwort class
, gefolgt vom Namen der
Typklasse (hier Eq
für Equality bzw. Gleichheit) und einem Platzhalter (hier a
)
für einen Typ, der Instanz der Klasse ist.
Nach dem Schlüsselwort where
folgen
Typdefinitionen für Funktionen, die Teil der Typklasse sind. In den Typdefinitionen kann der Platzhalter
verwendet werden.
01 class Eq a where
02 (==),(/=) :: a -> a -> Bool
|
Die Typklasse Eq
besteht aus allen Typen für die (==)
und
(/=)
definiert werden.
Der Typ der Funktionen ist dann folgendermassen eingeschränkt auf die Typklasse:
01 (==),(/=) :: Eq a => a -> a -> Bool
|
Instanzdeklaration für einen Datentyp
Um den Datentyp Bool
Teil der Typklasse werden zu lassen muss eine Instanzdeklaration für den Typen erfolgen.
Die Instanzdeklaration ähnelt der Deklaration der Typklasse, beginnt aber mit dem Schlüsselwort instance
und die Funktionen aus der Typklasse werden spezifiziert.
01 instance Eq Bool where
02 x == y = (x && y) || (not x && not y)
03 x /= y = not (x == y)
|
Beispiel Ordnungsrelation
Ein weiteres Beispiel für eine Typklasse ist Ord
, die eine Ordnungsrelation zwischen Elementen
eines Typs definiert. Ord
ist als Subklasse von Eq
definiert. Aus logischer Sicht
können nur Elemente geordnet sein, die sich vergleichen lassen. Aus programmtechnischner Sicht bedeutet das,
dass nur Instanzen der Klasse Eq
Instanzen der Klasse Ord
werden können.
Bei der Definition dieser Typklasse wird ausgenutzt, dass Standardimplementierungen für Funktionen
vorgegeben werden können. Bei Bedarf dürfen diese in der Instanzdeklaration überschrieben werden.
Der Vorteil ist aber, dass für die Deklaration einer Instanz nur noch die fehlende Funktion <
definiert werden braucht.
Ein Merkmal dieser Deklaration ist, dass Funktionen der Oberklasse genutzt werden.
01 class (Eq a) => Ord a where
02 (<),(<=),(>=),(>) :: a -> a -> Bool
03 (x <= y) = (x < y) || (x == y)
04 (x >= y) = (x > y) || (x == y)
05 (x > y) = not (x <= y)
|
Die Instanzdeklaration für den Datentyp Bool
sieht dann folgendermassen aus:
01 instance Ord Bool where
02 False < False = False
03 False < True = True
04 True < False = False
05 True < True = False
|
Die Funktionalität der Standardimplementierung wird in Haskell auch für die Typklassse Eq
verwendet. Tatsächlich ist die oben gezeigte Implementation der Ungleichheit eine Standardimplementierung.
Für Instanzen dieser Typklasse muss also lediglich die Gleichheit definiert werden.